From c004eacf334304b7a850185fe2cc4d6d521506b0 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Thu, 20 Oct 2016 19:58:55 +0200 Subject: [PATCH] SONAR-8134 merge PermissionRepository into PermissionTemplateService --- .../container/ComputeEngineContainerImpl.java | 2 - .../ComputeEngineContainerImplTest.java | 2 +- .../computation/queue/ReportSubmitter.java | 12 +- .../permission/PermissionTemplateService.java | 129 +++++++++++-- .../platformlevel/PlatformLevel4.java | 2 - .../queue/ReportSubmitterTest.java | 4 +- .../PermissionTemplateServiceTest.java | 33 ++-- .../ws/template/ApplyTemplateActionTest.java | 4 +- .../template/BulkApplyTemplateActionTest.java | 4 +- ...ission_template_by_component_id-result.xml | 0 ...lt_permission_template_by_component_id.xml | 0 ...hould_apply_permission_template-result.xml | 0 .../should_apply_permission_template.xml | 0 .../db/permission/PermissionRepository.java | 179 ------------------ ...ply_default_permission_template-result.xml | 125 ------------ .../apply_default_permission_template.xml | 115 ----------- .../should_count_component_permissions.xml | 26 --- .../should_remove_all_permissions-result.xml | 18 -- .../should_remove_all_permissions.xml | 26 --- ...reateNonAsciiPermissionTemplate-result.xml | 8 - .../createNonAsciiPermissionTemplate.xml | 1 - 21 files changed, 143 insertions(+), 547 deletions(-) rename sonar-db/src/test/java/org/sonar/db/permission/PermissionRepositoryTest.java => server/sonar-server/src/test/java/org/sonar/server/permission/PermissionTemplateServiceTest.java (87%) rename {sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest => server/sonar-server/src/test/resources/org/sonar/server/permission/PermissionTemplateServiceTest}/apply_default_permission_template_by_component_id-result.xml (100%) rename {sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest => server/sonar-server/src/test/resources/org/sonar/server/permission/PermissionTemplateServiceTest}/apply_default_permission_template_by_component_id.xml (100%) rename {sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest => server/sonar-server/src/test/resources/org/sonar/server/permission/PermissionTemplateServiceTest}/should_apply_permission_template-result.xml (100%) rename {sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest => server/sonar-server/src/test/resources/org/sonar/server/permission/PermissionTemplateServiceTest}/should_apply_permission_template.xml (100%) delete mode 100644 sonar-db/src/main/java/org/sonar/db/permission/PermissionRepository.java delete mode 100644 sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/apply_default_permission_template-result.xml delete mode 100644 sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/apply_default_permission_template.xml delete mode 100644 sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/should_count_component_permissions.xml delete mode 100644 sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/should_remove_all_permissions-result.xml delete mode 100644 sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/should_remove_all_permissions.xml delete mode 100644 sonar-db/src/test/resources/org/sonar/db/permission/template/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate-result.xml delete mode 100644 sonar-db/src/test/resources/org/sonar/db/permission/template/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate.xml diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java index b4a72714b08..6b2d0fdf938 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java @@ -61,7 +61,6 @@ import org.sonar.db.DaoModule; import org.sonar.db.DatabaseChecker; import org.sonar.db.DbClient; import org.sonar.db.DefaultDatabase; -import org.sonar.db.permission.PermissionRepository; import org.sonar.db.purge.PurgeProfiler; import org.sonar.db.version.DatabaseVersion; import org.sonar.process.Props; @@ -319,7 +318,6 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer { UserIndex.class, // permissions - PermissionRepository.class, PermissionTemplateService.class, PermissionUpdater.class, UserPermissionChanger.class, diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java index f46233de178..97bab6ac4bb 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java @@ -88,7 +88,7 @@ public class ComputeEngineContainerImplTest { assertThat(picoContainer.getComponentAdapters()) .hasSize( CONTAINER_ITSELF - + 78 // level 4 + + 77 // level 4 + 4 // content of CeConfigurationModule + 3 // content of CeHttpModule + 5 // content of CeQueueModule diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java index b8f448b3cac..81003ce173d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java @@ -21,7 +21,6 @@ package org.sonar.server.computation.queue; import com.google.common.base.Optional; import java.io.InputStream; -import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.commons.lang.StringUtils; import org.sonar.api.resources.Qualifiers; @@ -70,10 +69,12 @@ public class ReportSubmitter { } } - @CheckForNull private ComponentDto createProject(DbSession dbSession, String projectKey, @Nullable String projectBranch, @Nullable String projectName) { - boolean wouldCurrentUserHaveScanPermission = permissionTemplateService.wouldCurrentUserHavePermissionWithDefaultTemplate(dbSession, SCAN_EXECUTION, projectBranch, projectKey, - Qualifiers.PROJECT); + Integer userId = userSession.getUserId(); + Long projectCreatorUserId = userId == null ? null : userId.longValue(); + + boolean wouldCurrentUserHaveScanPermission = permissionTemplateService.wouldUserHavePermissionWithDefaultTemplate( + dbSession, projectCreatorUserId, SCAN_EXECUTION, projectBranch, projectKey, Qualifiers.PROJECT); if (!wouldCurrentUserHaveScanPermission) { throw insufficientPrivilegesException(); } @@ -84,8 +85,7 @@ public class ReportSubmitter { // "provisioning" permission is check in ComponentService ComponentDto project = componentService.create(dbSession, newProject); - Integer currentUserId = userSession.getUserId(); - permissionTemplateService.applyDefault(dbSession, project, currentUserId != null ? currentUserId.longValue() : null); + permissionTemplateService.applyDefault(dbSession, project, projectCreatorUserId); return project; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateService.java b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateService.java index bcfbeea2a04..5bc1ae77693 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateService.java @@ -19,9 +19,16 @@ */ package org.sonar.server.permission; +import java.text.MessageFormat; +import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; import java.util.List; +import java.util.Set; +import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.config.Settings; import org.sonar.api.resources.Qualifiers; import org.sonar.api.server.ServerSide; import org.sonar.core.component.ComponentKeys; @@ -31,12 +38,18 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ResourceDto; -import org.sonar.db.permission.PermissionRepository; +import org.sonar.db.permission.GroupPermissionDto; +import org.sonar.db.permission.UserPermissionDto; +import org.sonar.db.permission.template.PermissionTemplateCharacteristicDto; import org.sonar.db.permission.template.PermissionTemplateDto; +import org.sonar.db.permission.template.PermissionTemplateGroupDto; +import org.sonar.db.permission.template.PermissionTemplateUserDto; import org.sonar.server.permission.index.PermissionIndexer; import org.sonar.server.user.UserSession; +import static com.google.common.base.Preconditions.checkArgument; import static java.util.Arrays.asList; +import static org.sonar.api.security.DefaultGroups.isAnyone; import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentKey; import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; @@ -44,13 +57,13 @@ import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; public class PermissionTemplateService { private final DbClient dbClient; - private final PermissionRepository permissionRepository; + private final Settings settings; private final PermissionIndexer permissionIndexer; private final UserSession userSession; - public PermissionTemplateService(DbClient dbClient, PermissionRepository permissionRepository, PermissionIndexer permissionIndexer, UserSession userSession) { + public PermissionTemplateService(DbClient dbClient, Settings settings, PermissionIndexer permissionIndexer, UserSession userSession) { this.dbClient = dbClient; - this.permissionRepository = permissionRepository; + this.settings = settings; this.permissionIndexer = permissionIndexer; this.userSession = userSession; } @@ -85,20 +98,22 @@ public class PermissionTemplateService { Integer currentUserId = userSession.getUserId(); Long userId = Qualifiers.PROJECT.equals(component.qualifier()) && currentUserId != null ? currentUserId.longValue() : null; - permissionRepository.applyDefaultPermissionTemplate(session, component, userId); - session.commit(); - indexProjectPermissions(session, asList(component.uuid())); + applyDefault(session, component, userId); } - public boolean wouldCurrentUserHavePermissionWithDefaultTemplate(DbSession dbSession, String permission, @Nullable String branch, String projectKey, String qualifier) { + public boolean wouldUserHavePermissionWithDefaultTemplate(DbSession dbSession, @Nullable Long userId, String permission, @Nullable String branch, String projectKey, String qualifier) { if (userSession.hasPermission(permission)) { return true; } String effectiveKey = ComponentKeys.createKey(projectKey, branch); + PermissionTemplateDto template = findDefaultTemplate(dbSession, new ComponentDto().setKey(effectiveKey).setQualifier(qualifier)); + if (template == null) { + return false; + } - Long userId = userSession.getUserId() == null ? null : userSession.getUserId().longValue(); - return permissionRepository.wouldUserHavePermissionWithDefaultTemplate(dbSession, userId, permission, effectiveKey, qualifier); + List potentialPermissions = dbClient.permissionTemplateDao().selectPotentialPermissionsByUserIdAndTemplateId(dbSession, userId, template.getId()); + return potentialPermissions.contains(permission); } /** @@ -112,7 +127,7 @@ public class PermissionTemplateService { } for (ComponentDto project : projects) { - permissionRepository.apply(dbSession, template, project, null); + copyPermissions(dbSession, template, project, null); } dbSession.commit(); indexProjectPermissions(dbSession, projects.stream().map(ComponentDto::uuid).collect(Collectors.toList())); @@ -128,7 +143,9 @@ public class PermissionTemplateService { * benefit from the permissions defined in the template for "project creator". */ public void applyDefault(DbSession dbSession, ComponentDto component, @Nullable Long projectCreatorUserId) { - permissionRepository.applyDefaultPermissionTemplate(dbSession, component, projectCreatorUserId); + PermissionTemplateDto template = findDefaultTemplate(dbSession, component); + checkArgument(template != null, "Can not retrieve default permission template"); + copyPermissions(dbSession, template, component, projectCreatorUserId); dbSession.commit(); indexProjectPermissions(dbSession, asList(component.uuid())); } @@ -136,4 +153,92 @@ public class PermissionTemplateService { private void indexProjectPermissions(DbSession dbSession, List projectUuids) { permissionIndexer.index(dbSession, projectUuids); } + + private void copyPermissions(DbSession dbSession, PermissionTemplateDto template, ComponentDto project, @Nullable Long projectCreatorUserId) { + dbClient.resourceDao().updateAuthorizationDate(project.getId(), dbSession); + dbClient.groupPermissionDao().deleteByRootComponentId(dbSession, project.getId()); + dbClient.userPermissionDao().deleteProjectPermissions(dbSession, project.getId()); + + List usersPermissions = dbClient.permissionTemplateDao().selectUserPermissionsByTemplateId(dbSession, template.getId()); + String organizationUuid = template.getOrganizationUuid(); + usersPermissions + .forEach(up -> { + UserPermissionDto dto = new UserPermissionDto(organizationUuid, up.getPermission(), up.getUserId(), project.getId()); + dbClient.userPermissionDao().insert(dbSession, dto); + }); + + List groupsPermissions = dbClient.permissionTemplateDao().selectGroupPermissionsByTemplateId(dbSession, template.getId()); + groupsPermissions.forEach(gp -> { + GroupPermissionDto dto = new GroupPermissionDto() + .setOrganizationUuid(organizationUuid) + .setGroupId(isAnyone(gp.getGroupName()) ? null : gp.getGroupId()) + .setRole(gp.getPermission()) + .setResourceId(project.getId()); + dbClient.groupPermissionDao().insert(dbSession, dto); + }); + + List characteristics = dbClient.permissionTemplateCharacteristicDao().selectByTemplateIds(dbSession, asList(template.getId())); + if (projectCreatorUserId != null) { + Set permissionsForCurrentUserAlreadyInDb = usersPermissions.stream() + .filter(userPermission -> projectCreatorUserId.equals(userPermission.getUserId())) + .map(PermissionTemplateUserDto::getPermission) + .collect(java.util.stream.Collectors.toSet()); + characteristics.stream() + .filter(PermissionTemplateCharacteristicDto::getWithProjectCreator) + .filter(characteristic -> !permissionsForCurrentUserAlreadyInDb.contains(characteristic.getPermission())) + .forEach(c -> { + UserPermissionDto dto = new UserPermissionDto(organizationUuid, c.getPermission(), projectCreatorUserId, project.getId()); + dbClient.userPermissionDao().insert(dbSession, dto); + }); + } + } + + /** + * Return the permission template for the given component. If no template key pattern match then consider default + * template for the component qualifier. + */ + @CheckForNull + private PermissionTemplateDto findDefaultTemplate(DbSession dbSession, ComponentDto component) { + // FIXME performance issue here, we should not load all templates + List allPermissionTemplates = dbClient.permissionTemplateDao().selectAll(dbSession); + List matchingTemplates = new ArrayList<>(); + for (PermissionTemplateDto permissionTemplateDto : allPermissionTemplates) { + String keyPattern = permissionTemplateDto.getKeyPattern(); + if (StringUtils.isNotBlank(keyPattern) && component.getKey().matches(keyPattern)) { + matchingTemplates.add(permissionTemplateDto); + } + } + checkAtMostOneMatchForComponentKey(component.getKey(), matchingTemplates); + if (matchingTemplates.size() == 1) { + return matchingTemplates.get(0); + } + String qualifierTemplateKey = settings.getString("sonar.permission.template." + component.qualifier() + ".default"); + if (!StringUtils.isBlank(qualifierTemplateKey)) { + return dbClient.permissionTemplateDao().selectByUuid(dbSession, qualifierTemplateKey); + } + + String defaultTemplateKey = settings.getString("sonar.permission.template.default"); + if (StringUtils.isBlank(defaultTemplateKey)) { + throw new IllegalStateException("At least one default permission template should be defined"); + } + return dbClient.permissionTemplateDao().selectByUuid(dbSession, defaultTemplateKey); + } + + private static void checkAtMostOneMatchForComponentKey(String componentKey, List matchingTemplates) { + if (matchingTemplates.size() > 1) { + StringBuilder templatesNames = new StringBuilder(); + for (Iterator it = matchingTemplates.iterator(); it.hasNext();) { + templatesNames.append("\"").append(it.next().getName()).append("\""); + if (it.hasNext()) { + templatesNames.append(", "); + } + } + throw new IllegalStateException(MessageFormat.format( + "The \"{0}\" key matches multiple permission templates: {1}." + + " A system administrator must update these templates so that only one of them matches the key.", + componentKey, + templatesNames.toString())); + } + } + } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index 0de4247ce5f..2847f719297 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -33,7 +33,6 @@ 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; @@ -431,7 +430,6 @@ public class PlatformLevel4 extends PlatformLevel { // permissions PermissionsWsModule.class, - PermissionRepository.class, PermissionTemplateService.class, PermissionUpdater.class, UserPermissionChanger.class, diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java index 645e8928c50..7367d0d2d21 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java @@ -107,7 +107,7 @@ public class ReportSubmitterTest { when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder(TASK_UUID)); ComponentDto createdProject = new ComponentDto().setUuid(PROJECT_UUID).setKey(PROJECT_KEY); when(componentService.create(any(DbSession.class), any(NewComponent.class))).thenReturn(createdProject); - when(permissionTemplateService.wouldCurrentUserHavePermissionWithDefaultTemplate(any(DbSession.class), eq(SCAN_EXECUTION), anyString(), eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) + when(permissionTemplateService.wouldUserHavePermissionWithDefaultTemplate(any(DbSession.class), anyLong(), eq(SCAN_EXECUTION), anyString(), eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) .thenReturn(true); underTest.submit(PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); @@ -134,7 +134,7 @@ public class ReportSubmitterTest { when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder(TASK_UUID)); when(componentService.create(any(DbSession.class), any(NewComponent.class))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setKey(PROJECT_KEY)); - when(permissionTemplateService.wouldCurrentUserHavePermissionWithDefaultTemplate(any(DbSession.class), eq(SCAN_EXECUTION), anyString(), eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) + when(permissionTemplateService.wouldUserHavePermissionWithDefaultTemplate(any(DbSession.class), anyLong(), eq(SCAN_EXECUTION), anyString(), eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) .thenReturn(true); underTest.submit(PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); diff --git a/sonar-db/src/test/java/org/sonar/db/permission/PermissionRepositoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/PermissionTemplateServiceTest.java similarity index 87% rename from sonar-db/src/test/java/org/sonar/db/permission/PermissionRepositoryTest.java rename to server/sonar-server/src/test/java/org/sonar/server/permission/PermissionTemplateServiceTest.java index 0d2b62332d8..acadfff16e4 100644 --- a/sonar-db/src/test/java/org/sonar/db/permission/PermissionRepositoryTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/PermissionTemplateServiceTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.db.permission; +package org.sonar.server.permission; import java.util.List; import javax.annotation.Nullable; @@ -37,15 +37,20 @@ import org.sonar.db.permission.template.PermissionTemplateDbTester; import org.sonar.db.permission.template.PermissionTemplateDto; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; +import org.sonar.server.permission.index.PermissionIndexer; +import org.sonar.server.tester.UserSessionRule; +import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.sonar.core.permission.GlobalPermissions.PROVISIONING; import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; import static org.sonar.db.component.ComponentTesting.newProjectDto; import static org.sonar.db.user.GroupTesting.newGroupDto; -public class PermissionRepositoryTest { + +public class PermissionTemplateServiceTest { private static final String DEFAULT_TEMPLATE = "default_20130101_010203"; private static final ComponentDto PROJECT = newProjectDto().setId(123L).setUuid("THE_PROJECT_UUID"); @@ -59,10 +64,12 @@ public class PermissionRepositoryTest { @Rule public DbTester dbTester = DbTester.create(system2); + private UserSessionRule userSession = UserSessionRule.standalone(); private PermissionTemplateDbTester templateDb = dbTester.permissionTemplates(); private DbSession session = dbTester.getSession(); private Settings settings = new MapSettings(); - private PermissionRepository underTest = new PermissionRepository(dbTester.getDbClient(), settings); + private PermissionIndexer permissionIndexer = mock(PermissionIndexer.class); + private PermissionTemplateService underTest = new PermissionTemplateService(dbTester.getDbClient(), settings, permissionIndexer, userSession); @Before public void setUp() { @@ -79,7 +86,7 @@ public class PermissionRepositoryTest { assertThat(selectProjectPermissionsOfUser(200L, PROJECT)).isEmpty(); PermissionTemplateDto template = dbTester.getDbClient().permissionTemplateDao().selectByUuid(session, "default_20130101_010203"); - underTest.apply(session, template, PROJECT, null); + underTest.apply(session, template, singletonList(PROJECT)); assertThat(selectProjectPermissionsOfGroup("org1", 100L, PROJECT)).containsOnly("admin", "issueadmin"); assertThat(selectProjectPermissionsOfGroup("org1", 101L, PROJECT)).containsOnly("user", "codeviewer"); @@ -100,27 +107,17 @@ public class PermissionRepositoryTest { } @Test - public void apply_default_permission_template_from_component_id() { + public void applyDefaultPermissionTemplate_from_component_key() { dbTester.prepareDbUnit(getClass(), "apply_default_permission_template_by_component_id.xml"); + userSession.setGlobalPermissions(PROVISIONING); settings.setProperty("sonar.permission.template.default", DEFAULT_TEMPLATE); - underTest.applyDefaultPermissionTemplate(session, PROJECT.getId()); + underTest.applyDefaultPermissionTemplate("org.struts:struts"); session.commit(); dbTester.assertDbUnitTable(getClass(), "apply_default_permission_template_by_component_id-result.xml", "user_roles", "user_id", "resource_id", "role"); } - @Test - public void apply_default_permission_template_from_component() { - dbTester.prepareDbUnit(getClass(), "apply_default_permission_template.xml"); - settings.setProperty("sonar.permission.template.default", DEFAULT_TEMPLATE); - - underTest.applyDefaultPermissionTemplate(session, dbTester.getDbClient().componentDao().selectOrFailByKey(session, "org.struts:struts"), 201L); - session.commit(); - - dbTester.assertDbUnitTable(getClass(), "apply_default_permission_template-result.xml", "user_roles", "user_id", "resource_id", "role"); - } - @Test public void would_user_have_permission_with_default_permission_template() { UserDto user = dbTester.users().insertUser(); @@ -164,7 +161,7 @@ public class PermissionRepositoryTest { } private void checkWouldUserHavePermission(@Nullable Long userId, String permission, boolean expectedResult) { - assertThat(underTest.wouldUserHavePermissionWithDefaultTemplate(session, userId, permission, "PROJECT_KEY", Qualifiers.PROJECT)).isEqualTo(expectedResult); + assertThat(underTest.wouldUserHavePermissionWithDefaultTemplate(session, userId, permission, null, "PROJECT_KEY", Qualifiers.PROJECT)).isEqualTo(expectedResult); } private void checkAuthorizationUpdatedAtIsUpdated() { diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/ApplyTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/ApplyTemplateActionTest.java index 8a7fff304a3..27cb72abf97 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/ApplyTemplateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/ApplyTemplateActionTest.java @@ -31,7 +31,6 @@ import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.permission.PermissionQuery; -import org.sonar.db.permission.PermissionRepository; import org.sonar.db.permission.template.PermissionTemplateDto; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; @@ -76,8 +75,7 @@ public class ApplyTemplateActionTest extends BasePermissionWsTest - * Should be removed when batch will no more create permission, and be replaced by a new PermissionService in module server (probably be a merge with InternalPermissionService) - *

- * WARNING, this class is called by Deveveloper Cockpit to apply default permission template on new developers - */ -public class PermissionRepository { - - private final DbClient dbClient; - private final Settings settings; - - public PermissionRepository(DbClient dbClient, Settings settings) { - this.dbClient = dbClient; - this.settings = settings; - } - - public void apply(DbSession session, PermissionTemplateDto template, ComponentDto project, @Nullable Long currentUserId) { - updateProjectAuthorizationDate(session, project.getId()); - dbClient.groupPermissionDao().deleteByRootComponentId(session, project.getId()); - dbClient.userPermissionDao().deleteProjectPermissions(session, project.getId()); - - List usersPermissions = dbClient.permissionTemplateDao().selectUserPermissionsByTemplateId(session, template.getId()); - String organizationUuid = template.getOrganizationUuid(); - usersPermissions - .forEach(up -> { - UserPermissionDto dto = new UserPermissionDto(organizationUuid, up.getPermission(), up.getUserId(), project.getId()); - dbClient.userPermissionDao().insert(session, dto); - }); - - List groupsPermissions = dbClient.permissionTemplateDao().selectGroupPermissionsByTemplateId(session, template.getId()); - groupsPermissions.forEach(gp -> { - GroupPermissionDto dto = new GroupPermissionDto() - .setOrganizationUuid(organizationUuid) - .setGroupId(isAnyone(gp.getGroupName()) ? null : gp.getGroupId()) - .setRole(gp.getPermission()) - .setResourceId(project.getId()); - dbClient.groupPermissionDao().insert(session, dto); - }); - - List characteristics = dbClient.permissionTemplateCharacteristicDao().selectByTemplateIds(session, asList(template.getId())); - if (currentUserId != null) { - Set permissionsForCurrentUserAlreadyInDb = usersPermissions.stream() - .filter(userPermission -> currentUserId.equals(userPermission.getUserId())) - .map(PermissionTemplateUserDto::getPermission) - .collect(Collectors.toSet()); - characteristics.stream() - .filter(PermissionTemplateCharacteristicDto::getWithProjectCreator) - .filter(characteristic -> !permissionsForCurrentUserAlreadyInDb.contains(characteristic.getPermission())) - .forEach(c -> { - UserPermissionDto dto = new UserPermissionDto(organizationUuid, c.getPermission(), currentUserId, project.getId()); - dbClient.userPermissionDao().insert(session, dto); - }); - } - } - - /** - * Warning, this method is also used by the Developer Cockpit plugin - */ - public void applyDefaultPermissionTemplate(DbSession session, long componentId) { - ComponentDto component = dbClient.componentDao().selectOrFailById(session, componentId); - applyDefaultPermissionTemplate(session, component, null); - } - - public void applyDefaultPermissionTemplate(DbSession dbSession, ComponentDto componentDto, @Nullable Long userId) { - PermissionTemplateDto template = getApplicablePermissionTemplate(dbSession, componentDto); - if (template == null) { - throw new IllegalArgumentException("Can not retrieve default permission template"); - } - apply(dbSession, template, componentDto, userId); - } - - /** - * Return the permission template for the given componentKey. If no template key pattern match then consider default - * permission template for the resource qualifier. - */ - @CheckForNull - private PermissionTemplateDto getApplicablePermissionTemplate(DbSession dbSession, ComponentDto component) { - // FIXME performance issue here, we should not load all templates - List allPermissionTemplates = dbClient.permissionTemplateDao().selectAll(dbSession); - List matchingTemplates = new ArrayList<>(); - for (PermissionTemplateDto permissionTemplateDto : allPermissionTemplates) { - String keyPattern = permissionTemplateDto.getKeyPattern(); - if (StringUtils.isNotBlank(keyPattern) && component.getKey().matches(keyPattern)) { - matchingTemplates.add(permissionTemplateDto); - } - } - checkAtMostOneMatchForComponentKey(component.getKey(), matchingTemplates); - if (matchingTemplates.size() == 1) { - return matchingTemplates.get(0); - } - String qualifierTemplateKey = settings.getString("sonar.permission.template." + component.qualifier() + ".default"); - if (!StringUtils.isBlank(qualifierTemplateKey)) { - return dbClient.permissionTemplateDao().selectByUuid(dbSession, qualifierTemplateKey); - } - - String defaultTemplateKey = settings.getString("sonar.permission.template.default"); - if (StringUtils.isBlank(defaultTemplateKey)) { - throw new IllegalStateException("At least one default permission template should be defined"); - } - return dbClient.permissionTemplateDao().selectByUuid(dbSession, defaultTemplateKey); - } - - public boolean wouldUserHavePermissionWithDefaultTemplate(DbSession dbSession, @Nullable Long currentUserId, String permission, String projectKey, String qualifier) { - PermissionTemplateDto template = getApplicablePermissionTemplate(dbSession, new ComponentDto().setKey(projectKey).setQualifier(qualifier)); - if (template == null) { - return false; - } - - List potentialPermissions = dbClient.permissionTemplateDao().selectPotentialPermissionsByUserIdAndTemplateId(dbSession, currentUserId, template.getId()); - return potentialPermissions.contains(permission); - } - - private static void checkAtMostOneMatchForComponentKey(final String componentKey, List matchingTemplates) { - if (matchingTemplates.size() > 1) { - StringBuilder templatesNames = new StringBuilder(); - for (Iterator it = matchingTemplates.iterator(); it.hasNext();) { - templatesNames.append("\"").append(it.next().getName()).append("\""); - if (it.hasNext()) { - templatesNames.append(", "); - } - } - throw new IllegalStateException(MessageFormat.format( - "The \"{0}\" key matches multiple permission templates: {1}." - + " A system administrator must update these templates so that only one of them matches the key.", - componentKey, - templatesNames.toString())); - } - } - - /** - * For each modification of permission on a project, update the authorization_updated_at to help ES reindex only relevant changes - */ - private void updateProjectAuthorizationDate(DbSession dbSession, long projectId) { - dbClient.resourceDao().updateAuthorizationDate(projectId, dbSession); - } -} diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/apply_default_permission_template-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/apply_default_permission_template-result.xml deleted file mode 100644 index 4e6496e31e3..00000000000 --- a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/apply_default_permission_template-result.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/apply_default_permission_template.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/apply_default_permission_template.xml deleted file mode 100644 index 04c60e6a91f..00000000000 --- a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/apply_default_permission_template.xml +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/should_count_component_permissions.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/should_count_component_permissions.xml deleted file mode 100644 index 3c91825413a..00000000000 --- a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/should_count_component_permissions.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/should_remove_all_permissions-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/should_remove_all_permissions-result.xml deleted file mode 100644 index 77964cdc299..00000000000 --- a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/should_remove_all_permissions-result.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/should_remove_all_permissions.xml b/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/should_remove_all_permissions.xml deleted file mode 100644 index 3c91825413a..00000000000 --- a/sonar-db/src/test/resources/org/sonar/db/permission/PermissionRepositoryTest/should_remove_all_permissions.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/template/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate-result.xml b/sonar-db/src/test/resources/org/sonar/db/permission/template/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate-result.xml deleted file mode 100644 index 519de675357..00000000000 --- a/sonar-db/src/test/resources/org/sonar/db/permission/template/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate-result.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/sonar-db/src/test/resources/org/sonar/db/permission/template/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate.xml b/sonar-db/src/test/resources/org/sonar/db/permission/template/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate.xml deleted file mode 100644 index 5ed00ba028b..00000000000 --- a/sonar-db/src/test/resources/org/sonar/db/permission/template/PermissionTemplateDaoTest/createNonAsciiPermissionTemplate.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file -- 2.39.5