From: Teryk Bellahsene Date: Mon, 10 Aug 2015 11:50:51 +0000 (+0200) Subject: SONAR-6490 WS permissions/add_group add project permissions to a group X-Git-Tag: 5.2-RC1~801 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=5aa1d8eeed7498999f5ce25289339f49c2ad4ec0;p=sonarqube.git SONAR-6490 WS permissions/add_group add project permissions to a group --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentFinder.java b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentFinder.java index 5acd0f73da3..aadbf41dfa7 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentFinder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentFinder.java @@ -22,9 +22,11 @@ package org.sonar.server.component; import com.google.common.base.Optional; import javax.annotation.Nullable; +import org.sonar.api.resources.Qualifiers; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; +import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.NotFoundException; import static com.google.common.base.Preconditions.checkArgument; @@ -54,10 +56,23 @@ public class ComponentFinder { return getIfPresentOrFail(dbClient.componentDao().selectByUuid(dbSession, uuid), String.format("Component id '%s' not found", uuid)); } + public ComponentDto getProjectByUuidOrKey(DbSession dbSession, @Nullable String projectUuid, @Nullable String projectKey) { + ComponentDto project = getByUuidOrKey(dbSession, projectUuid, projectKey); + checkIsProjectOrModule(project); + + return project; + } + private static ComponentDto getIfPresentOrFail(Optional component, String errorMsg) { if (!component.isPresent()) { throw new NotFoundException(errorMsg); } return component.get(); } + + private static void checkIsProjectOrModule(ComponentDto component) { + if (!Qualifiers.PROJECT.equals(component.qualifier()) && !Qualifiers.MODULE.equals(component.qualifier())) { + throw new BadRequestException(String.format("Component '%s' (id: %s) must be a project or a module.", component.key(), component.uuid())); + } + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionChange.java b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionChange.java index ebec68b6f19..29e4db4e06c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionChange.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionChange.java @@ -21,17 +21,15 @@ package org.sonar.server.permission; import com.google.common.base.Strings; +import java.util.Map; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.sonar.core.permission.ComponentPermissions; import org.sonar.core.permission.GlobalPermissions; import org.sonar.server.exceptions.BadRequestException; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import java.util.Map; - public class PermissionChange { static final String USER_KEY = "user"; diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupAction.java index cf847398204..242ae06b863 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupAction.java @@ -20,35 +20,44 @@ package org.sonar.server.permission.ws; +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; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.component.ComponentDto; +import org.sonar.server.component.ComponentFinder; import org.sonar.server.permission.PermissionChange; import org.sonar.server.permission.PermissionUpdater; -import static org.sonar.server.permission.ws.PermissionWsCommons.searchName; - public class AddGroupAction implements PermissionsWsAction { public static final String ACTION = "add_group"; public static final String PARAM_PERMISSION = "permission"; public static final String PARAM_GROUP_NAME = "groupName"; public static final String PARAM_GROUP_ID = "groupId"; + public static final String PARAM_PROJECT_ID = "projectId"; + public static final String PARAM_PROJECT_KEY = "projectKey"; - private final PermissionUpdater permissionUpdater; private final DbClient dbClient; + private final PermissionWsCommons permissionWsCommons; + private final PermissionUpdater permissionUpdater; + private final ComponentFinder componentFinder; - public AddGroupAction(PermissionUpdater permissionUpdater, DbClient dbClient) { + public AddGroupAction(DbClient dbClient, PermissionWsCommons permissionWsCommons, PermissionUpdater permissionUpdater, ComponentFinder componentFinder) { + this.permissionWsCommons = permissionWsCommons; this.permissionUpdater = permissionUpdater; this.dbClient = dbClient; + this.componentFinder = componentFinder; } @Override public void define(WebService.NewController context) { WebService.NewAction action = context.createAction(ACTION) .setDescription("Add permission to a group.
" + + "If the project id is provided, a project permission is created.
" + "The group name or group id must be provided.
" + "Requires 'Administer System' permission.") .setSince("5.2") @@ -65,8 +74,16 @@ public class AddGroupAction implements PermissionsWsAction { .setExampleValue("sonar-administrators"); action.createParam(PARAM_GROUP_ID) - .setDescription("Group ID") + .setDescription("Group id") .setExampleValue("42"); + + action.createParam(PARAM_PROJECT_ID) + .setDescription("Project id") + .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d"); + + action.createParam(PARAM_PROJECT_KEY) + .setDescription("Project key") + .setExampleValue("org.apache.hbas:hbase"); } @Override @@ -74,15 +91,34 @@ public class AddGroupAction implements PermissionsWsAction { String permission = request.mandatoryParam(PARAM_PERMISSION); String groupNameParam = request.param(PARAM_GROUP_NAME); Long groupId = request.paramAsLong(PARAM_GROUP_ID); + String projectUuid = request.param(PARAM_PROJECT_ID); + String projectKey = request.param(PARAM_PROJECT_KEY); - String groupName = searchName(dbClient, groupNameParam, groupId); + DbSession dbSession = dbClient.openSession(false); + try { + String groupName = permissionWsCommons.searchGroupName(dbSession, groupNameParam, groupId); + PermissionChange permissionChange = permissionChange(dbSession, permission, groupName, projectUuid, projectKey); - permissionUpdater.addPermission( - new PermissionChange() - .setPermission(permission) - .setGroup(groupName) - ); + permissionUpdater.addPermission(permissionChange); + } finally { + dbClient.closeSession(dbSession); + } response.noContent(); } + + private PermissionChange permissionChange(DbSession dbSession, String permission, String groupName, @Nullable String projectUuid, @Nullable String projectKey) { + PermissionChange permissionChange = new PermissionChange() + .setPermission(permission) + .setGroup(groupName); + if (isProjectUuidOrProjectKeyProvided(projectUuid, projectKey)) { + ComponentDto project = componentFinder.getProjectByUuidOrKey(dbSession, projectUuid, projectKey); + permissionChange.setComponentKey(project.key()); + } + return permissionChange; + } + + private static boolean isProjectUuidOrProjectKeyProvided(@Nullable String projectUuid, @Nullable String projectKey) { + return projectUuid != null || projectKey != null; + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionWsCommons.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionWsCommons.java index 5eea1e0293a..6660989bf99 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionWsCommons.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionWsCommons.java @@ -29,27 +29,24 @@ import org.sonar.server.exceptions.NotFoundException; public class PermissionWsCommons { - private PermissionWsCommons() { - // static stuff only + private final DbClient dbClient; + + public PermissionWsCommons(DbClient dbClient) { + this.dbClient = dbClient; } - public static String searchName(DbClient dbClient, @Nullable String groupNameParam, @Nullable Long groupId) { + public String searchGroupName(DbSession dbSession, @Nullable String groupNameParam, @Nullable Long groupId) { checkParameters(groupNameParam, groupId); if (groupNameParam != null) { return groupNameParam; } - DbSession dbSession = dbClient.openSession(false); - try { - GroupDto group = dbClient.groupDao().selectById(dbSession, groupId); - if (group == null) { - throw new NotFoundException(String.format("Group with id '%d' is not found", groupId)); - } - - return group.getName(); - } finally { - dbClient.closeSession(dbSession); + GroupDto group = dbClient.groupDao().selectById(dbSession, groupId); + if (group == null) { + throw new NotFoundException(String.format("Group with id '%d' is not found", groupId)); } + + return group.getName(); } private static void checkParameters(@Nullable String groupName, @Nullable Long groupId) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java index 25f11a7c386..afc43beb42c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java @@ -33,6 +33,7 @@ public class PermissionsWsModule extends Module { RemoveUserAction.class, UsersAction.class, GroupsAction.class, - SearchGlobalPermissionsAction.class); + SearchGlobalPermissionsAction.class, + PermissionWsCommons.class); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupAction.java index e5f0bf42e6e..aab9f958648 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupAction.java @@ -25,11 +25,10 @@ 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.server.permission.PermissionChange; import org.sonar.server.permission.PermissionUpdater; -import static org.sonar.server.permission.ws.PermissionWsCommons.searchName; - public class RemoveGroupAction implements PermissionsWsAction { public static final String ACTION = "remove_group"; @@ -37,12 +36,14 @@ public class RemoveGroupAction implements PermissionsWsAction { public static final String PARAM_GROUP_NAME = "groupName"; public static final String PARAM_GROUP_ID = "groupId"; - private final PermissionUpdater permissionUpdater; private final DbClient dbClient; + private final PermissionWsCommons permissionWsCommons; + private final PermissionUpdater permissionUpdater; - public RemoveGroupAction(PermissionUpdater permissionUpdater, DbClient dbClient) { - this.permissionUpdater = permissionUpdater; + public RemoveGroupAction(DbClient dbClient, PermissionWsCommons permissionWsCommons, PermissionUpdater permissionUpdater) { this.dbClient = dbClient; + this.permissionWsCommons = permissionWsCommons; + this.permissionUpdater = permissionUpdater; } @Override @@ -75,13 +76,18 @@ public class RemoveGroupAction implements PermissionsWsAction { String groupNameParam = request.param(PARAM_GROUP_NAME); Long groupId = request.paramAsLong(PARAM_GROUP_ID); - String groupName = searchName(dbClient, groupNameParam, groupId); + DbSession dbSession = dbClient.openSession(false); + try { + String groupName = permissionWsCommons.searchGroupName(dbSession, groupNameParam, groupId); - permissionUpdater.removePermission( - new PermissionChange() - .setPermission(permission) - .setGroup(groupName) - ); + permissionUpdater.removePermission( + new PermissionChange() + .setPermission(permission) + .setGroup(groupName) + ); + } finally { + dbClient.closeSession(dbSession); + } response.noContent(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupActionTest.java index 26745d5185b..fc7fb740369 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupActionTest.java @@ -27,9 +27,14 @@ import org.junit.experimental.categories.Category; import org.junit.rules.ExpectedException; import org.mockito.ArgumentCaptor; import org.sonar.api.utils.System2; +import org.sonar.db.DbClient; import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDto; import org.sonar.db.user.GroupDto; +import org.sonar.server.component.ComponentFinder; +import org.sonar.server.component.ComponentTesting; import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.exceptions.ServerException; import org.sonar.server.permission.PermissionChange; import org.sonar.server.permission.PermissionUpdater; @@ -42,6 +47,12 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; import static org.sonar.server.permission.ws.AddGroupAction.ACTION; +import static org.sonar.server.permission.ws.AddGroupAction.PARAM_GROUP_ID; +import static org.sonar.server.permission.ws.AddGroupAction.PARAM_GROUP_NAME; +import static org.sonar.server.permission.ws.AddGroupAction.PARAM_PERMISSION; +import static org.sonar.server.permission.ws.AddGroupAction.PARAM_PROJECT_ID; +import static org.sonar.server.permission.ws.AddGroupAction.PARAM_PROJECT_KEY; +import static org.sonar.server.permission.ws.PermissionsWs.ENDPOINT; @Category(DbTests.class) public class AddGroupActionTest { @@ -52,24 +63,26 @@ public class AddGroupActionTest { @Rule public ExpectedException expectedException = ExpectedException.none(); private PermissionUpdater permissionUpdater; + private DbClient dbClient; + private ArgumentCaptor permissionChangeCaptor; @Before public void setUp() { permissionUpdater = mock(PermissionUpdater.class); + permissionChangeCaptor = ArgumentCaptor.forClass(PermissionChange.class); + dbClient = db.getDbClient(); ws = new WsTester(new PermissionsWs( - new AddGroupAction(permissionUpdater, db.getDbClient()))); + new AddGroupAction(dbClient, new PermissionWsCommons(dbClient), permissionUpdater, new ComponentFinder(dbClient)))); userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN); - } @Test public void call_permission_service_with_right_data() throws Exception { - ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) - .setParam(AddGroupAction.PARAM_GROUP_NAME, "sonar-administrators") - .setParam(AddGroupAction.PARAM_PERMISSION, SYSTEM_ADMIN) + newRequest() + .setParam(PARAM_GROUP_NAME, "sonar-administrators") + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) .execute(); - ArgumentCaptor permissionChangeCaptor = ArgumentCaptor.forClass(PermissionChange.class); verify(permissionUpdater).addPermission(permissionChangeCaptor.capture()); PermissionChange permissionChange = permissionChangeCaptor.getValue(); assertThat(permissionChange.group()).isEqualTo("sonar-administrators"); @@ -77,29 +90,95 @@ public class AddGroupActionTest { } @Test - public void search_with_group_id() throws Exception { - GroupDto group = db.getDbClient().groupDao().insert(db.getSession(), new GroupDto() - .setName("sonar-administrators")); - db.getSession().commit(); + public void add_with_group_id() throws Exception { + GroupDto group = insertGroup("sonar-administrators"); + commit(); + + newRequest() + .setParam(PARAM_GROUP_ID, group.getId().toString()) + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) + .execute(); + + verify(permissionUpdater).addPermission(permissionChangeCaptor.capture()); + PermissionChange permissionChange = permissionChangeCaptor.getValue(); + assertThat(permissionChange.group()).isEqualTo("sonar-administrators"); + } + + @Test + public void add_with_project_uuid() throws Exception { + insertGroup("sonar-administrators"); + insertComponent(ComponentTesting.newProjectDto("project-uuid").setKey("project-key")); + commit(); + + newRequest() + .setParam(PARAM_GROUP_NAME, "sonar-administrators") + .setParam(PARAM_PROJECT_ID, "project-uuid") + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) + .execute(); + + verify(permissionUpdater).addPermission(permissionChangeCaptor.capture()); + PermissionChange permissionChange = permissionChangeCaptor.getValue(); + assertThat(permissionChange.component()).isEqualTo("project-key"); + assertThat(permissionChange.group()).isEqualTo("sonar-administrators"); + } - ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) - .setParam(AddGroupAction.PARAM_GROUP_ID, group.getId().toString()) - .setParam(AddGroupAction.PARAM_PERMISSION, SYSTEM_ADMIN) + @Test + public void add_with_project_key() throws Exception { + insertGroup("sonar-administrators"); + insertComponent(ComponentTesting.newProjectDto("project-uuid").setKey("project-key")); + commit(); + + newRequest() + .setParam(PARAM_GROUP_NAME, "sonar-administrators") + .setParam(PARAM_PROJECT_KEY, "project-key") + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) .execute(); - ArgumentCaptor permissionChangeCaptor = ArgumentCaptor.forClass(PermissionChange.class); verify(permissionUpdater).addPermission(permissionChangeCaptor.capture()); PermissionChange permissionChange = permissionChangeCaptor.getValue(); + assertThat(permissionChange.component()).isEqualTo("project-key"); assertThat(permissionChange.group()).isEqualTo("sonar-administrators"); } + @Test + public void fail_if_project_uuid_not_found() throws Exception { + expectedException.expect(NotFoundException.class); + + insertGroup("sonar-administrators"); + insertComponent(ComponentTesting.newProjectDto("project-uuid").setKey("project-key")); + commit(); + + newRequest() + .setParam(PARAM_GROUP_NAME, "sonar-administrators") + .setParam(PARAM_PROJECT_ID, "unknown-project-uuid") + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) + .execute(); + } + + @Test + public void fail_if_component_uuid_is_not_a_project() throws Exception { + expectedException.expect(BadRequestException.class); + + insertGroup("sonar-administrators"); + ComponentDto project = ComponentTesting.newProjectDto("project-uuid").setKey("project-key"); + insertComponent(project); + insertComponent(ComponentTesting.newFileDto(project, "file-uuid")); + commit(); + + newRequest() + .setParam(PARAM_GROUP_NAME, "sonar-administrators") + .setParam(PARAM_PROJECT_ID, "file-uuid") + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) + .execute(); + } + @Test public void fail_when_get_request() throws Exception { expectedException.expect(ServerException.class); - ws.newGetRequest(PermissionsWs.ENDPOINT, ACTION) - .setParam(AddGroupAction.PARAM_GROUP_NAME, "sonar-administrators") - .setParam(AddGroupAction.PARAM_PERMISSION, SYSTEM_ADMIN) + ws.newGetRequest(ENDPOINT, ACTION) + .setParam(PARAM_GROUP_NAME, "sonar-administrators") + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) .execute(); } @@ -108,8 +187,8 @@ public class AddGroupActionTest { expectedException.expect(BadRequestException.class); expectedException.expectMessage("Group name or group id must be provided, not both"); - ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) - .setParam(AddGroupAction.PARAM_PERMISSION, SYSTEM_ADMIN) + newRequest() + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) .execute(); } @@ -117,8 +196,24 @@ public class AddGroupActionTest { public void fail_when_permission_is_missing() throws Exception { expectedException.expect(IllegalArgumentException.class); - ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) - .setParam(AddGroupAction.PARAM_GROUP_NAME, "sonar-administrators") + newRequest() + .setParam(PARAM_GROUP_NAME, "sonar-administrators") .execute(); } + + private WsTester.TestRequest newRequest() { + return ws.newPostRequest(ENDPOINT, ACTION); + } + + private void commit() { + db.getSession().commit(); + } + + private void insertComponent(ComponentDto component) { + dbClient.componentDao().insert(db.getSession(), component); + } + + private GroupDto insertGroup(String name) { + return dbClient.groupDao().insert(db.getSession(), new GroupDto().setName(name)); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java index 8a922b8ad3c..bb8acb48d47 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java @@ -30,6 +30,6 @@ public class PermissionsWsModuleTest { public void verify_count_of_added_components() { ComponentContainer container = new ComponentContainer(); new PermissionsWsModule().configure(container); - assertThat(container.size()).isEqualTo(10); + assertThat(container.size()).isEqualTo(11); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupActionTest.java index 52d0b7847ce..cf2aba1ff80 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupActionTest.java @@ -55,7 +55,7 @@ public class RemoveGroupActionTest { public void setUp() { permissionUpdater = mock(PermissionUpdater.class); ws = new WsTester(new PermissionsWs( - new RemoveGroupAction(permissionUpdater, db.getDbClient()))); + new RemoveGroupAction(db.getDbClient(), new PermissionWsCommons(db.getDbClient()), permissionUpdater))); userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN); }