@@ -98,7 +98,8 @@ public String toString() {
9898 protected static final String PERSONAL_ACCESS_TOKEN_REGEX = "\\ {\" new_token\" :\" ([^\" ]*)\" " ;
9999 protected static final Pattern PERSONAL_ACCESS_TOKEN_PATTERN = Pattern .compile (PERSONAL_ACCESS_TOKEN_REGEX );
100100
101- protected static final String REVOKE_PERSONAL_ACCESS_TOKEN_REGEX = "href=\\ \" ([^\\ \" ]*)\\ \" " ;
101+ protected static final String REVOKE_PERSONAL_ACCESS_TOKEN_REGEX =
102+ "\\ {.*?"name":"(.*?)",.*?"scopes":\\ [(.*?)\\ ],.*?"revoke_path":"(.*?)"\\ }" ;
102103 protected static final Pattern REVOKE_PERSONAL_ACCESS_TOKEN_PATTERN = Pattern .compile (REVOKE_PERSONAL_ACCESS_TOKEN_REGEX );
103104
104105 protected static final String FEED_TOKEN_REGEX = "<div data-tokens-data=\\ \" \\ {.*"feed_token":\\ {.*?"token":"(.*?)"," ;
@@ -325,49 +326,59 @@ public static final void revokePersonalAccessToken(final String baseUrl, final S
325326 * Step 3: Submit the /profile/personal_access_tokens page with the info to *
326327 * revoke the first matching personal access token. *
327328 *******************************************************************************/
328- int indexOfTokenName = content .indexOf ("<td>" + tokenName + "</td>" );
329- if (indexOfTokenName == -1 ) {
329+ String tokensDataAttribute = "data-initial-active-access-tokens" ;
330+ int indexOfStartOfTokensJsonData = content .indexOf (tokensDataAttribute );
331+ if (indexOfStartOfTokensJsonData == -1 ) {
330332 throw new GitLabApiException ("personal access token not found, aborting!" );
331333 }
334+ indexOfStartOfTokensJsonData += tokensDataAttribute .length () + 2 ; // attribute name + ="
332335
333- content = content .substring (indexOfTokenName );
334- int indexOfLinkEnd = content .indexOf ("</a> " );
335- if (indexOfTokenName == -1 ) {
336+ content = content .substring (indexOfStartOfTokensJsonData );
337+ int indexOfEndOfTokensJsonData = content .indexOf ("\" " );
338+ if (indexOfEndOfTokensJsonData == -1 ) {
336339 throw new GitLabApiException ("personal access token not found, aborting!" );
337340 }
338341
339- content = content .substring (0 , indexOfLinkEnd );
340- String scopesText = "" ;
341- if (scopes != null && scopes .size () > 0 ) {
342- final StringJoiner joiner = new StringJoiner (", " );
343- scopes .forEach (s -> joiner .add (s .toString ()));
344- scopesText = joiner .toString ();
345- }
342+ content = content .substring (0 , indexOfEndOfTokensJsonData );
346343
347- if (content .indexOf (scopesText ) == -1 ) {
344+ matcher = REVOKE_PERSONAL_ACCESS_TOKEN_PATTERN .matcher (content );
345+ if (!matcher .find ()) {
348346 throw new GitLabApiException ("personal access token not found, aborting!" );
349347 }
350348
351- matcher = REVOKE_PERSONAL_ACCESS_TOKEN_PATTERN .matcher (content );
352- if (!matcher .find ()) {
349+ // the first token returned should be the one we want to revoke
350+ // iterate over the remaining matches if that changes
351+ String foundTokenName = matcher .group (1 );
352+ String foundTokenScopes = matcher .group (2 ); // eg: "api","sudo"
353+ foundTokenScopes = foundTokenScopes .replace (""" , "" );
354+ String foundTokenRevokePath = matcher .group (3 );
355+
356+ String expectedScopesText = "" ;
357+ if (scopes != null && scopes .size () > 0 ) {
358+ final StringJoiner joiner = new StringJoiner ("," );
359+ scopes .forEach (s -> joiner .add (s .toString ()));
360+ expectedScopesText = joiner .toString ();
361+ }
362+
363+ if (!foundTokenName .equals (tokenName ) || !foundTokenScopes .equals (expectedScopesText )) {
353364 throw new GitLabApiException ("personal access token not found, aborting!" );
354365 }
355366
356- String revokePath = matcher .group (1 );
357- url = new URL (baseUrl + revokePath );
367+ url = new URL (baseUrl + foundTokenRevokePath );
358368 connection = (HttpURLConnection ) url .openConnection ();
359369 connection .setRequestProperty ("User-Agent" , USER_AGENT );
360370 connection .setRequestProperty ("Content-Type" , "application/x-www-form-urlencoded" );
361371 connection .setRequestProperty ("Charset" , "utf-8" );
362372 connection .setRequestProperty ("Cookie" , cookies );
363373 connection .setReadTimeout (10000 );
364374 connection .setConnectTimeout (10000 );
365- connection .setRequestMethod ("PUT " );
375+ connection .setRequestMethod ("POST " );
366376 connection .setDoInput (true );
367377 connection .setDoOutput (true );
368378
369379 // Submit the form
370380 StringBuilder formData = new StringBuilder ();
381+ addFormData (formData , "_method" , "put" );
371382 addFormData (formData , "authenticity_token" , csrfToken );
372383 connection .setRequestProperty ("Content-Length" , String .valueOf (formData .length ()));
373384 OutputStream output = connection .getOutputStream ();
0 commit comments