Browse Source

SONAR-7747 Check potential permissions when submitting a report

tags/6.0-RC1
Teryk Bellahsene 8 years ago
parent
commit
0ca7748625
22 changed files with 504 additions and 312 deletions
  1. 33
    11
      server/sonar-server/src/main/java/org/sonar/ce/queue/report/ReportSubmitter.java
  2. 9
    16
      server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java
  3. 13
    0
      server/sonar-server/src/main/java/org/sonar/server/permission/PermissionService.java
  4. 26
    14
      server/sonar-server/src/test/java/org/sonar/ce/queue/report/ReportSubmitterTest.java
  5. 0
    12
      server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java
  6. 9
    14
      server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DeleteTemplateActionTest.java
  7. 1
    1
      sonar-db/src/main/java/org/sonar/db/MyBatis.java
  8. 16
    6
      sonar-db/src/main/java/org/sonar/db/permission/PermissionRepository.java
  9. 57
    0
      sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplate.java
  10. 17
    21
      sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java
  11. 0
    34
      sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDto.java
  12. 0
    1
      sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateGroupDto.java
  13. 5
    4
      sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateMapper.java
  14. 0
    1
      sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateUserDto.java
  15. 2
    0
      sonar-db/src/main/java/org/sonar/db/permission/template/PermissionTemplateCharacteristicMapper.java
  16. 57
    71
      sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml
  17. 14
    5
      sonar-db/src/main/resources/org/sonar/db/permission/template/PermissionTemplateCharacteristicMapper.xml
  18. 61
    3
      sonar-db/src/test/java/org/sonar/db/permission/PermissionRepositoryTest.java
  19. 101
    98
      sonar-db/src/test/java/org/sonar/db/permission/PermissionTemplateDaoTest.java
  20. 71
    0
      sonar-db/src/test/java/org/sonar/db/permission/template/PermissionTemplateDbTester.java
  21. 6
    0
      sonar-db/src/test/java/org/sonar/db/user/GroupDbTester.java
  22. 6
    0
      sonar-db/src/test/java/org/sonar/db/user/UserDbTester.java

+ 33
- 11
server/sonar-server/src/main/java/org/sonar/ce/queue/report/ReportSubmitter.java View File

@@ -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);

+ 9
- 16
server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java View File

@@ -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<String, Object> params) {

+ 13
- 0
server/sonar-server/src/main/java/org/sonar/server/permission/PermissionService.java View File

@@ -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
*/

+ 26
- 14
server/sonar-server/src/test/java/org/sonar/ce/queue/report/ReportSubmitterTest.java View File

@@ -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<CeTaskSubmit>() {
@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}"));

+ 0
- 12
server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java View File

@@ -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";

+ 9
- 14
server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/DeleteTemplateActionTest.java View File

@@ -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.<String>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

+ 1
- 1
sonar-db/src/main/java/org/sonar/db/MyBatis.java View File

@@ -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);

+ 16
- 6
sonar-db/src/main/java/org/sonar/db/permission/PermissionRepository.java View File

@@ -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
* <p/>
@@ -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<PermissionTemplateUserDto> usersPermissions = requireNonNull(permissionTemplate.getUsersPermissions());
List<PermissionTemplateUserDto> usersPermissions = permissionTemplate.getUserPermissions();
usersPermissions.forEach(userPermission -> insertUserPermission(componentId, userPermission.getUserId(), userPermission.getPermission(), false, session));

List<PermissionTemplateGroupDto> groupsPermissions = requireNonNull(permissionTemplate.getGroupsPermissions());
List<PermissionTemplateGroupDto> groupsPermissions = permissionTemplate.getGroupPermissions();
groupsPermissions.forEach(groupPermission -> insertGroupPermission(componentId, groupPermission.getGroupId(), groupPermission.getPermission(), false, session));

List<PermissionTemplateCharacteristicDto> characteristics = requireNonNull(permissionTemplate.getCharacteristics());
List<PermissionTemplateCharacteristicDto> characteristics = permissionTemplate.getCharacteristics();
if (currentUserId != null) {
Set<String> 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<String> potentialPermissions = dbClient.permissionTemplateDao().selectPotentialPermissionsByUserIdAndTemplateId(dbSession, currentUserId, template.getId());

return potentialPermissions.contains(permission);
}

