From: Julien Lancelot Date: Mon, 1 Jun 2015 08:51:30 +0000 (+0200) Subject: SONAR-6259 Grant project permission on the compute engine X-Git-Tag: 5.2-RC1~1761 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=95d5833985ba0755053fd9408e0a7aeda010b8d9;p=sonarqube.git SONAR-6259 Grant project permission on the compute engine --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ApplyPermissionsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ApplyPermissionsStep.java index 022ee3eb068..2a9f886e680 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ApplyPermissionsStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ApplyPermissionsStep.java @@ -20,25 +20,50 @@ 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"; } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/IndexIssuesStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/IndexIssuesStep.java index e1caae311ef..fc8af3c9d6f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/IndexIssuesStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/IndexIssuesStep.java @@ -21,22 +21,18 @@ 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(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ApplyPermissionsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ApplyPermissionsStepTest.java index 09a793d5641..8aa76fad30f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ApplyPermissionsStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ApplyPermissionsStepTest.java @@ -19,22 +19,155 @@ */ 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 issueAuthorizationHits = esTester.getDocuments(IssueIndexDefinition.INDEX, IssueIndexDefinition.TYPE_AUTHORIZATION); + assertThat(issueAuthorizationHits).hasSize(1); + Map issueAhutorization = issueAuthorizationHits.get(0).sourceAsMap(); + assertThat(issueAhutorization.get("project")).isEqualTo(PROJECT_UUID); + assertThat((List) issueAhutorization.get("groups")).containsOnly(DefaultGroups.ANYONE); + assertThat((List) 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 diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexIssuesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexIssuesStepTest.java index 5388cd90eea..9477db1ca42 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexIssuesStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexIssuesStepTest.java @@ -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(); } } diff --git a/sonar-core/src/main/java/org/sonar/core/permission/PermissionFacade.java b/sonar-core/src/main/java/org/sonar/core/permission/PermissionFacade.java index ac2d768ef1c..b4a0c68c6cf 100644 --- a/sonar-core/src/main/java/org/sonar/core/permission/PermissionFacade.java +++ b/sonar-core/src/main/java/org/sonar/core/permission/PermissionFacade.java @@ -21,11 +21,16 @@ 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); } diff --git a/sonar-core/src/test/java/org/sonar/core/resource/DefaultResourcePermissionsTest.java b/sonar-core/src/test/java/org/sonar/core/resource/DefaultResourcePermissionsTest.java index a3f75efac0b..0ccbedaadda 100644 --- a/sonar-core/src/test/java/org/sonar/core/resource/DefaultResourcePermissionsTest.java +++ b/sonar-core/src/test/java/org/sonar/core/resource/DefaultResourcePermissionsTest.java @@ -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 index 00000000000..1fffc1facb2 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/resource/DefaultResourcePermissionsTest/fail_when_no_default_template_is_defined.xml @@ -0,0 +1,5 @@ + + + + +