MyBatis.closeQuietly(session);
}
}
-
- public int countSystemAdministrators(@Nullable String groupName) {
- SqlSession session = mybatis.openSession();
- try {
- RoleMapper mapper = session.getMapper(RoleMapper.class);
- return mapper.countSystemAdministrators(groupName);
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
}
int countUserRoles(Long resourceId);
- int countSystemAdministrators(@Nullable @Param("groupName") String groupName);
+ List<Long> countSystemAdministrators(@Nullable @Param("groupName") String groupName);
}
SELECT count(id)
FROM group_roles WHERE resource_id=#{id}
</select>
-
- <select id="countSystemAdministrators" parameterType="String" resultType="int">
- SELECT COUNT(DISTINCT u.id)
- FROM users AS u
- LEFT JOIN user_roles AS ur ON ur.user_id = u.id
- INNER JOIN groups_users AS gu ON gu.user_id = u.id
- INNER JOIN group_roles AS gr ON gr.group_id = gu.group_id
- INNER JOIN groups AS g ON g.id = gu.group_id
- WHERE (ur.role = 'admin' AND ur.resource_id IS NULL) OR (gr.role = 'admin' AND gr.resource_id IS NULL)
- AND u.active = ${_true}
- <if test="groupName != null">
- AND g.name != #{groupName}
- </if>
- </select>
</mapper>
checkTable("groupPermissions", "group_roles", "group_id", "role");
}
- @Test
- public void should_retrieve_system_admins_count() throws Exception {
- setupData("systemAdminsCount");
-
- RoleDao dao = new RoleDao(getMyBatis());
- int overallAdminsCount = dao.countSystemAdministrators(null);
- int adminsCountAfterWholeGroupRemoval = dao.countSystemAdministrators("sonar-administrators");
- int adminsCountAfterNonAdminGroupRemoval = dao.countSystemAdministrators("sonar-users");
-
- assertThat(overallAdminsCount).isEqualTo(3);
- assertThat(adminsCountAfterWholeGroupRemoval).isEqualTo(1);
- assertThat(adminsCountAfterNonAdminGroupRemoval).isEqualTo(3);
- }
}
+++ /dev/null
-<dataset>
-
- <users id="200" login="admin" name="admin" active="[true]"/>
- <users id="201" login="user_admin" name="user_admin" active="[true]"/>
- <users id="202" login="user_in_admin_group" name="user_in_admin_group" active="[true]"/>
- <users id="203" login="non_admin" name="non_admin" active="[true]"/>
-
- <user_roles id="1" user_id="201" role="admin"/>
-
- <groups_users group_id="100" user_id="200"/>
- <groups_users group_id="100" user_id="202"/>
- <groups_users group_id="101" user_id="201"/>
- <groups_users group_id="101" user_id="203"/>
-
- <groups id="100" name="sonar-administrators"/>
- <groups id="101" name="sonar-users"/>
-
- <group_roles id="1" group_id="100" role="admin"/>
- <group_roles id="2" group_id="100" role="profileadmin"/>
- <group_roles id="3" group_id="100" role="sharedashboard"/>
- <group_roles id="4" group_id="101" role="sharedashboard"/>
-
-</dataset>
\ No newline at end of file
UserSession.get().checkPermission(Permissions.SYSTEM_ADMIN);
PermissionChangeQuery permissionChangeQuery = PermissionChangeQuery.buildFromParams(params);
if(permissionChangeQuery.isValid()) {
- if(Permissions.SYSTEM_ADMIN.equals(permissionChangeQuery.getRole()) && REMOVE.equals(permissionChange)) {
- checkThatAtLeastOneAdminRemains(permissionChangeQuery);
- }
applyPermissionChange(permissionChange, permissionChangeQuery);
} else {
String errorMsg = String.format("Request '%s permission %s' is invalid", permissionChange, permissionChangeQuery.getRole());
return (ADD.equals(operation) && existingPermissions.contains(role)) ||
(REMOVE.equals(operation) && !existingPermissions.contains(role));
}
-
- private void checkThatAtLeastOneAdminRemains(PermissionChangeQuery permissionChangeQuery) {
- int remainingSystemAdmins = roleDao.countSystemAdministrators(permissionChangeQuery.getGroup());
- if(remainingSystemAdmins == 0) {
- String errorMsg = String.format("Cannot remove permission %s to %s - At least one system administrator should remain active",
- permissionChangeQuery.getRole(), permissionChangeQuery.getUser() == null ? permissionChangeQuery.getGroup() : permissionChangeQuery.getUser());
- LOG.error(errorMsg);
- throw new BadRequestException(errorMsg);
- }
- }
}
service.addPermission(params);
}
- @Test
- public void should_prevent_last_admin_removal() throws Exception {
- throwable.expect(BadRequestException.class);
- params = buildParams("admin", null, Permissions.SYSTEM_ADMIN);
- when(roleDao.countSystemAdministrators(null)).thenReturn(0);
-
- service.removePermission(params);
- }
-
- @Test
- public void should_prevent_last_admin_group_removal() throws Exception {
- throwable.expect(BadRequestException.class);
- params = buildParams(null, "sonar-administrators", Permissions.SYSTEM_ADMIN);
- GroupDto adminGroups = new GroupDto().setId(2L).setName("sonar-administrators");
-
- roleDao = mock(RoleDao.class);
- when(roleDao.selectGroupPermissions("sonar-administrators")).thenReturn(Lists.newArrayList(Permissions.SYSTEM_ADMIN));
- when(roleDao.countSystemAdministrators("sonar-administrators")).thenReturn(0);
-
- userDao = mock(UserDao.class);
- when(userDao.selectGroupByName("sonar-administrators")).thenReturn(adminGroups);
-
- service = new InternalPermissionService(roleDao, userDao);
- service.removePermission(params);
- }
-
@Test
public void should_fail_on_anonymous_access() throws Exception {
throwable.expect(ForbiddenException.class);