private static void checkAtMostOneMatchForComponentKey(final String componentKey, List<PermissionTemplateDto> matchingTemplates) {
if (matchingTemplates.size() > 1) {
StringBuilder templatesNames = new StringBuilder();

+ 57
- 0
sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplate.java View File

@@ -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<PermissionTemplateUserDto> userPermissions;
private final List<PermissionTemplateGroupDto> groupPermissions;
private final List<PermissionTemplateCharacteristicDto> characteristics;

public PermissionTemplate(PermissionTemplateDto template,
List<PermissionTemplateUserDto> userPermissions,
List<PermissionTemplateGroupDto> groupPermissions,
List<PermissionTemplateCharacteristicDto> characteristics) {
this.template = template;
this.userPermissions = userPermissions;
this.groupPermissions = groupPermissions;
this.characteristics = characteristics;
}

public PermissionTemplateDto getTemplate() {
return template;
}

public List<PermissionTemplateUserDto> getUserPermissions() {
return userPermissions;
}

public List<PermissionTemplateGroupDto> getGroupPermissions() {
return groupPermissions;
}

public List<PermissionTemplateCharacteristicDto> getCharacteristics() {
return characteristics;
}
}

+ 17
- 21
sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java View File

@@ -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<PermissionTemplateUserDto> userPermissions = templateWithUserPermissions == null ? emptyList() : templateWithUserPermissions.getUsersPermissions();
template.setUsersPermissions(userPermissions);

PermissionTemplateDto templateWithGroupPermissions = mapper.selectTemplateGroupsPermissions(templateUuid);
List<PermissionTemplateGroupDto> groupPermissions = templateWithGroupPermissions == null ? emptyList() : templateWithGroupPermissions.getGroupsPermissions();
template.setGroupsByPermission(groupPermissions);

PermissionTemplateDto templateWithCharacteristics = mapper.selectTemplateCharacteristics(templateUuid);
List<PermissionTemplateCharacteristicDto> characteristics = templateWithCharacteristics == null ? emptyList() : templateWithCharacteristics.getCharacteristics();
template.setCharacteristics(characteristics);
List<PermissionTemplateUserDto> userPermissions = mapper.selectUserPermissionsByTemplateId(template.getId());
List<PermissionTemplateGroupDto> groupPermissions = mapper.selectGroupPermissionsByTemplateId(template.getId());
PermissionTemplateCharacteristicMapper characteristicMapper = session.getMapper(PermissionTemplateCharacteristicMapper.class);
List<PermissionTemplateCharacteristicDto> 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<String> 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)
*/

+ 0
- 34
sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDto.java View File

@@ -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<PermissionTemplateUserDto> usersPermissions;
private List<PermissionTemplateGroupDto> groupsPermissions;
private List<PermissionTemplateCharacteristicDto> characteristics;
private Date createdAt;
private Date updatedAt;

@@ -108,26 +103,6 @@ public class PermissionTemplateDto {
return this;
}

@CheckForNull
public List<PermissionTemplateUserDto> getUsersPermissions() {
return usersPermissions;
}

public PermissionTemplateDto setUsersPermissions(@Nullable List<PermissionTemplateUserDto> usersPermissions) {
this.usersPermissions = usersPermissions;
return this;
}

@CheckForNull
public List<PermissionTemplateGroupDto> getGroupsPermissions() {
return groupsPermissions;
}

public PermissionTemplateDto setGroupsByPermission(@Nullable List<PermissionTemplateGroupDto> 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<PermissionTemplateCharacteristicDto> getCharacteristics() {
return characteristics;
}

public PermissionTemplateDto setCharacteristics(List<PermissionTemplateCharacteristicDto> characteristics) {
this.characteristics = characteristics;
return this;
}
}

+ 0
- 1
sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateGroupDto.java View File

@@ -23,7 +23,6 @@ import java.util.Date;
import javax.annotation.Nullable;

