aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-webapi
diff options
context:
space:
mode:
authorbelen-pruvost-sonarsource <belen.pruvost@sonarsource.com>2021-10-13 18:25:51 +0200
committersonartech <sonartech@sonarsource.com>2021-10-22 20:03:27 +0000
commit06672268a78369a8442e1d8f291b2d80c6d95f9a (patch)
tree9bbcee010a24b2294e07e4f4558905bc255d5bb5 /server/sonar-webserver-webapi
parent2d5130b8f3150af215721aa44d76fa97612874f1 (diff)
downloadsonarqube-06672268a78369a8442e1d8f291b2d80c6d95f9a.tar.gz
sonarqube-06672268a78369a8442e1d8f291b2d80c6d95f9a.zip
SONAR-15441 - Create api/qualitygates/add_group endpoint
Diffstat (limited to 'server/sonar-webserver-webapi')
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddGroupAction.java112
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGateWsModule.java4
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsParameters.java1
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsSupport.java8
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/AddGroupActionTest.java175
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/QualityGateWsModuleTest.java2
6 files changed, 298 insertions, 4 deletions
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddGroupAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddGroupAction.java
new file mode 100644
index 00000000000..c3cfa0c7c6b
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddGroupAction.java
@@ -0,0 +1,112 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 java.util.Optional;
+import org.jetbrains.annotations.NotNull;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.db.qualitygate.QualityGateGroupPermissionsDto;
+import org.sonar.db.user.GroupDto;
+
+import static org.sonar.server.exceptions.NotFoundException.checkFoundWithOptional;
+import static org.sonar.server.qualitygate.ws.CreateAction.NAME_MAXIMUM_LENGTH;
+import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.ACTION_ADD_GROUP;
+import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_GATE_NAME;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_NAME;
+
+public class AddGroupAction implements QualityGatesWsAction {
+ private final DbClient dbClient;
+ private final UuidFactory uuidFactory;
+ private final QualityGatesWsSupport wsSupport;
+
+ public AddGroupAction(DbClient dbClient, UuidFactory uuidFactory, QualityGatesWsSupport wsSupport) {
+ this.dbClient = dbClient;
+ this.uuidFactory = uuidFactory;
+ this.wsSupport = wsSupport;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context
+ .createAction(ACTION_ADD_GROUP)
+ .setDescription("Allow a group of users to edit a Quality Gate.<br>" +
+ "Requires one of the following permissions:" +
+ "<ul>" +
+ " <li>'Administer Quality Gates'</li>" +
+ " <li>Edit right on the specified quality gate</li>" +
+ "</ul>")
+ .setHandler(this)
+ .setPost(true)
+ .setInternal(true)
+ .setSince("9.2");
+
+ action.createParam(PARAM_GATE_NAME)
+ .setDescription("Quality Gate name")
+ .setRequired(true)
+ .setMaximumLength(NAME_MAXIMUM_LENGTH)
+ .setExampleValue("SonarSource Way");
+
+ action.createParam(PARAM_GROUP_NAME)
+ .setDescription("Group name or 'anyone' (case insensitive)")
+ .setRequired(true)
+ .setExampleValue("sonar-administrators");
+
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ final String groupName = request.mandatoryParam(PARAM_GROUP_NAME);
+ final String qualityGateName = request.mandatoryParam(PARAM_GATE_NAME);
+
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ QualityGateDto qualityGateDto = wsSupport.getByName(dbSession, qualityGateName);
+ wsSupport.checkCanLimitedEdit(dbSession, qualityGateDto);
+ GroupDto group = getGroup(dbSession, groupName);
+ addGroup(dbSession, qualityGateDto, group);
+ }
+ response.noContent();
+ }
+
+ @NotNull
+ private GroupDto getGroup(DbSession dbSession, String groupName) {
+ Optional<GroupDto> group = dbClient.groupDao().selectByName(dbSession, groupName);
+ checkFoundWithOptional(group, "Group with name '%s' is not found", groupName);
+ return group.get();
+ }
+
+ private void addGroup(DbSession dbSession, QualityGateDto qualityGate, GroupDto group) {
+ if (dbClient.qualityGateGroupPermissionsDao().exists(dbSession, qualityGate, group)) {
+ return;
+ }
+ dbClient.qualityGateGroupPermissionsDao().insert(dbSession,
+ new QualityGateGroupPermissionsDto()
+ .setUuid(uuidFactory.create())
+ .setGroupUuid(group.getUuid())
+ .setQualityGateUuid(qualityGate.getUuid()));
+ dbSession.commit();
+ }
+
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGateWsModule.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGateWsModule.java
index b453501cf57..b018c949ffb 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGateWsModule.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGateWsModule.java
@@ -42,8 +42,8 @@ public class QualityGateWsModule extends Module {
DeleteConditionAction.class,
UpdateConditionAction.class,
ProjectStatusAction.class,
- GetByProjectAction.class
-
+ GetByProjectAction.class,
+ AddGroupAction.class
);
}
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsParameters.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsParameters.java
index 960ec78b0fd..cc2e826581e 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsParameters.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsParameters.java
@@ -29,6 +29,7 @@ public class QualityGatesWsParameters {
public static final String ACTION_CREATE = "create";
public static final String ACTION_CREATE_CONDITION = "create_condition";
public static final String ACTION_UPDATE_CONDITION = "update_condition";
+ public static final String ACTION_ADD_GROUP = "add_group";
public static final String ACTION_ADD_USER = "add_user";
public static final String PARAM_ANALYSIS_ID = "analysisId";
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsSupport.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsSupport.java
index c3daf8d406d..a958f63c638 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsSupport.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsSupport.java
@@ -88,11 +88,17 @@ public class QualityGatesWsSupport {
void checkCanLimitedEdit(DbSession dbSession, QualityGateDto qualityGate) {
checkNotBuiltIn(qualityGate);
- if (!userSession.hasPermission(ADMINISTER_QUALITY_GATES) && !userHasPermission(dbSession, qualityGate)) {
+ if (!userSession.hasPermission(ADMINISTER_QUALITY_GATES)
+ && !userHasPermission(dbSession, qualityGate)
+ && !userHasGroupPermission(dbSession, qualityGate)) {
throw insufficientPrivilegesException();
}
}
+ boolean userHasGroupPermission(DbSession dbSession, QualityGateDto qualityGate) {
+ return userSession.isLoggedIn() && dbClient.qualityGateGroupPermissionsDao().exists(dbSession, qualityGate, userSession.getGroups());
+ }
+
boolean userHasPermission(DbSession dbSession, QualityGateDto qualityGate) {
return userSession.isLoggedIn() && dbClient.qualityGateUserPermissionDao().exists(dbSession, qualityGate.getUuid(), userSession.getUuid());
}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/AddGroupActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/AddGroupActionTest.java
new file mode 100644
index 00000000000..4b871cc4f2d
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/AddGroupActionTest.java
@@ -0,0 +1,175 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.permission.GlobalPermission;
+import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.db.user.GroupDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.component.TestComponentFinder;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_GATE_NAME;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_NAME;
+
+@RunWith(DataProviderRunner.class)
+public class AddGroupActionTest {
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+
+ private final DbClient dbClient = db.getDbClient();
+ private final QualityGatesWsSupport wsSupport = new QualityGatesWsSupport(dbClient, userSession, TestComponentFinder.from(db));
+ private final UuidFactory uuidFactory = UuidFactoryFast.getInstance();
+ private final WsActionTester ws = new WsActionTester(new AddGroupAction(dbClient, uuidFactory, wsSupport));
+
+ @Test
+ public void test_definition() {
+ WebService.Action def = ws.getDef();
+ assertThat(def.key()).isEqualTo("add_group");
+ assertThat(def.isPost()).isTrue();
+ assertThat(def.isInternal()).isTrue();
+ assertThat(def.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("groupName", "gateName");
+ }
+
+ @Test
+ public void add_group() {
+ QualityGateDto qualityGateDto = db.qualityGates().insertQualityGate();
+ GroupDto group = db.users().insertDefaultGroup();
+ userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES);
+
+ TestResponse response = ws.newRequest()
+ .setParam(PARAM_GATE_NAME, qualityGateDto.getName())
+ .setParam(PARAM_GROUP_NAME, group.getName())
+ .execute();
+
+ assertThat(response.getStatus()).isEqualTo(204);
+ assertThat(dbClient.qualityGateGroupPermissionsDao().exists(db.getSession(), qualityGateDto, group)).isTrue();
+ }
+
+ @Test
+ public void does_nothing_when_group_can_already_edit_qualityGateDto() {
+ QualityGateDto qualityGateDto = db.qualityGates().insertQualityGate();
+ GroupDto group = db.users().insertDefaultGroup();
+
+ db.qualityGates().addGroupPermission(qualityGateDto, group);
+ assertThat(dbClient.qualityGateGroupPermissionsDao().exists(db.getSession(), qualityGateDto, group)).isTrue();
+ userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES);
+
+ ws.newRequest()
+ .setParam(PARAM_GATE_NAME, qualityGateDto.getName())
+ .setParam(PARAM_GROUP_NAME, group.getName())
+ .execute();
+
+ assertThat(dbClient.qualityGateGroupPermissionsDao().exists(db.getSession(), qualityGateDto, group)).isTrue();
+ }
+
+ @Test
+ public void quality_gate_administers_can_add_group() {
+ QualityGateDto qualityGateDto = db.qualityGates().insertQualityGate();
+ GroupDto group = db.users().insertDefaultGroup();
+ userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES);
+
+ ws.newRequest()
+ .setParam(PARAM_GATE_NAME, qualityGateDto.getName())
+ .setParam(PARAM_GROUP_NAME, group.getName())
+ .execute();
+
+ assertThat(dbClient.qualityGateGroupPermissionsDao().exists(db.getSession(), qualityGateDto, group)).isTrue();
+ }
+
+ @Test
+ public void quality_gate_editors_can_add_group() {
+ QualityGateDto qualityGateDto = db.qualityGates().insertQualityGate();
+
+ GroupDto originalGroup = db.users().insertDefaultGroup();
+ UserDto userAllowedToEditQualityGate = db.users().insertUser();
+ db.users().insertMember(originalGroup, userAllowedToEditQualityGate);
+
+ db.qualityGates().addGroupPermission(qualityGateDto, originalGroup);
+ userSession.logIn(userAllowedToEditQualityGate).setGroups(originalGroup);
+ GroupDto newGroup = db.users().insertGroup();
+
+ ws.newRequest()
+ .setParam(PARAM_GATE_NAME, qualityGateDto.getName())
+ .setParam(PARAM_GROUP_NAME, newGroup.getName())
+ .execute();
+
+ assertThat(dbClient.qualityGateGroupPermissionsDao().exists(db.getSession(), qualityGateDto, originalGroup)).isTrue();
+ }
+
+ @Test
+ public void fail_when_group_does_not_exist() {
+ QualityGateDto qualityGateDto = db.qualityGates().insertQualityGate();
+ userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES);
+
+ TestRequest request = ws.newRequest()
+ .setParam(PARAM_GATE_NAME, qualityGateDto.getName())
+ .setParam(PARAM_GROUP_NAME, "unknown");
+
+ assertThatThrownBy(() -> request.execute())
+ .isInstanceOf(NotFoundException.class)
+ .hasMessage("Group with name 'unknown' is not found");
+ }
+
+ @Test
+ public void fail_when_qualityGateDto_does_not_exist() {
+ GroupDto group = db.users().insertDefaultGroup();
+ userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES);
+
+ TestRequest request = ws.newRequest()
+ .setParam(PARAM_GATE_NAME, "unknown")
+ .setParam(PARAM_GROUP_NAME, group.getName());
+
+ assertThatThrownBy(() -> request.execute())
+ .isInstanceOf(NotFoundException.class)
+ .hasMessage("No quality gate has been found for name unknown");
+ }
+
+ @Test
+ public void fail_when_not_enough_permission() {
+ QualityGateDto qualityGateDto = db.qualityGates().insertQualityGate();
+ GroupDto group = db.users().insertDefaultGroup();
+
+ TestRequest request = ws.newRequest()
+ .setParam(PARAM_GATE_NAME, qualityGateDto.getName())
+ .setParam(PARAM_GROUP_NAME, group.getName());
+
+ assertThatThrownBy(() -> request.execute()).isInstanceOf(ForbiddenException.class);
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/QualityGateWsModuleTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/QualityGateWsModuleTest.java
index dc59e33e600..d7b30969647 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/QualityGateWsModuleTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/QualityGateWsModuleTest.java
@@ -30,7 +30,7 @@ public class QualityGateWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new QualityGateWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 18);
+ assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 19);
}
}