]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6912 do not remove admin permission on user if no more admins
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 3 Nov 2016 14:47:21 +0000 (15:47 +0100)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 3 Nov 2016 17:19:18 +0000 (18:19 +0100)
server/sonar-server/src/main/java/org/sonar/server/permission/UserPermissionChanger.java
sonar-db/src/main/java/org/sonar/db/permission/AuthorizationDao.java
sonar-db/src/main/java/org/sonar/db/permission/AuthorizationMapper.java
sonar-db/src/main/resources/org/sonar/db/permission/AuthorizationMapper.xml
sonar-db/src/test/java/org/sonar/db/permission/AuthorizationDaoTest.java

index 61b4e977762e6c289a699be00803b1f685eac3c8..060592528a4f5be691594de404bedaede636b79f 100644 (file)
@@ -92,7 +92,7 @@ public class UserPermissionChanger {
 
   private void checkOtherAdminsExist(DbSession dbSession, UserPermissionChange change) {
     if (SYSTEM_ADMIN.equals(change.getPermission()) && !change.getProjectId().isPresent()) {
-      int remaining = dbClient.authorizationDao().countUsersWithGlobalPermissionExcludingUser(dbSession,
+      int remaining = dbClient.authorizationDao().countUsersWithGlobalPermissionExcludingUserPermission(dbSession,
         change.getOrganizationUuid(), change.getPermission(), change.getUserId().getId());
       if (remaining == 0) {
         throw new BadRequestException(String.format("Last user with permission '%s'. Permission cannot be removed.", SYSTEM_ADMIN));
index 50845b65cea9eb3fc7ec1fbef9bb3e01959c51fe..84462aba5ca4b1b2b8191cbfdc009c37839e251b 100644 (file)
@@ -107,6 +107,17 @@ public class AuthorizationDao implements Dao {
     return mapper(dbSession).countUsersWithGlobalPermissionExcludingGroupMember(organizationUuid, permission, groupId, userId);
   }
 
+  /**
+   * The number of users who will still have the permission if the permission {@code permission}
+   * is removed from user {@code userId}. The anyone virtual group is not taken into account.
+   * Contrary to {@link #countUsersWithGlobalPermissionExcludingUser(DbSession, String, String, long)}, user
+   * still exists and may have the permission through groups.
+   */
+  public int countUsersWithGlobalPermissionExcludingUserPermission(DbSession dbSession, String organizationUuid,
+    String permission, long userId) {
+    return mapper(dbSession).countUsersWithGlobalPermissionExcludingUserPermission(organizationUuid, permission, userId);
+  }
+
   public Set<Long> keepAuthorizedProjectIds(DbSession dbSession, Collection<Long> componentIds, @Nullable Integer userId, String role) {
     return executeLargeInputsIntoSet(
       componentIds,
index 5c7e2ae853e8bef894615fd1bb2c4a632f60a0bb..975bd65c7f7f425ed8c33a5a90b4b45537075485 100644 (file)
@@ -46,8 +46,11 @@ public interface AuthorizationMapper {
   int countUsersWithGlobalPermissionExcludingGroupMember(@Param("organizationUuid") String organizationUuid,
                                                          @Param("permission") String permission, @Param("groupId") long groupId, @Param("userId") long userId);
 
-  Set<Long> keepAuthorizedProjectIdsForAnonymous(@Param("role") String role, @Param("componentIds") Collection<Long> componentIds);
+  int countUsersWithGlobalPermissionExcludingUserPermission(@Param("organizationUuid") String organizationUuid,
+                                                            @Param("permission") String permission, @Param("userId") long userId);
 
+  Set<Long> keepAuthorizedProjectIdsForAnonymous(@Param("role") String role, @Param("componentIds") Collection<Long> componentIds);
+  
   Set<Long> keepAuthorizedProjectIdsForUser(@Param("userId") long userId, @Param("role") String role, @Param("componentIds") Collection<Long> componentIds);
 
   List<String> keepAuthorizedComponentKeysForAnonymous(@Param("role") String role, @Param("componentKeys") Collection<String> componentKeys);
@@ -55,4 +58,6 @@ public interface AuthorizationMapper {
   List<String> keepAuthorizedComponentKeysForUser(@Param("userId") Integer userId, @Param("role") String role, @Param("componentKeys") Collection<String> componentKeys);
 
   List<Long> keepAuthorizedUsersForRoleAndProject(@Param("role") String role, @Param("componentId") long componentId, @Param("userIds") List<Long> userIds);
+
+
 }
index 2300f9d8c9e56c5d2a2431a0f924bc2f39f0a49e..6c132aeb4346b1cefb9393c95261689fcfe93599 100644 (file)
     ) remaining
   </select>
 
+  <select id="countUsersWithGlobalPermissionExcludingUserPermission" 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
+
+    union
+
+    select ur.user_id
+    from user_roles ur
+    where
+    ur.organization_uuid = #{organizationUuid,jdbcType=VARCHAR} and
+    ur.resource_id is null and
+    ur.role = #{permission,jdbcType=VARCHAR} and
+    ur.user_id != #{userId,jdbcType=BIGINT}
+    ) remaining
+  </select>
+
   <select id="keepAuthorizedProjectIdsForUser" parameterType="map" resultType="long">
     SELECT gr.resource_id
     FROM group_roles gr
index 53696810791b79b2d921d3230575a43a53d6a95c..9f213a99fbe49d668b29f0d25cf7c6baddc80de0 100644 (file)
@@ -561,4 +561,32 @@ public class AuthorizationDaoTest {
     count = underTest.countUsersWithGlobalPermissionExcludingGroupMember(dbSession, org.getUuid(), DOES_NOT_EXIST,  group1.getId(), u2.getId());
     assertThat(count).isEqualTo(0);
   }
+
+  @Test
+  public void countUsersWithGlobalPermissionExcludingUserPermission() {
+    // u1 and u2 have the direct permission, u3 has the permission through his group
+    UserDto u1 = db.users().insertUser();
+    db.users().insertPermissionOnUser(org, u1, A_PERMISSION);
+    UserDto u2 = db.users().insertUser();
+    db.users().insertPermissionOnUser(org, u2, A_PERMISSION);
+    db.users().insertPermissionOnGroup(group1, A_PERMISSION);
+    UserDto u3 = db.users().insertUser();
+    db.users().insertMember(group1, u3);
+
+    // excluding u2 permission --> remain u1 and u3
+    int count = underTest.countUsersWithGlobalPermissionExcludingUserPermission(dbSession, org.getUuid(), A_PERMISSION, u2.getId());
+    assertThat(count).isEqualTo(2);
+
+    // excluding unknown user
+    count = underTest.countUsersWithGlobalPermissionExcludingUserPermission(dbSession, org.getUuid(), A_PERMISSION, MISSING_ID);
+    assertThat(count).isEqualTo(3);
+
+    // another organization
+    count = underTest.countUsersWithGlobalPermissionExcludingUserPermission(dbSession, DOES_NOT_EXIST, A_PERMISSION,  u2.getId());
+    assertThat(count).isEqualTo(0);
+
+    // another permission
+    count = underTest.countUsersWithGlobalPermissionExcludingUserPermission(dbSession, org.getUuid(), DOES_NOT_EXIST,  u2.getId());
+    assertThat(count).isEqualTo(0);
+  }
 }