package org.sonar.server.permission;
import java.util.List;
-import org.sonar.core.permission.GlobalPermissions;
+import java.util.Optional;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.permission.GroupPermissionDto;
import org.sonar.server.exceptions.BadRequestException;
+import static java.lang.String.format;
+import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
import static org.sonar.server.permission.ws.PermissionRequestValidator.validateNotAnyoneAndAdminPermission;
public class GroupPermissionChanger {
}
public boolean apply(DbSession dbSession, GroupPermissionChange change) {
- if (shouldSkip(dbSession, change)) {
- return false;
- }
-
switch (change.getOperation()) {
case ADD:
- validateNotAnyoneAndAdminPermission(change.getPermission(), change.getGroupIdOrAnyone());
- GroupPermissionDto addedDto = new GroupPermissionDto()
- .setRole(change.getPermission())
- .setOrganizationUuid(change.getOrganizationUuid())
- .setGroupId(change.getGroupIdOrAnyone().getId())
- .setResourceId(change.getNullableProjectId());
- dbClient.groupPermissionDao().insert(dbSession, addedDto);
- break;
+ return addPermission(dbSession, change);
case REMOVE:
- checkAdminUsersExistOutsideTheRemovedGroup(dbSession, change);
- dbClient.groupPermissionDao().delete(dbSession,
- change.getPermission(),
- change.getOrganizationUuid(),
- change.getGroupIdOrAnyone().getId(),
- change.getNullableProjectId());
- break;
+ return removePermission(dbSession, change);
default:
throw new UnsupportedOperationException("Unsupported permission change: " + change.getOperation());
}
+ }
+
+ private boolean addPermission(DbSession dbSession, GroupPermissionChange change) {
+ if (loadExistingPermissions(dbSession, change).contains(change.getPermission())) {
+ return false;
+ }
+
+ validateNotAnyoneAndAdminPermission(change.getPermission(), change.getGroupIdOrAnyone());
+ GroupPermissionDto addedDto = new GroupPermissionDto()
+ .setRole(change.getPermission())
+ .setOrganizationUuid(change.getOrganizationUuid())
+ .setGroupId(change.getGroupIdOrAnyone().getId())
+ .setResourceId(change.getNullableProjectId());
+ dbClient.groupPermissionDao().insert(dbSession, addedDto);
return true;
}
- private boolean shouldSkip(DbSession dbSession, GroupPermissionChange change) {
- List<String> existingPermissions;
- if (change.getGroupIdOrAnyone().isAnyone()) {
- existingPermissions = dbClient.groupPermissionDao().selectAnyonePermissions(dbSession, change.getNullableProjectId());
- } else {
- existingPermissions = dbClient.groupPermissionDao().selectGroupPermissions(dbSession, change.getGroupIdOrAnyone().getId(), change.getNullableProjectId());
+ private boolean removePermission(DbSession dbSession, GroupPermissionChange change) {
+ if (!loadExistingPermissions(dbSession, change).contains(change.getPermission())) {
+ return false;
}
- switch (change.getOperation()) {
- case ADD:
- return existingPermissions.contains(change.getPermission());
- case REMOVE:
- return !existingPermissions.contains(change.getPermission());
- default:
- throw new UnsupportedOperationException("Unsupported operation: " + change.getOperation());
+ checkIfRemainingGlobalAdministrators(dbSession, change);
+ dbClient.groupPermissionDao().delete(dbSession,
+ change.getPermission(),
+ change.getOrganizationUuid(),
+ change.getGroupIdOrAnyone().getId(),
+ change.getNullableProjectId());
+ return true;
+ }
+
+ private List<String> loadExistingPermissions(DbSession dbSession, GroupPermissionChange change) {
+ Optional<ProjectId> projectId = change.getProjectId();
+ if (projectId.isPresent()) {
+ return dbClient.groupPermissionDao().selectProjectPermissionsOfGroup(dbSession,
+ change.getOrganizationUuid(),
+ change.getGroupIdOrAnyone().getId(),
+ projectId.get().getId());
}
+ return dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession,
+ change.getOrganizationUuid(),
+ change.getGroupIdOrAnyone().getId());
}
- private void checkAdminUsersExistOutsideTheRemovedGroup(DbSession dbSession, GroupPermissionChange change) {
- if (GlobalPermissions.SYSTEM_ADMIN.equals(change.getPermission()) &&
- !change.getProjectId().isPresent() &&
- // TODO support organizations
- dbClient.roleDao().countUserPermissions(dbSession, change.getPermission(), change.getGroupIdOrAnyone().getId()) <= 0) {
- throw new BadRequestException(String.format("Last group with '%s' permission. Permission cannot be removed.", GlobalPermissions.SYSTEM_ADMIN));
+ private void checkIfRemainingGlobalAdministrators(DbSession dbSession, GroupPermissionChange change) {
+ if (SYSTEM_ADMIN.equals(change.getPermission()) &&
+ !change.getGroupIdOrAnyone().isAnyone() &&
+ !change.getProjectId().isPresent()) {
+ // removing global admin permission from group
+ int remaining = dbClient.authorizationDao().countRemainingUserIdsWithGlobalPermissionIfExcludeGroup(dbSession,
+ change.getOrganizationUuid(), SYSTEM_ADMIN, change.getGroupIdOrAnyone().getId());
+
+ if (remaining == 0) {
+ throw new BadRequestException(format("Last group with permission '%s'. Permission cannot be removed.", SYSTEM_ADMIN));
+ }
}
}
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.NewController;
-import org.sonar.core.permission.GlobalPermissions;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
-import org.sonar.db.permission.PermissionQuery;
import org.sonar.db.user.GroupDto;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.user.UserSession;
import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
+import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_ID;
import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_NAME;
import static org.sonar.server.usergroups.ws.GroupWsSupport.defineGroupWsParameters;
@Override
public void handle(Request request, Response response) throws Exception {
- userSession.checkLoggedIn().checkPermission(GlobalPermissions.SYSTEM_ADMIN);
-
try (DbSession dbSession = dbClient.openSession(false)) {
GroupId groupId = support.findGroup(dbSession, request);
+ userSession.checkOrganizationPermission(groupId.getOrganizationUuid(), SYSTEM_ADMIN);
checkNotTryingToDeleteDefaultGroup(dbSession, groupId);
- checkNotTryingToDeleteLastSystemAdminGroup(dbSession, groupId);
+ checkNotTryingToDeleteLastAdminGroup(dbSession, groupId);
removeGroupMembers(dbSession, groupId);
removeGroupPermissions(dbSession, groupId);
removeFromPermissionTemplates(dbSession, groupId);
}
}
- private void checkNotTryingToDeleteLastSystemAdminGroup(DbSession dbSession, GroupId group) {
- boolean hasAdminPermission = dbClient.groupPermissionDao()
- .selectGroupPermissions(dbSession, group.getId(), null)
- .contains(GlobalPermissions.SYSTEM_ADMIN);
- // TODO support organizations
- boolean isOneRemainingAdminGroup = dbClient.groupPermissionDao().countGroups(dbSession, GlobalPermissions.SYSTEM_ADMIN, null) == 1;
- boolean hasNoStandaloneAdminUser = dbClient.userPermissionDao().countUsers(dbSession,
- PermissionQuery.builder().setPermission(GlobalPermissions.SYSTEM_ADMIN).withAtLeastOnePermission().build()) == 0;
- boolean isLastAdminGroup = hasAdminPermission && isOneRemainingAdminGroup && hasNoStandaloneAdminUser;
-
- checkArgument(!isLastAdminGroup, "The last system admin group cannot be deleted");
+ private void checkNotTryingToDeleteLastAdminGroup(DbSession dbSession, GroupId group) {
+ int remaining = dbClient.authorizationDao().countRemainingUserIdsWithGlobalPermissionIfExcludeGroup(dbSession,
+ group.getOrganizationUuid(), SYSTEM_ADMIN, group.getId());
+
+ checkArgument(remaining > 0, "The last system admin group cannot be deleted");
}
private void removeGroupMembers(DbSession dbSession, GroupId groupId) {
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.organization.OrganizationTesting;
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;
@Test
public void add_permission_to_anyone() {
- GroupIdOrAnyone groupId = new GroupIdOrAnyone(db.getDefaultOrganization().getUuid(), null);
+ OrganizationDto defaultOrganization = db.getDefaultOrganization();
+ GroupIdOrAnyone groupId = new GroupIdOrAnyone(defaultOrganization.getUuid(), null);
apply(new GroupPermissionChange(PermissionChange.Operation.ADD, GlobalPermissions.QUALITY_GATE_ADMIN, null, groupId));
assertThat(db.users().selectGroupPermissions(group, null)).isEmpty();
- assertThat(db.users().selectAnyonePermissions(null)).containsOnly(GlobalPermissions.QUALITY_GATE_ADMIN);
+ assertThat(db.users().selectAnyonePermissions(defaultOrganization, null)).containsOnly(GlobalPermissions.QUALITY_GATE_ADMIN);
}
@Test
public void add_project_permission_to_anyone() {
- GroupIdOrAnyone groupId = new GroupIdOrAnyone(db.getDefaultOrganization().getUuid(), null);
+ OrganizationDto defaultOrganization = db.getDefaultOrganization();
+ GroupIdOrAnyone groupId = new GroupIdOrAnyone(defaultOrganization.getUuid(), null);
apply(new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.ISSUE_ADMIN, new ProjectId(project), groupId));
- assertThat(db.users().selectAnyonePermissions(null)).isEmpty();
- assertThat(db.users().selectAnyonePermissions(project)).containsOnly(UserRole.ISSUE_ADMIN);
+ assertThat(db.users().selectAnyonePermissions(defaultOrganization, null)).isEmpty();
+ assertThat(db.users().selectAnyonePermissions(defaultOrganization, project)).containsOnly(UserRole.ISSUE_ADMIN);
}
@Test
}
@Test
- public void fail_to_remove_sysadmin_permission_if_no_more_sysadmins() {
+ public void fail_to_remove_admin_permission_if_no_more_admins() {
GroupIdOrAnyone groupId = new GroupIdOrAnyone(group);
db.users().insertPermissionOnGroup(group, GlobalPermissions.SYSTEM_ADMIN);
expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Last group with 'admin' permission. Permission cannot be removed.");
+ expectedException.expectMessage("Last group with permission 'admin'. Permission cannot be removed.");
underTest.apply(db.getSession(), new GroupPermissionChange(PermissionChange.Operation.REMOVE, GlobalPermissions.SYSTEM_ADMIN, null, groupId));
}
+ @Test
+ public void remove_admin_group_if_still_other_admins() {
+ GroupIdOrAnyone groupId = new GroupIdOrAnyone(group);
+ db.users().insertPermissionOnGroup(group, GlobalPermissions.SYSTEM_ADMIN);
+ UserDto admin = db.users().insertUser();
+ db.users().insertPermissionOnUser(admin, GlobalPermissions.SYSTEM_ADMIN);
+
+ apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, GlobalPermissions.SYSTEM_ADMIN, null, groupId));
+
+ assertThat(db.users().selectGroupPermissions(group, null)).isEmpty();
+ }
+
private void apply(GroupPermissionChange change) {
underTest.apply(db.getSession(), change);
db.commit();
}
@Test
- public void fail_to_remove_last_sysadmin_permission() throws Exception {
+ public void fail_to_remove_last_admin_permission() throws Exception {
db.users().insertPermissionOnGroup(aGroup, SYSTEM_ADMIN);
db.users().insertPermissionOnGroup(aGroup, PROVISIONING);
loginAsAdmin();
expectedException.expect(BadRequestException.class);
- expectedException.expectMessage("Last group with 'admin' permission. Permission cannot be removed.");
+ expectedException.expectMessage("Last group with permission 'admin'. Permission cannot be removed.");
newRequest()
.setParam(PARAM_GROUP_NAME, aGroup.getName())
import org.sonar.api.config.Settings;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
+import org.sonar.core.permission.GlobalPermissions;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.organization.OrganizationTesting;
+import org.sonar.db.permission.template.PermissionTemplateDto;
+import org.sonar.db.permission.template.PermissionTemplateTesting;
import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.exceptions.NotFoundException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto;
+import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_ID;
import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_NAME;
import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_ORGANIZATION_KEY;
@Before
public void setUp() {
- defaultGroup = db.users().insertGroup(defaultOrganizationProvider.getDto(), CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE);
+ defaultGroup = db.users().insertGroup(db.getDefaultOrganization(), CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE);
Settings settings = new MapSettings().setProperty(CoreProperties.CORE_DEFAULT_GROUP, CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE);
ws = new WsTester(new UserGroupsWs(
@Test
public void delete_by_id() throws Exception {
- GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "to-delete");
+ addAdmin(db.getDefaultOrganization());
+ GroupDto group = db.users().insertGroup();
+ loginAsAdminOnDefaultOrganization();
- loginAsAdmin();
newRequest()
.setParam("id", group.getId().toString())
.execute()
@Test
public void delete_by_name_on_default_organization() throws Exception {
- GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "to-delete");
+ addAdminToDefaultOrganization();
+ GroupDto group = db.users().insertGroup();
+ loginAsAdminOnDefaultOrganization();
- loginAsAdmin();
newRequest()
.setParam(PARAM_GROUP_NAME, group.getName())
.execute()
@Test
public void delete_by_name_and_organization() throws Exception {
OrganizationDto org = OrganizationTesting.insert(db, newOrganizationDto());
+ addAdmin(org);
GroupDto group = db.users().insertGroup(org, "to-delete");
+ loginAsAdmin(org);
- loginAsAdmin();
newRequest()
.setParam(PARAM_ORGANIZATION_KEY, org.getKey())
.setParam(PARAM_GROUP_NAME, group.getName())
@Test
public void delete_by_name_fails_if_organization_is_not_correct() throws Exception {
- OrganizationDto org = newOrganizationDto().setUuid("org1");
+ OrganizationDto org = newOrganizationDto();
OrganizationTesting.insert(db, org);
- loginAsAdmin();
+ loginAsAdmin(org);
expectedException.expect(NotFoundException.class);
- expectedException.expectMessage("No organization with key 'org1'");
+ expectedException.expectMessage("No organization with key 'missing'");
newRequest()
- .setParam(PARAM_ORGANIZATION_KEY, "org1")
+ .setParam(PARAM_ORGANIZATION_KEY, "missing")
.setParam(PARAM_GROUP_NAME, "a-group")
.execute();
}
@Test
public void delete_members() throws Exception {
- GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "to-be-deleted");
- UserDto user = db.users().insertUser("a-user");
+ addAdminToDefaultOrganization();
+ GroupDto group = db.users().insertGroup();
+ UserDto user = db.users().insertUser();
db.users().insertMember(group, user);
+ loginAsAdminOnDefaultOrganization();
- loginAsAdmin();
newRequest()
.setParam("id", group.getId().toString())
.execute()
@Test
public void delete_permissions() throws Exception {
- GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "to-be-deleted");
+ addAdminToDefaultOrganization();
+ GroupDto group = db.users().insertGroup();
ComponentDto project = componentTester.insertComponent(ComponentTesting.newProjectDto());
db.users().insertProjectPermissionOnGroup(group, UserRole.ADMIN, project);
+ loginAsAdminOnDefaultOrganization();
- loginAsAdmin();
newRequest()
.setParam("id", group.getId().toString())
.execute()
}
@Test
- public void delete_permission_templates() throws Exception {
- GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "to-be-deleted");
- // TODO
+ public void delete_group_from_permission_templates() throws Exception {
+ addAdminToDefaultOrganization();
+ GroupDto group = db.users().insertGroup();
+ PermissionTemplateDto template = db.getDbClient().permissionTemplateDao().insert(db.getSession(), PermissionTemplateTesting.newPermissionTemplateDto());
+ db.getDbClient().permissionTemplateDao().insertGroupPermission(db.getSession(), template.getId(), group.getId(), "perm");
+ db.commit();
+ loginAsAdminOnDefaultOrganization();
+ assertThat(db.countRowsOfTable("perm_templates_groups")).isEqualTo(1);
- loginAsAdmin();
newRequest()
.setParam("id", group.getId().toString())
.execute().assertNoContent();
assertThat(db.countRowsOfTable("perm_templates_groups")).isEqualTo(0);
}
- @Test(expected = NotFoundException.class)
+ @Test
public void fail_if_id_does_not_exist() throws Exception {
- loginAsAdmin();
+ addAdminToDefaultOrganization();
+ loginAsAdminOnDefaultOrganization();
+ long groupId = defaultGroup.getId() + 123;
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("No group with id '" + groupId + "'");
+
newRequest()
- .setParam("id", String.valueOf(defaultGroup.getId() + 123))
+ .setParam("id", String.valueOf(groupId))
.execute();
}
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void cannot_delete_default_group_of_default_organization() throws Exception {
- loginAsAdmin();
+ loginAsAdminOnDefaultOrganization();
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Default group 'sonar-users' cannot be deleted");
+
newRequest()
.setParam("id", defaultGroup.getId().toString())
.execute();
@Test
public void delete_group_of_an_organization_even_if_name_is_default_group_of_default_organization() throws Exception {
OrganizationDto org = OrganizationTesting.insert(db, newOrganizationDto());
+ addAdmin(org);
GroupDto group = db.users().insertGroup(org, defaultGroup.getName());
+ loginAsAdmin(org);
- loginAsAdmin();
newRequest()
.setParam("id", group.getId().toString())
.execute();
@Test
public void cannot_delete_last_system_admin_group() throws Exception {
- GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "system-admins");
+ GroupDto group = db.users().insertGroup();
db.users().insertPermissionOnGroup(group, SYSTEM_ADMIN);
-
- loginAsAdmin();
+ loginAsAdminOnDefaultOrganization();
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("The last system admin group cannot be deleted");
}
@Test
- public void delete_system_admin_group_if_not_last() throws Exception {
- OrganizationDto defaultOrg = defaultOrganizationProvider.getDto();
- GroupDto funkyAdmins = db.users().insertGroup(defaultOrg, "funky-admins");
- db.users().insertPermissionOnGroup(funkyAdmins, SYSTEM_ADMIN);
- GroupDto boringAdmins = db.users().insertGroup(defaultOrg, "boring-admins");
- db.users().insertPermissionOnGroup(boringAdmins, SYSTEM_ADMIN);
-
- loginAsAdmin();
+ public void delete_admin_group_fails_if_no_admin_users_left() throws Exception {
+ // admin users are part of the group to be deleted
+ OrganizationDto org = OrganizationTesting.insert(db, newOrganizationDto());
+ GroupDto adminGroup = db.users().insertGroup(org, "admins");
+ db.users().insertPermissionOnGroup(adminGroup, SYSTEM_ADMIN);
+ UserDto bigBoss = db.users().insertUser();
+ db.users().insertMember(adminGroup, bigBoss);
+ loginAsAdmin(org);
- newRequest()
- .setParam(PARAM_GROUP_NAME, boringAdmins.getName())
- .execute();
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("The last system admin group cannot be deleted");
- assertThat(db.getDbClient().groupPermissionDao().countGroups(db.getSession(), SYSTEM_ADMIN, null)).isEqualTo(1);
+ newRequest().setParam(PARAM_GROUP_ID, adminGroup.getId().toString()).execute();
}
@Test
- public void delete_last_system_admin_group_if_admin_user_left() throws Exception {
- GroupDto lastGroup = db.users().insertGroup(defaultOrganizationProvider.getDto(), "last-group");
- db.users().insertPermissionOnGroup(lastGroup, SYSTEM_ADMIN);
- UserDto bigBoss = db.users().insertUser("big.boss");
- db.users().insertPermissionOnUser(bigBoss, SYSTEM_ADMIN);
+ public void delete_admin_group_succeeds_if_other_groups_have_administrators() throws Exception {
+ OrganizationDto org = OrganizationTesting.insert(db, newOrganizationDto());
+ GroupDto adminGroup1 = db.users().insertGroup(org, "admins");
+ db.users().insertPermissionOnGroup(adminGroup1, SYSTEM_ADMIN);
+ GroupDto adminGroup2 = db.users().insertGroup(org, "admins");
+ db.users().insertPermissionOnGroup(adminGroup2, SYSTEM_ADMIN);
+ UserDto bigBoss = db.users().insertUser();
+ db.users().insertMember(adminGroup2, bigBoss);
+ loginAsAdmin(org);
+
+ newRequest().setParam(PARAM_GROUP_ID, adminGroup1.getId().toString()).execute();
- loginAsAdmin();
- newRequest().setParam(PARAM_GROUP_NAME, lastGroup.getName()).execute();
+ assertThat(db.users().selectGroupPermissions(adminGroup2, null)).hasSize(1);
+ }
+
+ private void addAdminToDefaultOrganization() {
+ addAdmin(db.getDefaultOrganization());
+ }
+
+ private void addAdmin(OrganizationDto org) {
+ UserDto admin = db.users().insertUser();
+ db.users().insertPermissionOnUser(org, admin, SYSTEM_ADMIN);
+ }
- assertThat(db.users().selectGroupById(lastGroup.getId())).isNull();
+ private void loginAsAdminOnDefaultOrganization() {
+ loginAsAdmin(db.getDefaultOrganization());
}
- private void loginAsAdmin() {
- userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN);
+ private void loginAsAdmin(OrganizationDto org) {
+ userSession.login().addOrganizationPermission(org.getUuid(), GlobalPermissions.SYSTEM_ADMIN);
}
private WsTester.TestRequest newRequest() {
return mapper(dbSession).selectRootComponentPermissionsOfAnonymous(rootComponentId);
}
+ /**
+ * The number of users who will still have the permission when the group {@code excludedGroupId}
+ * is deleted.
+ */
+ public int countRemainingUserIdsWithGlobalPermissionIfExcludeGroup(DbSession dbSession, String organizationUuid,
+ String permission, long excludedGroupId) {
+ return mapper(dbSession).countRemainingUserIdsWithGlobalPermissionIfExcludeGroup(organizationUuid, permission, excludedGroupId);
+ }
+
public Collection<Long> keepAuthorizedProjectIds(DbSession dbSession, Collection<Long> componentIds, @Nullable Integer userId, String role) {
return executeLargeInputs(
componentIds,
Set<String> selectRootComponentPermissionsOfAnonymous(@Param("rootComponentId") long rootComponentId);
+ int countRemainingUserIdsWithGlobalPermissionIfExcludeGroup(@Param("organizationUuid") String organizationUuid, @Param("permission") String permission, @Param("excludedGroupId") long excludedGroupId);
+
List<Long> keepAuthorizedProjectIdsForAnonymous(@Param("role") String role, @Param("componentIds") Collection<Long> componentIds);
List<Long> keepAuthorizedProjectIdsForUser(@Param("userId") long userId, @Param("role") String role, @Param("componentIds") Collection<Long> componentIds);
}
/**
- * @return the permissions granted to the requested group, optionally on the requested project. An
- * empty list is returned if the group or project do not exist.
+ * Selects the global permissions granted to group. An empty list is returned if the
+ * group does not exist.
*/
- public List<String> selectGroupPermissions(DbSession session, long groupId, @Nullable Long projectId) {
- return session.getMapper(GroupPermissionMapper.class).selectGroupPermissions(groupId, projectId);
+ public List<String> selectGlobalPermissionsOfGroup(DbSession session, String organizationUuid, @Nullable Long groupId) {
+ return mapper(session).selectGlobalPermissionsOfGroup(organizationUuid, groupId);
}
+
/**
- * @return the permissions granted to Anyone virtual group, optionally on the requested project. An
- * empty list is returned if the project does not exist.
- * @deprecated not compatible with organizations if {@code projectId} is null. Should have an organization parameter.
+ * Selects the permissions granted to group and project. An empty list is returned if the
+ * group or project do not exist.
*/
- @Deprecated
- public List<String> selectAnyonePermissions(DbSession session, @Nullable Long projectId) {
- return session.getMapper(GroupPermissionMapper.class).selectAnyonePermissions(projectId);
+ public List<String> selectProjectPermissionsOfGroup(DbSession session, String organizationUuid, @Nullable Long groupId, long projectId) {
+ return mapper(session).selectProjectPermissionsOfGroup(organizationUuid, groupId, projectId);
}
/**
void groupsCountByProjectIdAndPermission(Map<String, Object> parameters, ResultHandler resultHandler);
- List<String> selectGroupPermissions(@Param("groupId") long groupId, @Nullable @Param("projectId") Long projectId);
-
- List<String> selectAnyonePermissions(@Nullable @Param("projectId") Long projectId);
-
void insert(GroupPermissionDto dto);
void deleteByRootComponentId(@Param("rootComponentId") long componentId);
@Nullable @Param("groupId") Long groupId, @Nullable @Param("rootComponentId") Long rootComponentId);
int countRowsByRootComponentId(@Param("rootComponentId") long rootComponentId);
+
+ List<String> selectGlobalPermissionsOfGroup(@Param("organizationUuid") String organizationUuid, @Nullable @Param("groupId") Long groupId);
+
+ List<String> selectProjectPermissionsOfGroup(@Param("organizationUuid") String organizationUuid, @Nullable @Param("groupId") Long groupId, @Param("projectId") long projectId);
}
mapper(session).deleteGroupRolesByGroupId(groupId);
}
+ /**
+ * @deprecated does not support organizations
+ */
+ @Deprecated
public int countUserPermissions(DbSession session, String permission, @Nullable Long allGroupsExceptThisGroupId) {
return mapper(session).countUsersWithPermission(permission, allGroupsExceptThisGroupId);
}
gr.group_id is null
</select>
+ <select id="countRemainingUserIdsWithGlobalPermissionIfExcludeGroup" parameterType="map" resultType="int">
+ select count(1) from
+ (
+ select gu.user_id
+ from groups_users gu
+ inner join group_roles gr on gr.group_id = gu.group_id
+ where
+ gr.organization_uuid = #{organizationUuid,jdbcType=VARCHAR} and
+ gr.role = #{permission,jdbcType=VARCHAR} and
+ gr.resource_id is null and
+ gr.group_id is not null and
+ gr.group_id != #{excludedGroupId,jdbcType=BIGINT}
+
+ union
+
+ select ur.user_id
+ from user_roles ur
+ where
+ ur.resource_id is null and
+ ur.role = #{permission,jdbcType=VARCHAR}
+ ) remaining
+ </select>
+
<select id="keepAuthorizedProjectIdsForUser" parameterType="map" resultType="long">
SELECT gr.resource_id
FROM group_roles gr
</if>
</select>
- <select id="selectGroupPermissions" parameterType="map" resultType="String">
+ <select id="selectGlobalPermissionsOfGroup" parameterType="map" resultType="String">
select gr.role
from group_roles gr
- where gr.group_id = #{groupId}
- and
- <if test="projectId == null">
- gr.resource_id is null
- </if>
- <if test="projectId != null">
- gr.resource_id = #{projectId}
- </if>
+ where
+ gr.organization_uuid = #{organizationUuid,jdbcType=VARCHAR} and
+ gr.resource_id is null and
+ <choose>
+ <when test="groupId != null">
+ gr.group_id = #{groupId,jdbcType=BIGINT}
+ </when>
+ <otherwise>
+ gr.group_id is null
+ </otherwise>
+ </choose>
</select>
- <select id="selectAnyonePermissions" parameterType="map" resultType="String">
+ <select id="selectProjectPermissionsOfGroup" parameterType="map" resultType="String">
select gr.role
from group_roles gr
- where gr.group_id is null
- and
- <if test="projectId == null">
- gr.resource_id is null
- </if>
- <if test="projectId != null">
- gr.resource_id = #{projectId}
- </if>
+ where
+ gr.organization_uuid = #{organizationUuid,jdbcType=VARCHAR} and
+ gr.resource_id = #{projectId,jdbcType=BIGINT} and
+ <choose>
+ <when test="groupId != null">
+ gr.group_id = #{groupId,jdbcType=BIGINT}
+ </when>
+ <otherwise>
+ gr.group_id is null
+ </otherwise>
+ </choose>
</select>
<select id="countRowsByRootComponentId" parameterType="long" resultType="int">
USER, "admin")).isEmpty();
}
+ @Test
+ public void countRemainingUserIdsWithGlobalPermissionIfExcludeGroup() {
+ // users with global permission "perm1" :
+ // - "u1" and "u2" through group "g1"
+ // - "u1" and "u3" through group "g2"
+ // - "u4"
+
+ UserDto user1 = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
+ UserDto user3 = db.users().insertUser();
+ UserDto user4 = db.users().insertUser();
+ UserDto user5 = db.users().insertUser();
+
+ OrganizationDto org = OrganizationTesting.insert(db, newOrganizationDto());
+ GroupDto group1 = db.users().insertGroup(org, "g1");
+ db.users().insertPermissionOnGroup(group1, "perm1");
+ db.users().insertPermissionOnGroup(group1, "perm2");
+ db.users().insertMember(group1, user1);
+ db.users().insertMember(group1, user2);
+
+ GroupDto group2 = db.users().insertGroup(org, "g2");
+ db.users().insertPermissionOnGroup(group2, "perm1");
+ db.users().insertPermissionOnGroup(group2, "perm2");
+ db.users().insertMember(group2, user1);
+ db.users().insertMember(group2, user3);
+
+ // group3 has the permission "perm1" but has no users
+ GroupDto group3 = db.users().insertGroup(org, "g2");
+ db.users().insertPermissionOnGroup(group3, "perm1");
+
+ db.users().insertPermissionOnUser(user4, "perm1");
+ db.users().insertPermissionOnUser(user4, "perm2");
+
+ db.users().insertPermissionOnAnyone(org, "perm1");
+
+ // excluding group "g1" -> remain u1, u3 and u4
+ assertThat(underTest.countRemainingUserIdsWithGlobalPermissionIfExcludeGroup(db.getSession(),
+ org.getUuid(), "perm1", group1.getId())).isEqualTo(3);
+
+ // excluding group "g2" -> remain u1, u2 and u4
+ assertThat(underTest.countRemainingUserIdsWithGlobalPermissionIfExcludeGroup(db.getSession(),
+ org.getUuid(), "perm1", group2.getId())).isEqualTo(3);
+
+ // excluding group "g3" -> remain u1, u2, u3 and u4
+ assertThat(underTest.countRemainingUserIdsWithGlobalPermissionIfExcludeGroup(db.getSession(),
+ org.getUuid(), "perm1", group3.getId())).isEqualTo(4);
+
+ // nobody has the permission
+ assertThat(underTest.countRemainingUserIdsWithGlobalPermissionIfExcludeGroup(db.getSession(),
+ org.getUuid(), "missingPermission", group1.getId())).isEqualTo(0);
+
+ }
+
@Test
public void keep_authorized_project_ids_for_user() {
db.prepareDbUnit(getClass(), "keep_authorized_project_ids_for_user.xml");
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.organization.OrganizationTesting;
import org.sonar.db.user.GroupDto;
import static java.util.Arrays.asList;
import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION;
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
import static org.sonar.db.component.ComponentTesting.newProjectDto;
+import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto;
import static org.sonar.db.user.GroupTesting.newGroupDto;
public class GroupPermissionDaoTest {
}
@Test
- public void selectGroupPermissions() {
- GroupDto group1 = db.users().insertGroup(newGroupDto());
- GroupDto group2 = db.users().insertGroup(newGroupDto());
+ public void selectGlobalPermissionsOfGroup() {
+ OrganizationDto org1 = OrganizationTesting.insert(db, newOrganizationDto());
+ OrganizationDto org2 = OrganizationTesting.insert(db, newOrganizationDto());
+ GroupDto group1 = db.users().insertGroup(org1, "group1");
+ GroupDto group2 = db.users().insertGroup(org2, "group2");
ComponentDto project = db.components().insertProject();
- db.users().insertPermissionOnAnyone("perm1");
+ db.users().insertPermissionOnAnyone(org1, "perm1");
db.users().insertPermissionOnGroup(group1, "perm2");
db.users().insertPermissionOnGroup(group1, "perm3");
db.users().insertPermissionOnGroup(group2, "perm4");
db.users().insertProjectPermissionOnGroup(group1, "perm5", project);
- db.users().insertProjectPermissionOnAnyone("perm6", project);
+ db.users().insertProjectPermissionOnAnyone(org1, "perm6", project);
- // select global permissions on group
- assertThat(underTest.selectGroupPermissions(dbSession, group1.getId(), null)).containsOnly("perm2", "perm3");
- assertThat(underTest.selectGroupPermissions(dbSession, UNKNOWN_GROUP_ID, null)).isEmpty();
+ assertThat(underTest.selectGlobalPermissionsOfGroup(dbSession, org1.getUuid(), group1.getId())).containsOnly("perm2", "perm3");
+ assertThat(underTest.selectGlobalPermissionsOfGroup(dbSession, org2.getUuid(), group2.getId())).containsOnly("perm4");
+ assertThat(underTest.selectGlobalPermissionsOfGroup(dbSession, org1.getUuid(), null)).containsOnly("perm1");
- // select project permissions on group
- assertThat(underTest.selectGroupPermissions(dbSession, group1.getId(), project.getId())).containsOnly("perm5");
- assertThat(underTest.selectGroupPermissions(dbSession, group1.getId(), UNKNOWN_PROJECT_ID)).isEmpty();
+ // group1 is not in org2
+ assertThat(underTest.selectGlobalPermissionsOfGroup(dbSession, org2.getUuid(), group1.getId())).isEmpty();
+ assertThat(underTest.selectGlobalPermissionsOfGroup(dbSession, org2.getUuid(), null)).isEmpty();
}
@Test
- public void selectAnyonePermissions() {
- GroupDto group1 = db.users().insertGroup(newGroupDto());
- ComponentDto project = db.components().insertProject();
+ public void selectProjectPermissionsOfGroup() {
+ OrganizationDto org1 = OrganizationTesting.insert(db, newOrganizationDto());
+ GroupDto group1 = db.users().insertGroup(org1, "group1");
+ ComponentDto project1 = db.components().insertProject();
+ ComponentDto project2 = db.components().insertProject();
- db.users().insertPermissionOnAnyone("perm1");
+ db.users().insertPermissionOnAnyone(org1, "perm1");
db.users().insertPermissionOnGroup(group1, "perm2");
- db.users().insertProjectPermissionOnGroup(group1, "perm3", project);
- db.users().insertProjectPermissionOnAnyone("perm4", project);
-
- // select global permissions on group
- assertThat(underTest.selectAnyonePermissions(dbSession, null)).containsOnly("perm1");
-
- // select project permissions on group
- assertThat(underTest.selectAnyonePermissions(dbSession, project.getId())).containsOnly("perm4");
- assertThat(underTest.selectAnyonePermissions(dbSession, UNKNOWN_PROJECT_ID)).isEmpty();
+ db.users().insertProjectPermissionOnGroup(group1, "perm3", project1);
+ db.users().insertProjectPermissionOnGroup(group1, "perm4", project1);
+ db.users().insertProjectPermissionOnGroup(group1, "perm5", project2);
+ db.users().insertProjectPermissionOnAnyone(org1, "perm6", project1);
+
+ assertThat(underTest.selectProjectPermissionsOfGroup(dbSession, org1.getUuid(), group1.getId(), project1.getId()))
+ .containsOnly("perm3", "perm4");
+ assertThat(underTest.selectProjectPermissionsOfGroup(dbSession, org1.getUuid(), group1.getId(), project2.getId()))
+ .containsOnly("perm5");
+ assertThat(underTest.selectProjectPermissionsOfGroup(dbSession, org1.getUuid(), null, project1.getId()))
+ .containsOnly("perm6");
+ assertThat(underTest.selectProjectPermissionsOfGroup(dbSession, org1.getUuid(), null, project2.getId()))
+ .isEmpty();
}
@Test
}
public List<String> selectGroupPermissions(GroupDto group, @Nullable ComponentDto project) {
- return db.getDbClient().groupPermissionDao().selectGroupPermissions(db.getSession(), group.getId(), project == null ? null : project.getId());
- }
-
- /**
- * @deprecated does not support organizations
- */
- @Deprecated
- public List<String> selectAnyonePermissions(@Nullable ComponentDto project) {
- return db.getDbClient().groupPermissionDao().selectAnyonePermissions(db.getSession(), project == null ? null : project.getId());
+ if (project == null) {
+ return db.getDbClient().groupPermissionDao().selectGlobalPermissionsOfGroup(db.getSession(),
+ group.getOrganizationUuid(), group.getId());
+ }
+ return db.getDbClient().groupPermissionDao().selectProjectPermissionsOfGroup(db.getSession(),
+ group.getOrganizationUuid(), group.getId(), project.getId());
+ }
+
+ public List<String> selectAnyonePermissions(OrganizationDto org, @Nullable ComponentDto project) {
+ if (project == null) {
+ return db.getDbClient().groupPermissionDao().selectGlobalPermissionsOfGroup(db.getSession(),
+ org.getUuid(), null);
+ }
+ return db.getDbClient().groupPermissionDao().selectProjectPermissionsOfGroup(db.getSession(),
+ org.getUuid(), null, project.getId());
}
// USER PERMISSIONS