From: Julien Lancelot Date: Thu, 7 Dec 2017 14:23:51 +0000 (+0100) Subject: SONAR-10134 Add organization parameter in project_status action X-Git-Tag: 7.0-RC1~124 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=f894f4384f112f1ba2377872fb44eae0fcf9fd1d;p=sonarqube.git SONAR-10134 Add organization parameter in project_status action --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java index 7bd685e3203..7e2c818de9d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java @@ -37,6 +37,7 @@ import org.sonar.db.component.ComponentDto; import org.sonar.db.component.SnapshotDto; import org.sonar.db.measure.LiveMeasureDto; import org.sonar.db.measure.MeasureDto; +import org.sonar.db.organization.OrganizationDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.component.ComponentFinder.ParamNames; import org.sonar.server.exceptions.BadRequestException; @@ -45,14 +46,14 @@ import org.sonar.server.ws.KeyExamples; import org.sonarqube.ws.Qualitygates.ProjectStatusResponse; import static com.google.common.base.Strings.isNullOrEmpty; -import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; -import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; -import static org.sonar.server.ws.WsUtils.checkRequest; -import static org.sonar.server.ws.WsUtils.writeProtobuf; import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.ACTION_PROJECT_STATUS; import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_ANALYSIS_ID; import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PROJECT_ID; import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PROJECT_KEY; +import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; +import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; +import static org.sonar.server.ws.WsUtils.checkRequest; +import static org.sonar.server.ws.WsUtils.writeProtobuf; public class ProjectStatusAction implements QualityGatesWsAction { private static final String QG_STATUSES_ONE_LINE = Arrays.stream(ProjectStatusResponse.Status.values()) @@ -63,11 +64,13 @@ public class ProjectStatusAction implements QualityGatesWsAction { private final DbClient dbClient; private final ComponentFinder componentFinder; private final UserSession userSession; + private final QualityGatesWsSupport wsSupport; - public ProjectStatusAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession) { + public ProjectStatusAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, QualityGatesWsSupport wsSupport) { this.dbClient = dbClient; this.componentFinder = componentFinder; this.userSession = userSession; + this.wsSupport = wsSupport; } @Override @@ -102,6 +105,8 @@ public class ProjectStatusAction implements QualityGatesWsAction { .setSince("5.4") .setDescription("Project key") .setExampleValue(KeyExamples.KEY_PROJECT_EXAMPLE_001); + + wsSupport.createOrganizationParam(action); } @Override @@ -114,22 +119,25 @@ public class ProjectStatusAction implements QualityGatesWsAction { ^ !isNullOrEmpty(projectId) ^ !isNullOrEmpty(projectKey), MSG_ONE_PARAMETER_ONLY); - ProjectStatusResponse projectStatusResponse = doHandle(analysisId, projectId, projectKey); - writeProtobuf(projectStatusResponse, request, response); - } - private ProjectStatusResponse doHandle(@Nullable String analysisId, @Nullable String projectId, @Nullable String projectKey) { try (DbSession dbSession = dbClient.openSession(false)) { - ProjectAndSnapshot projectAndSnapshot = getProjectAndSnapshot(dbSession, analysisId, projectId, projectKey); - checkPermission(projectAndSnapshot.project); - Optional measureData = loadQualityGateDetails(dbSession, projectAndSnapshot, analysisId != null); - - return ProjectStatusResponse.newBuilder() - .setProjectStatus(new QualityGateDetailsFormatter(measureData, projectAndSnapshot.snapshotDto).format()) - .build(); + OrganizationDto organization = wsSupport.getOrganization(dbSession, request); + ProjectStatusResponse projectStatusResponse = doHandle(dbSession, organization, analysisId, projectId, projectKey); + writeProtobuf(projectStatusResponse, request, response); } } + private ProjectStatusResponse doHandle(DbSession dbSession, OrganizationDto organization, @Nullable String analysisId, @Nullable String projectId, @Nullable String projectKey) { + ProjectAndSnapshot projectAndSnapshot = getProjectAndSnapshot(dbSession, analysisId, projectId, projectKey); + wsSupport.checkProjectBelongsToOrganization(organization, projectAndSnapshot.project); + checkPermission(projectAndSnapshot.project); + Optional measureData = loadQualityGateDetails(dbSession, projectAndSnapshot, analysisId != null); + + return ProjectStatusResponse.newBuilder() + .setProjectStatus(new QualityGateDetailsFormatter(measureData, projectAndSnapshot.snapshotDto).format()) + .build(); + } + private ProjectAndSnapshot getProjectAndSnapshot(DbSession dbSession, @Nullable String analysisId, @Nullable String projectId, @Nullable String projectKey) { if (!isNullOrEmpty(analysisId)) { return getSnapshotThenProject(dbSession, analysisId); diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java index 7fa0d673a72..a1a0d00be91 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java @@ -33,7 +33,6 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ComponentTesting; import org.sonar.db.component.SnapshotDto; import org.sonar.db.metric.MetricDto; import org.sonar.db.organization.OrganizationDto; @@ -41,6 +40,7 @@ import org.sonar.server.component.TestComponentFinder; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.organization.TestDefaultOrganizationProvider; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsActionTester; import org.sonarqube.ws.Qualitygates.ProjectStatusResponse; @@ -54,6 +54,7 @@ import static org.sonar.db.measure.MeasureTesting.newLiveMeasure; import static org.sonar.db.measure.MeasureTesting.newMeasureDto; import static org.sonar.db.metric.MetricTesting.newMetricDto; import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_ANALYSIS_ID; +import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_ORGANIZATION; import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PROJECT_ID; import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PROJECT_KEY; import static org.sonar.test.JsonAssert.assertJson; @@ -71,19 +72,27 @@ public class ProjectStatusActionTest { private DbClient dbClient = db.getDbClient(); private DbSession dbSession = db.getSession(); - private WsActionTester ws = new WsActionTester(new ProjectStatusAction(dbClient, TestComponentFinder.from(db), userSession)); + private WsActionTester ws = new WsActionTester(new ProjectStatusAction(dbClient, TestComponentFinder.from(db), userSession, + new QualityGatesWsSupport(db.getDbClient(), userSession, TestDefaultOrganizationProvider.from(db)))); @Test public void test_definition() { - WebService.Action def = ws.getDef(); - assertThat(def.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("analysisId", "projectKey", "projectId"); - assertThat(def.changelog()).extracting(Change::getVersion, Change::getDescription).containsExactly( + WebService.Action action = ws.getDef(); + assertThat(action.changelog()).extracting(Change::getVersion, Change::getDescription).containsExactly( tuple("6.4", "The field 'ignoredConditions' is added to the response")); + assertThat(action.params()) + .extracting(WebService.Param::key, WebService.Param::isRequired) + .containsExactlyInAnyOrder( + tuple("analysisId", false), + tuple("projectKey", false), + tuple("projectId", false), + tuple("organization", false)); } @Test public void test_json_example() throws IOException { - ComponentDto project = db.components().insertPrivateProject(db.organizations().insert()); + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); userSession.addProjectPermission(UserRole.USER, project); MetricDto gateDetailsMetric = insertGateDetailMetric(); @@ -98,6 +107,7 @@ public class ProjectStatusActionTest { String response = ws.newRequest() .setParam("analysisId", snapshot.getUuid()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) .execute().getInput(); assertJson(response).isSimilarTo(getClass().getResource("project_status-example.json")); @@ -105,7 +115,8 @@ public class ProjectStatusActionTest { @Test public void return_past_status_when_project_is_referenced_by_past_analysis_id() throws IOException { - ComponentDto project = db.components().insertPrivateProject(db.organizations().insert()); + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); SnapshotDto pastAnalysis = dbClient.snapshotDao().insert(dbSession, newAnalysis(project) .setLast(false) .setPeriodMode("last_version") @@ -128,6 +139,7 @@ public class ProjectStatusActionTest { String response = ws.newRequest() .setParam(PARAM_ANALYSIS_ID, pastAnalysis.getUuid()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) .execute().getInput(); assertJson(response).isSimilarTo(getClass().getResource("project_status-example.json")); @@ -135,7 +147,8 @@ public class ProjectStatusActionTest { @Test public void return_live_status_when_project_is_referenced_by_its_id() throws IOException { - ComponentDto project = db.components().insertPrivateProject(db.organizations().insert()); + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); dbClient.snapshotDao().insert(dbSession, newAnalysis(project) .setPeriodMode("last_version") .setPeriodParam("2015-12-07") @@ -149,6 +162,7 @@ public class ProjectStatusActionTest { String response = ws.newRequest() .setParam(PARAM_PROJECT_ID, project.uuid()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) .execute().getInput(); assertJson(response).isSimilarTo(getClass().getResource("project_status-example.json")); @@ -156,7 +170,8 @@ public class ProjectStatusActionTest { @Test public void return_live_status_when_project_is_referenced_by_its_key() throws IOException { - ComponentDto project = db.components().insertComponent(ComponentTesting.newPrivateProjectDto(db.organizations().insert()).setDbKey("project-key")); + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); dbClient.snapshotDao().insert(dbSession, newAnalysis(project) .setPeriodMode("last_version") .setPeriodParam("2015-12-07") @@ -169,7 +184,8 @@ public class ProjectStatusActionTest { userSession.addProjectPermission(UserRole.USER, project); String response = ws.newRequest() - .setParam(PARAM_PROJECT_KEY, "project-key") + .setParam(PARAM_PROJECT_KEY, project.getKey()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) .execute().getInput(); assertJson(response).isSimilarTo(getClass().getResource("project_status-example.json")); @@ -177,13 +193,15 @@ public class ProjectStatusActionTest { @Test public void return_undefined_status_if_specified_analysis_is_not_found() { - ComponentDto project = db.components().insertPrivateProject(db.organizations().insert()); + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(project)); dbSession.commit(); userSession.addProjectPermission(UserRole.USER, project); ProjectStatusResponse result = ws.newRequest() .setParam(PARAM_ANALYSIS_ID, snapshot.getUuid()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) .executeProtobuf(ProjectStatusResponse.class); assertThat(result.getProjectStatus().getStatus()).isEqualTo(Status.NONE); @@ -192,11 +210,13 @@ public class ProjectStatusActionTest { @Test public void return_undefined_status_if_project_is_not_analyzed() { - ComponentDto project = db.components().insertPrivateProject(db.organizations().insert()); + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); userSession.addProjectPermission(UserRole.USER, project); ProjectStatusResponse result = ws.newRequest() .setParam(PARAM_PROJECT_ID, project.uuid()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) .executeProtobuf(ProjectStatusResponse.class); assertThat(result.getProjectStatus().getStatus()).isEqualTo(Status.NONE); @@ -205,30 +225,66 @@ public class ProjectStatusActionTest { @Test public void project_administrator_is_allowed_to_get_project_status() { - ComponentDto project = db.components().insertPrivateProject(db.organizations().insert()); + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(project)); dbSession.commit(); userSession.addProjectPermission(UserRole.ADMIN, project); ws.newRequest() .setParam(PARAM_ANALYSIS_ID, snapshot.getUuid()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) .executeProtobuf(ProjectStatusResponse.class); } @Test public void project_user_is_allowed_to_get_project_status() { - ComponentDto project = db.components().insertPrivateProject(db.organizations().insert()); + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(project)); dbSession.commit(); userSession.addProjectPermission(UserRole.USER, project); ws.newRequest() .setParam(PARAM_ANALYSIS_ID, snapshot.getUuid()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) + .executeProtobuf(ProjectStatusResponse.class); + } + + @Test + public void default_organization_is_used_when_no_organization_parameter() { + OrganizationDto organization = db.getDefaultOrganization(); + ComponentDto project = db.components().insertPrivateProject(organization); + userSession.logIn().addProjectPermission(UserRole.USER, project); + + ProjectStatusResponse result = ws.newRequest() + .setParam(PARAM_PROJECT_ID, project.uuid()) + .executeProtobuf(ProjectStatusResponse.class); + + assertThat(result.getProjectStatus().getStatus()).isEqualTo(Status.NONE); + } + + @Test + public void fail_when_project_does_not_not_belong_to_organization() { + OrganizationDto organization = db.organizations().insert(); + OrganizationDto otherOrganization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(otherOrganization); + SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(project)); + dbSession.commit(); + userSession.addProjectPermission(UserRole.ADMIN, project); + + expectedException.expect(NotFoundException.class); + expectedException.expectMessage(String.format("Project '%s' doesn't exist in organization '%s'", project.getKey(), organization.getKey())); + + ws.newRequest() + .setParam(PARAM_ANALYSIS_ID, snapshot.getUuid()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) .executeProtobuf(ProjectStatusResponse.class); } @Test public void fail_if_no_snapshot_id_found() { + OrganizationDto organization = db.organizations().insert(); logInAsSystemAdministrator(); expectedException.expect(NotFoundException.class); @@ -236,12 +292,14 @@ public class ProjectStatusActionTest { ws.newRequest() .setParam(PARAM_ANALYSIS_ID, ANALYSIS_ID) + .setParam(PARAM_ORGANIZATION, organization.getKey()) .executeProtobuf(ProjectStatusResponse.class); } @Test public void fail_if_insufficient_privileges() { - ComponentDto project = db.components().insertPrivateProject(db.organizations().insert()); + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(project)); dbSession.commit(); userSession.logIn(); @@ -250,11 +308,14 @@ public class ProjectStatusActionTest { ws.newRequest() .setParam(PARAM_ANALYSIS_ID, snapshot.getUuid()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) .executeProtobuf(ProjectStatusResponse.class); } @Test public void fail_if_project_id_and_ce_task_id_provided() { + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); logInAsSystemAdministrator(); expectedException.expect(BadRequestException.class); @@ -263,6 +324,7 @@ public class ProjectStatusActionTest { ws.newRequest() .setParam(PARAM_ANALYSIS_ID, "analysis-id") .setParam(PARAM_PROJECT_ID, "project-uuid") + .setParam(PARAM_ORGANIZATION, organization.getKey()) .execute().getInput(); } @@ -273,7 +335,9 @@ public class ProjectStatusActionTest { expectedException.expect(BadRequestException.class); expectedException.expectMessage("Either 'analysisId', 'projectId' or 'projectKey' must be provided"); - ws.newRequest().execute().getInput(); + ws.newRequest() + .execute() + .getInput(); } @Test @@ -289,6 +353,7 @@ public class ProjectStatusActionTest { ws.newRequest() .setParam(PARAM_PROJECT_KEY, branch.getDbKey()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) .execute(); } @@ -305,6 +370,7 @@ public class ProjectStatusActionTest { ws.newRequest() .setParam("projectId", branch.uuid()) + .setParam(PARAM_ORGANIZATION, organization.getKey()) .execute(); }