From 0cdd471479b9243b0e18d754c03d66aa139f6349 Mon Sep 17 00:00:00 2001 From: Teryk Bellahsene Date: Thu, 17 Mar 2016 18:17:38 +0100 Subject: [PATCH] SONAR-7106 WS api/permissions/bulk_apply_template bulk apply permission template --- .../server/permission/PermissionService.java | 27 +- .../permission/ws/PermissionsWsModule.java | 2 + .../ws/template/BulkApplyTemplateAction.java | 134 ++++++++ .../ws/PermissionsWsModuleTest.java | 2 +- .../template/BulkApplyTemplateActionTest.java | 285 ++++++++++++++++++ .../sonar/db/component/ComponentQuery.java | 2 +- .../sonar/db/component/ComponentMapper.xml | 16 +- .../sonar/db/component/ComponentDaoTest.java | 8 +- .../BulkApplyTemplateWsRequest.java | 71 +++++ 9 files changed, 521 insertions(+), 26 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/BulkApplyTemplateAction.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/BulkApplyTemplateActionTest.java create mode 100644 sonar-ws/src/main/java/org/sonarqube/ws/client/permission/BulkApplyTemplateWsRequest.java 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 e0698ee5d69..882e16aa568 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 @@ -85,20 +85,25 @@ public class PermissionService { public void applyPermissionTemplate(ApplyPermissionTemplateQuery query) { DbSession dbSession = dbClient.openSession(false); try { - if (query.getComponentKeys().size() == 1) { - checkProjectAdminUserByComponentKey(userSession, query.getComponentKeys().get(0)); - } else { - checkGlobalAdminUser(userSession); - } - - for (String componentKey : query.getComponentKeys()) { - ComponentDto component = componentFinder.getByKey(dbSession, componentKey); - permissionRepository.applyPermissionTemplate(dbSession, query.getTemplateUuid(), component.getId()); - } - dbSession.commit(); + applyPermissionTemplate(dbSession, query); } finally { dbClient.closeSession(dbSession); } + } + + public void applyPermissionTemplate(DbSession dbSession, ApplyPermissionTemplateQuery query) { + if (query.getComponentKeys().size() == 1) { + checkProjectAdminUserByComponentKey(userSession, query.getComponentKeys().get(0)); + } else { + checkGlobalAdminUser(userSession); + } + + // TODO apply permission templates in on query instead of on on each project + for (String componentKey : query.getComponentKeys()) { + ComponentDto component = componentFinder.getByKey(dbSession, componentKey); + permissionRepository.applyPermissionTemplate(dbSession, query.getTemplateUuid(), component.getId()); + } + dbSession.commit(); indexProjectPermissions(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java index ea98a083d1f..1f30fd0875f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java @@ -23,6 +23,7 @@ import org.sonar.core.platform.Module; import org.sonar.server.permission.ws.template.AddGroupToTemplateAction; import org.sonar.server.permission.ws.template.AddUserToTemplateAction; import org.sonar.server.permission.ws.template.ApplyTemplateAction; +import org.sonar.server.permission.ws.template.BulkApplyTemplateAction; import org.sonar.server.permission.ws.template.CreateTemplateAction; import org.sonar.server.permission.ws.template.DefaultPermissionTemplateFinder; import org.sonar.server.permission.ws.template.RemoveGroupFromTemplateAction; @@ -58,6 +59,7 @@ public class PermissionsWsModule extends Module { SearchTemplatesAction.class, TemplateUsersAction.class, TemplateGroupsAction.class, + BulkApplyTemplateAction.class, // utility classes PermissionChangeBuilder.class, SearchProjectPermissionsDataLoader.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/BulkApplyTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/BulkApplyTemplateAction.java new file mode 100644 index 00000000000..702bf50eb0f --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/BulkApplyTemplateAction.java @@ -0,0 +1,134 @@ +/* + * 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.server.permission.ws.template; + +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import java.util.List; +import javax.annotation.Nullable; +import org.sonar.api.i18n.I18n; +import org.sonar.api.resources.ResourceTypes; +import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.Response; +import org.sonar.api.server.ws.WebService; +import org.sonar.api.server.ws.WebService.Param; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.ComponentDtoFunctions; +import org.sonar.db.component.ComponentQuery; +import org.sonar.db.permission.PermissionTemplateDto; +import org.sonar.server.permission.ApplyPermissionTemplateQuery; +import org.sonar.server.permission.PermissionService; +import org.sonar.server.permission.ws.PermissionDependenciesFinder; +import org.sonar.server.permission.ws.PermissionsWsAction; +import org.sonar.server.user.UserSession; +import org.sonarqube.ws.client.permission.BulkApplyTemplateWsRequest; + +import static org.sonar.server.component.ResourceTypeFunctions.RESOURCE_TYPE_TO_QUALIFIER; +import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createTemplateParameters; +import static org.sonar.server.permission.ws.WsTemplateRef.newTemplateRef; +import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext; +import static org.sonar.server.ws.WsParameterBuilder.createRootQualifierParameter; +import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER; +import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID; +import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME; + +public class BulkApplyTemplateAction implements PermissionsWsAction { + private final DbClient dbClient; + private final PermissionService permissionService; + private final PermissionDependenciesFinder finder; + private final UserSession userSession; + private final I18n i18n; + private final ResourceTypes resourceTypes; + + public BulkApplyTemplateAction(DbClient dbClient, PermissionService permissionService, PermissionDependenciesFinder finder, UserSession userSession, I18n i18n, + ResourceTypes resourceTypes) { + this.dbClient = dbClient; + this.permissionService = permissionService; + this.finder = finder; + this.userSession = userSession; + this.i18n = i18n; + this.resourceTypes = resourceTypes; + } + + @Override + public void define(WebService.NewController context) { + WebService.NewAction action = context.createAction("bulk_apply_template") + .setDescription("Apply a permission template to several projects.
" + + "The template id or name must be provided.
" + + "It requires administration permissions to access.") + .setPost(true) + .setSince("5.5") + .setHandler(this); + + action.createParam(Param.TEXT_QUERY) + .setDescription("Limit search to: ") + .setExampleValue("apac"); + createRootQualifierParameter(action, newQualifierParameterContext(userSession, i18n, resourceTypes)); + createTemplateParameters(action); + } + + @Override + public void handle(Request request, Response response) throws Exception { + doHandle(toBulkApplyTemplateWsRequest(request)); + response.noContent(); + } + + private void doHandle(BulkApplyTemplateWsRequest request) { + DbSession dbSession = dbClient.openSession(false); + try { + PermissionTemplateDto template = finder.getTemplate(dbSession, newTemplateRef(request.getTemplateId(), request.getTemplateName())); + ComponentQuery componentQuery = ComponentQuery.builder() + .setNameOrKeyQuery(request.getQuery()) + .setQualifiers(qualifiers(request.getQualifier())) + .build(); + List rootComponents = dbClient.componentDao().selectByQuery(dbSession, componentQuery, 0, Integer.MAX_VALUE); + if (rootComponents.isEmpty()) { + return; + } + + ApplyPermissionTemplateQuery query = ApplyPermissionTemplateQuery.create( + template.getUuid(), + Lists.transform(rootComponents, ComponentDtoFunctions.toKey())); + permissionService.applyPermissionTemplate(dbSession, query); + } finally { + dbClient.closeSession(dbSession); + } + } + + private String[] qualifiers(@Nullable String qualifier) { + return qualifier == null + ? Collections2.transform(resourceTypes.getRoots(), RESOURCE_TYPE_TO_QUALIFIER).toArray(new String[resourceTypes.getRoots().size()]) + : new String[] {qualifier}; + } + + private static BulkApplyTemplateWsRequest toBulkApplyTemplateWsRequest(Request request) { + return new BulkApplyTemplateWsRequest() + .setTemplateId(request.param(PARAM_TEMPLATE_ID)) + .setTemplateName(request.param(PARAM_TEMPLATE_NAME)) + .setQualifier(request.param(PARAM_QUALIFIER)) + .setQuery(request.param(Param.TEXT_QUERY)); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java index 4d0cefca1e0..aaf3b6d3308 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java @@ -29,6 +29,6 @@ public class PermissionsWsModuleTest { public void verify_count_of_added_components() { ComponentContainer container = new ComponentContainer(); new PermissionsWsModule().configure(container); - assertThat(container.size()).isEqualTo(28); + assertThat(container.size()).isEqualTo(2 + 27); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/BulkApplyTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/BulkApplyTemplateActionTest.java new file mode 100644 index 00000000000..629c32a1a0e --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/BulkApplyTemplateActionTest.java @@ -0,0 +1,285 @@ +/* + * 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.server.permission.ws.template; + +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import java.util.List; +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.server.ws.WebService.Param; +import org.sonar.api.utils.System2; +import org.sonar.api.web.UserRole; +import org.sonar.core.permission.GlobalPermissions; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDbTester; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.ResourceTypesRule; +import org.sonar.db.permission.GroupWithPermissionDto; +import org.sonar.db.permission.PermissionQuery; +import org.sonar.db.permission.PermissionRepository; +import org.sonar.db.permission.PermissionTemplateDto; +import org.sonar.db.permission.UserWithPermissionDto; +import org.sonar.db.user.GroupDbTester; +import org.sonar.db.user.GroupDto; +import org.sonar.db.user.GroupRoleDto; +import org.sonar.db.user.UserDbTester; +import org.sonar.db.user.UserDto; +import org.sonar.db.user.UserRoleDto; +import org.sonar.server.component.ComponentFinder; +import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.i18n.I18nRule; +import org.sonar.server.issue.index.IssueAuthorizationIndexer; +import org.sonar.server.permission.PermissionService; +import org.sonar.server.permission.ws.PermissionDependenciesFinder; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.usergroups.ws.UserGroupFinder; +import org.sonar.server.ws.TestRequest; +import org.sonar.server.ws.WsActionTester; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.sonar.db.component.ComponentTesting.newDeveloper; +import static org.sonar.db.component.ComponentTesting.newProjectDto; +import static org.sonar.db.component.ComponentTesting.newView; +import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto; +import static org.sonar.db.user.GroupMembershipQuery.IN; +import static org.sonar.db.user.GroupTesting.newGroupDto; +import static org.sonar.db.user.UserTesting.newUserDto; +import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER; +import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID; +import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME; + +public class BulkApplyTemplateActionTest { + @Rule + public UserSessionRule userSession = UserSessionRule.standalone().login("login").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Rule + public DbTester db = DbTester.create(System2.INSTANCE); + ComponentDbTester componentDb = new ComponentDbTester(db); + UserDbTester userDb = new UserDbTester(db); + GroupDbTester groupDb = new GroupDbTester(db); + DbClient dbClient = db.getDbClient(); + DbSession dbSession = db.getSession(); + + ResourceTypesRule resourceTypes = new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT, Qualifiers.VIEW, "DEV"); + I18nRule i18n = new I18nRule(); + WsActionTester ws; + + UserDto user1; + UserDto user2; + GroupDto group1; + GroupDto group2; + PermissionTemplateDto template1; + PermissionTemplateDto template2; + IssueAuthorizationIndexer issueAuthorizationIndexer = mock(IssueAuthorizationIndexer.class); + + @Before + public void setUp() { + PermissionRepository repository = new PermissionRepository(dbClient, new Settings()); + ComponentFinder componentFinder = new ComponentFinder(dbClient); + PermissionService permissionService = new PermissionService(dbClient, repository, issueAuthorizationIndexer, userSession, componentFinder); + PermissionDependenciesFinder permissionDependenciesFinder = new PermissionDependenciesFinder(dbClient, componentFinder, new UserGroupFinder(dbClient), resourceTypes); + + BulkApplyTemplateAction underTest = new BulkApplyTemplateAction(dbClient, permissionService, permissionDependenciesFinder, userSession, i18n, resourceTypes); + ws = new WsActionTester(underTest); + + user1 = userDb.insertUser(newUserDto().setLogin("user-login-1")); + user2 = userDb.insertUser(newUserDto().setLogin("user-login-2")); + group1 = groupDb.insertGroup(newGroupDto().setName("group-name-1")); + group2 = groupDb.insertGroup(newGroupDto().setName("group-name-2")); + + // template 1 + template1 = insertTemplate(newPermissionTemplateDto().setUuid("permission-template-uuid-1")); + addUserToTemplate(user1, template1, UserRole.CODEVIEWER); + addUserToTemplate(user2, template1, UserRole.ISSUE_ADMIN); + addGroupToTemplate(group1, template1, UserRole.ADMIN); + addGroupToTemplate(group2, template1, UserRole.USER); + // template 2 + template2 = insertTemplate(newPermissionTemplateDto().setUuid("permission-template-uuid-2")); + addUserToTemplate(user1, template2, UserRole.USER); + addUserToTemplate(user2, template2, UserRole.USER); + addGroupToTemplate(group1, template2, UserRole.USER); + addGroupToTemplate(group2, template2, UserRole.USER); + + commit(); + } + + @Test + public void bulk_apply_template_by_template_uuid() { + ComponentDto project = componentDb.insertComponent(newProjectDto()); + ComponentDto view = componentDb.insertComponent(newView()); + ComponentDto developer = componentDb.insertComponent(newDeveloper("developer-name")); + addUserPermissionToProject(user1, developer, UserRole.ADMIN); + addUserPermissionToProject(user2, developer, UserRole.ADMIN); + addGroupPermissionToProject(group1, developer, UserRole.ADMIN); + addGroupPermissionToProject(group2, developer, UserRole.ADMIN); + db.commit(); + + call(ws.newRequest().setParam(PARAM_TEMPLATE_ID, template1.getUuid())); + + assertTemplate1AppliedToProject(project); + assertTemplate1AppliedToProject(view); + assertTemplate1AppliedToProject(developer); + } + + @Test + public void bulk_apply_template_by_template_name() { + ComponentDto project = componentDb.insertComponent(newProjectDto()); + + call(ws.newRequest().setParam(PARAM_TEMPLATE_NAME, template1.getName())); + + assertTemplate1AppliedToProject(project); + } + + @Test + public void apply_template_by_qualifier() { + ComponentDto project = componentDb.insertComponent(newProjectDto()); + ComponentDto view = componentDb.insertComponent(newView()); + + call(ws.newRequest() + .setParam(PARAM_TEMPLATE_ID, template1.getUuid()) + .setParam(PARAM_QUALIFIER, project.qualifier())); + + assertTemplate1AppliedToProject(project); + assertNoPermissionOnProject(view); + } + + @Test + public void apply_template_by_query_on_name_and_key() { + ComponentDto projectFoundByKey = newProjectDto().setKey("sonar"); + componentDb.insertProjectAndSnapshot(projectFoundByKey); + ComponentDto projectFoundByName = newProjectDto().setName("name-sonar-name"); + componentDb.insertProjectAndSnapshot(projectFoundByName); + // match must be exact on key + ComponentDto projectUntouched = newProjectDto().setKey("new-sonar").setName("project-name"); + componentDb.insertProjectAndSnapshot(projectUntouched); + componentDb.indexProjects(); + + call(ws.newRequest() + .setParam(PARAM_TEMPLATE_ID, template1.getUuid()) + .setParam(Param.TEXT_QUERY, "sonar")); + + assertTemplate1AppliedToProject(projectFoundByKey); + assertTemplate1AppliedToProject(projectFoundByName); + assertNoPermissionOnProject(projectUntouched); + } + + @Test + public void fail_if_no_template_parameter() { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Template name or template id must be provided, not both."); + + call(ws.newRequest()); + } + + @Test + public void fail_if_template_name_is_incorrect() { + expectedException.expect(NotFoundException.class); + expectedException.expectMessage("Permission template with id 'unknown-template-uuid' is not found"); + + call(ws.newRequest().setParam(PARAM_TEMPLATE_ID, "unknown-template-uuid")); + } + + private void call(TestRequest request) { + request.execute(); + db.commit(); + } + + private void assertTemplate1AppliedToProject(ComponentDto project) { + assertThat(selectProjectPermissionGroups(project, UserRole.ADMIN)).extracting("name").containsExactly(group1.getName()); + assertThat(selectProjectPermissionGroups(project, UserRole.USER)).extracting("name").containsExactly(group2.getName()); + assertThat(selectProjectPermissionUsers(project, UserRole.ADMIN)).isEmpty(); + assertThat(selectProjectPermissionUsers(project, UserRole.CODEVIEWER)).extracting("login").containsExactly(user1.getLogin()); + assertThat(selectProjectPermissionUsers(project, UserRole.ISSUE_ADMIN)).extracting("login").containsExactly(user2.getLogin()); + } + + private void assertNoPermissionOnProject(ComponentDto project) { + assertThat(selectProjectPermissionGroups(project, UserRole.ADMIN)).isEmpty(); + assertThat(selectProjectPermissionGroups(project, UserRole.CODEVIEWER)).isEmpty(); + assertThat(selectProjectPermissionGroups(project, UserRole.ISSUE_ADMIN)).isEmpty(); + assertThat(selectProjectPermissionGroups(project, UserRole.USER)).isEmpty(); + assertThat(selectProjectPermissionUsers(project, UserRole.ADMIN)).isEmpty(); + assertThat(selectProjectPermissionUsers(project, UserRole.CODEVIEWER)).isEmpty(); + assertThat(selectProjectPermissionUsers(project, UserRole.ISSUE_ADMIN)).isEmpty(); + assertThat(selectProjectPermissionUsers(project, UserRole.USER)).isEmpty(); + } + + private PermissionTemplateDto insertTemplate(PermissionTemplateDto template) { + return dbClient.permissionTemplateDao().insert(dbSession, template); + } + + private void addUserToTemplate(UserDto user, PermissionTemplateDto permissionTemplate, String permission) { + dbClient.permissionTemplateDao().insertUserPermission(dbSession, permissionTemplate.getId(), user.getId(), permission); + } + + private void addGroupToTemplate(GroupDto group, PermissionTemplateDto permissionTemplate, String permission) { + dbClient.permissionTemplateDao().insertGroupPermission(dbSession, permissionTemplate.getId(), group.getId(), permission); + } + + private void addUserPermissionToProject(UserDto user, ComponentDto project, String permission) { + dbClient.roleDao().insertUserRole(dbSession, new UserRoleDto() + .setRole(permission) + .setUserId(user.getId()) + .setResourceId(project.getId())); + } + + private void addGroupPermissionToProject(GroupDto group, ComponentDto project, String permission) { + dbClient.roleDao().insertGroupRole(dbSession, new GroupRoleDto() + .setRole(permission) + .setResourceId(project.getId()) + .setGroupId(group.getId())); + } + + private List selectProjectPermissionGroups(ComponentDto project, String permission) { + return FluentIterable.from(dbClient.permissionDao().selectGroups(dbSession, query(permission), project.getId())) + .filter(new PermissionNotNull()) + .toList(); + } + + private List selectProjectPermissionUsers(ComponentDto project, String permission) { + return dbClient.permissionDao().selectUsers(dbSession, query(permission), project.getId(), 0, Integer.MAX_VALUE); + } + + private void commit() { + dbSession.commit(); + } + + private static PermissionQuery query(String permission) { + return PermissionQuery.builder().membership(IN).permission(permission).build(); + } + + private static class PermissionNotNull implements Predicate { + @Override + public boolean apply(@Nullable GroupWithPermissionDto input) { + return input.getPermission() != null; + } + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentQuery.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentQuery.java index 538ab6e8f46..fbff51076e6 100644 --- a/sonar-db/src/main/java/org/sonar/db/component/ComponentQuery.java +++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentQuery.java @@ -89,7 +89,7 @@ public class ComponentQuery { } public Builder setQualifiers(String... qualifiers) { - this.qualifiers = validateQualifiers(qualifiers); + this.qualifiers = qualifiers; return this; } diff --git a/sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml index 8dc2a0e550c..d310528ad8a 100644 --- a/sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml +++ b/sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml @@ -280,10 +280,12 @@ AND p.enabled=${_true} AND p.copy_resource_id is null + AND p.qualifier in - - #{qualifier} - + + #{qualifier} + + AND p.language = #{query.language} @@ -295,10 +297,12 @@ SELECT ri.resource_id FROM resource_index ri WHERE ri.kee like #{query.nameOrKeyQueryToSqlForResourceIndex} ESCAPE '/' + AND ri.qualifier in - - #{qualifier} - + + #{qualifier} + + ) ) diff --git a/sonar-db/src/test/java/org/sonar/db/component/ComponentDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/ComponentDaoTest.java index 0d835b443de..1026c04ab04 100644 --- a/sonar-db/src/test/java/org/sonar/db/component/ComponentDaoTest.java +++ b/sonar-db/src/test/java/org/sonar/db/component/ComponentDaoTest.java @@ -46,7 +46,6 @@ import static org.sonar.db.component.ComponentTesting.newProjectDto; import static org.sonar.db.component.ComponentTesting.newSubView; import static org.sonar.db.component.ComponentTesting.newView; - public class ComponentDaoTest { @Rule @@ -679,7 +678,6 @@ public class ComponentDaoTest { for (int i = 9; i >= 1; i--) { componentDb.insertProjectAndSnapshot(newProjectDto().setName("project-" + i)); } - db.commit(); componentDb.indexProjects(); ComponentQuery query = ComponentQuery.builder().setNameOrKeyQuery("oJect").setQualifiers(Qualifiers.PROJECT).build(); @@ -693,7 +691,6 @@ public class ComponentDaoTest { @Test public void select_by_query_name_with_special_characters() { componentDb.insertProjectAndSnapshot(newProjectDto().setName("project-\\_%/-name")); - db.commit(); componentDb.indexProjects(); ComponentQuery query = ComponentQuery.builder().setNameOrKeyQuery("-\\_%/-").setQualifiers(Qualifiers.PROJECT).build(); @@ -705,9 +702,7 @@ public class ComponentDaoTest { @Test public void select_by_query_key_with_special_characters() { - componentDb.insertProjectAndSnapshot(newProjectDto() - .setKey("project-_%-key")); - db.commit(); + componentDb.insertProjectAndSnapshot(newProjectDto().setKey("project-_%-key")); componentDb.indexProjects(); ComponentQuery query = ComponentQuery.builder().setNameOrKeyQuery("project-_%-key").setQualifiers(Qualifiers.PROJECT).build(); @@ -721,7 +716,6 @@ public class ComponentDaoTest { public void select_by_query_filter_on_language() { componentDb.insertComponent(newProjectDto().setKey("java-project-key").setLanguage("java")); componentDb.insertComponent(newProjectDto().setKey("cpp-project-key").setLanguage("cpp")); - db.commit(); ComponentQuery query = ComponentQuery.builder().setLanguage("java").setQualifiers(Qualifiers.PROJECT).build(); List result = underTest.selectByQuery(dbSession, query, 0, 10); diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/BulkApplyTemplateWsRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/BulkApplyTemplateWsRequest.java new file mode 100644 index 00000000000..f5271f85787 --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/BulkApplyTemplateWsRequest.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.sonarqube.ws.client.permission; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public class BulkApplyTemplateWsRequest { + private String templateId; + private String templateName; + private String query; + private String qualifier; + + @CheckForNull + public String getTemplateId() { + return templateId; + } + + public BulkApplyTemplateWsRequest setTemplateId(@Nullable String templateId) { + this.templateId = templateId; + return this; + } + + @CheckForNull + public String getTemplateName() { + return templateName; + } + + public BulkApplyTemplateWsRequest setTemplateName(@Nullable String templateName) { + this.templateName = templateName; + return this; + } + + @CheckForNull + public String getQuery() { + return query; + } + + public BulkApplyTemplateWsRequest setQuery(@Nullable String query) { + this.query = query; + return this; + } + + @CheckForNull + public String getQualifier() { + return qualifier; + } + + public BulkApplyTemplateWsRequest setQualifier(@Nullable String qualifier) { + this.qualifier = qualifier; + return this; + } +} -- 2.39.5