From 0ca7748625936c6516a4a13c1391cc148027eb5e Mon Sep 17 00:00:00 2001 From: Teryk Bellahsene Date: Thu, 16 Jun 2016 13:52:57 +0200 Subject: [PATCH] SONAR-7747 Check potential permissions when submitting a report --- .../ce/queue/report/ReportSubmitter.java | 44 +++- .../DefaultRubyComponentService.java | 25 +-- .../server/permission/PermissionService.java | 13 ++ .../ce/queue/report/ReportSubmitterTest.java | 40 ++-- .../DefaultRubyComponentServiceTest.java | 12 -- .../ws/template/DeleteTemplateActionTest.java | 23 +- .../src/main/java/org/sonar/db/MyBatis.java | 2 +- .../db/permission/PermissionRepository.java | 22 +- .../db/permission/PermissionTemplate.java | 57 +++++ .../db/permission/PermissionTemplateDao.java | 38 ++-- .../db/permission/PermissionTemplateDto.java | 34 --- .../PermissionTemplateGroupDto.java | 1 - .../permission/PermissionTemplateMapper.java | 9 +- .../permission/PermissionTemplateUserDto.java | 1 - ...ermissionTemplateCharacteristicMapper.java | 2 + .../permission/PermissionTemplateMapper.xml | 128 +++++------ ...PermissionTemplateCharacteristicMapper.xml | 19 +- .../permission/PermissionRepositoryTest.java | 64 +++++- .../permission/PermissionTemplateDaoTest.java | 199 +++++++++--------- .../template/PermissionTemplateDbTester.java | 71 +++++++ .../java/org/sonar/db/user/GroupDbTester.java | 6 + .../java/org/sonar/db/user/UserDbTester.java | 6 + 22 files changed, 504 insertions(+), 312 deletions(-) create mode 100644 sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplate.java create mode 100644 sonar-db/src/test/java/org/sonar/db/permission/template/PermissionTemplateDbTester.java diff --git a/server/sonar-server/src/main/java/org/sonar/ce/queue/report/ReportSubmitter.java b/server/sonar-server/src/main/java/org/sonar/ce/queue/report/ReportSubmitter.java index aa3536f237c..de515bdec77 100644 --- a/server/sonar-server/src/main/java/org/sonar/ce/queue/report/ReportSubmitter.java +++ b/server/sonar-server/src/main/java/org/sonar/ce/queue/report/ReportSubmitter.java @@ -20,14 +20,17 @@ package org.sonar.ce.queue.report; import java.io.InputStream; +import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.commons.lang.StringUtils; -import org.sonar.api.resources.Qualifiers; import org.sonar.api.ce.ComputeEngineSide; +import org.sonar.api.resources.Qualifiers; import org.sonar.ce.queue.CeQueue; import org.sonar.ce.queue.CeTask; import org.sonar.ce.queue.CeTaskSubmit; import org.sonar.core.component.ComponentKeys; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; import org.sonar.db.ce.CeTaskTypes; import org.sonar.db.component.ComponentDto; import org.sonar.server.component.ComponentService; @@ -36,6 +39,7 @@ import org.sonar.server.permission.PermissionService; import org.sonar.server.user.UserSession; import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; +import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; @ComputeEngineSide public class ReportSubmitter { @@ -45,35 +49,53 @@ public class ReportSubmitter { private final ReportFiles reportFiles; private final ComponentService componentService; private final PermissionService permissionService; + private final DbClient dbClient; public ReportSubmitter(CeQueue queue, UserSession userSession, ReportFiles reportFiles, - ComponentService componentService, PermissionService permissionService) { + ComponentService componentService, PermissionService permissionService, DbClient dbClient) { this.queue = queue; this.userSession = userSession; this.reportFiles = reportFiles; this.componentService = componentService; this.permissionService = permissionService; + this.dbClient = dbClient; } public CeTask submit(String projectKey, @Nullable String projectBranch, @Nullable String projectName, InputStream reportInput) { String effectiveProjectKey = ComponentKeys.createKey(projectKey, projectBranch); ComponentDto project = componentService.getNullableByKey(effectiveProjectKey); if (project == null) { - // the project does not exist -> require global permission - userSession.checkPermission(SCAN_EXECUTION); + project = createProject(projectKey, projectBranch, projectName); + } + + userSession.checkComponentPermission(SCAN_EXECUTION, projectKey); + + return submitReport(reportInput, project); + } + + @CheckForNull + private ComponentDto createProject(String projectKey, @Nullable String projectBranch, @Nullable String projectName) { + DbSession dbSession = dbClient.openSession(false); + try { + boolean wouldCurrentUserHaveScanPermission = permissionService.wouldCurrentUserHavePermissionWithDefaultTemplate(dbSession, SCAN_EXECUTION, projectBranch, projectKey, + Qualifiers.PROJECT); + if (!wouldCurrentUserHaveScanPermission) { + throw insufficientPrivilegesException(); + } - // the project does not exist -> requires to provision it NewComponent newProject = new NewComponent(projectKey, StringUtils.defaultIfBlank(projectName, projectKey)); newProject.setBranch(projectBranch); newProject.setQualifier(Qualifiers.PROJECT); - // no need to verify the permission "provisioning" as it's already handled by componentService - project = componentService.create(newProject); - permissionService.applyDefaultPermissionTemplate(project.getKey()); - } else { - // the project exists -> require global or project permission - userSession.checkComponentPermission(SCAN_EXECUTION, projectKey); + // "provisioning" permission is check in ComponentService + ComponentDto project = componentService.create(dbSession, newProject); + permissionService.applyDefaultPermissionTemplate(dbSession, project.getKey()); + return project; + } finally { + dbClient.closeSession(dbSession); } + } + private CeTask submitReport(InputStream reportInput, ComponentDto project) { // the report file must be saved before submitting the task CeTaskSubmit.Builder submit = queue.prepareSubmit(); reportFiles.save(submit.getUuid(), reportInput); diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java b/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java index 3ccfe6e9922..8ed51f62c64 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java @@ -27,14 +27,14 @@ import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.api.component.Component; import org.sonar.api.component.RubyComponentService; -import org.sonar.api.resources.Qualifiers; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ResourceDao; import org.sonar.db.component.ResourceDto; -import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.permission.PermissionService; import org.sonar.server.util.RubyUtils; +import static org.sonar.server.ws.WsUtils.checkRequest; + public class DefaultRubyComponentService implements RubyComponentService { private final ResourceDao resourceDao; @@ -71,20 +71,13 @@ public class DefaultRubyComponentService implements RubyComponentService { @CheckForNull public Long createComponent(String key, @Nullable String branch, String name, @Nullable String qualifier) { - // Sub view should not be created with provisioning. Will be fixed by http://jira.sonarsource.com/browse/VIEWS-296 - if (!Qualifiers.SUBVIEW.equals(qualifier)) { - ComponentDto componentDto = componentService.create(NewComponent.create(key, name).setQualifier(qualifier).setBranch(branch)); - if (componentDto == null) { - throw new BadRequestException(String.format("Component not created: %s", key)); - } - ComponentDto component = (ComponentDto) resourceDao.selectByKey(componentDto.getKey()); - if (component == null) { - throw new BadRequestException(String.format("Component not created: %s", key)); - } - permissionService.applyDefaultPermissionTemplate(component.getKey()); - return component.getId(); - } - return null; + ComponentDto provisionedComponent = componentService.create(NewComponent.create(key, name).setQualifier(qualifier).setBranch(branch)); + checkRequest(provisionedComponent != null, "Component not created: %s", key); + ComponentDto componentInDb = (ComponentDto) resourceDao.selectByKey(provisionedComponent.getKey()); + checkRequest(componentInDb != null, "Component not created: %s", key); + + permissionService.applyDefaultPermissionTemplate(componentInDb.getKey()); + return componentInDb.getId(); } public DefaultComponentQueryResult find(Map params) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionService.java b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionService.java index 03c9c8e5c52..0b8ec5e2059 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionService.java @@ -20,8 +20,10 @@ package org.sonar.server.permission; import java.util.List; +import javax.annotation.Nullable; import org.sonar.api.resources.Qualifiers; import org.sonar.api.server.ServerSide; +import org.sonar.core.component.ComponentKeys; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; @@ -82,6 +84,17 @@ public class PermissionService { indexProjectPermissions(); } + public boolean wouldCurrentUserHavePermissionWithDefaultTemplate(DbSession dbSession, String permission, @Nullable String branch, String projectKey, String qualifier) { + if (userSession.hasPermission(permission)) { + return true; + } + + String effectiveKey = ComponentKeys.createKey(projectKey, branch); + + Long userId = userSession.getUserId() == null ? null : userSession.getUserId().longValue(); + return permissionRepository.wouldUserHavePermissionWithDefaultTemplate(dbSession, userId, permission, effectiveKey, qualifier); + } + /** * Important - this method checks caller permissions */ diff --git a/server/sonar-server/src/test/java/org/sonar/ce/queue/report/ReportSubmitterTest.java b/server/sonar-server/src/test/java/org/sonar/ce/queue/report/ReportSubmitterTest.java index 80ddfdc4f63..c98b751ae2f 100644 --- a/server/sonar-server/src/test/java/org/sonar/ce/queue/report/ReportSubmitterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/ce/queue/report/ReportSubmitterTest.java @@ -25,24 +25,31 @@ import org.hamcrest.TypeSafeMatcher; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.sonar.api.resources.Qualifiers; +import org.sonar.ce.queue.CeQueue; +import org.sonar.ce.queue.CeQueueImpl; +import org.sonar.ce.queue.CeTaskSubmit; import org.sonar.core.permission.GlobalPermissions; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; import org.sonar.db.ce.CeTaskTypes; import org.sonar.db.component.ComponentDto; import org.sonar.server.component.ComponentService; import org.sonar.server.component.NewComponent; -import org.sonar.ce.queue.CeQueue; -import org.sonar.ce.queue.CeQueueImpl; -import org.sonar.ce.queue.CeTaskSubmit; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.permission.PermissionService; import org.sonar.server.tester.UserSessionRule; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.argThat; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; +import static org.sonar.core.permission.GlobalPermissions.PROVISIONING; +import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; public class ReportSubmitterTest { @@ -61,11 +68,12 @@ public class ReportSubmitterTest { ReportFiles reportFiles = mock(ReportFiles.class); ComponentService componentService = mock(ComponentService.class); PermissionService permissionService = mock(PermissionService.class); - ReportSubmitter underTest = new ReportSubmitter(queue, userSession, reportFiles, componentService, permissionService); + DbClient dbClient = mock(DbClient.class); + ReportSubmitter underTest = new ReportSubmitter(queue, userSession, reportFiles, componentService, permissionService, dbClient); @Test public void submit_a_report_on_existing_project() { - userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); + userSession.setGlobalPermissions(SCAN_EXECUTION); when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder(TASK_UUID)); when(componentService.getNullableByKey(PROJECT_KEY)).thenReturn(new ComponentDto().setUuid(PROJECT_UUID)); @@ -89,15 +97,17 @@ public class ReportSubmitterTest { @Test public void provision_project_if_does_not_exist() throws Exception { - userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.PROVISIONING); + userSession.setGlobalPermissions(SCAN_EXECUTION, PROVISIONING); when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder(TASK_UUID)); when(componentService.getNullableByKey(PROJECT_KEY)).thenReturn(null); - when(componentService.create(any(NewComponent.class))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setKey(PROJECT_KEY)); + when(componentService.create(any(DbSession.class), any(NewComponent.class))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setKey(PROJECT_KEY)); + when(permissionService.wouldCurrentUserHavePermissionWithDefaultTemplate(any(DbSession.class), eq(SCAN_EXECUTION), anyString(), eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) + .thenReturn(true); underTest.submit(PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); - verify(permissionService).applyDefaultPermissionTemplate(PROJECT_KEY); + verify(permissionService).applyDefaultPermissionTemplate(any(DbSession.class), eq(PROJECT_KEY)); verify(queue).submit(argThat(new TypeSafeMatcher() { @Override protected boolean matchesSafely(CeTaskSubmit submit) { @@ -114,11 +124,13 @@ public class ReportSubmitterTest { @Test public void submit_a_report_on_new_project_with_global_scan_permission() { - userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); + userSession.setGlobalPermissions(SCAN_EXECUTION, PROVISIONING); when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder(TASK_UUID)); when(componentService.getNullableByKey(PROJECT_KEY)).thenReturn(null); - when(componentService.create(any(NewComponent.class))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setKey(PROJECT_KEY)); + when(componentService.create(any(DbSession.class), any(NewComponent.class))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setKey(PROJECT_KEY)); + when(permissionService.wouldCurrentUserHavePermissionWithDefaultTemplate(any(DbSession.class), eq(SCAN_EXECUTION), anyString(), eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) + .thenReturn(true); underTest.submit(PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); @@ -127,7 +139,7 @@ public class ReportSubmitterTest { @Test public void submit_a_report_on_existing_project_with_global_scan_permission() { - userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); + userSession.setGlobalPermissions(SCAN_EXECUTION); when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder(TASK_UUID)); when(componentService.getNullableByKey(PROJECT_KEY)).thenReturn(new ComponentDto().setUuid(PROJECT_UUID)); @@ -139,7 +151,7 @@ public class ReportSubmitterTest { @Test public void submit_a_report_on_existing_project_with_project_scan_permission() { - userSession.addProjectPermissions(GlobalPermissions.SCAN_EXECUTION, PROJECT_KEY); + userSession.addProjectPermissions(SCAN_EXECUTION, PROJECT_KEY); when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder(TASK_UUID)); when(componentService.getNullableByKey(PROJECT_KEY)).thenReturn(new ComponentDto().setUuid(PROJECT_UUID)); @@ -159,11 +171,11 @@ public class ReportSubmitterTest { @Test public void fail_with_forbidden_exception_on_new_project_when_only_project_scan_permission() { - userSession.addProjectPermissions(GlobalPermissions.SCAN_EXECUTION, PROJECT_KEY); + userSession.addProjectPermissions(SCAN_EXECUTION, PROJECT_KEY); when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder(TASK_UUID)); when(componentService.getNullableByKey(PROJECT_KEY)).thenReturn(null); - when(componentService.create(any(NewComponent.class))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setKey(PROJECT_KEY)); + when(componentService.create(any(DbSession.class), any(NewComponent.class))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setKey(PROJECT_KEY)); thrown.expect(ForbiddenException.class); underTest.submit(PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java index c7eab81818c..2dc8a1ff88c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java @@ -38,9 +38,7 @@ import static com.google.common.collect.Maps.newHashMap; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyListOf; -import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -104,16 +102,6 @@ public class DefaultRubyComponentServiceTest { verify(permissionService).applyDefaultPermissionTemplate(componentKey); } - @Test - public void not_create_component_on_sub_views() { - when(resourceDao.selectByKey(anyString())).thenReturn(ComponentTesting.newProjectDto()); - - service.createComponent("new-project", "New Project", Qualifiers.SUBVIEW); - - verify(componentService, never()).create(any(NewComponent.class)); - verify(permissionService, never()).applyDefaultPermissionTemplate(anyString()); - } - @Test(expected = BadRequestException.class) public void should_throw_exception_if_create_fails() { String componentKey = "new-project"; diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DeleteTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DeleteTemplateActionTest.java index e0fc453cf1d..2b36c654f13 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DeleteTemplateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DeleteTemplateActionTest.java @@ -19,15 +19,6 @@ */ package org.sonar.server.permission.ws.template; -import static com.google.common.primitives.Longs.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.mockito.internal.util.collections.Sets.newSet; -import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto; -import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID; -import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME; - import java.util.Collections; import java.util.Date; import javax.annotation.Nullable; @@ -62,6 +53,15 @@ import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.TestResponse; import org.sonar.server.ws.WsActionTester; +import static com.google.common.primitives.Longs.asList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.internal.util.collections.Sets.newSet; +import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto; +import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID; +import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME; + public class DeleteTemplateActionTest { static final String TEMPLATE_UUID = "permission-template-uuid"; @@ -91,12 +91,7 @@ public class DeleteTemplateActionTest { when(defaultTemplatePermissionFinder.getDefaultTemplateUuids()).thenReturn(Collections.emptySet()); PermissionDependenciesFinder finder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient), new UserGroupFinder(dbClient), resourceTypes); ws = new WsActionTester(new DeleteTemplateAction(dbClient, userSession, finder, defaultTemplatePermissionFinder)); - permissionTemplate = insertTemplateAndAssociatedPermissions(newPermissionTemplateDto().setUuid(TEMPLATE_UUID)); - PermissionTemplateDto permissionTemplateInDatabase = dbClient.permissionTemplateDao().selectByUuidWithUserAndGroupPermissions(dbSession, TEMPLATE_UUID); - assertThat(permissionTemplateInDatabase.getUuid()).isEqualTo(TEMPLATE_UUID); - assertThat(permissionTemplateInDatabase.getGroupsPermissions()).isNotEmpty(); - assertThat(permissionTemplateInDatabase.getUsersPermissions()).isNotEmpty(); } @Test diff --git a/sonar-db/src/main/java/org/sonar/db/MyBatis.java b/sonar-db/src/main/java/org/sonar/db/MyBatis.java index ad0a84f0ae3..73593e1b4c7 100644 --- a/sonar-db/src/main/java/org/sonar/db/MyBatis.java +++ b/sonar-db/src/main/java/org/sonar/db/MyBatis.java @@ -196,9 +196,9 @@ public class MyBatis { confBuilder.loadAlias("PermissionTemplate", PermissionTemplateDto.class); confBuilder.loadAlias("PermissionTemplateUser", PermissionTemplateUserDto.class); confBuilder.loadAlias("PermissionTemplateGroup", PermissionTemplateGroupDto.class); + confBuilder.loadAlias("PermissionTemplateCharacteristic", PermissionTemplateCharacteristicDto.class); confBuilder.loadAlias("UserWithPermission", UserWithPermissionDto.class); confBuilder.loadAlias("GroupWithPermission", GroupWithPermissionDto.class); - confBuilder.loadAlias("TemplatePermission", PermissionTemplateCharacteristicDto.class); confBuilder.loadAlias("QualityProfile", QualityProfileDto.class); confBuilder.loadAlias("ActiveRule", ActiveRuleDto.class); confBuilder.loadAlias("ActiveRuleParam", ActiveRuleParamDto.class); diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionRepository.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionRepository.java index 7e0361a3588..9b16a3cd84a 100644 --- a/sonar-db/src/main/java/org/sonar/db/permission/PermissionRepository.java +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionRepository.java @@ -37,8 +37,6 @@ import org.sonar.db.user.GroupDto; import org.sonar.db.user.GroupRoleDto; import org.sonar.db.user.UserRoleDto; -import static java.util.Objects.requireNonNull; - /** * This facade wraps db operations related to permissions *

@@ -146,17 +144,17 @@ public class PermissionRepository { } private void applyPermissionTemplate(DbSession session, String templateUuid, long componentId, @Nullable Long currentUserId) { - PermissionTemplateDto permissionTemplate = dbClient.permissionTemplateDao().selectPermissionTemplateWithPermissions(session, templateUuid); + PermissionTemplate permissionTemplate = dbClient.permissionTemplateDao().selectPermissionTemplateWithPermissions(session, templateUuid); updateProjectAuthorizationDate(session, componentId); dbClient.roleDao().removeAllPermissions(session, componentId); - List usersPermissions = requireNonNull(permissionTemplate.getUsersPermissions()); + List usersPermissions = permissionTemplate.getUserPermissions(); usersPermissions.forEach(userPermission -> insertUserPermission(componentId, userPermission.getUserId(), userPermission.getPermission(), false, session)); - List groupsPermissions = requireNonNull(permissionTemplate.getGroupsPermissions()); + List groupsPermissions = permissionTemplate.getGroupPermissions(); groupsPermissions.forEach(groupPermission -> insertGroupPermission(componentId, groupPermission.getGroupId(), groupPermission.getPermission(), false, session)); - List characteristics = requireNonNull(permissionTemplate.getCharacteristics()); + List characteristics = permissionTemplate.getCharacteristics(); if (currentUserId != null) { Set permissionsForCurrentUserAlreadyInDb = usersPermissions.stream() .filter(userPermission -> currentUserId.equals(userPermission.getUserId())) @@ -211,6 +209,18 @@ public class PermissionRepository { return defaultTemplateKey; } + public boolean wouldUserHavePermissionWithDefaultTemplate(DbSession dbSession, @Nullable Long currentUserId, String permission, String projectKey, String qualifier) { + String templateUuid = getApplicablePermissionTemplateKey(dbSession, projectKey, qualifier); + PermissionTemplateDto template = dbClient.permissionTemplateDao().selectByUuid(dbSession, templateUuid); + 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(); diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplate.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplate.java new file mode 100644 index 00000000000..79d920829c3 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplate.java @@ -0,0 +1,57 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * 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; + +import java.util.List; +import org.sonar.db.permission.template.PermissionTemplateCharacteristicDto; + +public class PermissionTemplate { + private final PermissionTemplateDto template; + private final List userPermissions; + private final List groupPermissions; + private final List characteristics; + + public PermissionTemplate(PermissionTemplateDto template, + List userPermissions, + List groupPermissions, + List characteristics) { + this.template = template; + this.userPermissions = userPermissions; + this.groupPermissions = groupPermissions; + this.characteristics = characteristics; + } + + public PermissionTemplateDto getTemplate() { + return template; + } + + public List getUserPermissions() { + return userPermissions; + } + + public List getGroupPermissions() { + return groupPermissions; + } + + public List getCharacteristics() { + return characteristics; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java index d327cee447c..f128410c8ae 100644 --- a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java @@ -41,7 +41,6 @@ import org.sonar.db.permission.template.PermissionTemplateCharacteristicMapper; import static com.google.common.collect.Maps.newHashMap; import static java.lang.String.format; -import static java.util.Collections.emptyList; import static org.sonar.db.DatabaseUtils.executeLargeInputsWithoutOutput; public class PermissionTemplateDao implements Dao { @@ -156,31 +155,24 @@ public class PermissionTemplateDao implements Dao { } @CheckForNull - public PermissionTemplateDto selectByUuidWithUserAndGroupPermissions(DbSession session, String templateUuid) { - PermissionTemplateDto template; + public PermissionTemplate selectByUuidWithUserAndGroupPermissions(DbSession session, String templateUuid) { PermissionTemplateMapper mapper = mapper(session); - template = mapper.selectByUuid(templateUuid); + + PermissionTemplateDto template = mapper.selectByUuid(templateUuid); if (template == null) { return null; } - PermissionTemplateDto templateWithUserPermissions = mapper.selectTemplateUsersPermissions(templateUuid); - List userPermissions = templateWithUserPermissions == null ? emptyList() : templateWithUserPermissions.getUsersPermissions(); - template.setUsersPermissions(userPermissions); - - PermissionTemplateDto templateWithGroupPermissions = mapper.selectTemplateGroupsPermissions(templateUuid); - List groupPermissions = templateWithGroupPermissions == null ? emptyList() : templateWithGroupPermissions.getGroupsPermissions(); - template.setGroupsByPermission(groupPermissions); - - PermissionTemplateDto templateWithCharacteristics = mapper.selectTemplateCharacteristics(templateUuid); - List characteristics = templateWithCharacteristics == null ? emptyList() : templateWithCharacteristics.getCharacteristics(); - template.setCharacteristics(characteristics); + List userPermissions = mapper.selectUserPermissionsByTemplateId(template.getId()); + List groupPermissions = mapper.selectGroupPermissionsByTemplateId(template.getId()); + PermissionTemplateCharacteristicMapper characteristicMapper = session.getMapper(PermissionTemplateCharacteristicMapper.class); + List characteristics = characteristicMapper.selectByTemplateId(template.getId()); - return template; + return new PermissionTemplate(template, userPermissions, groupPermissions, characteristics); } @CheckForNull - public PermissionTemplateDto selectByUuidWithUserAndGroupPermissions(String templateUuid) { + public PermissionTemplate selectByUuidWithUserAndGroupPermissions(String templateUuid) { DbSession session = myBatis.openSession(false); try { return selectByUuidWithUserAndGroupPermissions(session, templateUuid); @@ -396,22 +388,26 @@ public class PermissionTemplateDao implements Dao { /** * Load permission template and load associated collections of users and groups permissions, and characteristics */ - PermissionTemplateDto selectPermissionTemplateWithPermissions(DbSession session, String templateUuid) { + PermissionTemplate selectPermissionTemplateWithPermissions(DbSession session, String templateUuid) { PermissionTemplateDto template = selectByUuid(session, templateUuid); if (template == null) { throw new IllegalArgumentException("Could not retrieve permission template with uuid " + templateUuid); } - PermissionTemplateDto templateWithPermissions = selectByUuidWithUserAndGroupPermissions(session, template.getUuid()); - if (templateWithPermissions == null) { + PermissionTemplate templateWithDependencies = selectByUuidWithUserAndGroupPermissions(session, template.getUuid()); + if (templateWithDependencies == null) { throw new IllegalArgumentException("Could not retrieve permissions for template with uuid " + templateUuid); } - return templateWithPermissions; + return templateWithDependencies; } public PermissionTemplateDto selectByName(DbSession dbSession, String name) { return mapper(dbSession).selectByName(name.toUpperCase(Locale.ENGLISH)); } + public List selectPotentialPermissionsByUserIdAndTemplateId(DbSession dbSession, @Nullable Long currentUserId, long templateId) { + return mapper(dbSession).selectPotentialPermissionsByUserIdAndTemplateId(currentUserId, templateId); + } + /** * Remove a group from all templates (used when removing a group) */ diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDto.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDto.java index e268ffa0075..9ee2dea126a 100644 --- a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDto.java +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDto.java @@ -20,10 +20,8 @@ package org.sonar.db.permission; import java.util.Date; -import java.util.List; import javax.annotation.CheckForNull; import javax.annotation.Nullable; -import org.sonar.db.permission.template.PermissionTemplateCharacteristicDto; public class PermissionTemplateDto { @@ -32,9 +30,6 @@ public class PermissionTemplateDto { private String uuid; private String description; private String keyPattern; - private List usersPermissions; - private List groupsPermissions; - private List characteristics; private Date createdAt; private Date updatedAt; @@ -108,26 +103,6 @@ public class PermissionTemplateDto { return this; } - @CheckForNull - public List getUsersPermissions() { - return usersPermissions; - } - - public PermissionTemplateDto setUsersPermissions(@Nullable List usersPermissions) { - this.usersPermissions = usersPermissions; - return this; - } - - @CheckForNull - public List getGroupsPermissions() { - return groupsPermissions; - } - - public PermissionTemplateDto setGroupsByPermission(@Nullable List groupsPermissions) { - this.groupsPermissions = groupsPermissions; - return this; - } - public Date getCreatedAt() { return createdAt; } @@ -145,13 +120,4 @@ public class PermissionTemplateDto { this.updatedAt = updatedAt; return this; } - - public List getCharacteristics() { - return characteristics; - } - - public PermissionTemplateDto setCharacteristics(List characteristics) { - this.characteristics = characteristics; - return this; - } } diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateGroupDto.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateGroupDto.java index b4e95a457cc..65a820b27b6 100644 --- a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateGroupDto.java +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateGroupDto.java @@ -23,7 +23,6 @@ import java.util.Date; import javax.annotation.Nullable; public class PermissionTemplateGroupDto { - private Long id; private Long templateId; private Long groupId; diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateMapper.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateMapper.java index 1551cef2adb..442b6a91977 100644 --- a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateMapper.java @@ -21,6 +21,7 @@ package org.sonar.db.permission; import java.util.List; import java.util.Map; +import javax.annotation.Nullable; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; @@ -46,11 +47,9 @@ public interface PermissionTemplateMapper { PermissionTemplateDto selectByUuid(String templateUuid); - PermissionTemplateDto selectTemplateUsersPermissions(String templateKey); + List selectUserPermissionsByTemplateId(long templateId); - PermissionTemplateDto selectTemplateGroupsPermissions(String templateKey); - - PermissionTemplateDto selectTemplateCharacteristics(String templateKey); + List selectGroupPermissionsByTemplateId(long templateId); void insertUserPermission(PermissionTemplateUserDto permissionTemplateUser); @@ -75,4 +74,6 @@ public interface PermissionTemplateMapper { void usersCountByTemplateIdAndPermission(Map parameters, ResultHandler resultHandler); void groupsCountByTemplateIdAndPermission(Map parameters, ResultHandler resultHandler); + + List selectPotentialPermissionsByUserIdAndTemplateId(@Param("userId") @Nullable Long currentUserId, @Param("templateId") long templateId); } diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateUserDto.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateUserDto.java index 56403fb0995..20ace57a148 100644 --- a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateUserDto.java +++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateUserDto.java @@ -22,7 +22,6 @@ package org.sonar.db.permission; import java.util.Date; public class PermissionTemplateUserDto { - private Long id; private Long templateId; private Long userId; diff --git a/sonar-db/src/main/java/org/sonar/db/permission/template/PermissionTemplateCharacteristicMapper.java b/sonar-db/src/main/java/org/sonar/db/permission/template/PermissionTemplateCharacteristicMapper.java index 4cd80559984..00a30ee2147 100644 --- a/sonar-db/src/main/java/org/sonar/db/permission/template/PermissionTemplateCharacteristicMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/permission/template/PermissionTemplateCharacteristicMapper.java @@ -24,6 +24,8 @@ import java.util.List; import org.apache.ibatis.annotations.Param; public interface PermissionTemplateCharacteristicMapper { + List selectByTemplateId(long templateId); + List selectByTemplateIds(@Param("templateIds") List templateId); PermissionTemplateCharacteristicDto selectByPermissionAndTemplateId(@Param("permission") String permission, @Param("templateId") long templateId); diff --git a/sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml b/sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml index f84b0231441..e6f609e7977 100644 --- a/sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml +++ b/sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml @@ -218,55 +218,69 @@ WHERE UPPER(name)=#{templateName} - + SELECT + ptu.id, + ptu.template_id as templateId, + ptu.permission_reference AS permission, + ptu.user_id AS userId, + u.name AS userName, + u.login AS userLogin, + ptu.created_at AS createdAt, + ptu.updated_at AS updatedAt + FROM perm_templates_users ptu INNER JOIN users u ON u.id = ptu.user_id AND u.active = ${_true} - WHERE pt.kee = #{templateKey} + WHERE ptu.template_id = #{templateId} - + SELECT + ptg.id, + ptg.template_id as templateId, + ptg.permission_reference AS permission, + ptg.group_id AS groupId, + g.name AS groupName, + ptg.created_at as createdAt, + ptg.updated_at as updatedAt + FROM perm_templates_groups ptg + LEFT OUTER JOIN groups g ON g.id=ptg.group_id + WHERE ptg.template_id=#{templateId} AND (g.name IS NOT NULL OR ptg.group_id IS NULL) - + + -- from template users + select ptu.permission_reference as permission_key + from perm_templates_users ptu + + and ptu.user_id=#{userId} + and ptu.template_id=#{templateId} + + UNION + -- from template groups except anyone group + select ptg.permission_reference as permission_key + from perm_templates_groups ptg + inner join groups_users gu on ptg.group_id = gu.group_id + + and gu.user_id=#{userId} + and ptg.template_id=#{templateId} + + UNION + -- from template characteristics + select ptc.permission_key as permission_key + from perm_tpl_characteristics ptc + + and with_project_creator = ${_true} + and ptc.template_id = #{templateId} + + UNION + + -- from anyone group + select ptg.permission_reference as permission_key + from perm_templates_groups ptg + where ptg.template_id=#{templateId} + and ptg.group_id IS NULL - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sonar-db/src/main/resources/org/sonar/db/permission/template/PermissionTemplateCharacteristicMapper.xml b/sonar-db/src/main/resources/org/sonar/db/permission/template/PermissionTemplateCharacteristicMapper.xml index 59834cca7ad..309bf5d989f 100644 --- a/sonar-db/src/main/resources/org/sonar/db/permission/template/PermissionTemplateCharacteristicMapper.xml +++ b/sonar-db/src/main/resources/org/sonar/db/permission/template/PermissionTemplateCharacteristicMapper.xml @@ -10,7 +10,16 @@ ptc.updated_at as updatedAt - + select + + from perm_tpl_characteristics ptc + where + ptc.template_id = #{templateId} + order by id + + + - select from perm_tpl_characteristics ptc @@ -31,19 +40,19 @@ order by id - select from perm_tpl_characteristics ptc where ptc.id=#{id} - + insert into perm_tpl_characteristics(template_id, permission_key, with_project_creator, created_at, updated_at) values(#{templateId, jdbcType=BIGINT}, #{permission, jdbcType=VARCHAR}, #{withProjectCreator, jdbcType=BOOLEAN}, #{createdAt, jdbcType=BIGINT}, #{updatedAt, jdbcType=BIGINT}) - + update perm_tpl_characteristics set with_project_creator=#{withProjectCreator, jdbcType=BOOLEAN}, updated_at=#{updatedAt, jdbcType=BIGINT} diff --git a/sonar-db/src/test/java/org/sonar/db/permission/PermissionRepositoryTest.java b/sonar-db/src/test/java/org/sonar/db/permission/PermissionRepositoryTest.java index bd307d7be18..1a1b37cd1ca 100644 --- a/sonar-db/src/test/java/org/sonar/db/permission/PermissionRepositoryTest.java +++ b/sonar-db/src/test/java/org/sonar/db/permission/PermissionRepositoryTest.java @@ -19,21 +19,29 @@ */ package org.sonar.db.permission; +import javax.annotation.Nullable; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.config.Settings; +import org.sonar.api.resources.Qualifiers; import org.sonar.api.utils.System2; import org.sonar.api.web.UserRole; +import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import org.sonar.db.permission.template.PermissionTemplateDbTester; +import org.sonar.db.user.GroupDbTester; +import org.sonar.db.user.GroupDto; import org.sonar.db.user.RoleDao; +import org.sonar.db.user.UserDbTester; +import org.sonar.db.user.UserDto; 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.SCAN_EXECUTION; public class PermissionRepositoryTest { @@ -48,6 +56,10 @@ public class PermissionRepositoryTest { @Rule public DbTester dbTester = DbTester.create(system2); + GroupDbTester groupDb = new GroupDbTester(dbTester); + UserDbTester userDb = new UserDbTester(dbTester); + PermissionTemplateDbTester templateDb = new PermissionTemplateDbTester(dbTester); + DbClient dbClient = dbTester.getDbClient(); DbSession session = dbTester.getSession(); Settings settings = new Settings(); @@ -183,12 +195,58 @@ public class PermissionRepositoryTest { dbTester.assertDbUnitTable(getClass(), "should_delete_group_permission-result.xml", "projects", "authorization_updated_at"); } + @Test + public void would_user_have_permission_with_default_permission_template() { + UserDto user = userDb.insertUser(); + GroupDto group = groupDb.insertGroup(); + groupDb.addUserToGroup(user.getId(), group.getId()); + PermissionTemplateDto template = templateDb.insertTemplate(); + setDefaultTemplateUuid(template.getUuid()); + templateDb.addProjectCreatorToTemplate(template.getId(), SCAN_EXECUTION); + templateDb.addUserToTemplate(template.getId(), user.getId(), UserRole.USER); + templateDb.addGroupToTemplate(template.getId(), group.getId(), UserRole.CODEVIEWER); + templateDb.addGroupToTemplate(template.getId(), null, UserRole.ISSUE_ADMIN); + + // authenticated user + checkWouldUserHavePermission(user.getId(), UserRole.ADMIN, false); + checkWouldUserHavePermission(user.getId(), SCAN_EXECUTION, true); + checkWouldUserHavePermission(user.getId(), UserRole.USER, true); + checkWouldUserHavePermission(user.getId(), UserRole.CODEVIEWER, true); + checkWouldUserHavePermission(user.getId(), UserRole.ISSUE_ADMIN, true); + + // anonymous user + checkWouldUserHavePermission(null, UserRole.ADMIN, false); + checkWouldUserHavePermission(null, SCAN_EXECUTION, false); + checkWouldUserHavePermission(null, UserRole.USER, false); + checkWouldUserHavePermission(null, UserRole.CODEVIEWER, false); + checkWouldUserHavePermission(null, UserRole.ISSUE_ADMIN, true); + } + + @Test + public void would_user_have_permission_with_unknown_default_permission_template() { + setDefaultTemplateUuid("UNKNOWN_TEMPLATE_UUID"); + + checkWouldUserHavePermission(null, UserRole.ADMIN, false); + } + + @Test + public void would_user_have_permission_with_empty_template() { + PermissionTemplateDto template = templateDb.insertTemplate(); + setDefaultTemplateUuid(template.getUuid()); + + checkWouldUserHavePermission(null, UserRole.ADMIN, false); + } + + private void checkWouldUserHavePermission(@Nullable Long userId, String permission, boolean expectedResult) { + assertThat(underTest.wouldUserHavePermissionWithDefaultTemplate(session, userId, permission, "PROJECT_KEY", Qualifiers.PROJECT)).isEqualTo(expectedResult); + } + private void checkAuthorizationUpdatedAtIsUpdated() { assertThat(dbTester.getDbClient().resourceDao().selectResource(PROJECT_ID, session).getAuthorizationUpdatedAt()).isEqualTo(NOW); } - private void checkAuthorizationUpdatedAtIsNotUpdated() { - assertThat(dbTester.getDbClient().resourceDao().selectResource(PROJECT_ID, session).getAuthorizationUpdatedAt()).isNull(); + private void setDefaultTemplateUuid(String templateUuid) { + settings.setProperty("sonar.permission.template.default", templateUuid); } } diff --git a/sonar-db/src/test/java/org/sonar/db/permission/PermissionTemplateDaoTest.java b/sonar-db/src/test/java/org/sonar/db/permission/PermissionTemplateDaoTest.java index a51fe643ccd..82e96308022 100644 --- a/sonar-db/src/test/java/org/sonar/db/permission/PermissionTemplateDaoTest.java +++ b/sonar-db/src/test/java/org/sonar/db/permission/PermissionTemplateDaoTest.java @@ -25,7 +25,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; -import javax.annotation.Nullable; import org.apache.ibatis.session.ResultContext; import org.apache.ibatis.session.ResultHandler; import org.junit.Rule; @@ -37,6 +36,7 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.permission.template.PermissionTemplateCharacteristicDto; +import org.sonar.db.permission.template.PermissionTemplateDbTester; import org.sonar.db.user.GroupDbTester; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDbTester; @@ -50,10 +50,8 @@ 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.api.web.UserRole.USER; -import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateCharacteristicDto; +import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto; -import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateGroupDto; -import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateUserDto; import static org.sonar.db.user.GroupTesting.newGroupDto; import static org.sonar.db.user.UserTesting.newUserDto; @@ -69,6 +67,7 @@ public class PermissionTemplateDaoTest { DbSession dbSession = db.getSession(); GroupDbTester groupDb = new GroupDbTester(db); UserDbTester userDb = new UserDbTester(db); + PermissionTemplateDbTester templateDb = new PermissionTemplateDbTester(db); PermissionTemplateDao underTest = new PermissionTemplateDao(db.myBatis(), system); @@ -93,21 +92,24 @@ public class PermissionTemplateDaoTest { public void should_select_permission_template() { db.prepareDbUnit(getClass(), "selectPermissionTemplate.xml"); - PermissionTemplateDto permissionTemplate = underTest.selectByUuidWithUserAndGroupPermissions("my_template_20130102_030405"); - - assertThat(permissionTemplate).isNotNull(); - assertThat(permissionTemplate.getName()).isEqualTo("my template"); - assertThat(permissionTemplate.getUuid()).isEqualTo("my_template_20130102_030405"); - assertThat(permissionTemplate.getDescription()).isEqualTo("my description"); - assertThat(permissionTemplate.getUsersPermissions()).hasSize(3); - assertThat(permissionTemplate.getUsersPermissions()).extracting("userId").containsOnly(1L, 2L, 1L); - assertThat(permissionTemplate.getUsersPermissions()).extracting("userLogin").containsOnly("login1", "login2", "login2"); - assertThat(permissionTemplate.getUsersPermissions()).extracting("userName").containsOnly("user1", "user2", "user2"); - assertThat(permissionTemplate.getUsersPermissions()).extracting("permission").containsOnly("user_permission1", "user_permission1", "user_permission2"); - assertThat(permissionTemplate.getGroupsPermissions()).hasSize(3); - assertThat(permissionTemplate.getGroupsPermissions()).extracting("groupId").containsOnly(1L, 2L, null); - assertThat(permissionTemplate.getGroupsPermissions()).extracting("groupName").containsOnly("group1", "group2", null); - assertThat(permissionTemplate.getGroupsPermissions()).extracting("permission").containsOnly("group_permission1", "group_permission1", "group_permission2"); + PermissionTemplate result = underTest.selectByUuidWithUserAndGroupPermissions("my_template_20130102_030405"); + + assertThat(result).isNotNull(); + PermissionTemplateDto template = result.getTemplate(); + assertThat(template.getName()).isEqualTo("my template"); + assertThat(template.getUuid()).isEqualTo("my_template_20130102_030405"); + assertThat(template.getDescription()).isEqualTo("my description"); + List usersPermissions = result.getUserPermissions(); + assertThat(usersPermissions).hasSize(3); + assertThat(usersPermissions).extracting("userId").containsOnly(1L, 2L, 1L); + assertThat(usersPermissions).extracting("userLogin").containsOnly("login1", "login2", "login2"); + assertThat(usersPermissions).extracting("userName").containsOnly("user1", "user2", "user2"); + assertThat(usersPermissions).extracting("permission").containsOnly("user_permission1", "user_permission1", "user_permission2"); + List groupsPermissions = result.getGroupPermissions(); + assertThat(groupsPermissions).hasSize(3); + assertThat(groupsPermissions).extracting("groupId").containsOnly(1L, 2L, null); + assertThat(groupsPermissions).extracting("groupName").containsOnly("group1", "group2", null); + assertThat(groupsPermissions).extracting("permission").containsOnly("group_permission1", "group_permission1", "group_permission2"); } @Test @@ -225,19 +227,20 @@ public class PermissionTemplateDaoTest { public void new_permission_template_with_empty_user_group_characteristics() { PermissionTemplateDto template = underTest.insert(dbSession, newPermissionTemplateDto().setUuid("TEMPLATE_UUID")); - PermissionTemplateDto result = underTest.selectByUuidWithUserAndGroupPermissions(dbSession, "TEMPLATE_UUID"); + PermissionTemplate result = underTest.selectByUuidWithUserAndGroupPermissions(dbSession, "TEMPLATE_UUID"); - assertThat(result).extracting(PermissionTemplateDto::getId, PermissionTemplateDto::getUuid, PermissionTemplateDto::getName, PermissionTemplateDto::getDescription) + assertThat(result.getTemplate()) + .extracting(PermissionTemplateDto::getId, PermissionTemplateDto::getUuid, PermissionTemplateDto::getName, PermissionTemplateDto::getDescription) .containsExactly(template.getId(), template.getUuid(), template.getName(), template.getDescription()); - assertThat(result.getUsersPermissions()).isEmpty(); - assertThat(result.getGroupsPermissions()).isEmpty(); + assertThat(result.getUserPermissions()).isEmpty(); + assertThat(result.getGroupPermissions()).isEmpty(); assertThat(result.getCharacteristics()).isEmpty(); } @Test public void unknown_permission_template() { - PermissionTemplateDto result = underTest.selectByUuidWithUserAndGroupPermissions(dbSession, "UNKNOWN_TEMPLATE_UUID"); + PermissionTemplate result = underTest.selectByUuidWithUserAndGroupPermissions(dbSession, "UNKNOWN_TEMPLATE_UUID"); assertThat(result).isNull(); } @@ -245,32 +248,23 @@ public class PermissionTemplateDaoTest { @Test public void permission_template_with_user_group_and_characteristics() { PermissionTemplateDto template = dbClient.permissionTemplateDao().insert(dbSession, newPermissionTemplateDto().setUuid("TEMPLATE_UUID")); - PermissionTemplateCharacteristicDto characteristic = dbClient.permissionTemplateCharacteristicDao().insert(dbSession, newPermissionTemplateCharacteristicDto() - .setTemplateId(template.getId()) - .setPermission(UserRole.USER) - .setWithProjectCreator(true)); GroupDto group = groupDb.insertGroup(newGroupDto()); - PermissionTemplateGroupDto groupTemplate = newPermissionTemplateGroupDto() - .setTemplateId(template.getId()) - .setGroupId(group.getId()) - .setPermission(UserRole.ADMIN); - underTest.insertGroupPermission(dbSession, groupTemplate); UserDto user = userDb.insertUser(newUserDto()); - underTest.insertUserPermission(dbSession, newPermissionTemplateUserDto() - .setTemplateId(template.getId()) - .setPermission(UserRole.CODEVIEWER) - .setUserId(user.getId())); - db.commit(); - - PermissionTemplateDto result = underTest.selectByUuidWithUserAndGroupPermissions(dbSession, "TEMPLATE_UUID"); - assertThat(result).isEqualToIgnoringNullFields(template); + templateDb.addGroupToTemplate(template.getId(), group.getId(), UserRole.ADMIN); + templateDb.addUserToTemplate(template.getId(), user.getId(), UserRole.CODEVIEWER); + templateDb.addProjectCreatorToTemplate(template.getId(), UserRole.USER); + + PermissionTemplate result = underTest.selectByUuidWithUserAndGroupPermissions(dbSession, "TEMPLATE_UUID"); + assertThat(result.getTemplate()) + .extracting(PermissionTemplateDto::getId, PermissionTemplateDto::getUuid, PermissionTemplateDto::getName, PermissionTemplateDto::getDescription) + .containsExactly(template.getId(), template.getUuid(), template.getName(), template.getDescription()); assertThat(result.getCharacteristics()).hasSize(1) - .extracting(PermissionTemplateCharacteristicDto::getId, PermissionTemplateCharacteristicDto::getPermission, PermissionTemplateCharacteristicDto::getWithProjectCreator) - .containsExactly(tuple(characteristic.getId(), UserRole.USER, true)); - assertThat(result.getGroupsPermissions()).hasSize(1) + .extracting(PermissionTemplateCharacteristicDto::getPermission, PermissionTemplateCharacteristicDto::getWithProjectCreator) + .containsExactly(tuple(UserRole.USER, true)); + assertThat(result.getGroupPermissions()).hasSize(1) .extracting(PermissionTemplateGroupDto::getGroupId, PermissionTemplateGroupDto::getGroupName, PermissionTemplateGroupDto::getPermission) .containsExactly(tuple(group.getId(), group.getName(), UserRole.ADMIN)); - assertThat(result.getUsersPermissions()).hasSize(1) + assertThat(result.getUserPermissions()).hasSize(1) .extracting(PermissionTemplateUserDto::getUserId, PermissionTemplateUserDto::getUserLogin, PermissionTemplateUserDto::getPermission) .containsExactly(tuple(user.getId(), user.getLogin(), UserRole.CODEVIEWER)); } @@ -284,23 +278,21 @@ public class PermissionTemplateDaoTest { @Test public void group_count_by_template_and_permission() { - PermissionTemplateDto template1 = insertTemplate(newPermissionTemplateDto()); - PermissionTemplateDto template2 = insertTemplate(newPermissionTemplateDto()); - PermissionTemplateDto template3 = insertTemplate(newPermissionTemplateDto()); - - GroupDto group1 = insertGroup(newGroupDto()); - GroupDto group2 = insertGroup(newGroupDto()); - GroupDto group3 = insertGroup(newGroupDto()); - - addGroupToTemplate(42L, group1.getId(), ISSUE_ADMIN); - addGroupToTemplate(template1.getId(), group1.getId(), CODEVIEWER); - addGroupToTemplate(template1.getId(), group2.getId(), CODEVIEWER); - addGroupToTemplate(template1.getId(), group3.getId(), CODEVIEWER); - addGroupToTemplate(template1.getId(), null, CODEVIEWER); - addGroupToTemplate(template1.getId(), group1.getId(), ADMIN); - addGroupToTemplate(template2.getId(), group1.getId(), ADMIN); - - commit(); + PermissionTemplateDto template1 = templateDb.insertTemplate(); + PermissionTemplateDto template2 = templateDb.insertTemplate(); + PermissionTemplateDto template3 = templateDb.insertTemplate(); + + GroupDto group1 = groupDb.insertGroup(); + GroupDto group2 = groupDb.insertGroup(); + GroupDto group3 = groupDb.insertGroup(); + + templateDb.addGroupToTemplate(42L, group1.getId(), ISSUE_ADMIN); + templateDb.addGroupToTemplate(template1.getId(), group1.getId(), CODEVIEWER); + templateDb.addGroupToTemplate(template1.getId(), group2.getId(), CODEVIEWER); + templateDb.addGroupToTemplate(template1.getId(), group3.getId(), CODEVIEWER); + templateDb.addGroupToTemplate(template1.getId(), null, CODEVIEWER); + templateDb.addGroupToTemplate(template1.getId(), group1.getId(), ADMIN); + templateDb.addGroupToTemplate(template2.getId(), group1.getId(), ADMIN); final List result = new ArrayList<>(); underTest.groupsCountByTemplateIdAndPermission(dbSession, Arrays.asList(template1.getId(), template2.getId(), template3.getId()), new ResultHandler() { @@ -318,42 +310,34 @@ public class PermissionTemplateDaoTest { @Test public void user_count_by_template_and_permission() { - PermissionTemplateDto template1 = insertTemplate(newPermissionTemplateDto()); - PermissionTemplateDto template2 = insertTemplate(newPermissionTemplateDto()); - PermissionTemplateDto template3 = insertTemplate(newPermissionTemplateDto()); + PermissionTemplateDto template1 = templateDb.insertTemplate(); + PermissionTemplateDto template2 = templateDb.insertTemplate(); + PermissionTemplateDto template3 = templateDb.insertTemplate(); - UserDto user1 = insertUser(newUserDto()); - UserDto user2 = insertUser(newUserDto()); - UserDto user3 = insertUser(newUserDto()); + UserDto user1 = userDb.insertUser(); + UserDto user2 = userDb.insertUser(); + UserDto user3 = userDb.insertUser(); - addUserToTemplate(42L, user1.getId(), ISSUE_ADMIN); - addUserToTemplate(template1.getId(), user1.getId(), ADMIN); - addUserToTemplate(template1.getId(), user2.getId(), ADMIN); - addUserToTemplate(template1.getId(), user3.getId(), ADMIN); - addUserToTemplate(template1.getId(), user1.getId(), USER); - addUserToTemplate(template2.getId(), user1.getId(), USER); - - commit(); + templateDb.addUserToTemplate(42L, user1.getId(), ISSUE_ADMIN); + templateDb.addUserToTemplate(template1.getId(), user1.getId(), ADMIN); + templateDb.addUserToTemplate(template1.getId(), user2.getId(), ADMIN); + templateDb.addUserToTemplate(template1.getId(), user3.getId(), ADMIN); + templateDb.addUserToTemplate(template1.getId(), user1.getId(), USER); + templateDb.addUserToTemplate(template2.getId(), user1.getId(), USER); final List result = new ArrayList<>(); - underTest.usersCountByTemplateIdAndPermission(dbSession, Arrays.asList(template1.getId(), template2.getId(), template3.getId()), new ResultHandler() { - @Override - public void handleResult(ResultContext context) { - result.add((CountByTemplateAndPermissionDto) context.getResultObject()); - } - }); + underTest.usersCountByTemplateIdAndPermission(dbSession, Arrays.asList(template1.getId(), template2.getId(), template3.getId()), + context -> result.add((CountByTemplateAndPermissionDto) context.getResultObject())); assertThat(result).hasSize(3); assertThat(result).extracting("permission").containsOnly(ADMIN, USER); assertThat(result).extracting("templateId").containsOnly(template1.getId(), template2.getId()); assertThat(result).extracting("count").containsOnly(3, 1); - } @Test public void select_by_name_query_and_pagination() { - insertTemplate(newPermissionTemplateDto().setName("aaabbb")); - insertTemplate(newPermissionTemplateDto().setName("aaaccc")); - commit(); + templateDb.insertTemplate(newPermissionTemplateDto().setName("aaabbb")); + templateDb.insertTemplate(newPermissionTemplateDto().setName("aaaccc")); List templates = underTest.selectAll(dbSession, "aaa"); int count = underTest.countAll(dbSession, "aaa"); @@ -362,24 +346,43 @@ public class PermissionTemplateDaoTest { assertThat(count).isEqualTo(2); } - private PermissionTemplateDto insertTemplate(PermissionTemplateDto template) { - return dbClient.permissionTemplateDao().insert(dbSession, template); - } + @Test + public void selectPotentialPermissions_with_unknown_template_and_no_user() { + List result = underTest.selectPotentialPermissionsByUserIdAndTemplateId(dbSession, null, 42L); - private GroupDto insertGroup(GroupDto groupDto) { - return dbClient.groupDao().insert(dbSession, groupDto); + assertThat(result).isEmpty(); } - private UserDto insertUser(UserDto userDto) { - return dbClient.userDao().insert(dbSession, userDto.setActive(true)); - } + @Test + public void selectPotentialPermissions_with_empty_template_and_new_user() { + UserDto user = userDb.insertUser(); + PermissionTemplateDto template = templateDb.insertTemplate(); + + List result = underTest.selectPotentialPermissionsByUserIdAndTemplateId(dbSession, user.getId(), template.getId()); - private void addGroupToTemplate(long templateId, @Nullable Long groupId, String permission) { - dbClient.permissionTemplateDao().insertGroupPermission(dbSession, templateId, groupId, permission); + assertThat(result).isEmpty(); } - private void addUserToTemplate(long templateId, long userId, String permission) { - dbClient.permissionTemplateDao().insertUserPermission(dbSession, templateId, userId, permission); + @Test + public void selectPotentialPermission_with_template_users_groups_and_project_creator() { + UserDto user = userDb.insertUser(); + GroupDto group = groupDb.insertGroup(); + groupDb.addUserToGroup(user.getId(), group.getId()); + PermissionTemplateDto template = templateDb.insertTemplate(); + templateDb.addProjectCreatorToTemplate(template.getId(), SCAN_EXECUTION); + templateDb.addProjectCreatorToTemplate(template.getId(), UserRole.ADMIN); + templateDb.addUserToTemplate(template.getId(), user.getId(), UserRole.USER); + templateDb.addUserToTemplate(template.getId(), user.getId(), UserRole.ADMIN); + templateDb.addGroupToTemplate(template.getId(), group.getId(), UserRole.CODEVIEWER); + templateDb.addGroupToTemplate(template.getId(), group.getId(), UserRole.ADMIN); + templateDb.addGroupToTemplate(template.getId(), null, UserRole.ISSUE_ADMIN); + + List resultWithUser = underTest.selectPotentialPermissionsByUserIdAndTemplateId(dbSession, user.getId(), template.getId()); + List resultWithoutUser = underTest.selectPotentialPermissionsByUserIdAndTemplateId(dbSession, null, template.getId()); + + assertThat(resultWithUser).containsOnlyOnce(SCAN_EXECUTION, UserRole.ADMIN, UserRole.USER, UserRole.CODEVIEWER, UserRole.ISSUE_ADMIN); + // only permission from anyone group + assertThat(resultWithoutUser).containsOnly(UserRole.ISSUE_ADMIN); } private void commit() { diff --git a/sonar-db/src/test/java/org/sonar/db/permission/template/PermissionTemplateDbTester.java b/sonar-db/src/test/java/org/sonar/db/permission/template/PermissionTemplateDbTester.java new file mode 100644 index 00000000000..a1e4c380db2 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/permission/template/PermissionTemplateDbTester.java @@ -0,0 +1,71 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * 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.template; + +import javax.annotation.Nullable; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; +import org.sonar.db.permission.PermissionTemplateDto; + +import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateCharacteristicDto; +import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto; + +public class PermissionTemplateDbTester { + private final DbTester db; + private final DbClient dbClient; + private final DbSession dbSession; + + public PermissionTemplateDbTester(DbTester db) { + this.db = db; + this.dbClient = db.getDbClient(); + this.dbSession = db.getSession(); + } + + public PermissionTemplateDto insertTemplate() { + return insertTemplate(newPermissionTemplateDto()); + } + + public PermissionTemplateDto insertTemplate(PermissionTemplateDto template) { + PermissionTemplateDto templateInDb = dbClient.permissionTemplateDao().insert(dbSession, template); + db.commit(); + + return templateInDb; + } + + public void addGroupToTemplate(long templateId, @Nullable Long groupId, String permission) { + dbClient.permissionTemplateDao().insertGroupPermission(dbSession, templateId, groupId, permission); + db.commit(); + } + + public void addUserToTemplate(long templateId, long userId, String permission) { + dbClient.permissionTemplateDao().insertUserPermission(dbSession, templateId, userId, permission); + db.commit(); + } + + public void addProjectCreatorToTemplate(long templateId, String permission) { + dbClient.permissionTemplateCharacteristicDao().insert(dbSession, newPermissionTemplateCharacteristicDto() + .setWithProjectCreator(true) + .setTemplateId(templateId) + .setPermission(permission)); + db.commit(); + } +} diff --git a/sonar-db/src/test/java/org/sonar/db/user/GroupDbTester.java b/sonar-db/src/test/java/org/sonar/db/user/GroupDbTester.java index d3a77ab6501..94a9007e405 100644 --- a/sonar-db/src/test/java/org/sonar/db/user/GroupDbTester.java +++ b/sonar-db/src/test/java/org/sonar/db/user/GroupDbTester.java @@ -24,6 +24,8 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import static org.sonar.db.user.GroupTesting.newGroupDto; + public class GroupDbTester { private final DbTester db; private final DbClient dbClient; @@ -35,6 +37,10 @@ public class GroupDbTester { this.dbSession = db.getSession(); } + public GroupDto insertGroup() { + return insertGroup(newGroupDto()); + } + public GroupDto insertGroup(GroupDto groupDto) { GroupDto updatedGroup = dbClient.groupDao().insert(dbSession, groupDto); db.commit(); diff --git a/sonar-db/src/test/java/org/sonar/db/user/UserDbTester.java b/sonar-db/src/test/java/org/sonar/db/user/UserDbTester.java index 3de592f2ae0..7d976a6a41c 100644 --- a/sonar-db/src/test/java/org/sonar/db/user/UserDbTester.java +++ b/sonar-db/src/test/java/org/sonar/db/user/UserDbTester.java @@ -23,6 +23,8 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import static org.sonar.db.user.UserTesting.newUserDto; + public class UserDbTester { private final DbTester db; private final DbClient dbClient; @@ -34,6 +36,10 @@ public class UserDbTester { this.dbSession = db.getSession(); } + public UserDto insertUser() { + return insertUser(newUserDto()); + } + public UserDto insertUser(UserDto userDto) { UserDto updatedUser = dbClient.userDao().insert(dbSession, userDto); db.commit(); -- 2.39.5