]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8134 Remove check of authorization in PermissionUpdater
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 13 Oct 2016 18:22:59 +0000 (20:22 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Sun, 16 Oct 2016 17:10:40 +0000 (19:10 +0200)
so that Compute Engine can call it without emulating
authroization stack.
Authorization is verified directly in the api/permissions
web services.

24 files changed:
server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
server/sonar-server/src/main/java/org/sonar/server/permission/GroupPermissionChanger.java
server/sonar-server/src/main/java/org/sonar/server/permission/PermissionPrivilegeChecker.java
server/sonar-server/src/main/java/org/sonar/server/permission/PermissionUpdater.java
server/sonar-server/src/main/java/org/sonar/server/permission/UserPermissionChanger.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/GroupsAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsDataLoader.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/UsersAction.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
server/sonar-server/src/test/java/org/sonar/server/permission/GroupPermissionChangerTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/BasePermissionWsTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/SearchProjectPermissionsActionTest.java

index fadc3875c601184c5f72b86121fdc21fbd70195e..4394911e903a9be6684d4ef22947f988317f8003 100644 (file)
@@ -96,6 +96,10 @@ import org.sonar.server.notification.NotificationService;
 import org.sonar.server.notification.email.AlertsEmailTemplate;
 import org.sonar.server.notification.email.EmailNotificationChannel;
 import org.sonar.server.organization.DefaultOrganizationProviderImpl;
+import org.sonar.server.permission.GroupPermissionChanger;
+import org.sonar.server.permission.PermissionService;
+import org.sonar.server.permission.PermissionUpdater;
+import org.sonar.server.permission.UserPermissionChanger;
 import org.sonar.server.platform.DatabaseServerCompatibility;
 import org.sonar.server.platform.DefaultServerUpgradeStatus;
 import org.sonar.server.platform.ServerFileSystemImpl;
@@ -316,6 +320,11 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
 
       // permissions
       PermissionRepository.class,
+      PermissionService.class,
+      PermissionUpdater.class,
+      UserPermissionChanger.class,
+      GroupPermissionChanger.class,
+
 
       // components
       ComponentFinder.class, // used in ComponentService
index 0f7d829a7088be4244ecd7e57e95d3d473cd1952..f46233de17873f0db60d592b6c8bf7011d1057bc 100644 (file)
@@ -88,7 +88,7 @@ public class ComputeEngineContainerImplTest {
     assertThat(picoContainer.getComponentAdapters())
       .hasSize(
         CONTAINER_ITSELF
-          + 74 // level 4
+          + 78 // level 4
           + 4 // content of CeConfigurationModule
           + 3 // content of CeHttpModule
           + 5 // content of CeQueueModule
index c0f09291e0d1e97722bffed0ff3cf9e99fa024b9..5139541f3aaace2aeb710ec42382998946ede119 100644 (file)
@@ -25,23 +25,18 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.permission.GroupPermissionDto;
 import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.user.UserSession;
 
 import static org.sonar.server.permission.ws.PermissionRequestValidator.validateNotAnyoneAndAdminPermission;
 
 public class GroupPermissionChanger {
 
   private final DbClient dbClient;
-  private final UserSession userSession;
 
-  public GroupPermissionChanger(DbClient dbClient, UserSession userSession) {
+  public GroupPermissionChanger(DbClient dbClient) {
     this.dbClient = dbClient;
-    this.userSession = userSession;
   }
 
   public boolean apply(DbSession dbSession, GroupPermissionChange change) {
-    PermissionPrivilegeChecker.checkProjectAdminUserByComponentUuid(userSession, change.getProjectUuid());
-
     if (shouldSkip(dbSession, change)) {
       return false;
     }
index 9b5531297066c2d7e066eadf6738606ab82ed30a..f470a7c590ce9126502aa93f2ded2fc84b5fc6b6 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.permission;
 
+import java.util.Optional;
 import javax.annotation.Nullable;
 import org.sonar.api.web.UserRole;
 import org.sonar.core.permission.GlobalPermissions;
@@ -42,9 +43,9 @@ public class PermissionPrivilegeChecker {
     }
   }
 
-  public static void checkProjectAdminUserByComponentUuid(UserSession userSession, @Nullable String componentUuid) {
+  public static void checkAdministrationPermission(UserSession userSession, Optional<ProjectId> projectId) {
     userSession.checkLoggedIn();
-    if (componentUuid == null || !userSession.hasComponentUuidPermission(UserRole.ADMIN, componentUuid)) {
+    if (!projectId.isPresent() || !userSession.hasComponentUuidPermission(UserRole.ADMIN, projectId.get().getUuid())) {
       userSession.checkPermission(GlobalPermissions.SYSTEM_ADMIN);
     }
   }
index 1d110b929dae9e007fef90f4478af6aa0345ec9e..78d9cdbf7331bacc762f5d14d5edb34094c07f80 100644 (file)
@@ -27,6 +27,11 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.server.issue.index.IssueAuthorizationIndexer;
 
+/**
+ * Add or remove global/project permissions to a group. This class
+ * does not verify that caller has administration right on the related
+ * organization or project.
+ */
 public class PermissionUpdater {
 
   private final DbClient dbClient;
index bdc0e8f0409021b8f615f7dc3139511966426e51..87f26dc7c59d711974646976edffb37b5896eb8e 100644 (file)
@@ -26,23 +26,16 @@ import org.sonar.db.DbSession;
 import org.sonar.db.permission.UserPermissionDto;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.permission.PermissionChange.Operation;
-import org.sonar.server.user.UserSession;
-
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentUuid;
 
 public class UserPermissionChanger {
 
   private final DbClient dbClient;
-  private final UserSession userSession;
 
-  public UserPermissionChanger(DbClient dbClient, UserSession userSession) {
+  public UserPermissionChanger(DbClient dbClient) {
     this.dbClient = dbClient;
-    this.userSession = userSession;
   }
 
   public boolean apply(DbSession dbSession, UserPermissionChange change) {
-    checkProjectAdminUserByComponentUuid(userSession, change.getProjectUuid());
-
     if (shouldSkipChange(dbSession, change)) {
       return false;
     }
index 88461d536e9b16d7abcddba3370e98fa18aaf9d8..d729812290cde14a426c40eab595c14634454d07 100644 (file)
@@ -29,9 +29,11 @@ import org.sonar.server.permission.GroupPermissionChange;
 import org.sonar.server.permission.PermissionChange;
 import org.sonar.server.permission.PermissionUpdater;
 import org.sonar.server.permission.ProjectId;
+import org.sonar.server.user.UserSession;
 import org.sonar.server.usergroups.ws.GroupIdOrAnyone;
 
 import static java.util.Arrays.asList;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkAdministrationPermission;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createGroupIdParameter;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createGroupNameParameter;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createPermissionParameter;
@@ -43,11 +45,13 @@ public class AddGroupAction implements PermissionsWsAction {
   public static final String ACTION = "add_group";
 
   private final DbClient dbClient;
+  private final UserSession userSession;
   private final PermissionUpdater permissionUpdater;
   private final PermissionWsSupport support;
 
-  public AddGroupAction(DbClient dbClient, PermissionUpdater permissionUpdater, PermissionWsSupport support) {
+  public AddGroupAction(DbClient dbClient, UserSession userSession, PermissionUpdater permissionUpdater, PermissionWsSupport support) {
     this.dbClient = dbClient;
+    this.userSession = userSession;
     this.permissionUpdater = permissionUpdater;
     this.support = support;
   }
@@ -75,6 +79,8 @@ public class AddGroupAction implements PermissionsWsAction {
       GroupIdOrAnyone group = support.findGroup(dbSession, request);
       Optional<ProjectId> projectId = support.findProject(dbSession, request);
 
+      checkAdministrationPermission(userSession, projectId);
+
       PermissionChange change = new GroupPermissionChange(
         PermissionChange.Operation.ADD,
         request.mandatoryParam(PARAM_PERMISSION),
index bb189138ad78d155c7bf3f33c92a4c95810ce392..5bc9589095365ecdfed6c3e811feb389e23a9b84 100644 (file)
@@ -31,8 +31,10 @@ import org.sonar.server.permission.PermissionUpdater;
 import org.sonar.server.permission.ProjectId;
 import org.sonar.server.permission.UserId;
 import org.sonar.server.permission.UserPermissionChange;
+import org.sonar.server.user.UserSession;
 
 import static java.util.Arrays.asList;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkAdministrationPermission;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createOrganizationParameter;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createPermissionParameter;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createProjectParameters;
@@ -46,11 +48,13 @@ public class AddUserAction implements PermissionsWsAction {
   public static final String ACTION = "add_user";
 
   private final DbClient dbClient;
+  private final UserSession userSession;
   private final PermissionUpdater permissionUpdater;
   private final PermissionWsSupport support;
 
-  public AddUserAction(DbClient dbClient, PermissionUpdater permissionUpdater, PermissionWsSupport support) {
+  public AddUserAction(DbClient dbClient, UserSession userSession, PermissionUpdater permissionUpdater, PermissionWsSupport support) {
     this.dbClient = dbClient;
+    this.userSession = userSession;
     this.permissionUpdater = permissionUpdater;
     this.support = support;
   }
@@ -77,6 +81,9 @@ public class AddUserAction implements PermissionsWsAction {
       UserId user = support.findUser(dbSession, request.mandatoryParam(PARAM_USER_LOGIN));
       Optional<ProjectId> projectId = support.findProject(dbSession, request);
       OrganizationDto org = support.findOrganization(dbSession, request.param(PARAM_ORGANIZATION_KEY));
+
+      checkAdministrationPermission(userSession, projectId);
+
       PermissionChange change = new UserPermissionChange(
         PermissionChange.Operation.ADD,
         org.getUuid(),
index 0b4047486739e78ff96653e38d8e13797879da92..1b6862a34b315f68855b8a99f8b2fb3d4848d58e 100644 (file)
@@ -46,7 +46,7 @@ import static java.util.Collections.emptyList;
 import static org.sonar.db.permission.PermissionQuery.DEFAULT_PAGE_SIZE;
 import static org.sonar.db.permission.PermissionQuery.RESULTS_MAX_SIZE;
 import static org.sonar.db.permission.PermissionQuery.SEARCH_QUERY_MIN_LENGTH;
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentUuid;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkAdministrationPermission;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createPermissionParameter;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createProjectParameters;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
@@ -87,7 +87,7 @@ public class GroupsAction implements PermissionsWsAction {
   public void handle(Request request, Response response) throws Exception {
     try (DbSession dbSession = dbClient.openSession(false)) {
       Optional<ProjectId> projectId = support.findProject(dbSession, request);
-      checkProjectAdminUserByComponentUuid(userSession, projectId.isPresent() ? projectId.get().getUuid() : null);
+      checkAdministrationPermission(userSession, projectId);
 
       PermissionQuery query = buildPermissionQuery(request, projectId);
       // TODO validatePermission(groupsRequest.getPermission(), wsProjectRef);
index f987e1a4a6ded404452ea2d6e801cc866e07a60a..2204f7f6b6e501f8ab8b0302bdfee4de82df7b30 100644 (file)
 package org.sonar.server.permission.ws;
 
 import org.sonar.core.platform.Module;
-import org.sonar.db.permission.PermissionRepository;
-import org.sonar.server.permission.GroupPermissionChanger;
-import org.sonar.server.permission.PermissionService;
-import org.sonar.server.permission.PermissionUpdater;
-import org.sonar.server.permission.UserPermissionChanger;
 import org.sonar.server.permission.ws.template.AddGroupToTemplateAction;
 import org.sonar.server.permission.ws.template.AddProjectCreatorToTemplateAction;
 import org.sonar.server.permission.ws.template.AddUserToTemplateAction;
@@ -73,11 +68,6 @@ public class PermissionsWsModule extends Module {
       TemplateGroupsAction.class,
       BulkApplyTemplateAction.class,
       // utility classes
-      PermissionRepository.class,
-      PermissionService.class,
-      PermissionUpdater.class,
-      UserPermissionChanger.class,
-      GroupPermissionChanger.class,
       SearchProjectPermissionsDataLoader.class,
       SearchTemplatesDataLoader.class,
       PermissionWsSupport.class,
index e45c817deb9e1722c196da2190378db86a85953c..aab5803873814ccb847f7a92ad50828944e29207 100644 (file)
@@ -29,9 +29,11 @@ import org.sonar.server.permission.GroupPermissionChange;
 import org.sonar.server.permission.PermissionChange;
 import org.sonar.server.permission.PermissionUpdater;
 import org.sonar.server.permission.ProjectId;
+import org.sonar.server.user.UserSession;
 import org.sonar.server.usergroups.ws.GroupIdOrAnyone;
 
 import static java.util.Arrays.asList;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkAdministrationPermission;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createGroupIdParameter;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createGroupNameParameter;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createPermissionParameter;
@@ -43,11 +45,13 @@ public class RemoveGroupAction implements PermissionsWsAction {
   public static final String ACTION = "remove_group";
 
   private final DbClient dbClient;
+  private final UserSession userSession;
   private final PermissionUpdater permissionUpdater;
   private final PermissionWsSupport support;
 
-  public RemoveGroupAction(DbClient dbClient, PermissionUpdater permissionUpdater, PermissionWsSupport support) {
+  public RemoveGroupAction(DbClient dbClient, UserSession userSession, PermissionUpdater permissionUpdater, PermissionWsSupport support) {
     this.dbClient = dbClient;
+    this.userSession = userSession;
     this.permissionUpdater = permissionUpdater;
     this.support = support;
   }
@@ -75,6 +79,8 @@ public class RemoveGroupAction implements PermissionsWsAction {
       GroupIdOrAnyone group = support.findGroup(dbSession, request);
       Optional<ProjectId> projectId = support.findProject(dbSession, request);
 
+      checkAdministrationPermission(userSession, projectId);
+
       PermissionChange change = new GroupPermissionChange(
         PermissionChange.Operation.REMOVE,
         request.mandatoryParam(PARAM_PERMISSION),
index 8ec84d1fac831fba455f03c2c61ca013e7bfa76a..69b11ec718b58c077473e26d53fc2a6b8f74410f 100644 (file)
@@ -31,8 +31,10 @@ import org.sonar.server.permission.PermissionUpdater;
 import org.sonar.server.permission.ProjectId;
 import org.sonar.server.permission.UserId;
 import org.sonar.server.permission.UserPermissionChange;
+import org.sonar.server.user.UserSession;
 
 import static java.util.Arrays.asList;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkAdministrationPermission;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createOrganizationParameter;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createPermissionParameter;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createProjectParameters;
@@ -46,11 +48,13 @@ public class RemoveUserAction implements PermissionsWsAction {
   public static final String ACTION = "remove_user";
 
   private final DbClient dbClient;
+  private final UserSession userSession;
   private final PermissionUpdater permissionUpdater;
   private final PermissionWsSupport support;
 
-  public RemoveUserAction(DbClient dbClient, PermissionUpdater permissionUpdater, PermissionWsSupport support) {
+  public RemoveUserAction(DbClient dbClient, UserSession userSession, PermissionUpdater permissionUpdater, PermissionWsSupport support) {
     this.dbClient = dbClient;
+    this.userSession = userSession;
     this.permissionUpdater = permissionUpdater;
     this.support = support;
   }
@@ -78,6 +82,8 @@ public class RemoveUserAction implements PermissionsWsAction {
       Optional<ProjectId> projectId = support.findProject(dbSession, request);
       OrganizationDto org = support.findOrganization(dbSession, request.param(PARAM_ORGANIZATION_KEY));
 
+      checkAdministrationPermission(userSession, projectId);
+
       PermissionChange change = new UserPermissionChange(
         PermissionChange.Operation.REMOVE,
         org.getUuid(),
index 685de7e4646c76afabe91032abb3146eedec14a0..31177960f81b93debf094019c0731cc3be231f61 100644 (file)
@@ -19,8 +19,8 @@
  */
 package org.sonar.server.permission.ws;
 
-import com.google.common.base.Optional;
 import java.util.Locale;
+import java.util.Optional;
 import org.sonar.api.i18n.I18n;
 import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.server.ws.Request;
@@ -30,7 +30,9 @@ import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.Paging;
 import org.sonar.core.permission.ProjectPermissions;
 import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.server.permission.ProjectId;
 import org.sonar.server.user.UserSession;
 import org.sonarqube.ws.Common;
 import org.sonarqube.ws.WsPermissions.Permission;
@@ -38,9 +40,7 @@ import org.sonarqube.ws.WsPermissions.SearchProjectPermissionsWsResponse;
 import org.sonarqube.ws.WsPermissions.SearchProjectPermissionsWsResponse.Project;
 import org.sonarqube.ws.client.permission.SearchProjectPermissionsWsRequest;
 
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentKey;
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentUuid;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkAdministrationPermission;
 import static org.sonar.server.permission.ws.PermissionRequestValidator.validateQualifier;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createProjectParameters;
 import static org.sonar.server.permission.ws.ProjectWsRef.newOptionalWsProjectRef;
@@ -60,13 +60,16 @@ public class SearchProjectPermissionsAction implements PermissionsWsAction {
   private final I18n i18n;
   private final ResourceTypes resourceTypes;
   private final SearchProjectPermissionsDataLoader dataLoader;
+  private final PermissionWsSupport wsSupport;
 
-  public SearchProjectPermissionsAction(DbClient dbClient, UserSession userSession, I18n i18n, ResourceTypes resourceTypes, SearchProjectPermissionsDataLoader dataLoader) {
+  public SearchProjectPermissionsAction(DbClient dbClient, UserSession userSession, I18n i18n, ResourceTypes resourceTypes,
+                                        SearchProjectPermissionsDataLoader dataLoader, PermissionWsSupport wsSupport) {
     this.dbClient = dbClient;
     this.userSession = userSession;
     this.i18n = i18n;
     this.resourceTypes = resourceTypes;
     this.dataLoader = dataLoader;
+    this.wsSupport = wsSupport;
   }
 
   @Override
@@ -97,10 +100,12 @@ public class SearchProjectPermissionsAction implements PermissionsWsAction {
   }
 
   private SearchProjectPermissionsWsResponse doHandle(SearchProjectPermissionsWsRequest request) {
-    checkRequestAndPermissions(request);
-    validateQualifier(request.getQualifier(), resourceTypes);
-    SearchProjectPermissionsData data = dataLoader.load(request);
-    return buildResponse(data);
+    try (DbSession dbSession = dbClient.openSession(false)) {
+      checkAuthorized(dbSession, request);
+      validateQualifier(request.getQualifier(), resourceTypes);
+      SearchProjectPermissionsData data = dataLoader.load(dbSession, request);
+      return buildResponse(data);
+    }
   }
 
   private static SearchProjectPermissionsWsRequest toSearchProjectPermissionsWsRequest(Request request) {
@@ -113,19 +118,15 @@ public class SearchProjectPermissionsAction implements PermissionsWsAction {
       .setQuery(request.param(Param.TEXT_QUERY));
   }
 
-  private void checkRequestAndPermissions(SearchProjectPermissionsWsRequest request) {
-    Optional<ProjectWsRef> project = newOptionalWsProjectRef(request.getProjectId(), request.getProjectKey());
-    boolean hasProject = project.isPresent();
-    boolean hasProjectUuid = hasProject && project.get().uuid() != null;
-    boolean hasProjectKey = hasProject && project.get().key() != null;
-
-    if (hasProjectUuid) {
-      checkProjectAdminUserByComponentUuid(userSession, project.get().uuid());
-    } else if (hasProjectKey) {
-      checkProjectAdminUserByComponentKey(userSession, project.get().key());
+  private void checkAuthorized(DbSession dbSession, SearchProjectPermissionsWsRequest request) {
+    com.google.common.base.Optional<ProjectWsRef> projectRef = newOptionalWsProjectRef(request.getProjectId(), request.getProjectKey());
+    Optional<ProjectId> projectId;
+    if (projectRef.isPresent()) {
+      projectId = Optional.of(wsSupport.findProject(dbSession, projectRef.get()));
     } else {
-      checkGlobalAdminUser(userSession);
+      projectId = Optional.empty();
     }
+    checkAdministrationPermission(userSession, projectId);
   }
 
   private SearchProjectPermissionsWsResponse buildResponse(SearchProjectPermissionsData data) {
index 2b94d10cf2ddffff05c0c7df15c37033b4056b2b..fd9481abb8dfb8813d24620d4c05a5e46b21ddb6 100644 (file)
@@ -38,8 +38,8 @@ import org.sonarqube.ws.client.permission.SearchProjectPermissionsWsRequest;
 import static java.util.Collections.singletonList;
 import static org.sonar.api.utils.Paging.forPageIndex;
 import static org.sonar.server.component.ResourceTypeFunctions.RESOURCE_TYPE_TO_QUALIFIER;
-import static org.sonar.server.permission.ws.SearchProjectPermissionsData.newBuilder;
 import static org.sonar.server.permission.ws.ProjectWsRef.newOptionalWsProjectRef;
+import static org.sonar.server.permission.ws.SearchProjectPermissionsData.newBuilder;
 
 public class SearchProjectPermissionsDataLoader {
   private final DbClient dbClient;
@@ -52,20 +52,18 @@ public class SearchProjectPermissionsDataLoader {
     this.rootQualifiers = Collections2.transform(resourceTypes.getRoots(), RESOURCE_TYPE_TO_QUALIFIER).toArray(new String[resourceTypes.getRoots().size()]);
   }
 
-  SearchProjectPermissionsData load(SearchProjectPermissionsWsRequest request) {
-    try (DbSession dbSession = dbClient.openSession(false)) {
-      SearchProjectPermissionsData.Builder data = newBuilder();
-      int countRootComponents = countRootComponents(dbSession, request);
-      List<ComponentDto> rootComponents = searchRootComponents(dbSession, request, paging(request, countRootComponents));
-      List<Long> rootComponentIds = Lists.transform(rootComponents, ComponentDto::getId);
+  SearchProjectPermissionsData load(DbSession dbSession, SearchProjectPermissionsWsRequest request) {
+    SearchProjectPermissionsData.Builder data = newBuilder();
+    int countRootComponents = countRootComponents(dbSession, request);
+    List<ComponentDto> rootComponents = searchRootComponents(dbSession, request, paging(request, countRootComponents));
+    List<Long> rootComponentIds = Lists.transform(rootComponents, ComponentDto::getId);
 
-      data.rootComponents(rootComponents)
-        .paging(paging(request, countRootComponents))
-        .userCountByProjectIdAndPermission(userCountByRootComponentIdAndPermission(dbSession, rootComponentIds))
-        .groupCountByProjectIdAndPermission(groupCountByRootComponentIdAndPermission(dbSession, rootComponentIds));
+    data.rootComponents(rootComponents)
+      .paging(paging(request, countRootComponents))
+      .userCountByProjectIdAndPermission(userCountByRootComponentIdAndPermission(dbSession, rootComponentIds))
+      .groupCountByProjectIdAndPermission(groupCountByRootComponentIdAndPermission(dbSession, rootComponentIds));
 
-      return data.build();
-    }
+    return data.build();
   }
 
   private static Paging paging(SearchProjectPermissionsWsRequest request, int total) {
index 3de7d0a7b214cf57cfe1e86968d1301e93f2ef30..635e5937affefc93edb5e38f30e6474a098fce2f 100644 (file)
@@ -44,7 +44,7 @@ import static java.util.Collections.emptyList;
 import static org.sonar.db.permission.PermissionQuery.DEFAULT_PAGE_SIZE;
 import static org.sonar.db.permission.PermissionQuery.RESULTS_MAX_SIZE;
 import static org.sonar.db.permission.PermissionQuery.SEARCH_QUERY_MIN_LENGTH;
-import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentUuid;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkAdministrationPermission;
 import static org.sonar.server.permission.ws.PermissionRequestValidator.validateGlobalPermission;
 import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPermission;
 import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createPermissionParameter;
@@ -90,7 +90,7 @@ public class UsersAction implements PermissionsWsAction {
   public void handle(Request request, Response response) throws Exception {
     try (DbSession dbSession = dbClient.openSession(false)) {
       Optional<ProjectId> projectId = support.findProject(dbSession, request);
-      checkProjectAdminUserByComponentUuid(userSession, projectId.isPresent() ? projectId.get().getUuid() : null);
+      checkAdministrationPermission(userSession, projectId);
 
       PermissionQuery query = buildPermissionQuery(request, projectId);
       List<UserDto> users = findUsers(dbSession, query);
index 2954c6493bc44c06e4a785918fabbb136e58befc..fd4ff65f9c5cc5dc7084cd31bd9581e566d003e4 100644 (file)
@@ -33,6 +33,7 @@ import org.sonar.ce.CeModule;
 import org.sonar.ce.settings.ProjectSettingsFactory;
 import org.sonar.core.component.DefaultResourceTypes;
 import org.sonar.core.timemachine.Periods;
+import org.sonar.db.permission.PermissionRepository;
 import org.sonar.server.authentication.AuthenticationModule;
 import org.sonar.server.batch.BatchWsModule;
 import org.sonar.server.ce.ws.CeWsModule;
@@ -135,6 +136,10 @@ import org.sonar.server.notification.NotificationService;
 import org.sonar.server.notification.email.AlertsEmailTemplate;
 import org.sonar.server.notification.email.EmailNotificationChannel;
 import org.sonar.server.organization.ws.OrganizationsWsModule;
+import org.sonar.server.permission.GroupPermissionChanger;
+import org.sonar.server.permission.PermissionService;
+import org.sonar.server.permission.PermissionUpdater;
+import org.sonar.server.permission.UserPermissionChanger;
 import org.sonar.server.permission.ws.PermissionsWsModule;
 import org.sonar.server.platform.BackendCleanup;
 import org.sonar.server.platform.PersistentSettings;
@@ -426,6 +431,11 @@ public class PlatformLevel4 extends PlatformLevel {
 
       // permissions
       PermissionsWsModule.class,
+      PermissionRepository.class,
+      PermissionService.class,
+      PermissionUpdater.class,
+      UserPermissionChanger.class,
+      GroupPermissionChanger.class,
 
       // components
       ProjectsWsModule.class,
index 09dc5971f43c62d7ba28c366f988dc96ea0ea8e2..af8d9deb5d730e2364d7b1787fc19ecfe70c55fc 100644 (file)
@@ -34,12 +34,9 @@ import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.organization.OrganizationTesting;
 import org.sonar.db.user.GroupDto;
 import org.sonar.server.exceptions.BadRequestException;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.usergroups.ws.GroupIdOrAnyone;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
 
 public class GroupPermissionChangerTest {
 
@@ -49,8 +46,7 @@ public class GroupPermissionChangerTest {
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
 
-  private UserSessionRule userSession = UserSessionRule.standalone();
-  private GroupPermissionChanger underTest = new GroupPermissionChanger(db.getDbClient(), userSession);
+  private GroupPermissionChanger underTest = new GroupPermissionChanger(db.getDbClient());
   private OrganizationDto org;
   private GroupDto group;
   private ComponentDto project;
@@ -66,7 +62,6 @@ public class GroupPermissionChangerTest {
   public void add_permission_to_group() {
     GroupIdOrAnyone groupId = new GroupIdOrAnyone(group);
 
-    loginAsAdmin();
     apply(new GroupPermissionChange(PermissionChange.Operation.ADD, GlobalPermissions.QUALITY_GATE_ADMIN, null, groupId));
 
     assertThat(db.users().selectGroupPermissions(group, null)).containsOnly(GlobalPermissions.QUALITY_GATE_ADMIN);
@@ -76,7 +71,6 @@ public class GroupPermissionChangerTest {
   public void add_project_permission_to_group() {
     GroupIdOrAnyone groupId = new GroupIdOrAnyone(group);
 
-    loginAsAdmin();
     apply(new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.ISSUE_ADMIN, new ProjectId(project), groupId));
 
     assertThat(db.users().selectGroupPermissions(group, null)).isEmpty();
@@ -87,7 +81,6 @@ public class GroupPermissionChangerTest {
   public void add_permission_to_anyone() {
     GroupIdOrAnyone groupId = new GroupIdOrAnyone(db.getDefaultOrganization().getUuid(), null);
 
-    loginAsAdmin();
     apply(new GroupPermissionChange(PermissionChange.Operation.ADD, GlobalPermissions.QUALITY_GATE_ADMIN, null, groupId));
 
     assertThat(db.users().selectGroupPermissions(group, null)).isEmpty();
@@ -98,29 +91,17 @@ public class GroupPermissionChangerTest {
   public void add_project_permission_to_anyone() {
     GroupIdOrAnyone groupId = new GroupIdOrAnyone(db.getDefaultOrganization().getUuid(), null);
 
-    loginAsAdmin();
     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);
   }
 
-  @Test
-  public void fail_to_add_permission_if_not_admin() {
-    GroupIdOrAnyone groupId = new GroupIdOrAnyone(db.getDefaultOrganization().getUuid(), null);
-
-    expectedException.expect(ForbiddenException.class);
-
-    userSession.login("a_guy");
-    underTest.apply(db.getSession(), new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.ISSUE_ADMIN, new ProjectId(project), groupId));
-  }
-
   @Test
   public void do_nothing_when_adding_permission_that_already_exists() {
     GroupIdOrAnyone groupId = new GroupIdOrAnyone(group);
     db.users().insertPermissionOnGroup(group, GlobalPermissions.QUALITY_GATE_ADMIN);
 
-    loginAsAdmin();
     apply(new GroupPermissionChange(PermissionChange.Operation.ADD, GlobalPermissions.QUALITY_GATE_ADMIN, null, groupId));
 
     assertThat(db.users().selectGroupPermissions(group, null)).containsOnly(GlobalPermissions.QUALITY_GATE_ADMIN);
@@ -133,7 +114,6 @@ public class GroupPermissionChangerTest {
     expectedException.expect(BadRequestException.class);
     expectedException.expectMessage("Invalid project permission 'gateadmin'. Valid values are [admin, codeviewer, issueadmin, scan, user]");
 
-    loginAsAdmin();
     apply(new GroupPermissionChange(PermissionChange.Operation.ADD, GlobalPermissions.QUALITY_GATE_ADMIN, new ProjectId(project), groupId));
   }
 
@@ -144,7 +124,6 @@ public class GroupPermissionChangerTest {
     expectedException.expect(BadRequestException.class);
     expectedException.expectMessage("Invalid global permission 'issueadmin'. Valid values are [admin, profileadmin, gateadmin, scan, provisioning]");
 
-    loginAsAdmin();
     apply(new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.ISSUE_ADMIN, null, groupId));
   }
 
@@ -154,7 +133,6 @@ public class GroupPermissionChangerTest {
     db.users().insertPermissionOnGroup(group, GlobalPermissions.QUALITY_GATE_ADMIN);
     db.users().insertPermissionOnGroup(group, GlobalPermissions.PROVISIONING);
 
-    loginAsAdmin();
     apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, GlobalPermissions.QUALITY_GATE_ADMIN, null, groupId));
 
     assertThat(db.users().selectGroupPermissions(group, null)).containsOnly(GlobalPermissions.PROVISIONING);
@@ -167,7 +145,6 @@ public class GroupPermissionChangerTest {
     db.users().insertProjectPermissionOnGroup(group, UserRole.ISSUE_ADMIN, project);
     db.users().insertProjectPermissionOnGroup(group, UserRole.CODEVIEWER, project);
 
-    loginAsAdmin();
     apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, UserRole.ISSUE_ADMIN, new ProjectId(project), groupId));
 
     assertThat(db.users().selectGroupPermissions(group, null)).containsOnly(GlobalPermissions.QUALITY_GATE_ADMIN);
@@ -178,23 +155,12 @@ public class GroupPermissionChangerTest {
   public void do_not_fail_if_removing_a_permission_that_does_not_exist() {
     GroupIdOrAnyone groupId = new GroupIdOrAnyone(group);
 
-    loginAsAdmin();
     apply(new GroupPermissionChange(PermissionChange.Operation.REMOVE, UserRole.ISSUE_ADMIN, new ProjectId(project), groupId));
 
     assertThat(db.users().selectGroupPermissions(group, null)).isEmpty();
     assertThat(db.users().selectGroupPermissions(group, project)).isEmpty();
   }
 
-  @Test
-  public void fail_to_remove_permission_if_not_admin() {
-    GroupIdOrAnyone groupId = new GroupIdOrAnyone(db.getDefaultOrganization().getUuid(), null);
-
-    expectedException.expect(ForbiddenException.class);
-
-    userSession.login("a_guy");
-    underTest.apply(db.getSession(), new GroupPermissionChange(PermissionChange.Operation.REMOVE, UserRole.ISSUE_ADMIN, new ProjectId(project), groupId));
-  }
-
   @Test
   public void fail_to_remove_sysadmin_permission_if_no_more_sysadmins() {
     GroupIdOrAnyone groupId = new GroupIdOrAnyone(group);
@@ -203,7 +169,6 @@ public class GroupPermissionChangerTest {
     expectedException.expect(BadRequestException.class);
     expectedException.expectMessage("Last group with 'admin' permission. Permission cannot be removed.");
 
-    loginAsAdmin();
     underTest.apply(db.getSession(), new GroupPermissionChange(PermissionChange.Operation.REMOVE, GlobalPermissions.SYSTEM_ADMIN, null, groupId));
   }
 
@@ -211,8 +176,4 @@ public class GroupPermissionChangerTest {
     underTest.apply(db.getSession(), change);
     db.commit();
   }
-
-  private void loginAsAdmin() {
-    userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN);
-  }
 }
index 3a1e69f9a6ef6f7a0909b21bd77185fbb3eaa9e3..042edfa6ad1315c3cc5aa26499c39c5e110fd88c 100644 (file)
@@ -31,6 +31,8 @@ import org.sonar.server.exceptions.ServerException;
 import org.sonar.server.ws.WsTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
+import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
 import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
 import static org.sonar.db.component.ComponentTesting.newProjectDto;
 import static org.sonar.db.component.ComponentTesting.newView;
@@ -49,7 +51,7 @@ public class AddGroupActionTest extends BasePermissionWsTest<AddGroupAction> {
 
   @Override
   protected AddGroupAction buildWsAction() {
-    return new AddGroupAction(db.getDbClient(), newPermissionUpdater(), newPermissionWsSupport());
+    return new AddGroupAction(db.getDbClient(), userSession, newPermissionUpdater(), newPermissionWsSupport());
   }
 
   @Test
@@ -221,17 +223,50 @@ public class AddGroupActionTest extends BasePermissionWsTest<AddGroupAction> {
       .execute();
   }
 
-  @Test(expected = ForbiddenException.class)
-  public void require_admin_permission() throws Exception {
+  @Test
+  public void adding_global_permission_fails_if_not_administrator_of_organization() throws Exception {
     GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "sonar-administrators");
-    ComponentDto project = db.components().insertComponent(newProjectDto(A_PROJECT_UUID).setKey(A_PROJECT_KEY));
-    userSession.login("not-admin");
+    userSession.login();
+
+    expectedException.expect(ForbiddenException.class);
+
+    newRequest()
+      .setParam(PARAM_GROUP_NAME, group.getName())
+      .setParam(PARAM_PERMISSION, PROVISIONING)
+      .execute();
+  }
+
+  @Test
+  public void adding_project_permission_fails_if_not_administrator_of_project() throws Exception {
+    GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "sonar-administrators");
+    ComponentDto project = db.components().insertProject();
+    userSession.login();
+
+    expectedException.expect(ForbiddenException.class);
+
+    newRequest()
+      .setParam(PARAM_GROUP_NAME, group.getName())
+      .setParam(PARAM_PERMISSION, PROVISIONING)
+      .setParam(PARAM_PROJECT_KEY, project.key())
+      .execute();
+  }
+
+  /**
+   * User is project administrator but not system administrator
+   */
+  @Test
+  public void adding_project_permission_is_allowed_to_project_administrators() throws Exception {
+    GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "sonar-administrators");
+    ComponentDto project = db.components().insertProject();
+    userSession.login().addProjectUuidPermissions(UserRole.ADMIN, project.uuid());
 
     newRequest()
       .setParam(PARAM_GROUP_NAME, group.getName())
-      .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
       .setParam(PARAM_PROJECT_ID, project.uuid())
+      .setParam(PARAM_PERMISSION, ISSUE_ADMIN)
       .execute();
+
+    assertThat(db.users().selectGroupPermissions(group, project)).containsOnly(ISSUE_ADMIN);
   }
 
   private WsTester.TestRequest newRequest() {
@@ -239,7 +274,7 @@ public class AddGroupActionTest extends BasePermissionWsTest<AddGroupAction> {
   }
 
   private void loginAsAdmin() {
-    userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN);
+    userSession.login().setGlobalPermissions(SYSTEM_ADMIN);
   }
 
 }
index 4f00c1d8765924ce2c3507e0caee22eb5e3544a3..6c2814976343e4059e3e38331dccd999558c6ed9 100644 (file)
@@ -25,10 +25,12 @@ import org.sonar.api.web.UserRole;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.user.UserDto;
 import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.exceptions.ServerException;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
 import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
 import static org.sonar.db.component.ComponentTesting.newFileDto;
 import static org.sonar.db.component.ComponentTesting.newProjectDto;
@@ -42,9 +44,6 @@ import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_U
 
 public class AddUserActionTest extends BasePermissionWsTest<AddUserAction> {
 
-  private static final String A_PROJECT_UUID = "project-uuid";
-  private static final String A_PROJECT_KEY = "project-key";
-
   private UserDto user;
 
   @Before
@@ -54,7 +53,7 @@ public class AddUserActionTest extends BasePermissionWsTest<AddUserAction> {
 
   @Override
   protected AddUserAction buildWsAction() {
-    return new AddUserAction(db.getDbClient(), newPermissionUpdater(), newPermissionWsSupport());
+    return new AddUserAction(db.getDbClient(), userSession, newPermissionUpdater(), newPermissionWsSupport());
   }
 
   @Test
@@ -70,7 +69,7 @@ public class AddUserActionTest extends BasePermissionWsTest<AddUserAction> {
 
   @Test
   public void add_permission_to_project_referenced_by_its_id() throws Exception {
-    ComponentDto project = db.components().insertComponent(newProjectDto("project-uuid").setKey("project-key"));
+    ComponentDto project = db.components().insertProject();
 
     loginAsAdmin();
     wsTester.newPostRequest(CONTROLLER, ACTION)
@@ -85,7 +84,7 @@ public class AddUserActionTest extends BasePermissionWsTest<AddUserAction> {
 
   @Test
   public void add_permission_to_project_referenced_by_its_key() throws Exception {
-    ComponentDto project = db.components().insertComponent(newProjectDto("project-uuid").setKey("project-key"));
+    ComponentDto project = db.components().insertProject();
 
     loginAsAdmin();
     wsTester.newPostRequest(CONTROLLER, ACTION)
@@ -188,7 +187,7 @@ public class AddUserActionTest extends BasePermissionWsTest<AddUserAction> {
 
   @Test
   public void fail_when_project_uuid_and_project_key_are_provided() throws Exception {
-    db.components().insertComponent(newProjectDto(A_PROJECT_UUID).setKey(A_PROJECT_KEY));
+    db.components().insertProject();
     loginAsAdmin();
 
     expectedException.expect(BadRequestException.class);
@@ -202,7 +201,51 @@ public class AddUserActionTest extends BasePermissionWsTest<AddUserAction> {
       .execute();
   }
 
+  @Test
+  public void adding_global_permission_fails_if_not_administrator_of_organization() throws Exception {
+    userSession.login();
+
+    expectedException.expect(ForbiddenException.class);
+
+    wsTester.newPostRequest(CONTROLLER, ACTION)
+      .setParam(PARAM_USER_LOGIN, user.getLogin())
+      .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
+      .execute();
+  }
+
+  @Test
+  public void adding_project_permission_fails_if_not_administrator_of_project() throws Exception {
+    ComponentDto project = db.components().insertProject();
+    userSession.login();
+
+    expectedException.expect(ForbiddenException.class);
+
+    wsTester.newPostRequest(CONTROLLER, ACTION)
+      .setParam(PARAM_USER_LOGIN, user.getLogin())
+      .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
+      .setParam(PARAM_PROJECT_KEY, project.getKey())
+      .execute();
+  }
+
+  /**
+   * User is project administrator but not system administrator
+   */
+  @Test
+  public void adding_project_permission_is_allowed_to_project_administrators() throws Exception {
+    ComponentDto project = db.components().insertProject();
+
+    userSession.login().addProjectUuidPermissions(UserRole.ADMIN, project.uuid());
+
+    wsTester.newPostRequest(CONTROLLER, ACTION)
+      .setParam(PARAM_USER_LOGIN, user.getLogin())
+      .setParam(PARAM_PROJECT_KEY, project.getKey())
+      .setParam(PARAM_PERMISSION, UserRole.ISSUE_ADMIN)
+      .execute();
+
+    assertThat(db.users().selectUserPermissions(user, project)).containsOnly(ISSUE_ADMIN);
+  }
+
   private void loginAsAdmin() {
-    userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN);
+    userSession.login().setGlobalPermissions(SYSTEM_ADMIN);
   }
 }
index ca41e9b8a374d9de81b6d2075c423d573ff6d0bd..88e35336c9ab3c29ea7d10d8bc322676d6dd6f3e 100644 (file)
@@ -76,8 +76,8 @@ public abstract class BasePermissionWsTest<A extends PermissionsWsAction> {
   protected PermissionUpdater newPermissionUpdater() {
     return new PermissionUpdater(db.getDbClient(),
       mock(IssueAuthorizationIndexer.class),
-      new UserPermissionChanger(db.getDbClient(), userSession),
-      new GroupPermissionChanger(db.getDbClient(), userSession));
+      new UserPermissionChanger(db.getDbClient()),
+      new GroupPermissionChanger(db.getDbClient()));
   }
 
   protected PermissionTemplateDto insertTemplate() {
index 8018e6dc894cd3712cec624423e5eb92373021da..0f0e343f919ee7b79eb9100c23c046049da32488 100644 (file)
@@ -29,6 +29,6 @@ public class PermissionsWsModuleTest {
   public void verify_count_of_added_components() {
     ComponentContainer container = new ComponentContainer();
     new PermissionsWsModule().configure(container);
-    assertThat(container.size()).isEqualTo(2 + 33);
+    assertThat(container.size()).isEqualTo(2 + 28);
   }
 }
index 58a7f4b7f57f1ce012e90645d0cb6a6a26c1d1f8..14f5b84d03875bd6c0a361cde041d8406bb50e47 100644 (file)
@@ -21,15 +21,18 @@ package org.sonar.server.permission.ws;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.sonar.api.web.UserRole;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.user.GroupDto;
 import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.exceptions.ServerException;
 import org.sonar.server.ws.WsTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.api.web.UserRole.ADMIN;
+import static org.sonar.api.web.UserRole.CODEVIEWER;
 import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
 import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
 import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
@@ -46,9 +49,6 @@ import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_P
 
 public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupAction> {
 
-  private static final String A_PROJECT_UUID = "project-uuid";
-  private static final String A_PROJECT_KEY = "project-key";
-
   private GroupDto aGroup;
 
   @Before
@@ -58,15 +58,15 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
 
   @Override
   protected RemoveGroupAction buildWsAction() {
-    return new RemoveGroupAction(db.getDbClient(), newPermissionUpdater(), newPermissionWsSupport());
+    return new RemoveGroupAction(db.getDbClient(), userSession, newPermissionUpdater(), newPermissionWsSupport());
   }
 
   @Test
   public void remove_permission_using_group_name() throws Exception {
     db.users().insertPermissionOnGroup(aGroup, SYSTEM_ADMIN);
     db.users().insertPermissionOnGroup(aGroup, PROVISIONING);
-
     loginAsAdmin();
+
     newRequest()
       .setParam(PARAM_GROUP_NAME, aGroup.getName())
       .setParam(PARAM_PERMISSION, PROVISIONING)
@@ -79,8 +79,8 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
   public void remove_permission_using_group_id() throws Exception {
     db.users().insertPermissionOnGroup(aGroup, SYSTEM_ADMIN);
     db.users().insertPermissionOnGroup(aGroup, PROVISIONING);
-
     loginAsAdmin();
+
     newRequest()
       .setParam(PARAM_GROUP_ID, aGroup.getId().toString())
       .setParam(PARAM_PERMISSION, PROVISIONING)
@@ -91,7 +91,7 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
 
   @Test
   public void remove_project_permission() throws Exception {
-    ComponentDto project = db.components().insertComponent(newProjectDto(A_PROJECT_UUID).setKey(A_PROJECT_KEY));
+    ComponentDto project = db.components().insertProject();
     db.users().insertPermissionOnGroup(aGroup, SYSTEM_ADMIN);
     db.users().insertProjectPermissionOnGroup(aGroup, ADMIN, project);
     db.users().insertProjectPermissionOnGroup(aGroup, ISSUE_ADMIN, project);
@@ -127,7 +127,7 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
 
   @Test
   public void remove_with_project_key() throws Exception {
-    ComponentDto project = db.components().insertComponent(newProjectDto(A_PROJECT_UUID).setKey(A_PROJECT_KEY));
+    ComponentDto project = db.components().insertProject();
     db.users().insertPermissionOnGroup(aGroup, SYSTEM_ADMIN);
     db.users().insertProjectPermissionOnGroup(aGroup, ADMIN, project);
     db.users().insertProjectPermissionOnGroup(aGroup, ISSUE_ADMIN, project);
@@ -160,6 +160,8 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
 
   @Test
   public void fail_when_project_does_not_exist() throws Exception {
+    loginAsAdmin();
+
     expectedException.expect(NotFoundException.class);
     expectedException.expectMessage("Project id 'unknown-project-uuid' not found");
 
@@ -172,6 +174,8 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
 
   @Test
   public void fail_when_project_project_permission_without_project() throws Exception {
+    loginAsAdmin();
+
     expectedException.expect(BadRequestException.class);
     expectedException.expectMessage("Invalid global permission 'issueadmin'. Valid values are [admin, profileadmin, gateadmin, scan, provisioning]");
 
@@ -183,7 +187,8 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
 
   @Test
   public void fail_when_component_is_not_a_project() throws Exception {
-    ComponentDto file = db.components().insertComponent(newFileDto(newProjectDto(A_PROJECT_UUID), null, "file-uuid"));
+    ComponentDto file = db.components().insertComponent(newFileDto(newProjectDto(), null, "file-uuid"));
+    loginAsAdmin();
 
     expectedException.expect(BadRequestException.class);
     expectedException.expectMessage("Component 'KEY_file-uuid' (id: file-uuid) must be a project or a module.");
@@ -197,6 +202,8 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
 
   @Test
   public void fail_when_get_request() throws Exception {
+    loginAsAdmin();
+
     expectedException.expect(ServerException.class);
     expectedException.expectMessage("HTTP method POST is required");
 
@@ -208,6 +215,8 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
 
   @Test
   public void fail_when_group_name_is_missing() throws Exception {
+    loginAsAdmin();
+
     expectedException.expect(BadRequestException.class);
     expectedException.expectMessage("Group name or group id must be provided");
 
@@ -218,6 +227,8 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
 
   @Test
   public void fail_when_permission_name_and_id_are_missing() throws Exception {
+    loginAsAdmin();
+
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("The 'permission' parameter is missing");
 
@@ -228,6 +239,8 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
 
   @Test
   public void fail_when_group_id_does_not_exist() throws Exception {
+    loginAsAdmin();
+
     expectedException.expect(NotFoundException.class);
     expectedException.expectMessage("No group with id '42'");
 
@@ -239,7 +252,8 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
 
   @Test
   public void fail_when_project_uuid_and_project_key_are_provided() throws Exception {
-    ComponentDto project = db.components().insertComponent(newProjectDto(A_PROJECT_UUID).setKey(A_PROJECT_KEY));
+    ComponentDto project = db.components().insertProject();
+    loginAsAdmin();
 
     expectedException.expect(BadRequestException.class);
     expectedException.expectMessage("Project id or project key can be provided, not both.");
@@ -252,12 +266,57 @@ public class RemoveGroupActionTest extends BasePermissionWsTest<RemoveGroupActio
       .execute();
   }
 
+  @Test
+  public void removing_global_permission_fails_if_not_administrator_of_organization() throws Exception {
+    userSession.login();
+
+    expectedException.expect(ForbiddenException.class);
+
+    newRequest()
+      .setParam(PARAM_GROUP_NAME, aGroup.getName())
+      .setParam(PARAM_PERMISSION, PROVISIONING)
+      .execute();
+  }
+
+  @Test
+  public void removing_project_permission_fails_if_not_administrator_of_project() throws Exception {
+    ComponentDto project = db.components().insertProject();
+    userSession.login();
+
+    expectedException.expect(ForbiddenException.class);
+
+    newRequest()
+      .setParam(PARAM_GROUP_NAME, aGroup.getName())
+      .setParam(PARAM_PERMISSION, PROVISIONING)
+      .setParam(PARAM_PROJECT_KEY, project.key())
+      .execute();
+  }
+
+  /**
+   * User is project administrator but not system administrator
+   */
+  @Test
+  public void removing_project_permission_is_allowed_to_project_administrators() throws Exception {
+    ComponentDto project = db.components().insertProject();
+    db.users().insertProjectPermissionOnGroup(aGroup, CODEVIEWER, project);
+    db.users().insertProjectPermissionOnGroup(aGroup, ISSUE_ADMIN, project);
+
+    userSession.login().addProjectUuidPermissions(UserRole.ADMIN, project.uuid());
+    newRequest()
+      .setParam(PARAM_GROUP_NAME, aGroup.getName())
+      .setParam(PARAM_PROJECT_ID, project.uuid())
+      .setParam(PARAM_PERMISSION, ISSUE_ADMIN)
+      .execute();
+
+    assertThat(db.users().selectGroupPermissions(aGroup, project)).containsOnly(CODEVIEWER);
+  }
+
   private WsTester.TestRequest newRequest() {
     return wsTester.newPostRequest(CONTROLLER, ACTION);
   }
 
   private void loginAsAdmin() {
-    userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN);
+    userSession.login().setGlobalPermissions(SYSTEM_ADMIN);
   }
 
 }
index 42ffbac6cf90a1096887eab17d27984cac694826..ff310370455d66c7fa1e29ea51144b4b7b090fc9 100644 (file)
@@ -21,9 +21,11 @@ package org.sonar.server.permission.ws;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.sonar.api.web.UserRole;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.user.UserDto;
 import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.exceptions.ServerException;
 
@@ -59,7 +61,7 @@ public class RemoveUserActionTest extends BasePermissionWsTest<RemoveUserAction>
 
   @Override
   protected RemoveUserAction buildWsAction() {
-    return new RemoveUserAction(db.getDbClient(), newPermissionUpdater(), newPermissionWsSupport());
+    return new RemoveUserAction(db.getDbClient(), userSession, newPermissionUpdater(), newPermissionWsSupport());
   }
 
   @Test
@@ -228,6 +230,51 @@ public class RemoveUserActionTest extends BasePermissionWsTest<RemoveUserAction>
       .execute();
   }
 
+  @Test
+  public void removing_global_permission_fails_if_not_administrator_of_organization() throws Exception {
+    userSession.login();
+
+    expectedException.expect(ForbiddenException.class);
+
+    wsTester.newPostRequest(CONTROLLER, ACTION)
+      .setParam(PARAM_USER_LOGIN, user.getLogin())
+      .setParam(PARAM_PERMISSION, PROVISIONING)
+      .execute();
+  }
+
+  @Test
+  public void removing_project_permission_fails_if_not_administrator_of_project() throws Exception {
+    ComponentDto project = db.components().insertProject();
+    userSession.login();
+
+    expectedException.expect(ForbiddenException.class);
+
+    wsTester.newPostRequest(CONTROLLER, ACTION)
+      .setParam(PARAM_USER_LOGIN, user.getLogin())
+      .setParam(PARAM_PERMISSION, ISSUE_ADMIN)
+      .setParam(PARAM_PROJECT_KEY, project.key())
+      .execute();
+  }
+
+  /**
+   * User is project administrator but not system administrator
+   */
+  @Test
+  public void removing_project_permission_is_allowed_to_project_administrators() throws Exception {
+    ComponentDto project = db.components().insertProject();
+    db.users().insertProjectPermissionOnUser(user, CODEVIEWER, project);
+    db.users().insertProjectPermissionOnUser(user, ISSUE_ADMIN, project);
+    userSession.login().addProjectUuidPermissions(UserRole.ADMIN, project.uuid());
+
+    wsTester.newPostRequest(CONTROLLER, ACTION)
+      .setParam(PARAM_USER_LOGIN, user.getLogin())
+      .setParam(PARAM_PROJECT_ID, project.uuid())
+      .setParam(PARAM_PERMISSION, ISSUE_ADMIN)
+      .execute();
+
+    assertThat(db.users().selectUserPermissions(user, project)).containsOnly(CODEVIEWER);
+  }
+
   private void loginAsAdmin() {
     userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN);
   }
index ea6d5bd69b4e360220918bf90a04ec232e0dd7f9..56bee1de7bb97093e71fb0dddace5d7ba38d587d 100644 (file)
@@ -65,8 +65,9 @@ public class SearchProjectPermissionsActionTest extends BasePermissionWsTest<Sea
   protected SearchProjectPermissionsAction buildWsAction() {
     i18n.setProjectPermissions();
     ResourceTypesRule rootResourceTypes = newRootResourceTypes();
-    SearchProjectPermissionsDataLoader dataLoader = new SearchProjectPermissionsDataLoader(db.getDbClient(), newPermissionWsSupport(), rootResourceTypes);
-    return new SearchProjectPermissionsAction(db.getDbClient(), userSession, i18n, rootResourceTypes, dataLoader);
+    PermissionWsSupport wsSupport = newPermissionWsSupport();
+    SearchProjectPermissionsDataLoader dataLoader = new SearchProjectPermissionsDataLoader(db.getDbClient(), wsSupport, rootResourceTypes);
+    return new SearchProjectPermissionsAction(db.getDbClient(), userSession, i18n, rootResourceTypes, dataLoader, wsSupport);
   }
 
   @Test