import org.sonar.server.qualitygate.ws.GetByProjectAction;
import org.sonar.server.qualitygate.ws.ListAction;
import org.sonar.server.qualitygate.ws.ProjectStatusAction;
+import org.sonar.server.qualitygate.ws.QGateWsSupport;
import org.sonar.server.qualitygate.ws.QualityGatesWs;
import org.sonar.server.qualitygate.ws.QualityGatesWsSupport;
import org.sonar.server.qualitygate.ws.RenameAction;
QgateProjectFinder.class,
QualityGateFinder.class,
// WS
+ QGateWsSupport.class,
QualityGatesWsSupport.class,
QualityGatesWs.class,
ListAction.class,
import com.google.common.io.Resources;
import java.util.Collection;
-import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
import org.sonar.api.server.ws.Change;
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.property.PropertyDto;
import org.sonar.db.qualitygate.QualityGateDto;
import org.sonarqube.ws.Qualitygates.ListWsResponse;
+import org.sonarqube.ws.Qualitygates.ListWsResponse.QualityGate;
import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.core.util.stream.MoreCollectors.toList;
-import static org.sonar.server.qualitygate.QualityGates.SONAR_QUALITYGATE_PROPERTY;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
public class ListAction implements QualityGatesWsAction {
private final DbClient dbClient;
+ private final QGateWsSupport wsSupport;
- public ListAction(DbClient dbClient) {
+ public ListAction(DbClient dbClient, QGateWsSupport wsSupport) {
this.dbClient = dbClient;
+ this.wsSupport = wsSupport;
}
@Override
.setChangelog(
new Change("7.0", "'isDefault' field is added on quality gate"),
new Change("7.0", "'default' field on root level is deprecated"),
- new Change("7.0", "'isBuiltIn' field is added in the response"))
+ new Change("7.0", "'isBuiltIn' field is added in the response"),
+ new Change("7.0", "'actions' fields are added in the response"))
.setHandler(this);
}
@Override
public void handle(Request request, Response response) {
try (DbSession dbSession = dbClient.openSession(false)) {
- QualityGateDto defaultQualityGate = getDefault(dbSession);
+ QualityGateDto defaultQualityGate = wsSupport.getDefault(dbSession);
Collection<QualityGateDto> qualityGates = dbClient.qualityGateDao().selectAll(dbSession);
writeProtobuf(buildResponse(qualityGates, defaultQualityGate), request, response);
}
}
- private static ListWsResponse buildResponse(Collection<QualityGateDto> qualityGates, @Nullable QualityGateDto defaultQualityGate) {
+ private ListWsResponse buildResponse(Collection<QualityGateDto> qualityGates, @Nullable QualityGateDto defaultQualityGate) {
Long defaultId = defaultQualityGate == null ? null : defaultQualityGate.getId();
ListWsResponse.Builder builder = ListWsResponse.newBuilder()
+ .setActions(ListWsResponse.RootActions.newBuilder().setCreate(wsSupport.isQualityGateAdmin()))
.addAllQualitygates(qualityGates.stream()
- .map(qualityGate -> ListWsResponse.QualityGate.newBuilder()
+ .map(qualityGate -> QualityGate.newBuilder()
.setId(qualityGate.getId())
.setName(qualityGate.getName())
.setIsDefault(qualityGate.getId().equals(defaultId))
.setIsBuiltIn(qualityGate.isBuiltIn())
+ .setActions(wsSupport.getActions(qualityGate, defaultQualityGate))
.build())
.collect(toList()));
setNullable(defaultId, builder::setDefault);
return builder.build();
}
- @CheckForNull
- private QualityGateDto getDefault(DbSession dbSession) {
- Long defaultId = getDefaultId(dbSession);
- if (defaultId == null) {
- return null;
- }
- return dbClient.qualityGateDao().selectById(dbSession, defaultId);
- }
-
- @CheckForNull
- private Long getDefaultId(DbSession dbSession) {
- PropertyDto defaultQgate = dbClient.propertiesDao().selectGlobalProperty(dbSession, SONAR_QUALITYGATE_PROPERTY);
- if (defaultQgate == null || StringUtils.isBlank(defaultQgate.getValue())) {
- return null;
- }
- return Long.valueOf(defaultQgate.getValue());
- }
-
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info 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.qualitygate.ws;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.server.ServerSide;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.property.PropertyDto;
+import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.server.organization.DefaultOrganizationProvider;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.Qualitygates;
+
+import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_GATES;
+import static org.sonar.server.qualitygate.QualityGates.SONAR_QUALITYGATE_PROPERTY;
+
+@ServerSide
+public class QGateWsSupport {
+
+ private final DbClient dbClient;
+ private final UserSession userSession;
+ private final DefaultOrganizationProvider defaultOrganizationProvider;
+
+ public QGateWsSupport(DbClient dbClient, UserSession userSession, DefaultOrganizationProvider defaultOrganizationProvider) {
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ this.defaultOrganizationProvider = defaultOrganizationProvider;
+ }
+
+ boolean isQualityGateAdmin() {
+ return userSession.hasPermission(ADMINISTER_QUALITY_GATES, defaultOrganizationProvider.get().getUuid());
+ }
+
+ Qualitygates.Actions getActions(QualityGateDto qualityGate, @Nullable QualityGateDto defaultQualityGate) {
+ Long defaultId = defaultQualityGate == null ? null : defaultQualityGate.getId();
+ boolean isDefault = qualityGate.getId().equals(defaultId);
+ boolean isBuiltIn = qualityGate.isBuiltIn();
+ boolean isQualityGateAdmin = isQualityGateAdmin();
+ return Qualitygates.Actions.newBuilder()
+ .setCopy(isQualityGateAdmin)
+ .setEdit(!isBuiltIn && isQualityGateAdmin)
+ .setSetAsDefault(!isDefault && isQualityGateAdmin)
+ .setAssociateProjects(!isDefault && isQualityGateAdmin)
+ .build();
+ }
+
+ @CheckForNull
+ QualityGateDto getDefault(DbSession dbSession) {
+ Long defaultId = getDefaultId(dbSession);
+ if (defaultId == null) {
+ return null;
+ }
+ return dbClient.qualityGateDao().selectById(dbSession, defaultId);
+ }
+
+ @CheckForNull
+ private Long getDefaultId(DbSession dbSession) {
+ PropertyDto defaultQgate = dbClient.propertiesDao().selectGlobalProperty(dbSession, SONAR_QUALITYGATE_PROPERTY);
+ if (defaultQgate == null || StringUtils.isBlank(defaultQgate.getValue())) {
+ return null;
+ }
+ return Long.valueOf(defaultQgate.getValue());
+ }
+
+}
"id": 2,
"name": "Sonar way",
"isDefault": true,
- "isBuiltIn": true
+ "isBuiltIn": true,
+ "actions": {
+ "edit": false,
+ "setAsDefault": false,
+ "copy": true,
+ "associateProjects": false
+ }
},
{
"id": 4,
"name": "Sonar way - Without Coverage",
"isDefault": false,
- "isBuiltIn": false
+ "isBuiltIn": false,
+ "actions": {
+ "edit": true,
+ "setAsDefault": true,
+ "copy": true,
+ "associateProjects": true
+ }
}
],
+ "actions": {
+ "create": true
+ },
"default": 2
}
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new QualityGateModule().configure(container);
- assertThat(container.size()).isEqualTo(24 + 2);
+ assertThat(container.size()).isEqualTo(25 + 2);
}
}
import org.sonar.api.server.ws.WebService;
import org.sonar.db.DbTester;
import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.server.organization.DefaultOrganizationProvider;
+import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.Qualitygates.ListWsResponse.QualityGate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.tuple;
+import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_GATES;
+import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.Qualitygates.ListWsResponse;
public UserSessionRule userSession = UserSessionRule.standalone();
@Rule
public DbTester db = DbTester.create();
+ private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
- private WsActionTester ws = new WsActionTester(new ListAction(db.getDbClient()));
+ private WsActionTester ws = new WsActionTester(new ListAction(db.getDbClient(), new QGateWsSupport(db.getDbClient(), userSession, defaultOrganizationProvider)));
@Test
public void verify_definition() {
.containsExactlyInAnyOrder(
tuple("7.0", "'isDefault' field is added on quality gate"),
tuple("7.0", "'default' field on root level is deprecated"),
- tuple("7.0", "'isBuiltIn' field is added in the response"));
+ tuple("7.0", "'isBuiltIn' field is added in the response"),
+ tuple("7.0", "'actions' fields are added in the response"));
assertThat(action.params()).isEmpty();
}
@Test
public void json_example() {
+ userSession.logIn("admin").addPermission(ADMINISTER_QUALITY_GATES, defaultOrganizationProvider.get().getUuid());
QualityGateDto defaultQualityGate = db.qualityGates().insertQualityGate(qualityGate -> qualityGate.setName("Sonar way").setBuiltIn(true));
db.qualityGates().insertQualityGate(qualityGate -> qualityGate.setName("Sonar way - Without Coverage").setBuiltIn(false));
db.qualityGates().setDefaultQualityGate(defaultQualityGate);
.containsExactlyInAnyOrder(tuple(qualityGate.getId(), qualityGate.getName(), false));
}
+ @Test
+ public void actions_with_quality_gate_administer_permission() {
+ userSession.logIn("john").addPermission(ADMINISTER_QUALITY_GATES, defaultOrganizationProvider.get().getUuid());
+ QualityGateDto defaultQualityGate = db.qualityGates().insertQualityGate(qg -> qg.setName("Sonar way").setBuiltIn(true));
+ QualityGateDto otherQualityGate = db.qualityGates().insertQualityGate(qg -> qg.setName("Sonar way - Without Coverage").setBuiltIn(false));
+ db.qualityGates().setDefaultQualityGate(defaultQualityGate);
+
+ ListWsResponse response = ws.newRequest().executeProtobuf(ListWsResponse.class);
+
+ assertThat(response.getActions())
+ .extracting(ListWsResponse.RootActions::getCreate)
+ .containsExactlyInAnyOrder(true);
+ assertThat(response.getQualitygatesList())
+ .extracting(QualityGate::getName,
+ qg -> qg.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault(), qp -> qp.getActions().getAssociateProjects())
+ .containsExactlyInAnyOrder(
+ tuple(defaultQualityGate.getName(), false, true, false, false),
+ tuple(otherQualityGate.getName(), true, true, true, true));
+ }
+
+ @Test
+ public void actions_without_quality_gate_administer_permission() {
+ userSession.logIn("john").addPermission(ADMINISTER_QUALITY_PROFILES, defaultOrganizationProvider.get().getUuid());
+ QualityGateDto defaultQualityGate = db.qualityGates().insertQualityGate(qg -> qg.setName("Sonar way").setBuiltIn(true));
+ QualityGateDto otherQualityGate = db.qualityGates().insertQualityGate(qg -> qg.setName("Sonar way - Without Coverage").setBuiltIn(false));
+ db.qualityGates().setDefaultQualityGate(defaultQualityGate);
+
+ ListWsResponse response = ws.newRequest().executeProtobuf(ListWsResponse.class);
+
+ assertThat(response.getActions())
+ .extracting(ListWsResponse.RootActions::getCreate)
+ .containsExactlyInAnyOrder(false);
+ assertThat(response.getQualitygatesList())
+ .extracting(QualityGate::getName,
+ qg -> qg.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault(), qp -> qp.getActions().getAssociateProjects())
+ .containsExactlyInAnyOrder(
+ tuple(defaultQualityGate.getName(), false, false, false, false),
+ tuple(otherQualityGate.getName(), false, false, false, false));
+ }
+
@Test
public void empty() {
ListWsResponse response = ws.newRequest().executeProtobuf(ListWsResponse.class);
repeated QualityGate qualitygates = 1;
// Deprecated since 7.0
optional int64 default = 2;
+ optional RootActions actions = 3;
message QualityGate {
optional int64 id = 1;
optional string name = 2;
optional bool isDefault = 3;
optional bool isBuiltIn = 4;
+ optional Actions actions = 5;
}
+
+ message RootActions {
+ optional bool create = 1;
+ }
+}
+
+message Actions {
+ optional bool edit = 1;
+ optional bool setAsDefault = 2;
+ optional bool copy = 3;
+ optional bool associateProjects = 4;
}
optional bool edit = 1;
optional bool setAsDefault = 2;
optional bool copy = 3;
- }
+ }
}
message Actions {