From 162d76a0e6964f1d42069b42ce0362fedd151f75 Mon Sep 17 00:00:00 2001 From: Teryk Bellahsene Date: Mon, 18 Jan 2016 09:43:40 +0100 Subject: [PATCH] SONAR-7210 WS user_tokens/search a user can search its own token --- .../server/usertoken/ws/SearchAction.java | 19 +++++---- .../ws/TokenPermissionsValidator.java | 5 ++- .../server/usertoken/ws/SearchActionTest.java | 42 ++++++++++++------- .../server/usertoken/ws/UserTokensWsTest.java | 2 +- .../ws/client/usertoken/SearchWsRequest.java | 6 ++- 5 files changed, 46 insertions(+), 28 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/usertoken/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/usertoken/ws/SearchAction.java index d43705f3421..c44f5cc9604 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usertoken/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usertoken/ws/SearchAction.java @@ -24,7 +24,6 @@ import java.util.List; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; -import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.user.UserTokenDto; @@ -50,15 +49,14 @@ public class SearchAction implements UserTokensWsAction { @Override public void define(WebService.NewController context) { WebService.NewAction action = context.createAction(ACTION_SEARCH) - .setDescription("List the access tokens of a user.
" + - "The login must exist and active.
" + - "It requires administration permissions.") + .setDescription("List the access tokens of a user.
" + + "The login must exist and active.
" + + "If the login is set, it requires administration permissions. Otherwise, a token is generated for the authenticated user.") .setResponseExample(getClass().getResource("search-example.json")) .setSince("5.3") .setHandler(this); action.createParam(PARAM_LOGIN) - .setRequired(true) .setDescription("User login") .setExampleValue("g.hopper"); } @@ -70,7 +68,7 @@ public class SearchAction implements UserTokensWsAction { } private SearchWsResponse doHandle(SearchWsRequest request) { - userSession.checkLoggedIn().checkPermission(GlobalPermissions.SYSTEM_ADMIN); + TokenPermissionsValidator.validate(userSession, request.getLogin()); DbSession dbSession = dbClient.openSession(false); try { @@ -83,9 +81,12 @@ public class SearchAction implements UserTokensWsAction { } } - private static SearchWsRequest toSearchWsRequest(Request request) { - return new SearchWsRequest() - .setLogin(request.mandatoryParam(PARAM_LOGIN)); + private SearchWsRequest toSearchWsRequest(Request request) { + SearchWsRequest searchWsRequest = new SearchWsRequest().setLogin(request.param(PARAM_LOGIN)); + if (searchWsRequest.getLogin() == null) { + searchWsRequest.setLogin(userSession.getLogin()); + } + return searchWsRequest; } private static SearchWsResponse buildResponse(String login, List userTokensDto) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/usertoken/ws/TokenPermissionsValidator.java b/server/sonar-server/src/main/java/org/sonar/server/usertoken/ws/TokenPermissionsValidator.java index 8be1c2a32e3..ff28731c2c7 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usertoken/ws/TokenPermissionsValidator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usertoken/ws/TokenPermissionsValidator.java @@ -19,6 +19,7 @@ */ package org.sonar.server.usertoken.ws; +import javax.annotation.Nullable; import org.sonar.core.permission.GlobalPermissions; import org.sonar.server.user.UserSession; @@ -29,9 +30,9 @@ class TokenPermissionsValidator { // prevent instantiation } - static void validate(UserSession userSession, String requestLogin) { + static void validate(UserSession userSession, @Nullable String requestLogin) { if (userSession.hasPermission(GlobalPermissions.SYSTEM_ADMIN) - || requestLogin.equals(userSession.getLogin())) { + || (requestLogin != null && requestLogin.equals(userSession.getLogin()))) { return; } diff --git a/server/sonar-server/src/test/java/org/sonar/server/usertoken/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/usertoken/ws/SearchActionTest.java index 3a532274fd1..82a9918e60b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/usertoken/ws/SearchActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/usertoken/ws/SearchActionTest.java @@ -21,6 +21,7 @@ package org.sonar.server.usertoken.ws; import com.google.common.base.Throwables; import java.io.IOException; +import javax.annotation.Nullable; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -34,14 +35,15 @@ import org.sonar.db.DbTester; import org.sonar.db.user.UserDbTester; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.exceptions.UnauthorizedException; import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.TestResponse; import org.sonar.server.ws.WsActionTester; import org.sonar.test.DbTests; import org.sonarqube.ws.MediaTypes; import org.sonarqube.ws.WsUserTokens.SearchWsResponse; +import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.db.user.UserTesting.newUserDto; import static org.sonar.db.user.UserTokenTesting.newUserToken; import static org.sonar.test.JsonAssert.assertJson; @@ -51,7 +53,6 @@ import static org.sonarqube.ws.client.usertoken.UserTokensWsParameters.PARAM_LOG public class SearchActionTest { static final String GRACE_HOPPER = "grace.hopper"; static final String ADA_LOVELACE = "ada.lovelace"; - static final String TOKEN_NAME = "token-name"; @Rule public ExpectedException expectedException = ExpectedException.none(); @@ -91,6 +92,7 @@ public class SearchActionTest { .setName("Project scan on Travis") .setLogin(ADA_LOVELACE)); dbSession.commit(); + String response = ws.newRequest() .setParam(PARAM_LOGIN, GRACE_HOPPER) .execute().getInput(); @@ -99,19 +101,25 @@ public class SearchActionTest { } @Test - public void fail_when_login_does_not_exist() { - expectedException.expect(NotFoundException.class); - expectedException.expectMessage("User with login 'unknown-login' not found"); + public void a_user_can_search_its_own_token() { + userSession.login(GRACE_HOPPER).setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); + dbClient.userTokenDao().insert(dbSession, newUserToken() + .setCreatedAt(1448523067221L) + .setName("Project scan on Travis") + .setLogin(GRACE_HOPPER)); + db.commit(); - newRequest("unknown-login"); + SearchWsResponse response = newRequest(null); + + assertThat(response.getUserTokensCount()).isEqualTo(1); } @Test - public void fail_when_not_logged_in() { - userSession.anonymous(); - expectedException.expect(UnauthorizedException.class); + public void fail_when_login_does_not_exist() { + expectedException.expect(NotFoundException.class); + expectedException.expectMessage("User with login 'unknown-login' not found"); - newRequest(GRACE_HOPPER); + newRequest("unknown-login"); } @Test @@ -122,11 +130,15 @@ public class SearchActionTest { newRequest(GRACE_HOPPER); } - private SearchWsResponse newRequest(String login) { - TestResponse response = ws.newRequest() - .setMediaType(MediaTypes.PROTOBUF) - .setParam(PARAM_LOGIN, login) - .execute(); + private SearchWsResponse newRequest(@Nullable String login) { + TestRequest testRequest = ws.newRequest() + .setMediaType(MediaTypes.PROTOBUF); + if (login != null) { + testRequest.setParam(PARAM_LOGIN, login); + } + + TestResponse response = testRequest.execute(); + try { return SearchWsResponse.parseFrom(response.getInputStream()); } catch (IOException e) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/usertoken/ws/UserTokensWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/usertoken/ws/UserTokensWsTest.java index ff8e819acb4..2ab34825658 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/usertoken/ws/UserTokensWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/usertoken/ws/UserTokensWsTest.java @@ -79,6 +79,6 @@ public class UserTokensWsTest { assertThat(action).isNotNull(); assertThat(action.since()).isEqualTo("5.3"); assertThat(action.isPost()).isFalse(); - assertThat(action.param("login").isRequired()).isTrue(); + assertThat(action.param("login").isRequired()).isFalse(); } } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/usertoken/SearchWsRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/usertoken/SearchWsRequest.java index 4c69e9487de..3fd52b200ff 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/usertoken/SearchWsRequest.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/usertoken/SearchWsRequest.java @@ -19,14 +19,18 @@ */ package org.sonarqube.ws.client.usertoken; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + public class SearchWsRequest { private String login; + @CheckForNull public String getLogin() { return login; } - public SearchWsRequest setLogin(String login) { + public SearchWsRequest setLogin(@Nullable String login) { this.login = login; return this; } -- 2.39.5