From 4181cd5c305ed4a54c43a59db646eb658b8f3c89 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Lievremont Date: Tue, 2 Jun 2015 10:20:01 +0200 Subject: [PATCH] SONAR-6470 SONAR-6475 Require admin permission to list group/user associations --- .../sonar/server/user/ws/GroupsAction.java | 26 ++++++++++++------- .../server/usergroups/ws/UsersAction.java | 20 ++++++++++---- .../server/user/ws/GroupsActionTest.java | 23 ++++++++++------ .../server/usergroups/ws/UsersActionTest.java | 20 +++++++++++--- 4 files changed, 64 insertions(+), 25 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java index 1df8897c762..9538cd93104 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java @@ -19,6 +19,8 @@ */ package org.sonar.server.user.ws; +import java.util.List; +import javax.annotation.Nullable; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService.NewAction; @@ -26,15 +28,13 @@ import org.sonar.api.server.ws.WebService.NewController; import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.Paging; import org.sonar.api.utils.text.JsonWriter; +import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.persistence.DbSession; import org.sonar.core.user.GroupMembershipDto; import org.sonar.core.user.GroupMembershipQuery; import org.sonar.core.user.UserDto; import org.sonar.server.db.DbClient; - -import javax.annotation.Nullable; - -import java.util.List; +import org.sonar.server.user.UserSession; public class GroupsAction implements UsersWsAction { @@ -42,13 +42,19 @@ public class GroupsAction implements UsersWsAction { private static final String PARAM_SELECTED = "selected"; private static final String SELECTION_ALL = "all"; - private static final String SELECTION_SELECTED = "selected"; + private static final String SELECTION_SELECTED = PARAM_SELECTED; private static final String SELECTION_DESELECTED = "deselected"; + private static final String FIELD_SELECTED = PARAM_SELECTED; + private static final String FIELD_DESCRIPTION = "description"; + private static final String FIELD_NAME = "name"; + private final DbClient dbClient; + private final UserSession userSession; - public GroupsAction(DbClient dbClient) { + public GroupsAction(DbClient dbClient, UserSession userSession) { this.dbClient = dbClient; + this.userSession = userSession; } @Override @@ -78,6 +84,8 @@ public class GroupsAction implements UsersWsAction { @Override public void handle(Request request, Response response) throws Exception { + userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN); + String login = request.mandatoryParam(PARAM_LOGIN); int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE); int page = request.mandatoryParamAsInt(Param.PAGE); @@ -112,9 +120,9 @@ public class GroupsAction implements UsersWsAction { json.name("groups").beginArray(); for (GroupMembershipDto group : groups) { json.beginObject() - .prop("name", group.getName()) - .prop("description", group.getDescription()) - .prop("selected", group.getUserId() != null) + .prop(FIELD_NAME, group.getName()) + .prop(FIELD_DESCRIPTION, group.getDescription()) + .prop(FIELD_SELECTED, group.getUserId() != null) .endObject(); } json.endArray(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UsersAction.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UsersAction.java index eabc744a716..526ddd114b9 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UsersAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UsersAction.java @@ -28,12 +28,14 @@ import org.sonar.api.server.ws.WebService.NewController; import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.Paging; import org.sonar.api.utils.text.JsonWriter; +import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; import org.sonar.core.user.GroupMembershipQuery; import org.sonar.core.user.UserMembershipDto; import org.sonar.core.user.UserMembershipQuery; import org.sonar.server.db.DbClient; +import org.sonar.server.user.UserSession; public class UsersAction implements UserGroupsWsAction { @@ -41,13 +43,19 @@ public class UsersAction implements UserGroupsWsAction { private static final String PARAM_SELECTED = "selected"; private static final String SELECTION_ALL = "all"; - private static final String SELECTION_SELECTED = "selected"; + private static final String SELECTION_SELECTED = PARAM_SELECTED; private static final String SELECTION_DESELECTED = "deselected"; + private static final String FIELD_SELECTED = PARAM_SELECTED; + private static final String FIELD_NAME = "name"; + private static final String FIELD_LOGIN = "login"; + private final DbClient dbClient; + private final UserSession userSession; - public UsersAction(DbClient dbClient) { + public UsersAction(DbClient dbClient, UserSession userSession) { this.dbClient = dbClient; + this.userSession = userSession; } @Override @@ -75,6 +83,8 @@ public class UsersAction implements UserGroupsWsAction { @Override public void handle(Request request, Response response) throws Exception { + userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN); + Long groupId = request.mandatoryParamAsLong(PARAM_ID); int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE); int page = request.mandatoryParamAsInt(Param.PAGE); @@ -109,9 +119,9 @@ public class UsersAction implements UserGroupsWsAction { json.name("users").beginArray(); for (UserMembershipDto user : users) { json.beginObject() - .prop("login", user.getLogin()) - .prop("name", user.getName()) - .prop("selected", user.getGroupId() != null) + .prop(FIELD_LOGIN, user.getLogin()) + .prop(FIELD_NAME, user.getName()) + .prop(FIELD_SELECTED, user.getGroupId() != null) .endObject(); } json.endArray(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java index 1764914bd18..c35d5cb0a06 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java @@ -23,10 +23,11 @@ package org.sonar.server.user.ws; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; -import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.System2; +import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.DbTester; import org.sonar.core.user.GroupDto; @@ -34,7 +35,9 @@ import org.sonar.core.user.GroupMembershipDao; import org.sonar.core.user.UserDto; import org.sonar.core.user.UserGroupDto; import org.sonar.server.db.DbClient; +import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.tester.UserSessionRule; import org.sonar.server.user.db.GroupDao; import org.sonar.server.user.db.UserDao; import org.sonar.server.user.db.UserGroupDao; @@ -44,13 +47,11 @@ public class GroupsActionTest { @ClassRule public static final DbTester dbTester = new DbTester(); - - WebService.Controller controller; + @Rule + public UserSessionRule userSession = UserSessionRule.standalone(); WsTester tester; - DbClient dbClient; - DbSession session; @Before @@ -67,9 +68,8 @@ public class GroupsActionTest { session = dbClient.openSession(false); session.commit(); - tester = new WsTester(new UsersWs(new GroupsAction(dbClient))); - controller = tester.controller("api/users"); - + tester = new WsTester(new UsersWs(new GroupsAction(dbClient, userSession))); + userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); } @After @@ -83,6 +83,13 @@ public class GroupsActionTest { .setParam("login", "john").execute(); } + @Test(expected = ForbiddenException.class) + public void fail_on_missing_permission() throws Exception { + userSession.login("not-admin"); + tester.newGetRequest("api/users", "groups") + .setParam("login", "john").execute(); + } + @Test public void empty_groups() throws Exception { createUser(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UsersActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UsersActionTest.java index 928e0c638a5..30c31d346cc 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UsersActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UsersActionTest.java @@ -20,14 +20,14 @@ package org.sonar.server.usergroups.ws; -import org.sonar.server.ws.WsTester.TestRequest; - import org.junit.After; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.sonar.api.utils.System2; +import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.DbTester; import org.sonar.core.user.GroupDto; @@ -35,11 +35,14 @@ import org.sonar.core.user.GroupMembershipDao; import org.sonar.core.user.UserDto; import org.sonar.core.user.UserGroupDto; import org.sonar.server.db.DbClient; +import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.tester.UserSessionRule; import org.sonar.server.user.db.GroupDao; import org.sonar.server.user.db.UserDao; import org.sonar.server.user.db.UserGroupDao; import org.sonar.server.ws.WsTester; +import org.sonar.server.ws.WsTester.TestRequest; import org.sonar.test.DbTests; @Category(DbTests.class) @@ -47,6 +50,8 @@ public class UsersActionTest { @ClassRule public static final DbTester dbTester = new DbTester(); + @Rule + public UserSessionRule userSession = UserSessionRule.standalone(); WsTester wsTester; DbClient dbClient; @@ -66,7 +71,8 @@ public class UsersActionTest { session = dbClient.openSession(false); session.commit(); - wsTester = new WsTester(new UserGroupsWs(new UsersAction(dbClient))); + wsTester = new WsTester(new UserGroupsWs(new UsersAction(dbClient, userSession))); + userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); } @@ -82,6 +88,14 @@ public class UsersActionTest { .setParam("login", "john").execute(); } + @Test(expected = ForbiddenException.class) + public void fail_on_missing_permission() throws Exception { + userSession.login("not-admin"); + newUsersRequest() + .setParam("id", "42") + .setParam("login", "john").execute(); + } + private TestRequest newUsersRequest() { return wsTester.newGetRequest("api/usergroups", "users"); } -- 2.39.5