import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.sonar.wsclient.SonarClient;
-import org.sonar.wsclient.base.HttpException;
-import org.sonar.wsclient.project.NewProject;
-import org.sonar.wsclient.project.Project;
+import org.sonarqube.ws.WsProjects.CreateWsResponse.Project;
+import org.sonarqube.ws.client.HttpException;
import org.sonarqube.ws.client.permission.AddGroupWsRequest;
import org.sonarqube.ws.client.permission.AddUserWsRequest;
import org.sonarqube.ws.client.permission.PermissionsService;
import org.sonarqube.ws.client.permission.RemoveGroupWsRequest;
import org.sonarqube.ws.client.permission.RemoveUserWsRequest;
+import org.sonarqube.ws.client.project.CreateRequest;
import util.user.UserRule;
import static org.assertj.core.api.Assertions.assertThat;
import static util.ItUtils.newAdminWsClient;
+import static util.ItUtils.newUserWsClient;
import static util.selenium.Selenese.runSelenese;
public class ProvisioningPermissionTest {
final String newKey = "new-project";
final String newName = "New Project";
- SonarClient client = orchestrator.getServer().wsClient(USER_WITH_PROVISIONING, PASSWORD);
-
- Project created = client.projectClient().create(NewProject.create().key(newKey).name(newName));
+ Project created = newUserWsClient(orchestrator, USER_WITH_PROVISIONING, PASSWORD).projects()
+ .create(CreateRequest.builder().setKey(newKey).setName(newName).build())
+ .getProject();
assertThat(created).isNotNull();
- assertThat(created.key()).isEqualTo(newKey);
- assertThat(created.name()).isEqualTo(newName);
+ assertThat(created.getKey()).isEqualTo(newKey);
+ assertThat(created.getName()).isEqualTo(newName);
}
/**
*/
@Test
public void should_not_be_allowed_on_ws_without_permission() {
- SonarClient client = orchestrator.getServer().wsClient(USER_WITHOUT_PROVISIONING, PASSWORD);
-
thrown.expect(HttpException.class);
- thrown.expectMessage("401");
- client.projectClient().create(NewProject.create().key("new-project").name("New Project"));
+ thrown.expectMessage("403");
+
+ newUserWsClient(orchestrator, USER_WITHOUT_PROVISIONING, PASSWORD).projects()
+ .create(CreateRequest.builder().setKey("new-project").setName("New Project").build())
+ .getProject();
}
private static void addUserPermission(String login, String permission) {
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
-import org.sonar.wsclient.project.NewProject;
import org.sonar.wsclient.qualitygate.NewCondition;
import org.sonar.wsclient.qualitygate.QualityGate;
import org.sonar.wsclient.qualitygate.QualityGateClient;
import org.sonarqube.ws.WsMeasures.Measure;
import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse;
import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.WsClient;
import org.sonarqube.ws.client.WsResponse;
import org.sonarqube.ws.client.qualitygate.ProjectStatusWsRequest;
private static long DEFAULT_QUALITY_GATE;
- private long provisionedProjectId = -1L;
-
private static final String PROJECT_KEY = "sample";
@ClassRule
}
@Before
- public void cleanUp() {
+ public void before() {
orchestrator.resetData();
- provisionedProjectId = Long.parseLong(orchestrator.getServer().adminWsClient().projectClient().create(NewProject.create().key(PROJECT_KEY).name("Sample")).id());
+ orchestrator.getServer().provisionProject(PROJECT_KEY, "Sample");
}
@Test
qgClient().createCondition(NewCondition.create(error.id()).metricKey("ncloc").operator("GT").errorThreshold("10"));
qgClient().setDefault(alert.id());
- qgClient().selectProject(error.id(), provisionedProjectId);
+ associateQualityGateToProject(error.id(), PROJECT_KEY);
try {
SonarScanner build = SonarScanner.create(projectDir("qualitygate/xoo-sample"));
return orchestrator.getServer().adminWsClient().qualityGateClient();
}
+ private static void associateQualityGateToProject(long qGateId, String projectKey) {
+ newAdminWsClient(orchestrator).wsConnector()
+ .call(new PostRequest("api/qualitygates/select")
+ .setParam("gateId", qGateId)
+ .setParam("projectKey", projectKey))
+ .failIfNotSuccessful();
+ }
+
private static List<String> extractPosttaskPluginLogs(String taskUuid, Iterable<String> ceLogs) {
return StreamSupport.stream(ceLogs.spliterator(), false)
.filter(s -> s.contains("POSTASKPLUGIN: finished()"))
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;
// 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());
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;
}
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();
.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);
--- /dev/null
+/*
+ * 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();
+ }
+
+}
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;
.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();
}
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);
- }
}
protected void configureModule() {
add(
ProjectsWs.class,
+ CreateAction.class,
BulkDeleteAction.class,
DeleteAction.class,
GhostsAction.class,
--- /dev/null
+{
+ "project": {
+ "key": "project-key",
+ "name": "project-name",
+ "qualifier": "TRK"
+ }
+}
+++ /dev/null
-{
- "id": "30057",
- "k": "org.jenkins-ci.plugins:sonar",
- "nm": "Jenkins Sonar Plugin",
- "sc": "PRJ",
- "qu": "TRK"
-}
-
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) {
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. " +
public String formatInteger(Locale locale, Integer value) {
return String.valueOf(value);
}
+
}
+/*
+ * 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());
+ }
+
+}
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);
}
}
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");
}
assertThat(controller).isNotNull();
assertThat(controller.description()).isNotEmpty();
assertThat(controller.since()).isEqualTo("2.10");
- assertThat(controller.actions()).hasSize(5);
+ assertThat(controller.actions()).hasSize(4);
}
@Test
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);
- }
}
public class FavoriteDbTester {
private static final String PROP_FAVORITE_KEY = "favourite";
- private final DbTester db;
private final DbClient dbClient;
private final DbSession dbSession;
public FavoriteDbTester(DbTester db) {
- this.db = db;
this.dbClient = db.getDbClient();
this.dbSession = db.getSession();
}
return !result.isEmpty();
}
+
+ public boolean hasNoFavorite(ComponentDto componentDto) {
+ List<PropertyDto> result = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder()
+ .setKey(PROP_FAVORITE_KEY)
+ .setComponentId(componentDto.getId())
+ .build(), dbSession);
+ return result.isEmpty();
+ }
}
package org.sonarqube.ws.client.project;
+import org.sonarqube.ws.WsProjects.CreateWsResponse;
import org.sonarqube.ws.client.BaseService;
import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.WsConnector;
+import static org.sonarqube.ws.client.project.ProjectsWsParameters.ACTION_CREATE;
+import static org.sonarqube.ws.client.project.ProjectsWsParameters.CONTROLLER;
+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;
+
/**
* Maps web service {@code api/projects}.
* @since 5.5
public class ProjectsService extends BaseService {
public ProjectsService(WsConnector wsConnector) {
- super(wsConnector, "api/projects");
+ super(wsConnector, CONTROLLER);
}
/**
*
* @throws org.sonarqube.ws.client.HttpException if HTTP status code is not 2xx.
*/
- public void create(CreateRequest project) {
- PostRequest request = new PostRequest(path("create"))
- .setParam("key", project.getKey())
- .setParam("name", project.getName())
- .setParam("branch", project.getBranch());
- call(request);
+ public CreateWsResponse create(CreateRequest project) {
+ PostRequest request = new PostRequest(path(ACTION_CREATE))
+ .setParam(PARAM_PROJECT, project.getKey())
+ .setParam(PARAM_NAME, project.getName())
+ .setParam(PARAM_BRANCH, project.getBranch());
+ return call(request, CreateWsResponse.parser());
}
/**
--- /dev/null
+/*
+ * 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.project;
+
+public class ProjectsWsParameters {
+
+ public static final String CONTROLLER = "api/projects";
+
+ public static final String ACTION_CREATE = "create";
+
+ public static final String PARAM_PROJECT = "project";
+ public static final String PARAM_NAME = "name";
+ public static final String PARAM_BRANCH = "branch";
+
+ private ProjectsWsParameters() {
+ // static utils only
+ }
+}
optional sonarqube.ws.commons.Paging paging = 1;
repeated Project projects = 2;
}
+
+message CreateWsResponse {
+ optional Project project = 1;
+
+ message Project {
+ optional string key = 1;
+ optional string name = 2;
+ optional string qualifier = 3;
+ }
+}
+
import org.junit.Rule;
import org.junit.Test;
+import org.sonarqube.ws.WsProjects;
import org.sonarqube.ws.client.ServiceTester;
import org.sonarqube.ws.client.WsConnector;
.setName("Project Name")
.build());
+ assertThat(serviceTester.getPostParser()).isSameAs(WsProjects.CreateWsResponse.parser());
assertThat(serviceTester.getPostRequest().getPath()).isEqualTo("api/projects/create");
assertThat(serviceTester.getPostRequest().getParams()).containsOnly(
- entry("key", "project_key"),
+ entry("project", "project_key"),
entry("name", "Project Name"));
}
assertThat(serviceTester.getPostRequest().getPath()).isEqualTo("api/projects/create");
assertThat(serviceTester.getPostRequest().getParams()).containsOnly(
- entry("key", "project_key"),
+ entry("project", "project_key"),
entry("name", "Project Name"),
entry("branch", "the_branch"));
}