]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9616 UserSession uses project to check permissions on branches
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Wed, 26 Jul 2017 21:24:02 +0000 (23:24 +0200)
committerJanos Gyerik <janos.gyerik@sonarsource.com>
Tue, 12 Sep 2017 08:52:52 +0000 (10:52 +0200)
server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDbTester.java
server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentTesting.java
server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDbTester.java
server/sonar-server/src/main/java/org/sonar/server/user/AbstractUserSession.java
server/sonar-server/src/main/java/org/sonar/server/user/ServerUserSession.java
server/sonar-server/src/test/java/org/sonar/server/user/ServerUserSessionTest.java

index 450ee8770bcb8b2e4198512054c69b8616a65c08..916fac227552886ac96b3e3065db05d37f506a25 100644 (file)
@@ -196,4 +196,11 @@ public class ComponentDbTester {
     db.commit();
   }
 
+  public ComponentDto insertProjectBranch(ComponentDto project, String branchName) {
+    ComponentDto branch = ComponentTesting.newProjectBranch(project, branchName);
+    insertComponent(branch);
+    db.commit();
+    return branch;
+  }
+
 }
index 88cb1226657f550bf12fe962a93a29355855d56f..f3814d67d838ed63bfaf0c633f00a32377246c65 100644 (file)
@@ -193,4 +193,27 @@ public class ComponentTesting {
       .setEnabled(true)
       .setPrivate(moduleOrProject.isPrivate());
   }
+
+  public static ComponentDto newProjectBranch(ComponentDto project, String branchName) {
+    checkArgument(project.qualifier().equals(Qualifiers.PROJECT));
+    String uuid = Uuids.createFast();
+    return new ComponentDto()
+      .setUuid(uuid)
+      .setOrganizationUuid(project.getOrganizationUuid())
+      .setUuidPath(ComponentDto.UUID_PATH_OF_ROOT)
+      .setProjectUuid(uuid)
+      .setModuleUuidPath(UUID_PATH_SEPARATOR + uuid + UUID_PATH_SEPARATOR)
+      .setRootUuid(uuid)
+      .setDbKey(project.getDbKey() + ":BRANCH:" + branchName)
+      .setMainBranchProjectUuid(project.uuid())
+      .setName(project.name())
+      .setLongName(project.longName())
+      .setDescription(project.description())
+      .setScope(project.scope())
+      .setQualifier(project.qualifier())
+      .setPath(null)
+      .setLanguage(null)
+      .setEnabled(true)
+      .setPrivate(project.isPrivate());
+  }
 }