public class PermissionTemplateGroupDto {

private Long id;
private Long templateId;
private Long groupId;

+ 5
- 4
sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateMapper.java View File

@@ -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<PermissionTemplateUserDto> selectUserPermissionsByTemplateId(long templateId);

PermissionTemplateDto selectTemplateGroupsPermissions(String templateKey);

PermissionTemplateDto selectTemplateCharacteristics(String templateKey);
List<PermissionTemplateGroupDto> selectGroupPermissionsByTemplateId(long templateId);

void insertUserPermission(PermissionTemplateUserDto permissionTemplateUser);

@@ -75,4 +74,6 @@ public interface PermissionTemplateMapper {
void usersCountByTemplateIdAndPermission(Map<String, Object> parameters, ResultHandler resultHandler);

void groupsCountByTemplateIdAndPermission(Map<String, Object> parameters, ResultHandler resultHandler);

List<String> selectPotentialPermissionsByUserIdAndTemplateId(@Param("userId") @Nullable Long currentUserId, @Param("templateId") long templateId);
}

+ 0
- 1
sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateUserDto.java View File

@@ -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;

+ 2
- 0
sonar-db/src/main/java/org/sonar/db/permission/template/PermissionTemplateCharacteristicMapper.java View File

@@ -24,6 +24,8 @@ import java.util.List;
import org.apache.ibatis.annotations.Param;

public interface PermissionTemplateCharacteristicMapper {
List<PermissionTemplateCharacteristicDto> selectByTemplateId(long templateId);

List<PermissionTemplateCharacteristicDto> selectByTemplateIds(@Param("templateIds") List<Long> templateId);

PermissionTemplateCharacteristicDto selectByPermissionAndTemplateId(@Param("permission") String permission, @Param("templateId") long templateId);

+ 57
- 71
sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml View File

@@ -218,55 +218,69 @@
WHERE UPPER(name)=#{templateName}
</select>

<select id="selectTemplateUsersPermissions" parameterType="String" resultMap="fullPermissionsTemplateResult">
SELECT pt.id AS template_id,
pt.name AS template_name,
pt.description AS template_description,
pt.key_pattern AS template_key_pattern,
pt.created_at AS template_created_at,
pt.updated_at AS template_updated_at,
ptu.id AS permission_template_user_id,
ptu.permission_reference AS user_permission,
ptu.user_id AS user_id,
u.name AS user_name,
u.login AS user_login
FROM permission_templates pt
INNER JOIN perm_templates_users ptu ON ptu.template_id = pt.id
<select id="selectUserPermissionsByTemplateId" parameterType="Long" resultType="PermissionTemplateUser">
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>

<select id="selectTemplateGroupsPermissions" parameterType="String" resultMap="fullPermissionsTemplateResult">
SELECT pt.id AS template_id,
pt.name AS template_name,
pt.description AS template_description,
pt.key_pattern AS template_key_pattern,
pt.created_at AS template_created_at,
pt.updated_at AS template_updated_at,
ptg.id AS permission_template_group_id,
ptg.permission_reference AS group_permission,
ptg.group_id AS group_id,
g.name AS group_name
FROM permission_templates pt
INNER JOIN perm_templates_groups ptg ON ptg.template_id = pt.id
LEFT OUTER JOIN groups g ON g.id = ptg.group_id
WHERE pt.kee = #{templateKey}
<select id="selectGroupPermissionsByTemplateId" parameterType="Long" resultType="PermissionTemplateGroup">
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)
</select>

<select id="selectTemplateCharacteristics" parameterType="String" resultMap="fullPermissionsTemplateResult">
SELECT pt.id AS template_id,
pt.name AS template_name,
pt.description AS template_description,
pt.key_pattern AS template_key_pattern,
pt.created_at AS template_created_at,
pt.updated_at AS template_updated_at,
ptc.id AS permission_template_characteristic_id,
ptc.permission_key AS characteristic_permission,
ptc.with_project_creator AS with_project_creator
FROM permission_templates pt
INNER JOIN perm_tpl_characteristics ptc ON ptc.template_id = pt.id
WHERE pt.kee = #{templateKey}
<select id="selectPotentialPermissionsByUserIdAndTemplateId" parameterType="map" resultType="String">
<if test="userId!=null">
-- from template users
select ptu.permission_reference as permission_key
from perm_templates_users ptu
<where>
and ptu.user_id=#{userId}
and ptu.template_id=#{templateId}
</where>
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
<where>
and gu.user_id=#{userId}
and ptg.template_id=#{templateId}
</where>
UNION
-- from template characteristics
select ptc.permission_key as permission_key
from perm_tpl_characteristics ptc
<where>
and with_project_creator = ${_true}
and ptc.template_id = #{templateId}
</where>
UNION
</if>
-- 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
</select>

<select id="usersCountByTemplateIdAndPermission" parameterType="map"
@@ -307,32 +321,4 @@
</where>
GROUP BY groups.permission, groups.templateId
</select>

<resultMap id="fullPermissionsTemplateResult" type="PermissionTemplate">
<id property="id" column="template_id"/>
<result property="name" column="template_name"/>
<result property="description" column="template_description"/>
<result property="keyPattern" column="template_key_pattern"/>
<result property="createdAt" column="template_created_at"/>
<result property="updatedAt" column="template_updated_at"/>
<collection property="usersPermissions" ofType="PermissionTemplateUser">
<id property="id" column="permission_template_user_id"/>
<result property="userId" column="user_id"/>
<result property="permission" column="user_permission"/>
<result property="userName" column="user_name"/>
<result property="userLogin" column="user_login"/>
</collection>
<collection property="groupsPermissions" ofType="PermissionTemplateGroup">
<id property="id" column="permission_template_group_id"/>
<result property="groupId" column="group_id"/>
<result property="permission" column="group_permission"/>
<result property="groupName" column="group_name"/>
</collection>
<collection property="characteristics" ofType="TemplatePermission">
<id property="id" column="permission_template_characteristic_id"/>
<result property="permission" column="characteristic_permission"/>
<result property="withProjectCreator" column="with_project_creator"/>
</collection>
</resultMap>

</mapper>

+ 14
- 5
sonar-db/src/main/resources/org/sonar/db/permission/template/PermissionTemplateCharacteristicMapper.xml View File

@@ -10,7 +10,16 @@
ptc.updated_at as updatedAt
</sql>

<select id="selectByTemplateIds" parameterType="long" resultType="TemplatePermission">
<select id="selectByTemplateId" parameterType="long" resultType="PermissionTemplateCharacteristic">
select
<include refid="columns" />
from perm_tpl_characteristics ptc
where
ptc.template_id = #{templateId}
order by id
</select>

<select id="selectByTemplateIds" parameterType="long" resultType="PermissionTemplateCharacteristic">
select
<include refid="columns" />
from perm_tpl_characteristics ptc
@@ -22,7 +31,7 @@
order by id
</select>

<select id="selectByPermissionAndTemplateId" parameterType="map" resultType="TemplatePermission">
<select id="selectByPermissionAndTemplateId" parameterType="map" resultType="PermissionTemplateCharacteristic">
select
<include refid="columns" />
from perm_tpl_characteristics ptc
@@ -31,19 +40,19 @@
order by id
</select>

<select id="selectById" parameterType="long" resultType="TemplatePermission">
<select id="selectById" parameterType="long" resultType="PermissionTemplateCharacteristic">
select
<include refid="columns" />
from perm_tpl_characteristics ptc
where ptc.id=#{id}
</select>

<insert id="insert" parameterType="TemplatePermission" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
<insert id="insert" parameterType="PermissionTemplateCharacteristic" keyColumn="id" useGeneratedKeys="true" keyProperty="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})
</insert>

<update id="update" parameterType="TemplatePermission" useGeneratedKeys="false">
<update id="update" parameterType="PermissionTemplateCharacteristic" useGeneratedKeys="false">
update perm_tpl_characteristics set
with_project_creator=#{withProjectCreator, jdbcType=BOOLEAN},
updated_at=#{updatedAt, jdbcType=BIGINT}

+ 61
- 3
sonar-db/src/test/java/org/sonar/db/permission/PermissionRepositoryTest.java View File

@@ -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);
}

}

+ 101
- 98
sonar-db/src/test/java/org/sonar/db/permission/PermissionTemplateDaoTest.java View File

@@ -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<PermissionTemplateUserDto> 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<PermissionTemplateGroupDto> 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<CountByTemplateAndPermissionDto> 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<CountByTemplateAndPermissionDto> 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<PermissionTemplateDto> 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<String> 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<String> 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<String> resultWithUser = underTest.selectPotentialPermissionsByUserIdAndTemplateId(dbSession, user.getId(), template.getId());
List<String> 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() {

+ 71
- 0
sonar-db/src/test/java/org/sonar/db/permission/template/PermissionTemplateDbTester.java View File

@@ -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();
}
}

+ 6
- 0
sonar-db/src/test/java/org/sonar/db/user/GroupDbTester.java View File

@@ -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();

+ 6
- 0
sonar-db/src/test/java/org/sonar/db/user/UserDbTester.java View File

@@ -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();

Loading…
Cancel
Save