diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2017-04-26 14:58:06 +0200 |
---|---|---|
committer | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2017-04-27 14:42:50 +0200 |
commit | 57e457274624994a75a5709e2d6432769c676e08 (patch) | |
tree | 3c0d3d76d7297c9d0ba2e2cbfcd0419eddd76384 /server | |
parent | 9997b7a557b0032283d8fd4813210c4a45e010dc (diff) | |
download | sonarqube-57e457274624994a75a5709e2d6432769c676e08.tar.gz sonarqube-57e457274624994a75a5709e2d6432769c676e08.zip |
SONAR-9102 support project visibility in api/permissions/add_group
Diffstat (limited to 'server')
4 files changed, 417 insertions, 35 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/GroupPermissionChanger.java b/server/sonar-server/src/main/java/org/sonar/server/permission/GroupPermissionChanger.java index 1b2e4ab27d8..f5f82b5af0b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/GroupPermissionChanger.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/GroupPermissionChanger.java @@ -21,11 +21,14 @@ package org.sonar.server.permission; import java.util.List; import java.util.Optional; +import org.sonar.core.permission.ProjectPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.permission.GroupPermissionDto; import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; +import static org.sonar.server.permission.PermissionChange.Operation.ADD; +import static org.sonar.server.permission.PermissionChange.Operation.REMOVE; import static org.sonar.server.permission.ws.PermissionRequestValidator.validateNotAnyoneAndAdminPermission; import static org.sonar.server.ws.WsUtils.checkRequest; @@ -38,6 +41,10 @@ public class GroupPermissionChanger { } public boolean apply(DbSession dbSession, GroupPermissionChange change) { + ensureConsistencyWithVisibility(change); + if (isImplicitlyAlreadyDone(change)) { + return false; + } switch (change.getOperation()) { case ADD: return addPermission(dbSession, change); @@ -48,6 +55,53 @@ public class GroupPermissionChanger { } } + private static boolean isImplicitlyAlreadyDone(GroupPermissionChange change) { + return change.getProjectId() + .map(projectId -> isImplicitlyAlreadyDone(projectId, change)) + .orElse(false); + } + + private static boolean isImplicitlyAlreadyDone(ProjectId projectId, GroupPermissionChange change) { + return isAttemptToAddPublicPermissionToPublicComponent(change, projectId) + || isAttemptToRemovePermissionFromAnyoneOnPrivateComponent(change, projectId); + } + + private static boolean isAttemptToAddPublicPermissionToPublicComponent(GroupPermissionChange change, ProjectId projectId) { + return !projectId.isPrivate() + && change.getOperation() == ADD + && ProjectPermissions.PUBLIC_PERMISSIONS.contains(change.getPermission()); + } + + private static boolean isAttemptToRemovePermissionFromAnyoneOnPrivateComponent(GroupPermissionChange change, ProjectId projectId) { + return projectId.isPrivate() + && change.getOperation() == REMOVE + && change.getGroupIdOrAnyone().isAnyone(); + } + + private static void ensureConsistencyWithVisibility(GroupPermissionChange change) { + change.getProjectId() + .ifPresent(projectId -> { + checkRequest( + !isAttemptToAddPermissionToAnyoneOnPrivateComponent(change, projectId), + "No permission can be granted to AnyOne on a private component"); + checkRequest( + !isAttemptToRemovePublicPermissionFromPublicComponent(change, projectId), + "Permission %s can't be removed from a public component", change.getPermission()); + }); + } + + private static boolean isAttemptToAddPermissionToAnyoneOnPrivateComponent(GroupPermissionChange change, ProjectId projectId) { + return projectId.isPrivate() + && change.getOperation() == ADD + && change.getGroupIdOrAnyone().isAnyone(); + } + + private static boolean isAttemptToRemovePublicPermissionFromPublicComponent(GroupPermissionChange change, ProjectId projectId) { + return !projectId.isPrivate() + && change.getOperation() == REMOVE + && ProjectPermissions.PUBLIC_PERMISSIONS.contains(change.getPermission()); + } + private boolean addPermission(DbSession dbSession, GroupPermissionChange change) { if (loadExistingPermissions(dbSession, change).contains(change.getPermission())) { return false; diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ProjectId.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ProjectId.java index 843086f09d5..9e8cc1a0dcb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ProjectId.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ProjectId.java @@ -36,10 +36,12 @@ public class ProjectId { private final long id; private final String uuid; + private final boolean isPrivate; public ProjectId(ComponentDto project) { this.id = requireNonNull(project.getId()); this.uuid = requireNonNull(project.uuid()); + this.isPrivate = project.isPrivate(); } public long getId() { @@ -49,4 +51,8 @@ public class ProjectId { public String getUuid() { return uuid; } + + public boolean isPrivate() { + return isPrivate; + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/GroupPermissionChangerTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/GroupPermissionChangerTest.java index 610d63c951a..4850eae1483 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/GroupPermissionChangerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/GroupPermissionChangerTest.java @@ -26,15 +26,19 @@ import org.junit.rules.ExpectedException; import org.sonar.api.utils.System2; import org.sonar.api.web.UserRole; import org.sonar.core.permission.GlobalPermissions; +import org.sonar.core.permission.ProjectPermissions; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.permission.GroupPermissionDto; +import org.sonar.db.permission.OrganizationPermission; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.usergroups.ws.GroupIdOrAnyone; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; import static org.sonar.db.permission.OrganizationPermission.ADMINISTER; import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_GATES; import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS; @@ -49,17 +53,19 @@ public class GroupPermissionChangerTest { private GroupPermissionChanger underTest = new GroupPermissionChanger(db.getDbClient()); private OrganizationDto org; private GroupDto group; - private ComponentDto project; + private ComponentDto privateProject; + private ComponentDto publicProject; @Before public void setUp() throws Exception { org = db.organizations().insert(); group = db.users().insertGroup(org, "a-group"); - project = db.components().insertPrivateProject(org); + privateProject = db.components().insertPrivateProject(org); + publicProject = db.components().insertPublicProject(org); } @Test - public void add_permission_to_group() { + public void apply_adds_organization_permission_to_group() { GroupIdOrAnyone groupId = GroupIdOrAnyone.from(group); apply(new GroupPermissionChange(PermissionChange.Operation.ADD, GlobalPermissions.QUALITY_GATE_ADMIN, null, groupId)); @@ -68,34 +74,229 @@ public class GroupPermissionChangerTest { } @Test - public void add_project_permission_to_group() { + public void apply_adds_organization_permission_to_group_AnyOne() { + GroupIdOrAnyone groupId = GroupIdOrAnyone.forAnyone(org.getUuid()); + + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, GlobalPermissions.QUALITY_GATE_ADMIN, null, groupId)); + + assertThat(db.users().selectAnyonePermissions(org, null)).containsOnly(GlobalPermissions.QUALITY_GATE_ADMIN); + } + + @Test + public void apply_fails_with_BadRequestException_when_adding_any_permission_to_group_AnyOne_on_private_project() { + GroupIdOrAnyone anyOneGroupId = GroupIdOrAnyone.forAnyone(org.getUuid()); + ProjectPermissions.ALL + .forEach(perm -> { + try { + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, perm, new ProjectId(privateProject), anyOneGroupId)); + fail("a BadRequestException should have been thrown"); + } catch (BadRequestException e) { + assertThat(e).hasMessage("No permission can be granted to AnyOne on a private component"); + } + }); + } + + @Test + public void apply_has_no_effect_when_removing_any_permission_to_group_AnyOne_on_private_project() { + ProjectPermissions.ALL + .forEach(this::unsafeInsertProjectPermissionOnAnyone); + + GroupIdOrAnyone anyOneGroupId = GroupIdOrAnyone.forAnyone(org.getUuid()); + ProjectPermissions.ALL + .forEach(perm -> { + apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, perm, new ProjectId(privateProject), anyOneGroupId)); + + assertThat(db.users().selectAnyonePermissions(org, privateProject)).contains(perm); + }); + } + + @Test + public void apply_adds_permission_USER_to_group_on_private_project() { + applyAddsPermissionToGroupOnPrivateProject(UserRole.USER); + } + + @Test + public void apply_adds_permission_CODEVIEWER_to_group_on_private_project() { + applyAddsPermissionToGroupOnPrivateProject(UserRole.CODEVIEWER); + } + + @Test + public void apply_adds_permission_ADMIN_to_group_on_private_project() { + applyAddsPermissionToGroupOnPrivateProject(UserRole.ADMIN); + } + + @Test + public void apply_adds_permission_ISSUE_ADMIN_to_group_on_private_project() { + applyAddsPermissionToGroupOnPrivateProject(UserRole.ISSUE_ADMIN); + } + + @Test + public void apply_adds_permission_SCAN_EXECUTION_to_group_on_private_project() { + applyAddsPermissionToGroupOnPrivateProject(GlobalPermissions.SCAN_EXECUTION); + } + + private void applyAddsPermissionToGroupOnPrivateProject(String permission) { GroupIdOrAnyone groupId = GroupIdOrAnyone.from(group); - apply(new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.ISSUE_ADMIN, new ProjectId(project), groupId)); + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, permission, new ProjectId(privateProject), groupId)); assertThat(db.users().selectGroupPermissions(group, null)).isEmpty(); - assertThat(db.users().selectGroupPermissions(group, project)).containsOnly(UserRole.ISSUE_ADMIN); + assertThat(db.users().selectGroupPermissions(group, privateProject)).containsOnly(permission); } @Test - public void add_permission_to_anyone() { - OrganizationDto defaultOrganization = db.getDefaultOrganization(); - GroupIdOrAnyone groupId = GroupIdOrAnyone.forAnyone(defaultOrganization.getUuid()); + public void apply_removes_permission_USER_from_group_on_private_project() { + applyRemovesPermissionFromGroupOnPrivateProject(UserRole.USER); + } - apply(new GroupPermissionChange(PermissionChange.Operation.ADD, GlobalPermissions.QUALITY_GATE_ADMIN, null, groupId)); + @Test + public void apply_removes_permission_CODEVIEWER_from_group_on_private_project() { + applyRemovesPermissionFromGroupOnPrivateProject(UserRole.CODEVIEWER); + } - assertThat(db.users().selectGroupPermissions(group, null)).isEmpty(); - assertThat(db.users().selectAnyonePermissions(defaultOrganization, null)).containsOnly(GlobalPermissions.QUALITY_GATE_ADMIN); + @Test + public void apply_removes_permission_ADMIN_from_on_private_project() { + applyRemovesPermissionFromGroupOnPrivateProject(UserRole.ADMIN); + } + + @Test + public void apply_removes_permission_ISSUE_ADMIN_from_on_private_project() { + applyRemovesPermissionFromGroupOnPrivateProject(UserRole.ISSUE_ADMIN); + } + + @Test + public void apply_removes_permission_SCAN_EXECUTION_from_on_private_project() { + applyRemovesPermissionFromGroupOnPrivateProject(GlobalPermissions.SCAN_EXECUTION); + } + + private void applyRemovesPermissionFromGroupOnPrivateProject(String permission) { + GroupIdOrAnyone groupId = GroupIdOrAnyone.from(group); + db.users().insertProjectPermissionOnGroup(group, permission, privateProject); + + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, permission, new ProjectId(privateProject), groupId)); + + assertThat(db.users().selectGroupPermissions(group, privateProject)).containsOnly(permission); + } + + @Test + public void apply_has_no_effect_when_adding_USER_permission_to_group_AnyOne_on_a_public_project() { + GroupIdOrAnyone groupId = GroupIdOrAnyone.forAnyone(org.getUuid()); + + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.USER, new ProjectId(publicProject), groupId)); + + assertThat(db.users().selectAnyonePermissions(org, publicProject)).isEmpty(); + } + + @Test + public void apply_has_no_effect_when_adding_CODEVIEWER_permission_to_group_AnyOne_on_a_public_project() { + GroupIdOrAnyone groupId = GroupIdOrAnyone.forAnyone(org.getUuid()); + + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.CODEVIEWER, new ProjectId(publicProject), groupId)); + + assertThat(db.users().selectAnyonePermissions(org, publicProject)).isEmpty(); + } + + @Test + public void apply_fails_with_BadRequestException_when_adding_permission_ADMIN_to_group_AnyOne_on_a_public_project() { + GroupIdOrAnyone groupId = GroupIdOrAnyone.forAnyone(org.getUuid()); + + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("It is not possible to add the 'admin' permission to group 'Anyone'"); + + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.ADMIN, new ProjectId(publicProject), groupId)); } @Test - public void add_project_permission_to_anyone() { + public void apply_adds_permission_ISSUE_ADMIN_to_group_AnyOne_on_a_public_project() { GroupIdOrAnyone groupId = GroupIdOrAnyone.forAnyone(org.getUuid()); - apply(new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.ISSUE_ADMIN, new ProjectId(project), groupId)); + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.ISSUE_ADMIN, new ProjectId(publicProject), groupId)); - assertThat(db.users().selectAnyonePermissions(org, null)).isEmpty(); - assertThat(db.users().selectAnyonePermissions(org, project)).containsOnly(UserRole.ISSUE_ADMIN); + assertThat(db.users().selectAnyonePermissions(org, publicProject)).containsOnly(UserRole.ISSUE_ADMIN); + } + + @Test + public void apply_adds_permission_SCAN_EXECUTION_to_group_AnyOne_on_a_public_project() { + GroupIdOrAnyone groupId = GroupIdOrAnyone.forAnyone(org.getUuid()); + + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, GlobalPermissions.SCAN_EXECUTION, new ProjectId(publicProject), groupId)); + + assertThat(db.users().selectAnyonePermissions(org, publicProject)).containsOnly(GlobalPermissions.SCAN_EXECUTION); + } + + @Test + public void apply_fails_with_BadRequestException_when_removing_USER_permission_from_group_AnyOne_on_a_public_project() { + GroupIdOrAnyone groupId = GroupIdOrAnyone.forAnyone(org.getUuid()); + + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Permission user can't be removed from a public component"); + + apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, UserRole.USER, new ProjectId(publicProject), groupId)); + } + + @Test + public void apply_fails_with_BadRequestException_when_removing_CODEVIEWER_permission_from_group_AnyOne_on_a_public_project() { + GroupIdOrAnyone groupId = GroupIdOrAnyone.forAnyone(org.getUuid()); + + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Permission codeviewer can't be removed from a public component"); + + apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, UserRole.CODEVIEWER, new ProjectId(publicProject), groupId)); + } + + @Test + public void apply_removes_ADMIN_permission_from_group_AnyOne_on_a_public_project() { + applyRemovesPermissionFromGroupAnyOneOnAPublicProject(UserRole.ADMIN); + } + + @Test + public void apply_removes_ISSUE_ADMIN_permission_from_group_AnyOne_on_a_public_project() { + applyRemovesPermissionFromGroupAnyOneOnAPublicProject(UserRole.ISSUE_ADMIN); + } + + @Test + public void apply_removes_SCAN_EXECUTION_permission_from_group_AnyOne_on_a_public_project() { + applyRemovesPermissionFromGroupAnyOneOnAPublicProject(GlobalPermissions.SCAN_EXECUTION); + } + + private void applyRemovesPermissionFromGroupAnyOneOnAPublicProject(String permission) { + GroupIdOrAnyone groupId = GroupIdOrAnyone.forAnyone(org.getUuid()); + db.users().insertProjectPermissionOnAnyone(permission, publicProject); + + apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, permission, new ProjectId(publicProject), groupId)); + + assertThat(db.users().selectAnyonePermissions(org, publicProject)).isEmpty(); + } + + @Test + public void apply_fails_with_BadRequestException_when_removing_USER_permission_from_a_group_on_a_public_project() { + GroupIdOrAnyone groupId = GroupIdOrAnyone.from(group); + + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Permission user can't be removed from a public component"); + + apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, UserRole.USER, new ProjectId(publicProject), groupId)); + } + + @Test + public void apply_fails_with_BadRequestException_when_removing_CODEVIEWER_permission_from_a_group_on_a_public_project() { + GroupIdOrAnyone groupId = GroupIdOrAnyone.from(group); + + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Permission codeviewer can't be removed from a public component"); + + apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, UserRole.CODEVIEWER, new ProjectId(publicProject), groupId)); + } + + @Test + public void add_permission_to_anyone() { + OrganizationDto defaultOrganization = db.getDefaultOrganization(); + GroupIdOrAnyone groupId = GroupIdOrAnyone.forAnyone(defaultOrganization.getUuid()); + + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, GlobalPermissions.QUALITY_GATE_ADMIN, null, groupId)); + + assertThat(db.users().selectGroupPermissions(group, null)).isEmpty(); + assertThat(db.users().selectAnyonePermissions(defaultOrganization, null)).containsOnly(GlobalPermissions.QUALITY_GATE_ADMIN); } @Test @@ -109,23 +310,54 @@ public class GroupPermissionChangerTest { } @Test - public void fail_to_add_global_permission_on_project() { + public void fail_to_add_global_permission_but_SCAN_and_ADMIN_on_private_project() { GroupIdOrAnyone groupId = GroupIdOrAnyone.from(group); - expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Invalid project permission 'gateadmin'. Valid values are [admin, codeviewer, issueadmin, scan, user]"); - - apply(new GroupPermissionChange(PermissionChange.Operation.ADD, GlobalPermissions.QUALITY_GATE_ADMIN, new ProjectId(project), groupId)); + OrganizationPermission.all() + .map(OrganizationPermission::getKey) + .filter(perm -> !UserRole.ADMIN.equals(perm) && !GlobalPermissions.SCAN_EXECUTION.equals(perm)) + .forEach(perm -> { + try { + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, perm, new ProjectId(privateProject), groupId)); + fail("a BadRequestException should have been thrown for permission " + perm); + } catch (BadRequestException e) { + assertThat(e).hasMessage("Invalid project permission '" + perm + "'. Valid values are [admin, codeviewer, issueadmin, scan, user]"); + } + }); } @Test - public void fail_to_add_project_permission_on_global_group() { + public void fail_to_add_global_permission_but_SCAN_and_ADMIN_on_public_project() { GroupIdOrAnyone groupId = GroupIdOrAnyone.from(group); - expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Invalid global permission 'issueadmin'. Valid values are [admin, profileadmin, gateadmin, scan, provisioning]"); + OrganizationPermission.all() + .map(OrganizationPermission::getKey) + .filter(perm -> !UserRole.ADMIN.equals(perm) && !GlobalPermissions.SCAN_EXECUTION.equals(perm)) + .forEach(perm -> { + try { + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, perm, new ProjectId(publicProject), groupId)); + fail("a BadRequestException should have been thrown for permission " + perm); + } catch (BadRequestException e) { + assertThat(e).hasMessage("Invalid project permission '" + perm + "'. Valid values are [admin, codeviewer, issueadmin, scan, user]"); + } + }); + } + + @Test + public void fail_to_add_project_permission_but_SCAN_and_ADMIN_on_global_group() { + GroupIdOrAnyone groupId = GroupIdOrAnyone.from(group); - apply(new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.ISSUE_ADMIN, null, groupId)); + ProjectPermissions.ALL + .stream() + .filter(perm -> !GlobalPermissions.SCAN_EXECUTION.equals(perm) && !OrganizationPermission.ADMINISTER.getKey().equals(perm)) + .forEach(permission -> { + try { + apply(new GroupPermissionChange(PermissionChange.Operation.ADD, permission, null, groupId)); + fail("a BadRequestException should have been thrown for permission " + permission); + } catch (BadRequestException e) { + assertThat(e).hasMessage("Invalid global permission '" + permission + "'. Valid values are [admin, profileadmin, gateadmin, scan, provisioning]"); + } + }); } @Test @@ -143,23 +375,23 @@ public class GroupPermissionChangerTest { public void remove_project_permission_from_group() { GroupIdOrAnyone groupId = GroupIdOrAnyone.from(group); db.users().insertPermissionOnGroup(group, ADMINISTER_QUALITY_GATES); - db.users().insertProjectPermissionOnGroup(group, UserRole.ISSUE_ADMIN, project); - db.users().insertProjectPermissionOnGroup(group, UserRole.CODEVIEWER, project); + db.users().insertProjectPermissionOnGroup(group, UserRole.ISSUE_ADMIN, privateProject); + db.users().insertProjectPermissionOnGroup(group, UserRole.CODEVIEWER, privateProject); - apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, UserRole.ISSUE_ADMIN, new ProjectId(project), groupId)); + apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, UserRole.ISSUE_ADMIN, new ProjectId(privateProject), groupId)); assertThat(db.users().selectGroupPermissions(group, null)).containsOnly(ADMINISTER_QUALITY_GATES.getKey()); - assertThat(db.users().selectGroupPermissions(group, project)).containsOnly(UserRole.CODEVIEWER); + assertThat(db.users().selectGroupPermissions(group, privateProject)).containsOnly(UserRole.CODEVIEWER); } @Test public void do_not_fail_if_removing_a_permission_that_does_not_exist() { GroupIdOrAnyone groupId = GroupIdOrAnyone.from(group); - apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, UserRole.ISSUE_ADMIN, new ProjectId(project), groupId)); + apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, UserRole.ISSUE_ADMIN, new ProjectId(privateProject), groupId)); assertThat(db.users().selectGroupPermissions(group, null)).isEmpty(); - assertThat(db.users().selectGroupPermissions(group, project)).isEmpty(); + assertThat(db.users().selectGroupPermissions(group, privateProject)).isEmpty(); } @Test @@ -189,4 +421,14 @@ public class GroupPermissionChangerTest { underTest.apply(db.getSession(), change); db.commit(); } + + private void unsafeInsertProjectPermissionOnAnyone(String perm) { + GroupPermissionDto dto = new GroupPermissionDto() + .setOrganizationUuid(privateProject.getOrganizationUuid()) + .setGroupId(null) + .setRole(perm) + .setResourceId(privateProject.getId()); + db.getDbClient().groupPermissionDao().insert(db.getSession(), dto); + db.commit(); + } } 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 3377321814d..40c2c352a6f 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 @@ -21,6 +21,7 @@ package org.sonar.server.permission.ws; import org.junit.Test; import org.sonar.api.web.UserRole; +import org.sonar.core.permission.ProjectPermissions; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; import org.sonar.db.organization.OrganizationDto; @@ -31,7 +32,10 @@ import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.exceptions.ServerException; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; +import static org.sonar.api.web.UserRole.CODEVIEWER; import static org.sonar.api.web.UserRole.ISSUE_ADMIN; +import static org.sonar.api.web.UserRole.USER; import static org.sonar.core.permission.GlobalPermissions.PROVISIONING; import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; @@ -312,12 +316,88 @@ public class AddGroupActionTest extends BasePermissionWsTest<AddGroupAction> { assertThat(db.users().selectGroupPermissions(group, project)).containsOnly(ISSUE_ADMIN); } - private void executeRequest(GroupDto groupDto, OrganizationDto organizationDto, String permission) throws Exception { + @Test + public void fails_when_adding_any_permission_to_group_AnyOne_on_a_private_project() { + ComponentDto project = db.components().insertPrivateProject(); + userSession.logIn().addProjectPermission(UserRole.ADMIN, project); + + ProjectPermissions.ALL + .forEach(permission -> { + try { + newRequest() + .setParam(PARAM_GROUP_NAME, "anyone") + .setParam(PARAM_PROJECT_ID, project.uuid()) + .setParam(PARAM_PERMISSION, permission) + .execute(); + fail("a BadRequestException should have been raised for " + permission); + } catch (BadRequestException e) { + assertThat(e).hasMessage("No permission can be granted to AnyOne on a private component"); + } + }); + } + + @Test + public void no_effect_when_adding_USER_permission_to_group_AnyOne_on_a_public_project() { + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPublicProject(organization); + userSession.logIn().addProjectPermission(UserRole.ADMIN, project); + newRequest() - .setParam(PARAM_GROUP_NAME, groupDto.getName()) - .setParam(PARAM_PERMISSION, permission) - .setParam(PARAM_ORGANIZATION, organizationDto.getKey()) + .setParam(PARAM_GROUP_NAME, "anyone") + .setParam(PARAM_PROJECT_ID, project.uuid()) + .setParam(PARAM_PERMISSION, USER) + .execute(); + + assertThat(db.users().selectAnyonePermissions(organization, project)).isEmpty(); + } + + @Test + public void no_effect_when_adding_CODEVIEWER_permission_to_group_AnyOne_on_a_public_project() { + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPublicProject(organization); + userSession.logIn().addProjectPermission(UserRole.ADMIN, project); + + newRequest() + .setParam(PARAM_GROUP_NAME, "anyone") + .setParam(PARAM_PROJECT_ID, project.uuid()) + .setParam(PARAM_PERMISSION, CODEVIEWER) .execute(); + + assertThat(db.users().selectAnyonePermissions(organization, project)).isEmpty(); + } + + @Test + public void no_effect_when_adding_USER_permission_to_group_on_a_public_project() { + OrganizationDto organization = db.organizations().insert(); + GroupDto group = db.users().insertGroup(organization); + ComponentDto project = db.components().insertPublicProject(organization); + userSession.logIn().addProjectPermission(UserRole.ADMIN, project); + + newRequest() + .setParam(PARAM_ORGANIZATION, organization.getKey()) + .setParam(PARAM_GROUP_NAME, group.getName()) + .setParam(PARAM_PROJECT_ID, project.uuid()) + .setParam(PARAM_PERMISSION, USER) + .execute(); + + assertThat(db.users().selectAnyonePermissions(organization, project)).isEmpty(); + } + + @Test + public void no_effect_when_adding_CODEVIEWER_permission_to_group_on_a_public_project() { + OrganizationDto organization = db.organizations().insert(); + GroupDto group = db.users().insertGroup(organization); + ComponentDto project = db.components().insertPublicProject(organization); + userSession.logIn().addProjectPermission(UserRole.ADMIN, project); + + newRequest() + .setParam(PARAM_ORGANIZATION, organization.getKey()) + .setParam(PARAM_GROUP_NAME, group.getName()) + .setParam(PARAM_PROJECT_ID, project.uuid()) + .setParam(PARAM_PERMISSION, CODEVIEWER) + .execute(); + + assertThat(db.users().selectAnyonePermissions(organization, project)).isEmpty(); } private void executeRequest(GroupDto groupDto, String permission) throws Exception { |