diff options
author | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2017-09-08 11:44:30 +0200 |
---|---|---|
committer | Stas Vilchik <stas.vilchik@sonarsource.com> | 2017-09-11 11:28:29 +0200 |
commit | f8176cf53cd19d154cb6c77bc9976f069bc54ae2 (patch) | |
tree | 676071f3cff68b78e592d910b54136a787ed5def | |
parent | 0ec5f41e2973a1d277e55b44ec7d435dba1be95b (diff) | |
download | sonarqube-f8176cf53cd19d154cb6c77bc9976f069bc54ae2.tar.gz sonarqube-f8176cf53cd19d154cb6c77bc9976f069bc54ae2.zip |
SONAR-9181 WS bulk_apply_template accepts the parameters as projects/search
6 files changed, 262 insertions, 36 deletions
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 index 5d17a3eb34a..f3e75e9ae84 100644 --- 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 @@ -19,6 +19,8 @@ */ package org.sonar.server.permission.ws.template; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import org.sonar.api.i18n.I18n; import org.sonar.api.resources.Qualifiers; @@ -35,20 +37,28 @@ import org.sonar.db.permission.template.PermissionTemplateDto; import org.sonar.server.permission.PermissionTemplateService; import org.sonar.server.permission.ws.PermissionWsSupport; import org.sonar.server.permission.ws.PermissionsWsAction; +import org.sonar.server.project.Visibility; import org.sonar.server.user.UserSession; import org.sonarqube.ws.client.permission.BulkApplyTemplateWsRequest; +import static org.sonar.api.utils.DateUtils.parseDateOrDateTime; import static org.sonar.core.util.Protobuf.setNullable; import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdmin; import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createTemplateParameters; import static org.sonar.server.permission.ws.template.WsTemplateRef.newTemplateRef; -import static org.sonar.server.ws.WsParameterBuilder.createRootQualifiersParameter; +import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; +import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_002; import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext; +import static org.sonar.server.ws.WsParameterBuilder.createRootQualifiersParameter; import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_ORGANIZATION; 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; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_ANALYZED_BEFORE; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_ON_PROVISIONED_ONLY; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_PROJECTS; import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_QUALIFIERS; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_VISIBILITY; public class BulkApplyTemplateAction implements PermissionsWsAction { @@ -91,6 +101,32 @@ public class BulkApplyTemplateAction implements PermissionsWsAction { .setDeprecatedKey(PARAM_QUALIFIER, "6.6"); createTemplateParameters(action); + + action + .createParam(PARAM_PROJECTS) + .setDescription("Comma-separated list of project keys") + .setSince("6.6") + .setExampleValue(String.join(",", KEY_PROJECT_EXAMPLE_001, KEY_PROJECT_EXAMPLE_002)); + + action.createParam(PARAM_VISIBILITY) + .setDescription("Filter the projects that should be visible to everyone (%s), or only specific user/groups (%s).<br/>" + + "If no visibility is specified, the default project visibility of the organization will be used.", + Visibility.PUBLIC.getLabel(), Visibility.PRIVATE.getLabel()) + .setRequired(false) + .setInternal(true) + .setSince("6.6") + .setPossibleValues(Visibility.getLabels()); + + action.createParam(PARAM_ANALYZED_BEFORE) + .setDescription("Filter the projects for which last analysis is older than the given date (exclusive).<br> " + + "Format: date or datetime ISO formats.") + .setSince("6.6"); + + action.createParam(PARAM_ON_PROVISIONED_ONLY) + .setDescription("Filter the projects that are provisioned") + .setBooleanPossibleValues() + .setDefaultValue("false") + .setSince("6.6"); } @Override @@ -118,15 +154,29 @@ public class BulkApplyTemplateAction implements PermissionsWsAction { .setTemplateId(request.param(PARAM_TEMPLATE_ID)) .setTemplateName(request.param(PARAM_TEMPLATE_NAME)) .setQualifiers(request.mandatoryParamAsStrings(PARAM_QUALIFIERS)) - .setQuery(request.param(Param.TEXT_QUERY)); + .setQuery(request.param(Param.TEXT_QUERY)) + .setVisibility(request.param(PARAM_VISIBILITY)) + .setOnProvisionedOnly(request.mandatoryParamAsBoolean(PARAM_ON_PROVISIONED_ONLY)) + .setAnalyzedBefore(request.param(PARAM_ANALYZED_BEFORE)) + .setProjects(request.paramAsStrings(PARAM_PROJECTS)); } private static ComponentQuery buildDbQuery(BulkApplyTemplateWsRequest request) { - ComponentQuery.Builder dbQuery = ComponentQuery.builder() - .setNameOrKeyQuery(request.getQuery()); - setNullable(request.getQualifiers(), l -> dbQuery.setQualifiers(l.toArray(new String[0]))); - - return dbQuery.build(); + Collection<String> qualifiers = request.getQualifiers(); + ComponentQuery.Builder query = ComponentQuery.builder() + .setQualifiers(qualifiers.toArray(new String[qualifiers.size()])); + + setNullable(request.getQuery(), q -> { + query.setNameOrKeyQuery(q); + query.setPartialMatchOnKey(true); + return query; + }); + setNullable(request.getVisibility(), v -> query.setPrivate(Visibility.isPrivate(v))); + setNullable(request.getAnalyzedBefore(), d -> query.setAnalyzedBefore(parseDateOrDateTime(d).getTime())); + setNullable(request.isOnProvisionedOnly(), query::setOnProvisionedOnly); + setNullable(request.getProjects(), keys -> query.setComponentKeys(new HashSet<>(keys))); + + return query.build(); } } 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 index ac6fffb08d5..0d04a677a5b 100644 --- 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 @@ -41,12 +41,18 @@ import org.sonar.server.permission.PermissionTemplateService; import org.sonar.server.permission.ws.BasePermissionWsTest; import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.api.utils.DateUtils.parseDate; import static org.sonar.db.component.ComponentTesting.newApplication; import static org.sonar.db.component.ComponentTesting.newView; +import static org.sonar.db.component.SnapshotTesting.newAnalysis; import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_ORGANIZATION; import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID; import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_ANALYZED_BEFORE; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_ON_PROVISIONED_ONLY; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_PROJECTS; import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_QUALIFIERS; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_VISIBILITY; public class BulkApplyTemplateActionTest extends BasePermissionWsTest<BulkApplyTemplateAction> { @@ -103,17 +109,14 @@ public class BulkApplyTemplateActionTest extends BasePermissionWsTest<BulkApplyT ComponentDto privateProject = db.components().insertPrivateProject(organization); ComponentDto publicProject = db.components().insertPublicProject(organization); - ComponentDto view = db.components().insertView(organization); loginAsAdmin(organization); newRequest() .setParam(PARAM_TEMPLATE_ID, template1.getUuid()) - .setParam(PARAM_QUALIFIERS, String.join(",", Qualifiers.PROJECT, Qualifiers.VIEW)) .execute(); assertTemplate1AppliedToPrivateProject(privateProject); assertTemplate1AppliedToPublicProject(publicProject); - assertTemplate1AppliedToPublicProject(view); } @Test @@ -171,14 +174,13 @@ public class BulkApplyTemplateActionTest extends BasePermissionWsTest<BulkApplyT db.components().insertProjectAndSnapshot(publicProjectFoundByKey); ComponentDto publicProjectFoundByName = ComponentTesting.newPublicProjectDto(organization).setName("name-sonar-name"); db.components().insertProjectAndSnapshot(publicProjectFoundByName); - // match must be exact on key - ComponentDto projectUntouched = ComponentTesting.newPublicProjectDto(organization).setDbKey("new-sonar").setName("project-name"); + ComponentDto projectUntouched = ComponentTesting.newPublicProjectDto(organization).setDbKey("new-sona").setName("project-name"); db.components().insertProjectAndSnapshot(projectUntouched); loginAsAdmin(organization); newRequest() .setParam(PARAM_TEMPLATE_ID, template1.getUuid()) - .setParam(Param.TEXT_QUERY, "sonar") + .setParam(Param.TEXT_QUERY, "SONAR") .execute(); assertTemplate1AppliedToPublicProject(publicProjectFoundByKey); @@ -188,18 +190,18 @@ public class BulkApplyTemplateActionTest extends BasePermissionWsTest<BulkApplyT @Test public void apply_template_by_query_on_name_and_key() throws Exception { - ComponentDto privateProjectFoundByKey = ComponentTesting.newPrivateProjectDto(organization).setDbKey("sonar"); + // partial match on key + ComponentDto privateProjectFoundByKey = ComponentTesting.newPrivateProjectDto(organization).setDbKey("sonarqube"); db.components().insertProjectAndSnapshot(privateProjectFoundByKey); ComponentDto privateProjectFoundByName = ComponentTesting.newPrivateProjectDto(organization).setName("name-sonar-name"); db.components().insertProjectAndSnapshot(privateProjectFoundByName); - // match must be exact on key - ComponentDto projectUntouched = ComponentTesting.newPublicProjectDto(organization).setDbKey("new-sonar").setName("project-name"); + ComponentDto projectUntouched = ComponentTesting.newPublicProjectDto(organization).setDbKey("new-sona").setName("project-name"); db.components().insertProjectAndSnapshot(projectUntouched); loginAsAdmin(organization); newRequest() .setParam(PARAM_TEMPLATE_ID, template1.getUuid()) - .setParam(Param.TEXT_QUERY, "sonar") + .setParam(Param.TEXT_QUERY, "SONAR") .execute(); assertTemplate1AppliedToPrivateProject(privateProjectFoundByKey); @@ -208,6 +210,78 @@ public class BulkApplyTemplateActionTest extends BasePermissionWsTest<BulkApplyT } @Test + public void apply_template_by_project_keys() throws Exception { + ComponentDto project1 = db.components().insertPrivateProject(organization); + ComponentDto project2 = db.components().insertPrivateProject(organization); + ComponentDto untouchedProject = db.components().insertPrivateProject(organization); + loginAsAdmin(organization); + + newRequest() + .setParam(PARAM_TEMPLATE_ID, template1.getUuid()) + .setParam(PARAM_PROJECTS, String.join(",", project1.getKey(), project2.getKey())) + .execute(); + + assertTemplate1AppliedToPrivateProject(project1); + assertTemplate1AppliedToPrivateProject(project2); + assertNoPermissionOnProject(untouchedProject); + } + + @Test + public void apply_template_by_provisioned_only() throws Exception { + ComponentDto provisionedProject1 = db.components().insertPrivateProject(organization); + ComponentDto provisionedProject2 = db.components().insertPrivateProject(organization); + ComponentDto analyzedProject = db.components().insertPrivateProject(organization); + db.components().insertSnapshot(newAnalysis(analyzedProject)); + loginAsAdmin(organization); + + newRequest() + .setParam(PARAM_TEMPLATE_ID, template1.getUuid()) + .setParam(PARAM_ON_PROVISIONED_ONLY, "true") + .execute(); + + assertTemplate1AppliedToPrivateProject(provisionedProject1); + assertTemplate1AppliedToPrivateProject(provisionedProject2); + assertNoPermissionOnProject(analyzedProject); + } + + @Test + public void apply_template_by_analyzed_before() throws Exception { + ComponentDto oldProject1 = db.components().insertPrivateProject(organization); + ComponentDto oldProject2 = db.components().insertPrivateProject(organization); + ComponentDto recentProject = db.components().insertPrivateProject(organization); + db.components().insertSnapshot(oldProject1, a -> a.setCreatedAt(parseDate("2015-02-03").getTime())); + db.components().insertSnapshot(oldProject2, a -> a.setCreatedAt(parseDate("2016-12-11").getTime())); + db.components().insertSnapshot(recentProject, a -> a.setCreatedAt(System.currentTimeMillis())); + loginAsAdmin(organization); + + newRequest() + .setParam(PARAM_TEMPLATE_ID, template1.getUuid()) + .setParam(PARAM_ANALYZED_BEFORE, "2017-09-07") + .execute(); + + assertTemplate1AppliedToPrivateProject(oldProject1); + assertTemplate1AppliedToPrivateProject(oldProject2); + assertNoPermissionOnProject(recentProject); + } + + @Test + public void apply_template_by_visibility() throws Exception { + ComponentDto privateProject1 = db.components().insertPrivateProject(organization); + ComponentDto privateProject2 = db.components().insertPrivateProject(organization); + ComponentDto publicProject = db.components().insertPublicProject(organization); + loginAsAdmin(organization); + + newRequest() + .setParam(PARAM_TEMPLATE_ID, template1.getUuid()) + .setParam(PARAM_VISIBILITY, "private") + .execute(); + + assertTemplate1AppliedToPrivateProject(privateProject1); + assertTemplate1AppliedToPrivateProject(privateProject2); + assertNoPermissionOnProject(publicProject); + } + + @Test public void fail_if_no_template_parameter() throws Exception { loginAsAdmin(db.getDefaultOrganization()); 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 index 77d7eff64b2..bb17eb37572 100644 --- 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 @@ -22,7 +22,9 @@ package org.sonarqube.ws.client.permission; import java.util.Collection; import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import org.sonar.api.resources.Qualifiers; +import static java.util.Collections.singleton; import static java.util.Objects.requireNonNull; public class BulkApplyTemplateWsRequest { @@ -30,7 +32,11 @@ public class BulkApplyTemplateWsRequest { private String organization; private String templateName; private String query; - private Collection<String> qualifiers; + private Collection<String> qualifiers = singleton(Qualifiers.PROJECT); + private String visibility; + private String analyzedBefore; + private boolean onProvisionedOnly = false; + private Collection<String> projects; @CheckForNull public String getTemplateId() { @@ -72,7 +78,6 @@ public class BulkApplyTemplateWsRequest { return this; } - @CheckForNull public Collection<String> getQualifiers() { return qualifiers; } @@ -81,4 +86,43 @@ public class BulkApplyTemplateWsRequest { this.qualifiers = requireNonNull(qualifiers); return this; } + + @CheckForNull + public String getVisibility() { + return visibility; + } + + public BulkApplyTemplateWsRequest setVisibility(@Nullable String visibility) { + this.visibility = visibility; + return this; + } + + @CheckForNull + public String getAnalyzedBefore() { + return analyzedBefore; + } + + public BulkApplyTemplateWsRequest setAnalyzedBefore(@Nullable String analyzedBefore) { + this.analyzedBefore = analyzedBefore; + return this; + } + + public boolean isOnProvisionedOnly() { + return onProvisionedOnly; + } + + public BulkApplyTemplateWsRequest setOnProvisionedOnly(boolean onProvisionedOnly) { + this.onProvisionedOnly = onProvisionedOnly; + return this; + } + + @CheckForNull + public Collection<String> getProjects() { + return projects; + } + + public BulkApplyTemplateWsRequest setProjects(@Nullable Collection<String> projects) { + this.projects = projects; + return this; + } } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/PermissionsService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/PermissionsService.java index 97802e65da7..ba58f34a274 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/PermissionsService.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/permission/PermissionsService.java @@ -30,6 +30,7 @@ import org.sonarqube.ws.client.BaseService; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.PostRequest; import org.sonarqube.ws.client.WsConnector; +import org.sonarqube.ws.client.project.ProjectsWsParameters; import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_DESCRIPTION; import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_ID; @@ -45,7 +46,6 @@ import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_Q import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID; import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME; import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_USER_LOGIN; -import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_QUALIFIERS; public class PermissionsService extends BaseService { @@ -124,7 +124,11 @@ public class PermissionsService extends BaseService { .setParam(PARAM_TEMPLATE_ID, request.getTemplateId()) .setParam(PARAM_TEMPLATE_NAME, request.getTemplateName()) .setParam("q", request.getQuery()) - .setParam(PARAM_QUALIFIERS, inlineMultipleParamValue(request.getQualifiers()))); + .setParam(ProjectsWsParameters.PARAM_QUALIFIERS, inlineMultipleParamValue(request.getQualifiers())) + .setParam(ProjectsWsParameters.PARAM_VISIBILITY, request.getVisibility()) + .setParam(ProjectsWsParameters.PARAM_ANALYZED_BEFORE, request.getAnalyzedBefore()) + .setParam(ProjectsWsParameters.PARAM_ON_PROVISIONED_ONLY, request.isOnProvisionedOnly()) + .setParam(ProjectsWsParameters.PARAM_PROJECTS, inlineMultipleParamValue(request.getProjects()))); } public CreateTemplateWsResponse createTemplate(CreateTemplateWsRequest request) { diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/permission/PermissionsServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/permission/PermissionsServiceTest.java index b83868acfa5..fa45cf550c6 100644 --- a/sonar-ws/src/test/java/org/sonarqube/ws/client/permission/PermissionsServiceTest.java +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/permission/PermissionsServiceTest.java @@ -44,7 +44,11 @@ import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_Q import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID; import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME; import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_USER_LOGIN; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_ANALYZED_BEFORE; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_ON_PROVISIONED_ONLY; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_PROJECTS; import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_QUALIFIERS; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_VISIBILITY; public class PermissionsServiceTest { private static final String ORGANIZATION_VALUE = "organization value"; @@ -220,7 +224,11 @@ public class PermissionsServiceTest { .setTemplateId(TEMPLATE_ID_VALUE) .setTemplateName(TEMPLATE_NAME_VALUE) .setQualifiers(Arrays.asList("TRK", "VW")) - .setQuery(QUERY_VALUE)); + .setQuery(QUERY_VALUE) + .setVisibility("private") + .setAnalyzedBefore("2017-04-01") + .setOnProvisionedOnly(true) + .setProjects(Arrays.asList("P1", "P2"))); assertThat(serviceTester.getPostParser()).isNull(); PostRequest postRequest = serviceTester.getPostRequest(); @@ -231,6 +239,10 @@ public class PermissionsServiceTest { .hasParam(PARAM_TEMPLATE_NAME, TEMPLATE_NAME_VALUE) .hasParam("q", QUERY_VALUE) .hasParam(PARAM_QUALIFIERS, "TRK,VW") + .hasParam(PARAM_VISIBILITY, "private") + .hasParam(PARAM_ANALYZED_BEFORE, "2017-04-01") + .hasParam(PARAM_ON_PROVISIONED_ONLY, "true") + .hasParam(PARAM_PROJECTS, "P1,P2") .andNoOtherParam(); } diff --git a/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionTemplateTest.java b/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionTemplateTest.java index 99d1542756e..366632b0644 100644 --- a/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionTemplateTest.java +++ b/tests/src/test/java/org/sonarqube/tests/authorisation/PermissionTemplateTest.java @@ -20,6 +20,7 @@ package org.sonarqube.tests.authorisation; import com.sonar.orchestrator.Orchestrator; +import java.util.Arrays; import java.util.Optional; import org.junit.After; import org.junit.ClassRule; @@ -32,16 +33,19 @@ import org.sonarqube.tests.Category6Suite; import org.sonarqube.tests.Tester; import org.sonarqube.ws.Organizations.Organization; import org.sonarqube.ws.WsPermissions; +import org.sonarqube.ws.WsPermissions.CreateTemplateWsResponse; import org.sonarqube.ws.WsProjects.CreateWsResponse.Project; -import org.sonarqube.ws.WsUsers; +import org.sonarqube.ws.WsUsers.CreateWsResponse; import org.sonarqube.ws.client.WsClient; import org.sonarqube.ws.client.component.SearchProjectsRequest; import org.sonarqube.ws.client.permission.AddUserToTemplateWsRequest; import org.sonarqube.ws.client.permission.ApplyTemplateWsRequest; +import org.sonarqube.ws.client.permission.BulkApplyTemplateWsRequest; import org.sonarqube.ws.client.permission.CreateTemplateWsRequest; import org.sonarqube.ws.client.permission.PermissionsService; import org.sonarqube.ws.client.permission.UsersWsRequest; +import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; public class PermissionTemplateTest { @@ -62,9 +66,9 @@ public class PermissionTemplateTest { @Test public void apply_permission_template_on_project() { Organization organization = tester.organizations().generate(); - Project project = tester.projects().generate(organization, p -> p.setVisibility("private")); - WsUsers.CreateWsResponse.User user = tester.users().generateMember(organization); - WsUsers.CreateWsResponse.User anotherUser = tester.users().generateMember(organization); + Project project = createPrivateProject(organization); + CreateWsResponse.User user = tester.users().generateMember(organization); + CreateWsResponse.User anotherUser = tester.users().generateMember(organization); assertThatUserDoesNotHavePermission(user, organization, project); assertThatUserDoesNotHavePermission(anotherUser, organization, project); @@ -81,11 +85,39 @@ public class PermissionTemplateTest { } @Test + public void bulk_apply_template_on_projects() { + Organization organization = tester.organizations().generate(); + CreateWsResponse.User user = tester.users().generateMember(organization); + CreateWsResponse.User anotherUser = tester.users().generateMember(organization); + WsPermissions.PermissionTemplate template = createTemplate(organization).getPermissionTemplate(); + tester.wsClient().permissions().addUserToTemplate(new AddUserToTemplateWsRequest() + .setOrganization(organization.getKey()) + .setTemplateId(template.getId()) + .setLogin(user.getLogin()) + .setPermission("user")); + Project project1 = createPrivateProject(organization); + Project project2 = createPrivateProject(organization); + Project untouchedProject = createPrivateProject(organization); + + tester.wsClient().permissions().bulkApplyTemplate(new BulkApplyTemplateWsRequest() + .setOrganization(organization.getKey()) + .setTemplateId(template.getId()) + .setProjects(Arrays.asList(project1.getKey(), project2.getKey()))); + + assertThatUserDoesNotHavePermission(anotherUser, organization, untouchedProject); + assertThatUserDoesNotHavePermission(anotherUser, organization, project1); + assertThatUserDoesNotHavePermission(anotherUser, organization, project2); + assertThatUserHasPermission(user, organization, project1); + assertThatUserHasPermission(user, organization, project2); + assertThatUserDoesNotHavePermission(user, organization, untouchedProject); + } + + @Test public void indexing_errors_are_recovered_when_applying_permission_template_on_project() throws Exception { Organization organization = tester.organizations().generate(); - Project project = tester.projects().generate(organization, p -> p.setVisibility("private")); - WsUsers.CreateWsResponse.User user = tester.users().generateMember(organization); - WsUsers.CreateWsResponse.User anotherUser = tester.users().generateMember(organization); + Project project = createPrivateProject(organization); + CreateWsResponse.User user = tester.users().generateMember(organization); + CreateWsResponse.User anotherUser = tester.users().generateMember(organization); lockWritesOnProjectIndices(); @@ -122,7 +154,7 @@ public class PermissionTemplateTest { * Gives the read access only to the specified user. All other users and groups * loose their ability to see the project. */ - private void createAndApplyTemplate(Organization organization, Project project, WsUsers.CreateWsResponse.User user) { + private void createAndApplyTemplate(Organization organization, Project project, CreateWsResponse.User user) { String templateName = "For user"; PermissionsService service = tester.wsClient().permissions(); service.createTemplate(new CreateTemplateWsRequest() @@ -140,15 +172,25 @@ public class PermissionTemplateTest { .setTemplateName(templateName)); } - private void assertThatUserHasPermission(WsUsers.CreateWsResponse.User user, Organization organization, Project project) { - assertThat(hasAdminPermission(user, organization, project)).isTrue(); + private CreateTemplateWsResponse createTemplate(Organization organization) { + return tester.wsClient().permissions().createTemplate(new CreateTemplateWsRequest() + .setOrganization(organization.getKey()) + .setName(randomAlphabetic(20))); + } + + private Project createPrivateProject(Organization organization) { + return tester.projects().generate(organization, p -> p.setVisibility("private")); + } + + private void assertThatUserHasPermission(CreateWsResponse.User user, Organization organization, Project project) { + assertThat(hasBrowsePermission(user, organization, project)).isTrue(); } - private void assertThatUserDoesNotHavePermission(WsUsers.CreateWsResponse.User user, Organization organization, Project project) { - assertThat(hasAdminPermission(user, organization, project)).isFalse(); + private void assertThatUserDoesNotHavePermission(CreateWsResponse.User user, Organization organization, Project project) { + assertThat(hasBrowsePermission(user, organization, project)).isFalse(); } - private boolean userHasAccessToIndexedProject(WsUsers.CreateWsResponse.User user, Organization organization, Project project) { + private boolean userHasAccessToIndexedProject(CreateWsResponse.User user, Organization organization, Project project) { SearchProjectsRequest request = SearchProjectsRequest.builder().setOrganization(organization.getKey()).build(); WsClient userSession = tester.as(user.getLogin()).wsClient(); return userSession.components().searchProjects(request) @@ -156,7 +198,7 @@ public class PermissionTemplateTest { .anyMatch(c -> c.getKey().equals(project.getKey())); } - private boolean hasAdminPermission(WsUsers.CreateWsResponse.User user, Organization organization, Project project) { + private boolean hasBrowsePermission(CreateWsResponse.User user, Organization organization, Project project) { UsersWsRequest request = new UsersWsRequest() .setOrganization(organization.getKey()) .setProjectKey(project.getKey()) |