diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-01-19 13:19:25 +0100 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-01-24 18:36:49 +0100 |
commit | 528c2312512686dba2dd9cf4dda4d38a184c56a2 (patch) | |
tree | 7e0482f4225311b1327cb14b1b13d2cd7242e273 /server | |
parent | 4795b2a1d9de7ac2b5e010565928000a45bad32e (diff) | |
download | sonarqube-528c2312512686dba2dd9cf4dda4d38a184c56a2.tar.gz sonarqube-528c2312512686dba2dd9cf4dda4d38a184c56a2.zip |
SONAR-7299 Replace Ruby WS api/projects/create by java
Diffstat (limited to 'server')
11 files changed, 497 insertions, 55 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java index 2fb921e6525..f525fb70326 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java @@ -35,7 +35,6 @@ import org.sonar.api.server.ServerSide; import org.sonar.api.utils.System2; import org.sonar.api.web.UserRole; import org.sonar.core.component.ComponentKeys; -import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.util.Uuids; import org.sonar.db.DbClient; import org.sonar.db.DbSession; @@ -89,7 +88,6 @@ public class ComponentService { // Used by SQ and Governance public ComponentDto create(DbSession session, NewComponent newComponent) { - userSession.checkPermission(GlobalPermissions.PROVISIONING); checkKeyFormat(newComponent.qualifier(), newComponent.key()); ComponentDto rootComponent = createRootComponent(session, newComponent); removeDuplicatedProjects(session, rootComponent.getKey()); diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java index 9adc1b4d766..e5660d58d88 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java @@ -43,6 +43,7 @@ import org.sonar.server.user.UserSession; import static com.google.common.base.Preconditions.checkArgument; import static java.lang.String.format; +import static org.sonar.core.permission.GlobalPermissions.PROVISIONING; import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; import static org.sonar.server.component.NewComponent.newComponentBuilder; import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; @@ -97,6 +98,7 @@ public class ReportSubmitter { } private ComponentDto createProject(DbSession dbSession, String organizationUuid, String projectKey, @Nullable String projectBranch, @Nullable String projectName) { + userSession.checkPermission(PROVISIONING); Integer userId = userSession.getUserId(); Long projectCreatorUserId = userId == null ? null : userId.longValue(); @@ -113,7 +115,6 @@ public class ReportSubmitter { .setBranch(projectBranch) .setQualifier(Qualifiers.PROJECT) .build(); - // "provisioning" permission is check in ComponentService ComponentDto project = componentService.create(dbSession, newProject); if (permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(dbSession, organizationUuid, project)) { favoriteUpdater.add(dbSession, project); diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/CreateAction.java new file mode 100644 index 00000000000..6ec82adcc0f --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/CreateAction.java @@ -0,0 +1,141 @@ +/* + * 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.project.ws; + +import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.Response; +import org.sonar.api.server.ws.WebService; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.component.ComponentDto; +import org.sonar.server.component.ComponentService; +import org.sonar.server.favorite.FavoriteUpdater; +import org.sonar.server.organization.DefaultOrganizationProvider; +import org.sonar.server.permission.PermissionTemplateService; +import org.sonar.server.user.UserSession; +import org.sonarqube.ws.WsProjects.CreateWsResponse; +import org.sonarqube.ws.client.project.CreateRequest; + +import static org.sonar.api.resources.Qualifiers.PROJECT; +import static org.sonar.core.permission.GlobalPermissions.PROVISIONING; +import static org.sonar.server.component.NewComponent.newComponentBuilder; +import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; +import static org.sonar.server.ws.WsUtils.writeProtobuf; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.ACTION_CREATE; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_BRANCH; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_NAME; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_PROJECT; + +public class CreateAction implements ProjectsWsAction { + + public static final String DEPRECATED_PARAM_KEY = "key"; + + private final DbClient dbClient; + private final UserSession userSession; + private final ComponentService componentService; + private final DefaultOrganizationProvider defaultOrganizationProvider; + private final PermissionTemplateService permissionTemplateService; + private final FavoriteUpdater favoriteUpdater; + + public CreateAction(DbClient dbClient, UserSession userSession, ComponentService componentService, PermissionTemplateService permissionTemplateService, + FavoriteUpdater favoriteUpdater, DefaultOrganizationProvider defaultOrganizationProvider) { + this.dbClient = dbClient; + this.userSession = userSession; + this.componentService = componentService; + this.permissionTemplateService = permissionTemplateService; + this.favoriteUpdater = favoriteUpdater; + this.defaultOrganizationProvider = defaultOrganizationProvider; + } + + @Override + public void define(WebService.NewController context) { + WebService.NewAction action = context.createAction(ACTION_CREATE) + .setDescription("Create a project.<br/>" + + "Requires 'Create Projects' permission<br/>" + + "Since 6.3, the response has been updated and does not contain the database ID anymore") + .setSince("4.0") + .setPost(true) + .setResponseExample(getClass().getResource("create-example.json")) + .setHandler(this); + + action.createParam(PARAM_PROJECT) + .setDescription("Key of the project") + .setDeprecatedKey(DEPRECATED_PARAM_KEY) + .setRequired(true) + .setExampleValue(KEY_PROJECT_EXAMPLE_001); + + action.createParam(PARAM_NAME) + .setDescription("Name of the project") + .setRequired(true) + .setExampleValue("SonarQube"); + + action.createParam(PARAM_BRANCH) + .setDescription("SCM Branch of the project. The key of the project will become key:branch, for instance 'SonarQube:branch-5.0'") + .setExampleValue("branch-5.0"); + } + + @Override + public void handle(Request request, Response response) throws Exception { + userSession.checkPermission(PROVISIONING); + CreateRequest createRequest = toCreateRequest(request); + writeProtobuf(doHandle(createRequest), request, response); + } + + private CreateWsResponse doHandle(CreateRequest request) { + String organizationUuid = defaultOrganizationProvider.get().getUuid(); + try (DbSession dbSession = dbClient.openSession(false)) { + ComponentDto componentDto = componentService.create(dbSession, newComponentBuilder() + .setOrganizationUuid(organizationUuid) + .setKey(request.getKey()) + .setName(request.getName()) + .setBranch(request.getBranch()) + .setQualifier(PROJECT) + .build()); + handlePermissionTemplate(dbSession, componentDto, organizationUuid); + return toCreateResponse(componentDto); + } + } + + private void handlePermissionTemplate(DbSession dbSession, ComponentDto componentDto, String organizationUuid) { + permissionTemplateService.applyDefault(dbSession, organizationUuid, componentDto, userSession.isLoggedIn() ? userSession.getUserId().longValue() : null); + if (permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(dbSession, organizationUuid, componentDto)) { + favoriteUpdater.add(dbSession, componentDto); + dbSession.commit(); + } + } + + private static CreateRequest toCreateRequest(Request request) { + return CreateRequest.builder() + .setKey(request.mandatoryParam(PARAM_PROJECT)) + .setName(request.mandatoryParam(PARAM_NAME)) + .setBranch(request.param(PARAM_BRANCH)) + .build(); + } + + private static CreateWsResponse toCreateResponse(ComponentDto componentDto) { + return CreateWsResponse.newBuilder() + .setProject(CreateWsResponse.Project.newBuilder() + .setKey(componentDto.key()) + .setName(componentDto.name()) + .setQualifier(componentDto.qualifier())) + .build(); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWs.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWs.java index 8a06da7d277..e6a42102996 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWs.java +++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWs.java @@ -20,6 +20,7 @@ package org.sonar.server.project.ws; import com.google.common.io.Resources; +import java.util.Arrays; import org.sonar.api.server.ws.RailsHandler; import org.sonar.api.server.ws.WebService; @@ -43,12 +44,7 @@ public class ProjectsWs implements WebService { .setDescription("Manage project existence."); defineIndexAction(controller); - defineCreateAction(controller); - - for (ProjectsWsAction action : actions) { - action.define(controller); - } - + Arrays.stream(actions).forEach(action -> action.define(controller)); controller.done(); } @@ -95,29 +91,4 @@ public class ProjectsWs implements WebService { RailsHandler.addFormatParam(action); } - private void defineCreateAction(NewController controller) { - WebService.NewAction action = controller.createAction("create") - .setDescription("Create a project. Requires Create Projects permission") - .setSince("4.0") - .setPost(true) - .setHandler(RailsHandler.INSTANCE) - .setResponseExample(Resources.getResource(this.getClass(), "projects-example-create.json")); - - action.createParam("key") - .setDescription("Key of the project") - .setRequired(true) - .setExampleValue(KEY_PROJECT_EXAMPLE_001); - - action.createParam("name") - .setDescription("Name of the project") - .setRequired(true) - .setExampleValue("SonarQube"); - - action.createParam("branch") - .setDescription("SCM Branch of the project. The key of the project will become key:branch, for instance 'SonarQube:branch-5.0'") - .setRequired(false) - .setExampleValue("branch-5.0"); - - RailsHandler.addFormatParam(action); - } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsModule.java index 782b619bd9a..e3e5138bf55 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/project/ws/ProjectsWsModule.java @@ -26,6 +26,7 @@ public class ProjectsWsModule extends Module { protected void configureModule() { add( ProjectsWs.class, + CreateAction.class, BulkDeleteAction.class, DeleteAction.class, GhostsAction.class, diff --git a/server/sonar-server/src/main/resources/org/sonar/server/project/ws/create-example.json b/server/sonar-server/src/main/resources/org/sonar/server/project/ws/create-example.json new file mode 100644 index 00000000000..077da7925c5 --- /dev/null +++ b/server/sonar-server/src/main/resources/org/sonar/server/project/ws/create-example.json @@ -0,0 +1,7 @@ +{ + "project": { + "key": "project-key", + "name": "project-name", + "qualifier": "TRK" + } +} diff --git a/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-create.json b/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-create.json deleted file mode 100644 index 043c4bb391d..00000000000 --- a/server/sonar-server/src/main/resources/org/sonar/server/project/ws/projects-example-create.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "30057", - "k": "org.jenkins-ci.plugins:sonar", - "nm": "Jenkins Sonar Plugin", - "sc": "PRJ", - "qu": "TRK" -} - diff --git a/server/sonar-server/src/test/java/org/sonar/server/i18n/I18nRule.java b/server/sonar-server/src/test/java/org/sonar/server/i18n/I18nRule.java index 5d2218620e2..eb6c4c01fbb 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/i18n/I18nRule.java +++ b/server/sonar-server/src/test/java/org/sonar/server/i18n/I18nRule.java @@ -26,9 +26,12 @@ import java.util.Locale; import java.util.Map; import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; import org.sonar.api.i18n.I18n; -public class I18nRule implements I18n { +public class I18nRule implements TestRule, I18n { private final Map<String, String> messages = new HashMap<>(); public I18nRule put(String key, String value) { @@ -36,6 +39,20 @@ public class I18nRule implements I18n { return this; } + @Override + public Statement apply(final Statement statement, Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + try { + statement.evaluate(); + } finally { + messages.clear(); + } + } + }; + } + public void setProjectPermissions() { put("projects_role.admin", "Administer"); put("projects_role.admin.desc", "Ability to access project settings and perform administration tasks. " + @@ -101,4 +118,5 @@ public class I18nRule implements I18n { public String formatInteger(Locale locale, Integer value) { return String.valueOf(value); } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java index e69de29bb2d..541ad2afdb3 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/project/ws/CreateActionTest.java @@ -0,0 +1,322 @@ +/* + * 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.project.ws; + +import com.google.common.base.Throwables; +import java.io.IOException; +import org.assertj.core.api.Assertions; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.config.MapSettings; +import org.sonar.api.config.Settings; +import org.sonar.api.server.ws.WebService; +import org.sonar.api.utils.System2; +import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.ComponentTesting; +import org.sonar.db.permission.template.PermissionTemplateDto; +import org.sonar.db.user.UserDto; +import org.sonar.server.component.ComponentService; +import org.sonar.server.component.index.ComponentIndexDefinition; +import org.sonar.server.component.index.ComponentIndexer; +import org.sonar.server.es.EsTester; +import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.exceptions.ForbiddenException; +import org.sonar.server.favorite.FavoriteUpdater; +import org.sonar.server.i18n.I18nRule; +import org.sonar.server.measure.index.ProjectMeasuresIndexDefinition; +import org.sonar.server.measure.index.ProjectMeasuresIndexer; +import org.sonar.server.organization.DefaultOrganizationProvider; +import org.sonar.server.organization.TestDefaultOrganizationProvider; +import org.sonar.server.permission.PermissionTemplateService; +import org.sonar.server.permission.index.PermissionIndexer; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.ws.TestRequest; +import org.sonar.server.ws.WsActionTester; +import org.sonarqube.ws.MediaTypes; +import org.sonarqube.ws.WsProjects.CreateWsResponse; +import org.sonarqube.ws.client.project.CreateRequest; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.sonar.api.web.UserRole.USER; +import static org.sonar.core.permission.GlobalPermissions.PROVISIONING; +import static org.sonar.core.permission.GlobalPermissions.QUALITY_GATE_ADMIN; +import static org.sonar.core.util.Protobuf.setNullable; +import static org.sonar.server.component.index.ComponentIndexDefinition.INDEX_COMPONENTS; +import static org.sonar.server.component.index.ComponentIndexDefinition.TYPE_COMPONENT; +import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES; +import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE; +import static org.sonar.test.JsonAssert.assertJson; +import static org.sonarqube.ws.client.WsRequest.Method.POST; +import static org.sonarqube.ws.client.project.ProjectsWsParameters.PARAM_NAME; + +public class CreateActionTest { + + private static final String DEFAULT_PROJECT_KEY = "project-key"; + private static final String DEFAULT_PROJECT_NAME = "project-name"; + + private System2 system2 = System2.INSTANCE; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Rule + public DbTester db = DbTester.create(system2); + + @Rule + public EsTester es = new EsTester(new ComponentIndexDefinition(new MapSettings()), new ProjectMeasuresIndexDefinition(new MapSettings())); + + @Rule + public UserSessionRule userSession = UserSessionRule.standalone(); + + @Rule + public I18nRule i18n = new I18nRule().put("qualifier.TRK", "Project"); + + private Settings settings = new MapSettings(); + + private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); + + private PermissionTemplateDto permissionTemplateDto; + + private WsActionTester ws = new WsActionTester( + new CreateAction( + db.getDbClient(), userSession, + new ComponentService(db.getDbClient(), i18n, userSession, system2, + new ProjectMeasuresIndexer(system2, db.getDbClient(), es.client()), + new ComponentIndexer(db.getDbClient(), es.client())), + new PermissionTemplateService(db.getDbClient(), settings, new PermissionIndexer(db.getDbClient(), es.client()), userSession), + new FavoriteUpdater(db.getDbClient(), userSession), + defaultOrganizationProvider)); + + @Before + public void setUp() throws Exception { + permissionTemplateDto = db.permissionTemplates().insertTemplate(); + setTemplateAsDefault(permissionTemplateDto); + } + + @Test + public void create_project() throws Exception { + userSession.setGlobalPermissions(PROVISIONING); + + CreateWsResponse response = call(CreateRequest.builder() + .setKey(DEFAULT_PROJECT_KEY) + .setName(DEFAULT_PROJECT_NAME) + .build()); + + assertThat(response.getProject().getKey()).isEqualTo(DEFAULT_PROJECT_KEY); + assertThat(response.getProject().getName()).isEqualTo(DEFAULT_PROJECT_NAME); + assertThat(response.getProject().getQualifier()).isEqualTo("TRK"); + ComponentDto project = db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY); + assertThat(project.getKey()).isEqualTo(DEFAULT_PROJECT_KEY); + assertThat(project.name()).isEqualTo(DEFAULT_PROJECT_NAME); + assertThat(project.qualifier()).isEqualTo("TRK"); + } + + @Test + public void create_project_with_branch() throws Exception { + userSession.setGlobalPermissions(PROVISIONING); + + CreateWsResponse response = call(CreateRequest.builder() + .setKey(DEFAULT_PROJECT_KEY) + .setName(DEFAULT_PROJECT_NAME) + .setBranch("origin/master") + .build()); + + assertThat(response.getProject().getKey()).isEqualTo("project-key:origin/master"); + } + + @Test + public void verify_permission_template_is_applied() throws Exception { + UserDto userDto = db.users().insertUser(); + userSession.login(userDto).setGlobalPermissions(PROVISIONING); + db.permissionTemplates().addUserToTemplate(permissionTemplateDto.getId(), userDto.getId(), USER); + + call(CreateRequest.builder() + .setKey(DEFAULT_PROJECT_KEY) + .setName(DEFAULT_PROJECT_NAME) + .build()); + + ComponentDto project = db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY); + assertThat(db.users().selectProjectPermissionsOfUser(userDto, project)).containsOnly(USER); + } + + @Test + public void add_project_to_favorite_when_logged() throws Exception { + UserDto userDto = db.users().insertUser(); + userSession.login(userDto).setGlobalPermissions(PROVISIONING); + db.permissionTemplates().addProjectCreatorToTemplate(permissionTemplateDto.getId(), USER); + + call(CreateRequest.builder() + .setKey(DEFAULT_PROJECT_KEY) + .setName(DEFAULT_PROJECT_NAME) + .build()); + + ComponentDto project = db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY); + assertThat(db.favorites().hasFavorite(project, userDto.getId())).isTrue(); + } + + @Test + public void does_not_add_project_to_favorite_when_not_logged() throws Exception { + userSession.setGlobalPermissions(PROVISIONING); + db.permissionTemplates().addProjectCreatorToTemplate(permissionTemplateDto.getId(), USER); + + call(CreateRequest.builder() + .setKey(DEFAULT_PROJECT_KEY) + .setName(DEFAULT_PROJECT_NAME) + .build()); + + ComponentDto project = db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY); + assertThat(db.favorites().hasNoFavorite(project)).isTrue(); + } + + @Test + public void does_not_add_project_to_favorite_when_project_create_has_no_permission_on_template() throws Exception { + UserDto userDto = db.users().insertUser(); + userSession.login(userDto).setGlobalPermissions(PROVISIONING); + + call(CreateRequest.builder() + .setKey(DEFAULT_PROJECT_KEY) + .setName(DEFAULT_PROJECT_NAME) + .build()); + + ComponentDto project = db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY); + assertThat(db.favorites().hasNoFavorite(project)).isTrue(); + } + + @Test + public void verify_project_exists_in_es_indexes() throws Exception { + userSession.setGlobalPermissions(PROVISIONING); + + call(CreateRequest.builder() + .setKey(DEFAULT_PROJECT_KEY) + .setName(DEFAULT_PROJECT_NAME) + .build()); + + ComponentDto project = db.getDbClient().componentDao().selectOrFailByKey(db.getSession(), DEFAULT_PROJECT_KEY); + assertThat(es.getIds(INDEX_COMPONENTS, TYPE_COMPONENT)).containsOnly(project.uuid()); + assertThat(es.getIds(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURE)).containsOnly(project.uuid()); + } + + @Test + public void create_project_with_deprecated_parameter() throws Exception { + userSession.setGlobalPermissions(PROVISIONING); + + ws.newRequest() + .setMethod(POST.name()) + .setParam("key", DEFAULT_PROJECT_KEY) + .setParam(PARAM_NAME, DEFAULT_PROJECT_NAME) + .execute(); + + assertThat(db.getDbClient().componentDao().selectByKey(db.getSession(), DEFAULT_PROJECT_KEY).isPresent()).isTrue(); + } + + @Test + public void fail_when_project_already_exists() throws Exception { + userSession.setGlobalPermissions(PROVISIONING); + db.components().insertComponent(ComponentTesting.newProjectDto(db.getDefaultOrganization()).setKey(DEFAULT_PROJECT_KEY)); + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Could not create Project, key already exists: project-key"); + + call(CreateRequest.builder() + .setKey(DEFAULT_PROJECT_KEY) + .setName(DEFAULT_PROJECT_NAME) + .build()); + } + + @Test + public void fail_when_missing_project_parameter() throws Exception { + userSession.setGlobalPermissions(PROVISIONING); + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("The 'project' parameter is missing"); + + call(CreateRequest.builder().setName(DEFAULT_PROJECT_NAME).build()); + } + + @Test + public void fail_when_missing_name_parameter() throws Exception { + userSession.setGlobalPermissions(PROVISIONING); + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("The 'name' parameter is missing"); + + call(CreateRequest.builder().setKey(DEFAULT_PROJECT_KEY).build()); + } + + @Test + public void fail_when_key_has_bad_format() throws Exception { + userSession.setGlobalPermissions(PROVISIONING); + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Malformed key for Project: 1234"); + + call(CreateRequest.builder().setKey("1234").setName(DEFAULT_PROJECT_NAME).build()); + } + + @Test + public void fail_when_missing_create_project_permission() throws Exception { + userSession.setGlobalPermissions(QUALITY_GATE_ADMIN); + expectedException.expect(ForbiddenException.class); + + call(CreateRequest.builder().setKey(DEFAULT_PROJECT_KEY).setName(DEFAULT_PROJECT_NAME).build()); + } + + @Test + public void test_example() { + userSession.setGlobalPermissions(PROVISIONING); + + String result = ws.newRequest() + .setParam("key", DEFAULT_PROJECT_KEY) + .setParam("name", DEFAULT_PROJECT_NAME) + .execute().getInput(); + + assertJson(result).isSimilarTo(getClass().getResource("create-example.json")); + } + + @Test + public void definition() { + WebService.Action definition = ws.getDef(); + + Assertions.assertThat(definition.key()).isEqualTo("create"); + Assertions.assertThat(definition.since()).isEqualTo("4.0"); + Assertions.assertThat(definition.isInternal()).isFalse(); + Assertions.assertThat(definition.responseExampleAsString()).isNotEmpty(); + Assertions.assertThat(definition.params()).hasSize(3); + } + + private CreateWsResponse call(CreateRequest request) { + TestRequest httpRequest = ws.newRequest() + .setMethod(POST.name()) + .setMediaType(MediaTypes.PROTOBUF); + setNullable(request.getKey(), e -> httpRequest.setParam("project", e)); + setNullable(request.getName(), e -> httpRequest.setParam("name", e)); + setNullable(request.getBranch(), e -> httpRequest.setParam("branch", e)); + try { + return CreateWsResponse.parseFrom(httpRequest.execute().getInputStream()); + } catch (IOException e) { + throw Throwables.propagate(e); + } + } + + private void setTemplateAsDefault(PermissionTemplateDto permissionTemplateDto) { + settings.appendProperty("sonar.permission.template.default", permissionTemplateDto.getUuid()); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsModuleTest.java index f2cbc94baf4..c2a2dab4b74 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsModuleTest.java @@ -29,6 +29,6 @@ public class ProjectsWsModuleTest { public void verify_count_of_added_components() { ComponentContainer container = new ComponentContainer(); new ProjectsWsModule().configure(container); - assertThat(container.size()).isEqualTo(2 + 7); + assertThat(container.size()).isEqualTo(2 + 8); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsTest.java index fe2701d163b..214e9f176e4 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/project/ws/ProjectsWsTest.java @@ -41,8 +41,7 @@ public class ProjectsWsTest { ws = new WsTester(new ProjectsWs( new BulkDeleteAction(mock(ComponentCleanerService.class), mock(DbClient.class), mock(UserSession.class)), new GhostsAction(mock(DbClient.class), mock(UserSession.class)), - new ProvisionedAction(mock(DbClient.class), mock(UserSession.class)) - )); + new ProvisionedAction(mock(DbClient.class), mock(UserSession.class)))); controller = ws.controller("api/projects"); } @@ -51,7 +50,7 @@ public class ProjectsWsTest { assertThat(controller).isNotNull(); assertThat(controller.description()).isNotEmpty(); assertThat(controller.since()).isEqualTo("2.10"); - assertThat(controller.actions()).hasSize(5); + assertThat(controller.actions()).hasSize(4); } @Test @@ -63,12 +62,4 @@ public class ProjectsWsTest { assertThat(action.params()).hasSize(8); } - @Test - public void define_create_action() { - WebService.Action action = controller.action("create"); - assertThat(action).isNotNull(); - assertThat(action.handler()).isInstanceOf(RailsHandler.class); - assertThat(action.responseExampleAsString()).isNotEmpty(); - assertThat(action.params()).hasSize(4); - } } |