From 6de5e4f3d0630a7269625c5c855cbc7205e413d2 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Wed, 6 Dec 2017 19:28:32 +0100 Subject: [PATCH] SONAR-10134 Add organization parameter in api/qualitygates/select --- .../server/qualitygate/ws/SelectAction.java | 56 ++++---- .../qualitygate/ws/QualityGatesWsTest.java | 8 +- .../qualitygate/ws/SelectActionTest.java | 136 +++++++++++++----- 3 files changed, 127 insertions(+), 73 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java index 1002fd8d083..138510d5cfc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java @@ -19,40 +19,42 @@ */ package org.sonar.server.qualitygate.ws; -import com.google.common.base.Optional; +import java.util.Optional; import javax.annotation.Nullable; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; -import org.sonar.api.web.UserRole; import org.sonar.core.util.Uuids; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; -import org.sonar.db.permission.OrganizationPermission; +import org.sonar.db.organization.OrganizationDto; import org.sonar.db.property.PropertyDto; +import org.sonar.db.qualitygate.QGateWithOrgDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.component.ComponentFinder.ParamNames; -import org.sonar.server.user.UserSession; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.qualitygate.QualityGateFinder; +import static java.lang.String.format; import static org.sonar.server.qualitygate.QualityGates.SONAR_QUALITYGATE_PROPERTY; -import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; -import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; -import static org.sonar.server.ws.WsUtils.checkFound; import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.ACTION_SELECT; import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_GATE_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.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; public class SelectAction implements QualityGatesWsAction { private final DbClient dbClient; - private final UserSession userSession; private final ComponentFinder componentFinder; + private final QualityGatesWsSupport wsSupport; + private final QualityGateFinder qualityGateFinder; - public SelectAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder) { + public SelectAction(DbClient dbClient, ComponentFinder componentFinder, QualityGatesWsSupport wsSupport, QualityGateFinder qualityGateFinder) { this.dbClient = dbClient; - this.userSession = userSession; this.componentFinder = componentFinder; + this.wsSupport = wsSupport; + this.qualityGateFinder = qualityGateFinder; } @Override @@ -61,7 +63,7 @@ public class SelectAction implements QualityGatesWsAction { .setDescription("Associate a project to a quality gate.
" + "The '%s' or '%s' must be provided.
" + "Project id as a numeric value is deprecated since 6.1. Please use the id similar to '%s'.
" + - "Requires the 'Administer Quality Gates' permission.", + "Requires the 'Administer Quality Gates' permission.", PARAM_PROJECT_ID, PARAM_PROJECT_KEY, Uuids.UUID_EXAMPLE_02) .setPost(true) @@ -81,6 +83,8 @@ public class SelectAction implements QualityGatesWsAction { .setDescription("Project key") .setExampleValue(KEY_PROJECT_EXAMPLE_001) .setSince("6.1"); + + wsSupport.createOrganizationParam(action); } @Override @@ -90,45 +94,41 @@ public class SelectAction implements QualityGatesWsAction { String projectKey = request.param(PARAM_PROJECT_KEY); try (DbSession dbSession = dbClient.openSession(false)) { - checkQualityGate(dbSession, gateId); - ComponentDto project = getProject(dbSession, projectId, projectKey); + OrganizationDto organization = wsSupport.getOrganization(dbSession, request); + QGateWithOrgDto qualityGate = qualityGateFinder.getByOrganizationAndId(dbSession, organization, gateId); + ComponentDto project = getProject(dbSession, organization, projectId, projectKey); + wsSupport.checkCanAdminProject(organization, project); dbClient.propertiesDao().saveProperty(dbSession, new PropertyDto() .setKey(SONAR_QUALITYGATE_PROPERTY) .setResourceId(project.getId()) - .setValue(String.valueOf(gateId))); + .setValue(String.valueOf(qualityGate.getId()))); dbSession.commit(); } response.noContent(); } - private ComponentDto getProject(DbSession dbSession, @Nullable String projectId, @Nullable String projectKey) { + private ComponentDto getProject(DbSession dbSession, OrganizationDto organization, @Nullable String projectId, @Nullable String projectKey) { ComponentDto project = selectProjectById(dbSession, projectId) - .or(() -> componentFinder.getByUuidOrKey(dbSession, projectId, projectKey, ParamNames.PROJECT_ID_AND_KEY)); - - if (!userSession.hasPermission(OrganizationPermission.ADMINISTER_QUALITY_GATES, project.getOrganizationUuid()) && - !userSession.hasComponentPermission(UserRole.ADMIN, project)) { - throw insufficientPrivilegesException(); + .orElseGet(() -> componentFinder.getByUuidOrKey(dbSession, projectId, projectKey, ParamNames.PROJECT_ID_AND_KEY)); + if (project.getOrganizationUuid().equals(organization.getUuid())) { + return project; } - - return project; + throw new NotFoundException(format("Project '%s' doesn't exist in organization '%s'", project.getKey(), organization.getKey())); } private Optional selectProjectById(DbSession dbSession, @Nullable String projectId) { if (projectId == null) { - return Optional.absent(); + return Optional.empty(); } try { long dbId = Long.parseLong(projectId); - return dbClient.componentDao().selectById(dbSession, dbId); + return Optional.ofNullable(dbClient.componentDao().selectById(dbSession, dbId).orNull()); } catch (NumberFormatException e) { - return Optional.absent(); + return Optional.empty(); } } - private void checkQualityGate(DbSession dbSession, long id) { - checkFound(dbClient.qualityGateDao().selectById(dbSession, id), "There is no quality gate with id=" + id); - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java index 6b8127ed5c6..0a6b0377215 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java @@ -31,14 +31,11 @@ import org.mockito.runners.MockitoJUnitRunner; import org.sonar.api.server.ws.Change; import org.sonar.api.server.ws.WebService.Action; import org.sonar.api.server.ws.WebService.Controller; -import org.sonar.db.DbClient; import org.sonar.db.qualitygate.ProjectQgateAssociation; import org.sonar.db.qualitygate.ProjectQgateAssociationQuery; -import org.sonar.server.component.ComponentFinder; import org.sonar.server.qualitygate.QgateProjectFinder; import org.sonar.server.qualitygate.QgateProjectFinder.Association; import org.sonar.server.qualitygate.QualityGates; -import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.RemovedWebServiceHandler; import org.sonar.server.ws.WsTester; @@ -65,13 +62,10 @@ public class QualityGatesWsTest { @Before public void setUp() { - SelectAction selectAction = new SelectAction(mock(DbClient.class), mock(UserSessionRule.class), mock(ComponentFinder.class)); - tester = new WsTester(new QualityGatesWs( new SearchAction(projectFinder), new CreateAction(null, null, null, null), - new SetAsDefaultAction(qGates), - selectAction)); + new SetAsDefaultAction(qGates))); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SelectActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SelectActionTest.java index b08a915d318..cbb7e770f67 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SelectActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SelectActionTest.java @@ -23,21 +23,24 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.utils.System2; -import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.qualitygate.QGateWithOrgDto; import org.sonar.db.qualitygate.QualityGateDto; import org.sonar.server.component.TestComponentFinder; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.organization.TestDefaultOrganizationProvider; +import org.sonar.server.qualitygate.QualityGateFinder; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsActionTester; import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.api.web.UserRole.ADMIN; +import static org.sonar.api.web.UserRole.ISSUE_ADMIN; import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_GATES; import static org.sonar.server.qualitygate.QualityGates.SONAR_QUALITYGATE_PROPERTY; @@ -51,18 +54,22 @@ public class SelectActionTest { public DbTester db = DbTester.create(System2.INSTANCE); private DbClient dbClient = db.getDbClient(); - private SelectAction underTest = new SelectAction(dbClient, userSession, TestComponentFinder.from(db)); + private SelectAction underTest = new SelectAction(dbClient, TestComponentFinder.from(db), + new QualityGatesWsSupport(db.getDbClient(), userSession, TestDefaultOrganizationProvider.from(db)), + new QualityGateFinder(db.getDbClient())); private WsActionTester ws = new WsActionTester(underTest); @Test public void select_by_id() { - userSession.addPermission(ADMINISTER_QUALITY_GATES, db.getDefaultOrganization()); - QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); - ComponentDto project = db.components().insertPrivateProject(); + OrganizationDto organization = db.organizations().insert(); + userSession.addPermission(ADMINISTER_QUALITY_GATES, organization); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); + ComponentDto project = db.components().insertPrivateProject(organization); ws.newRequest() .setParam("gateId", qualityGate.getId().toString()) .setParam("projectId", project.getId().toString()) + .setParam("organization", organization.getKey()) .execute(); assertSelected(qualityGate, project); @@ -70,13 +77,15 @@ public class SelectActionTest { @Test public void select_by_uuid() { - userSession.addPermission(ADMINISTER_QUALITY_GATES, db.getDefaultOrganization()); - QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); - ComponentDto project = db.components().insertPrivateProject(); + OrganizationDto organization = db.organizations().insert(); + userSession.addPermission(ADMINISTER_QUALITY_GATES, organization); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); + ComponentDto project = db.components().insertPrivateProject(organization); ws.newRequest() .setParam("gateId", qualityGate.getId().toString()) .setParam("projectId", project.uuid()) + .setParam("organization", organization.getKey()) .execute(); assertSelected(qualityGate, project); @@ -84,13 +93,15 @@ public class SelectActionTest { @Test public void select_by_key() { - userSession.addPermission(ADMINISTER_QUALITY_GATES, db.getDefaultOrganization()); - QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); - ComponentDto project = db.components().insertPrivateProject(); + OrganizationDto organization = db.organizations().insert(); + userSession.addPermission(ADMINISTER_QUALITY_GATES, organization); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); + ComponentDto project = db.components().insertPrivateProject(organization); ws.newRequest() .setParam("gateId", qualityGate.getId().toString()) - .setParam("projectKey", project.getDbKey()) + .setParam("projectKey", project.getKey()) + .setParam("organization", organization.getKey()) .execute(); assertSelected(qualityGate, project); @@ -98,13 +109,15 @@ public class SelectActionTest { @Test public void project_admin() { - QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); - ComponentDto project = db.components().insertPrivateProject(); + OrganizationDto organization = db.organizations().insert(); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); + ComponentDto project = db.components().insertPrivateProject(organization); userSession.logIn().addProjectPermission(ADMIN, project); ws.newRequest() .setParam("gateId", qualityGate.getId().toString()) - .setParam("projectKey", project.getDbKey()) + .setParam("projectKey", project.getKey()) + .setParam("organization", organization.getKey()) .execute(); assertSelected(qualityGate, project); @@ -112,103 +125,148 @@ public class SelectActionTest { @Test public void gate_administrator_can_associate_a_gate_to_a_project() { - QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); - ComponentDto project = db.components().insertPrivateProject(); - userSession.logIn().addPermission(ADMINISTER_QUALITY_GATES, project.getOrganizationUuid()); + OrganizationDto organization = db.organizations().insert(); + userSession.addPermission(ADMINISTER_QUALITY_GATES, organization); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); + ComponentDto project = db.components().insertPrivateProject(organization); ws.newRequest() .setParam("gateId", qualityGate.getId().toString()) - .setParam("projectKey", project.getDbKey()) + .setParam("projectKey", project.getKey()) + .setParam("organization", organization.getKey()) + .execute(); + + assertSelected(qualityGate, project); + } + + @Test + public void default_organization_is_used_when_no_organization_parameter() { + OrganizationDto organization = db.getDefaultOrganization(); + userSession.addPermission(ADMINISTER_QUALITY_GATES, organization); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); + ComponentDto project = db.components().insertPrivateProject(organization); + + ws.newRequest() + .setParam("gateId", qualityGate.getId().toString()) + .setParam("projectKey", project.getKey()) .execute(); assertSelected(qualityGate, project); } + @Test + public void fail_when_project_belongs_to_another_organization() { + OrganizationDto organization = db.organizations().insert(); + userSession.addPermission(ADMINISTER_QUALITY_GATES, organization); + OrganizationDto anotherOrganization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(anotherOrganization); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); + + expectedException.expect(NotFoundException.class); + expectedException.expectMessage(format("Project '%s' doesn't exist in organization '%s'", project.getKey(), organization.getKey())); + + ws.newRequest() + .setParam("gateId", qualityGate.getId().toString()) + .setParam("projectKey", project.getKey()) + .setParam("organization", organization.getKey()) + .execute(); + } + @Test public void fail_when_no_quality_gate() { - userSession.addPermission(ADMINISTER_QUALITY_GATES, db.getDefaultOrganization()); - ComponentDto project = db.components().insertPrivateProject(); + OrganizationDto organization = db.organizations().insert(); + userSession.addPermission(ADMINISTER_QUALITY_GATES, organization); + ComponentDto project = db.components().insertPrivateProject(organization); expectedException.expect(NotFoundException.class); ws.newRequest() .setParam("gateId", String.valueOf("1")) - .setParam("projectKey", project.getDbKey()) + .setParam("projectKey", project.getKey()) + .setParam("organization", organization.getKey()) .execute(); } @Test public void fail_when_no_project_id() { - userSession.addPermission(ADMINISTER_QUALITY_GATES, db.getDefaultOrganization()); - QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); + OrganizationDto organization = db.organizations().insert(); + userSession.addPermission(ADMINISTER_QUALITY_GATES, organization); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); expectedException.expect(NotFoundException.class); ws.newRequest() .setParam("gateId", qualityGate.getId().toString()) .setParam("projectId", String.valueOf((Long) 1L)) + .setParam("organization", organization.getKey()) .execute(); } @Test public void fail_when_no_project_key() { - userSession.addPermission(ADMINISTER_QUALITY_GATES, db.getDefaultOrganization()); - QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); + OrganizationDto organization = db.organizations().insert(); + userSession.addPermission(ADMINISTER_QUALITY_GATES, organization); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); expectedException.expect(NotFoundException.class); ws.newRequest() .setParam("gateId", qualityGate.getId().toString()) .setParam("projectKey", "unknown") + .setParam("organization", organization.getKey()) .execute(); } @Test public void fail_when_anonymous() { - userSession.addPermission(ADMINISTER_QUALITY_GATES, db.getDefaultOrganization()); - QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); - ComponentDto project = db.components().insertPrivateProject(); - + OrganizationDto organization = db.organizations().insert(); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); + ComponentDto project = db.components().insertPrivateProject(organization); userSession.anonymous(); expectedException.expect(ForbiddenException.class); ws.newRequest() .setParam("gateId", qualityGate.getId().toString()) - .setParam("projectKey", project.getDbKey()) + .setParam("projectKey", project.getKey()) + .setParam("organization", organization.getKey()) .execute(); } @Test public void fail_when_not_project_admin() { - QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); - ComponentDto project = db.components().insertPrivateProject(); - userSession.logIn().addProjectPermission(UserRole.ISSUE_ADMIN, project); + OrganizationDto organization = db.organizations().insert(); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); + ComponentDto project = db.components().insertPrivateProject(organization); + userSession.logIn().addProjectPermission(ISSUE_ADMIN, project); expectedException.expect(ForbiddenException.class); ws.newRequest() .setParam("gateId", qualityGate.getId().toString()) .setParam("projectKey", project.getDbKey()) + .setParam("organization", organization.getKey()) .execute(); } @Test public void fail_when_not_quality_gates_admin() { - QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); - ComponentDto project = db.components().insertPrivateProject(); + OrganizationDto organization = db.organizations().insert(); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); + ComponentDto project = db.components().insertPrivateProject(organization); userSession.logIn(); expectedException.expect(ForbiddenException.class); ws.newRequest() .setParam("gateId", qualityGate.getId().toString()) .setParam("projectKey", project.getDbKey()) + .setParam("organization", organization.getKey()) .execute(); } @Test public void fail_when_using_branch_db_key() throws Exception { OrganizationDto organization = db.organizations().insert(); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); ComponentDto project = db.components().insertMainBranch(organization); userSession.logIn().addProjectPermission(ADMIN, project); ComponentDto branch = db.components().insertProjectBranch(project); - QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); expectedException.expect(NotFoundException.class); expectedException.expectMessage(format("Component key '%s' not found", branch.getDbKey())); @@ -216,16 +274,17 @@ public class SelectActionTest { ws.newRequest() .setParam("gateId", qualityGate.getId().toString()) .setParam("projectKey", branch.getDbKey()) + .setParam("organization", organization.getKey()) .execute(); } @Test public void fail_when_using_branch_id() { OrganizationDto organization = db.organizations().insert(); + QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization); ComponentDto project = db.components().insertMainBranch(organization); userSession.logIn().addProjectPermission(ADMIN, project); ComponentDto branch = db.components().insertProjectBranch(project); - QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); expectedException.expect(NotFoundException.class); expectedException.expectMessage(format("Component id '%s' not found", branch.uuid())); @@ -233,6 +292,7 @@ public class SelectActionTest { ws.newRequest() .setParam("gateId", qualityGate.getId().toString()) .setParam("projectId", branch.uuid()) + .setParam("organization", organization.getKey()) .execute(); } -- 2.39.5