index 87c6adfd1014652194f52e01941204ad6fb01494..d402ac413346d2995c093059702dea1bbdb5e374 100644 (file)
@@ -217,6 +217,7 @@ public class UserDbTester {
     checkArgument(!project.isPrivate(), "No permission to group AnyOne can be granted on a private project");
     checkArgument(!ProjectPermissions.PUBLIC_PERMISSIONS.contains(permission),
       "permission %s can't be granted on a public project", permission);
+    checkArgument(project.getMainBranchProjectUuid()==null, "Permissions can't be granted on branches");
     GroupPermissionDto dto = new GroupPermissionDto()
       .setOrganizationUuid(project.getOrganizationUuid())
       .setGroupId(null)
@@ -236,6 +237,7 @@ public class UserDbTester {
     checkArgument(group.getOrganizationUuid().equals(project.getOrganizationUuid()), "Different organizations");
     checkArgument(project.isPrivate() || !ProjectPermissions.PUBLIC_PERMISSIONS.contains(permission),
       "%s can't be granted on a public project", permission);
+    checkArgument(project.getMainBranchProjectUuid()==null, "Permissions can't be granted on branches");
     GroupPermissionDto dto = new GroupPermissionDto()
       .setOrganizationUuid(group.getOrganizationUuid())
       .setGroupId(group.getId())
@@ -308,6 +310,7 @@ public class UserDbTester {
   public UserPermissionDto insertProjectPermissionOnUser(UserDto user, String permission, ComponentDto project) {
     checkArgument(project.isPrivate() || !ProjectPermissions.PUBLIC_PERMISSIONS.contains(permission),
       "%s can't be granted on a public project", permission);
+    checkArgument(project.getMainBranchProjectUuid()==null, "Permissions can't be granted on branches");
     UserPermissionDto dto = new UserPermissionDto(project.getOrganizationUuid(), permission, user.getId(), project.getId());
     db.getDbClient().userPermissionDao().insert(db.getSession(), dto);
     db.commit();
index db7784ff6f72872f41c5368a25947a4affae7449..bd4b62667f863ddb83288ed2da3785107af5e559 100644 (file)
@@ -27,9 +27,11 @@ import org.sonar.core.permission.ProjectPermissions;
 import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.permission.OrganizationPermission;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.db.permission.OrganizationPermission;
+
+import static org.apache.commons.lang.StringUtils.defaultString;
 
 public abstract class AbstractUserSession implements UserSession {
   private static final String INSUFFICIENT_PRIVILEGES_MESSAGE = "Insufficient privileges";
@@ -71,7 +73,11 @@ public abstract class AbstractUserSession implements UserSession {
 
   @Override
   public final boolean hasComponentPermission(String permission, ComponentDto component) {
-    return isRoot() || hasProjectUuidPermission(permission, component.projectUuid());
+    if (isRoot()) {
+      return true;
+    }
+    String projectUuid = defaultString(component.getMainBranchProjectUuid(), component.projectUuid());
+    return hasProjectUuidPermission(permission, projectUuid);
   }
 
   @Override
index 7f0fa79d67277b04a2900ed4e6d1c8ae0ffcbb4d..28ec0313cd27e7daadc33f5fa3c9b819a291c395 100644 (file)
@@ -43,6 +43,7 @@ import org.sonar.server.organization.DefaultOrganizationProvider;
 import org.sonar.server.organization.OrganizationFlags;
 
 import static com.google.common.collect.Maps.newHashMap;
+import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
 
 /**
  * Implementation of {@link UserSession} used in web server
@@ -143,7 +144,9 @@ public class ServerUserSession extends AbstractUserSession {
       if (!component.isPresent()) {
         return Optional.empty();
       }
-      projectUuid = component.get().projectUuid();
+      // if component is part of a branch, then permissions must be
+      // checked on the project (represented by its main branch)
+      projectUuid = defaultIfEmpty(component.get().getMainBranchProjectUuid(), component.get().projectUuid());
       projectUuidByComponentUuid.put(componentUuid, projectUuid);
       return Optional.of(projectUuid);
     }
index aa7f673da1dbf27798591b33695e4db9bacffea2..83b0fb4cdf76aa737ea042a91b4086a1bf910cc0 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonar.server.user;
 
 import java.util.Arrays;
-import java.util.Random;
 import javax.annotation.Nullable;
 import org.junit.Before;
 import org.junit.Rule;
@@ -40,9 +39,11 @@ import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.organization.TestDefaultOrganizationProvider;
 import org.sonar.server.organization.TestOrganizationFlags;
 
+import static com.google.common.base.Preconditions.checkState;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
 import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
+import static org.sonar.db.component.ComponentTesting.newChildComponent;
 import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
 import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS;
 import static org.sonar.db.permission.OrganizationPermission.SCAN;
@@ -50,8 +51,8 @@ import static org.sonar.db.permission.OrganizationPermission.SCAN;
 public class ServerUserSessionTest {
   private static final String LOGIN = "marius";
 
-  private static final String PUBLIC_PROJECT_UUID = "public project";
-  private static final String PRIVATE_PROJECT_UUID = "private project";
+  private static final String PUBLIC_PROJECT_UUID = "public_project";
+  private static final String PRIVATE_PROJECT_UUID = "private_project";
   private static final String FILE_KEY = "com.foo:Bar:BarFile.xoo";
   private static final String FILE_UUID = "BCDE";
   private static final UserDto ROOT_USER_DTO = new UserDto() {
@@ -390,7 +391,10 @@ public class ServerUserSessionTest {
   }
 
   private boolean hasComponentPermissionByDtoOrUuid(UserSession underTest, String permission, ComponentDto component) {
-    return new Random().nextBoolean() ? underTest.hasComponentPermission(permission, component) : underTest.hasComponentUuidPermission(permission, component.uuid());
+    boolean b1 = underTest.hasComponentPermission(permission, component);
+    boolean b2 = underTest.hasComponentUuidPermission(permission, component.uuid());
+    checkState(b1 == b2, "Different behaviors");
+    return b1;
   }
 
   @Test
@@ -512,6 +516,20 @@ public class ServerUserSessionTest {
     session.checkIsSystemAdministrator();
   }
 
+  @Test
+  public void hasComponentPermission_on_branch_checks_permissions_of_its_project() {
+    ComponentDto branch = db.components().insertProjectBranch(privateProject, "feature/foo");
+    ComponentDto fileInBranch = db.components().insertComponent(newChildComponent("fileUuid", branch, branch));
+
+    // permissions are defined on the project, not on the branch
+    db.users().insertProjectPermissionOnUser(user, "p1", privateProject);
+
+    UserSession underTest = newUserSession(user);
+    assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", privateProject)).isTrue();
+    assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", branch)).isTrue();
+    assertThat(hasComponentPermissionByDtoOrUuid(underTest, "p1", fileInBranch)).isTrue();
+  }
+
   private ServerUserSession newUserSession(@Nullable UserDto userDto) {
     return new ServerUserSession(dbClient, organizationFlags, defaultOrganizationProvider, userDto);
   }