]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7209 WS user_tokens/revoke a user can delete its own tokens
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 18 Jan 2016 08:37:27 +0000 (09:37 +0100)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 18 Jan 2016 17:35:43 +0000 (18:35 +0100)
server/sonar-server/src/main/java/org/sonar/server/usertoken/ws/RevokeAction.java
server/sonar-server/src/test/java/org/sonar/server/usertoken/ws/RevokeActionTest.java
server/sonar-server/src/test/java/org/sonar/server/usertoken/ws/UserTokensWsTest.java
sonar-ws/src/main/java/org/sonarqube/ws/client/usertoken/RevokeWsRequest.java

index dd36e067c6d8bd8f79b2c788c4d0bf3d41cc6491..2fdfefc23edad982379ec584734906e028b9519e 100644 (file)
@@ -27,7 +27,6 @@ import org.sonar.db.DbSession;
 import org.sonar.server.user.UserSession;
 import org.sonarqube.ws.client.usertoken.RevokeWsRequest;
 
-import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
 import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.ACTION_REVOKE;
 import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.PARAM_LOGIN;
 import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.PARAM_NAME;
@@ -45,13 +44,12 @@ public class RevokeAction implements UserTokensWsAction {
   public void define(WebService.NewController context) {
     WebService.NewAction action = context.createAction(ACTION_REVOKE)
       .setDescription("Revoke a user access token. <br/>"+
-        "It requires administration permissions.")
+        "If the login is set, it requires administration permissions. Otherwise, a token is generated for the authenticated user.")
       .setSince("5.3")
       .setPost(true)
       .setHandler(this);
 
     action.createParam(PARAM_LOGIN)
-      .setRequired(true)
       .setDescription("User login")
       .setExampleValue("g.hopper");
 
@@ -68,7 +66,7 @@ public class RevokeAction implements UserTokensWsAction {
   }
 
   private void doHandle(RevokeWsRequest request) {
-    userSession.checkLoggedIn().checkPermission(SYSTEM_ADMIN);
+    TokenPermissionsValidator.validate(userSession, request.getLogin());
 
     DbSession dbSession = dbClient.openSession(false);
     try {
@@ -79,9 +77,13 @@ public class RevokeAction implements UserTokensWsAction {
     }
   }
 
-  private static RevokeWsRequest toRevokeWsRequest(Request request) {
-    return new RevokeWsRequest()
-      .setLogin(request.mandatoryParam(PARAM_LOGIN))
+  private RevokeWsRequest toRevokeWsRequest(Request request) {
+    RevokeWsRequest revokeWsRequest = new RevokeWsRequest()
+      .setLogin(request.param(PARAM_LOGIN))
       .setName(request.mandatoryParam(PARAM_NAME));
+    if (revokeWsRequest.getLogin() == null) {
+      revokeWsRequest.setLogin(userSession.getLogin());
+    }
+    return revokeWsRequest;
   }
 }
index b93da65dc9b77f854bd1cc4bb322a8a2508fe4ef..05744c22d322c5f6b8cb0edc3f83ea791f94bba9 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.usertoken.ws;
 
+import javax.annotation.Nullable;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -31,8 +32,8 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.user.UserTokenDto;
 import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.UnauthorizedException;
 import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
 import org.sonar.server.ws.WsActionTester;
 import org.sonar.test.DbTests;
 
@@ -47,7 +48,6 @@ public class RevokeActionTest {
   static final String ADA_LOVELACE = "ada.lovelace";
   static final String TOKEN_NAME = "token-name";
 
-
   @Rule
   public DbTester db = DbTester.create(System2.INSTANCE);
   DbClient dbClient = db.getDbClient();
@@ -84,19 +84,21 @@ public class RevokeActionTest {
   }
 
   @Test
-  public void does_not_fail_when_incorrect_login_or_name() {
-    insertUserToken(newUserToken().setLogin(GRACE_HOPPER).setName(TOKEN_NAME));
+  public void user_can_delete_its_own_tokens() {
+    userSession.login(GRACE_HOPPER).setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
+    insertUserToken(newUserToken().setLogin(GRACE_HOPPER).setName("token-to-delete"));
 
-    newRequest(ADA_LOVELACE, "another-token-name");
+    String response = newRequest(null, "token-to-delete");
+
+    assertThat(response).isEmpty();
+    assertThat(dbClient.userTokenDao().selectByLogin(dbSession, GRACE_HOPPER)).isEmpty();
   }
 
   @Test
-  public void fail_if_not_logged_in() {
-    userSession.anonymous();
+  public void does_not_fail_when_incorrect_login_or_name() {
     insertUserToken(newUserToken().setLogin(GRACE_HOPPER).setName(TOKEN_NAME));
-    expectedException.expect(UnauthorizedException.class);
 
-    newRequest(GRACE_HOPPER, TOKEN_NAME);
+    newRequest(ADA_LOVELACE, "another-token-name");
   }
 
   @Test
@@ -108,11 +110,14 @@ public class RevokeActionTest {
     newRequest(GRACE_HOPPER, TOKEN_NAME);
   }
 
-  private String newRequest(String login, String name) {
-    return ws.newRequest()
-      .setParam(PARAM_LOGIN, login)
-      .setParam(PARAM_NAME, name)
-      .execute().getInput();
+  private String newRequest(@Nullable String login, String name) {
+    TestRequest testRequest = ws.newRequest()
+      .setParam(PARAM_NAME, name);
+    if (login != null) {
+      testRequest.setParam(PARAM_LOGIN, login);
+    }
+
+    return testRequest.execute().getInput();
   }
 
   private void insertUserToken(UserTokenDto userToken) {
index 86d40f98edbf9622fdc92d81ccb4b7b75a0d11fa..ff8e819acb48c6f585db72d9305244498bb71f76 100644 (file)
@@ -68,7 +68,7 @@ public class UserTokensWsTest {
     assertThat(action).isNotNull();
     assertThat(action.since()).isEqualTo("5.3");
     assertThat(action.isPost()).isTrue();
-    assertThat(action.param("login").isRequired()).isTrue();
+    assertThat(action.param("login").isRequired()).isFalse();
     assertThat(action.param("name").isRequired()).isTrue();
   }
 
index 8459ab277ea4a5594daafb5e7fe2fbb25c5a0c6a..65344ce3a4e11e794fd79a047dec90ee7e5e3f55 100644 (file)
  */
 package org.sonarqube.ws.client.usertoken;
 
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
 public class RevokeWsRequest {
   private String login;
   private String name;
 
+  @CheckForNull
   public String getLogin() {
     return login;
   }
 
-  public RevokeWsRequest setLogin(String login) {
+  public RevokeWsRequest setLogin(@Nullable String login) {
     this.login = login;
     return this;
   }