aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2017-04-26 14:58:06 +0200
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>2017-04-27 14:42:50 +0200
commit57e457274624994a75a5709e2d6432769c676e08 (patch)
tree3c0d3d76d7297c9d0ba2e2cbfcd0419eddd76384 /server
parent9997b7a557b0032283d8fd4813210c4a45e010dc (diff)
downloadsonarqube-57e457274624994a75a5709e2d6432769c676e08.tar.gz
sonarqube-57e457274624994a75a5709e2d6432769c676e08.zip
SONAR-9102 support project visibility in api/permissions/add_group
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/GroupPermissionChanger.java54
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/ProjectId.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/permission/GroupPermissionChangerTest.java304
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupActionTest.java88
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 {