]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6259 Grant project permission on the compute engine 341/head
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 1 Jun 2015 08:51:30 +0000 (10:51 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 1 Jun 2015 08:56:17 +0000 (10:56 +0200)
server/sonar-server/src/main/java/org/sonar/server/computation/step/ApplyPermissionsStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/IndexIssuesStep.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ApplyPermissionsStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexIssuesStepTest.java
sonar-core/src/main/java/org/sonar/core/permission/PermissionFacade.java
sonar-core/src/test/java/org/sonar/core/resource/DefaultResourcePermissionsTest.java
sonar-core/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/fail_when_no_default_template_is_defined.xml [new file with mode: 0644]

index 022ee3eb068759988ce07dd84cccc213f510a1e5..2a9f886e680f0a81f3b571964a74598b0fed77b1 100644 (file)
 
 package org.sonar.server.computation.step;
 
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.core.permission.PermissionFacade;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
 import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.computation.component.DbComponentsRefCache;
+import org.sonar.server.db.DbClient;
 import org.sonar.server.issue.index.IssueAuthorizationIndexer;
 
+/**
+ * Apply default permissions on new projects and index issues/authorization
+ */
 public class ApplyPermissionsStep implements ComputationStep {
 
+  private final DbClient dbClient;
+  private final DbComponentsRefCache dbComponentsRefCache;
   private final IssueAuthorizationIndexer indexer;
+  private final PermissionFacade permissionFacade;
 
-  public ApplyPermissionsStep(IssueAuthorizationIndexer indexer) {
+  public ApplyPermissionsStep(DbClient dbClient, DbComponentsRefCache dbComponentsRefCache, IssueAuthorizationIndexer indexer, PermissionFacade permissionFacade) {
+    this.dbClient = dbClient;
+    this.dbComponentsRefCache = dbComponentsRefCache;
     this.indexer = indexer;
+    this.permissionFacade = permissionFacade;
   }
 
   @Override
   public void execute(ComputationContext context) {
-    indexer.index();
+    DbSession session = dbClient.openSession(false);
+    try {
+      long projectId = dbComponentsRefCache.getByRef(context.getRoot().getRef()).getId();
+      if (permissionFacade.countComponentPermissions(session, projectId) == 0) {
+        permissionFacade.grantDefaultRoles(session, projectId, Qualifiers.PROJECT);
+        session.commit();
+        indexer.index();
+      }
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
   }
 
   @Override
   public String getDescription() {
-    return "Index project permissions";
+    return "Apply project permissions";
   }
 
 }
index e1caae311efa7f623d7a1d805b9c63ebd825f75e..fc8af3c9d6f2ba85b10b5b7c8d53c20facda2bdb 100644 (file)
 package org.sonar.server.computation.step;
 
 import org.sonar.server.computation.ComputationContext;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
 import org.sonar.server.issue.index.IssueIndexer;
 
 public class IndexIssuesStep implements ComputationStep {
 
-  private final IssueAuthorizationIndexer authorizationIndexer;
   private final IssueIndexer indexer;
 
-  public IndexIssuesStep(IssueAuthorizationIndexer authorizationIndexer, IssueIndexer indexer) {
-    this.authorizationIndexer = authorizationIndexer;
+  public IndexIssuesStep(IssueIndexer indexer) {
     this.indexer = indexer;
   }
 
   @Override
   public void execute(ComputationContext context) {
-    authorizationIndexer.index();
     indexer.index();
   }
 
index 09a793d56415d1417e9acc695b9235428018f40f..8aa76fad30fa0845f9586bbeb4d872c6d3196771 100644 (file)
  */
 package org.sonar.server.computation.step;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import org.elasticsearch.search.SearchHit;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.config.Settings;
+import org.sonar.api.security.DefaultGroups;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReportReader;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.permission.PermissionFacade;
+import org.sonar.core.permission.PermissionTemplateDao;
+import org.sonar.core.permission.PermissionTemplateDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.user.GroupRoleDto;
+import org.sonar.core.user.RoleDao;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
 import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.ComponentTreeBuilders;
+import org.sonar.server.computation.component.DbComponentsRefCache;
+import org.sonar.server.computation.component.DumbComponent;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.EsTester;
 import org.sonar.server.issue.index.IssueAuthorizationIndexer;
+import org.sonar.server.issue.index.IssueIndexDefinition;
+import org.sonar.test.DbTests;
 
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
+import static org.assertj.core.api.Assertions.assertThat;
 
+@Category(DbTests.class)
 public class ApplyPermissionsStepTest extends BaseStepTest {
 
-  IssueAuthorizationIndexer indexer = mock(IssueAuthorizationIndexer.class);
-  ApplyPermissionsStep step = new ApplyPermissionsStep(indexer);
+  private static final String PROJECT_KEY = "PROJECT_KEY";
+  private static final String PROJECT_UUID = "PROJECT_UUID";
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @ClassRule
+  public static EsTester esTester = new EsTester().addDefinitions(new IssueIndexDefinition(new Settings()));
+
+  @ClassRule
+  public static DbTester dbTester = new DbTester();
+
+  DbSession dbSession;
+
+  DbClient dbClient;
+
+  Settings settings;
+
+  DbComponentsRefCache dbComponentsRefCache;
+
+  IssueAuthorizationIndexer issueAuthorizationIndexer;
+  ApplyPermissionsStep step;
+
+  @Before
+  public void setUp() throws Exception {
+    dbTester.truncateTables();
+    esTester.truncateIndices();
+
+    RoleDao roleDao = new RoleDao();
+    PermissionTemplateDao permissionTemplateDao = new PermissionTemplateDao(dbTester.myBatis(), System2.INSTANCE);
+    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao(), roleDao, permissionTemplateDao);
+    dbSession = dbClient.openSession(false);
+
+    settings = new Settings();
+
+    issueAuthorizationIndexer = new IssueAuthorizationIndexer(dbClient, esTester.client());
+    issueAuthorizationIndexer.setEnabled(true);
+
+    dbComponentsRefCache = new DbComponentsRefCache();
+
+    step = new ApplyPermissionsStep(dbClient, dbComponentsRefCache, issueAuthorizationIndexer, new PermissionFacade(roleDao, null,
+      new ResourceDao(dbTester.myBatis(), System2.INSTANCE), permissionTemplateDao, settings));
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    dbSession.close();
+  }
+
+  @Test
+  public void grant_permission() throws Exception {
+    ComponentDto projectDto = ComponentTesting.newProjectDto(PROJECT_UUID).setKey(PROJECT_KEY);
+    dbClient.componentDao().insert(dbSession, projectDto);
+
+    // Create a permission template containing browse permission for anonymous group
+    PermissionTemplateDto permissionTemplateDto = dbClient.permissionTemplateDao().createPermissionTemplate("Default", null, null);
+    settings.setProperty("sonar.permission.template.default", permissionTemplateDto.getKee());
+    dbClient.permissionTemplateDao().addGroupPermission(permissionTemplateDto.getId(), null, UserRole.USER);
+    dbSession.commit();
+
+    dbComponentsRefCache.addComponent(1, new DbComponentsRefCache.DbComponent(projectDto.getId(), PROJECT_KEY, PROJECT_UUID));
+    Component project = new DumbComponent(Component.Type.PROJECT, 1, PROJECT_KEY, PROJECT_UUID);
+
+    step.execute(new ComputationContext(createDumbBatchReportReader(), null, null, null, ComponentTreeBuilders.from(project), null));
+    dbSession.commit();
+
+    assertThat(dbClient.componentDao().selectByKey(dbSession, PROJECT_KEY).getAuthorizationUpdatedAt()).isNotNull();
+    assertThat(dbClient.roleDao().selectGroupPermissions(dbSession, DefaultGroups.ANYONE, projectDto.getId())).containsOnly(UserRole.USER);
+    List<SearchHit> issueAuthorizationHits = esTester.getDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION);
+    assertThat(issueAuthorizationHits).hasSize(1);
+    Map<String, Object> issueAhutorization = issueAuthorizationHits.get(0).sourceAsMap();
+    assertThat(issueAhutorization.get("project")).isEqualTo(PROJECT_UUID);
+    assertThat((List<String>) issueAhutorization.get("groups")).containsOnly(DefaultGroups.ANYONE);
+    assertThat((List<String>) issueAhutorization.get("users")).isEmpty();
+  }
 
   @Test
-  public void index_issue_permissions() {
-    step.execute(mock(ComputationContext.class));
-    verify(indexer).index();
+  public void nothing_to_do() throws Exception {
+    long authorizationUpdatedAt = 1000L;
+
+    ComponentDto projectDto = ComponentTesting.newProjectDto(PROJECT_UUID).setKey(PROJECT_KEY).setAuthorizationUpdatedAt(authorizationUpdatedAt);
+    dbClient.componentDao().insert(dbSession, projectDto);
+    // Permissions are already set on the project
+    dbClient.roleDao().insertGroupRole(new GroupRoleDto().setRole(UserRole.USER).setGroupId(null).setResourceId(projectDto.getId()), dbSession);
+
+    dbSession.commit();
+
+    dbComponentsRefCache.addComponent(1, new DbComponentsRefCache.DbComponent(projectDto.getId(), PROJECT_KEY, PROJECT_UUID));
+    Component project = new DumbComponent(Component.Type.PROJECT, 1, PROJECT_KEY, PROJECT_UUID);
+
+    step.execute(new ComputationContext(createDumbBatchReportReader(), null, null, null, ComponentTreeBuilders.from(project), null));
+    dbSession.commit();
+
+    // Check that authorization updated at has not been changed -> Nothing has been done
+    assertThat(projectDto.getAuthorizationUpdatedAt()).isEqualTo(authorizationUpdatedAt);
+  }
+
+  private BatchReportReader createDumbBatchReportReader() throws IOException {
+    File dir = temp.newFolder();
+    BatchReportWriter writer = new BatchReportWriter(dir);
+    writer.writeMetadata(BatchReport.Metadata.newBuilder()
+      .build());
+    return new BatchReportReader(dir);
   }
 
   @Override
index 5388cd90eeadee4fd85b9f540bd2b4ca72ed30b9..9477db1ca427b50964bab1ffd41b6a078506132a 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.server.computation.step;
 
 import org.junit.Test;
 import org.sonar.server.computation.ComputationContext;
-import org.sonar.server.issue.index.IssueAuthorizationIndexer;
 import org.sonar.server.issue.index.IssueIndexer;
 
 import static org.mockito.Mockito.mock;
@@ -34,13 +33,11 @@ public class IndexIssuesStepTest {
 
   @Test
   public void call_indexers() {
-    IssueAuthorizationIndexer authorizationIndexer = mock(IssueAuthorizationIndexer.class);
     IssueIndexer issueIndexer = mock(IssueIndexer.class);
-    sut = new IndexIssuesStep(authorizationIndexer, issueIndexer);
+    sut = new IndexIssuesStep(issueIndexer);
 
     sut.execute(mock(ComputationContext.class));
 
-    verify(authorizationIndexer).index();
     verify(issueIndexer).index();
   }
 }
index ac2d768ef1c2081ce61d0eb6bf7de97d28d56106..b4a0c68c6cf400f9ffb91450f899360b1d395ca0 100644 (file)
 package org.sonar.core.permission;
 
 import com.google.common.annotations.VisibleForTesting;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.annotation.Nullable;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.batch.BatchSide;
-import org.sonar.api.server.ServerSide;
 import org.sonar.api.config.Settings;
 import org.sonar.api.security.DefaultGroups;
+import org.sonar.api.server.ServerSide;
 import org.sonar.core.persistence.DbSession;
 import org.sonar.core.resource.ResourceDao;
 import org.sonar.core.resource.ResourceDto;
@@ -35,13 +40,6 @@ import org.sonar.core.user.RoleDao;
 import org.sonar.core.user.UserDao;
 import org.sonar.core.user.UserRoleDto;
 
-import javax.annotation.Nullable;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
 /**
  * This facade wraps db operations related to permissions
  *
@@ -201,9 +199,6 @@ public class PermissionFacade {
 
   public void grantDefaultRoles(DbSession session, Long componentId, String qualifier) {
     ResourceDto resource = resourceDao.getResource(componentId, session);
-    if (resource == null) {
-      throw new IllegalStateException("Unable to find resource with id " + componentId);
-    }
     String applicablePermissionTemplateKey = getApplicablePermissionTemplateKey(session, resource.getKey(), qualifier);
     applyPermissionTemplate(session, applicablePermissionTemplateKey, componentId);
   }
index a3f75efac0bf1f64083563044d653575b0d9a86d..0ccbedaadda614c9ab517c3b5329447ffe596d8e 100644 (file)
@@ -224,8 +224,11 @@ public class DefaultResourcePermissionsTest extends AbstractDaoTestCase {
   }
 
   @Test
-  public void should_fail_when_no_default_template_is_defined() {
+  public void fail_when_no_default_template_is_defined() {
     throwable.expect(IllegalStateException.class);
+    throwable.expectMessage("At least one default permission template should be defined");
+
+    setupData("fail_when_no_default_template_is_defined");
 
     permissions.grantDefaultRoles(project);
   }
diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/fail_when_no_default_template_is_defined.xml b/sonar-core/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/fail_when_no_default_template_is_defined.xml
new file mode 100644 (file)
index 0000000..1fffc1f
--- /dev/null
@@ -0,0 +1,5 @@
+<dataset>
+
+  <projects id="123" kee="project"/>
+
+</dataset>