]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-15441 - QG Groups Remove Endpoint
authorBelen Pruvost <belen.pruvost@sonarsource.com>
Tue, 19 Oct 2021 10:27:16 +0000 (12:27 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 22 Oct 2021 20:03:27 +0000 (20:03 +0000)
server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsMapper.java
server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateGroupPermissionsMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsDaoTest.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AbstractGroupAction.java [new file with mode: 0644]
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddGroupAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGateWsModule.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsParameters.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/RemoveGroupAction.java [new file with mode: 0644]
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/QualityGateWsModuleTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/RemoveGroupActionTest.java [new file with mode: 0644]

index a95d8f5235f0cb3206ee1d39935e331d5cdc0017..e3c387411116101c339412927ef9185ede789969 100644 (file)
@@ -68,4 +68,8 @@ public class QualityGateGroupPermissionsDao implements Dao {
   public int countByQuery(DbSession dbSession, SearchPermissionQuery query) {
     return mapper(dbSession).countByQuery(query);
   }
+
+  public void deleteByQualityGateAndGroup(DbSession dbSession, QualityGateDto qualityGate, GroupDto group) {
+    mapper(dbSession).delete(qualityGate.getUuid(), group.getUuid());
+  }
 }
index 2d0800155cfd3f470a2c484758ffb8f5f93a2de0..eef27294b4239354d4b009c65c98cd4682e1c6f2 100644 (file)
@@ -36,4 +36,7 @@ public interface QualityGateGroupPermissionsMapper {
   List<SearchGroupMembershipDto> selectByQuery(@Param("query") SearchPermissionQuery query, @Param("pagination") Pagination pagination);
 
   int countByQuery(@Param("query") SearchPermissionQuery query);
+
+  void delete(@Param("qualityGateUuid") String qualityGateUuid, @Param("groupUuid") String groupUuid);
+
 }
index 740123d047fdc6e72614ba865968dd74161c3ff0..95e7ad615c1ec53cf31471ae67965256b8f6332f 100644 (file)
     )
   </insert>
 
+  <delete id="delete">
+    delete from qgate_group_permissions
+    where quality_gate_uuid = #{qualityGateUuid, jdbcType=VARCHAR}
+    and group_uuid = #{groupUuid, jdbcType=VARCHAR}
+  </delete>
+
 </mapper>
index 1f8d10b9a86bd5a1a97e0f91d13c98aa2e273216..cd8d5894106572d464f4a335efe145419ac80993 100644 (file)
@@ -202,6 +202,19 @@ public class QualityGateGroupPermissionsDaoTest {
       .containsExactly(group1.getUuid(), group2.getUuid(), group3.getUuid());
   }
 
+  @Test
+  public void deleteByQProfileAndGroup() {
+    QualityGateDto qualityGateDto = insertQualityGate();
+    GroupDto group = dbTester.users().insertGroup();
+    insertQualityGateGroupPermission(qualityGateDto.getUuid(), group.getUuid());
+
+    assertThat(underTest.exists(dbSession, qualityGateDto, group)).isTrue();
+
+    underTest.deleteByQualityGateAndGroup(dbSession, qualityGateDto, group);
+
+    assertThat(underTest.exists(dbSession, qualityGateDto, group)).isFalse();
+  }
+
   private QualityGateDto insertQualityGate() {
     QualityGateDto qg = new QualityGateDto()
       .setUuid(randomAlphabetic(5))
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AbstractGroupAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AbstractGroupAction.java
new file mode 100644 (file)
index 0000000..78fba11
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.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.qualitygate.QualityGateDto;
+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.PARAM_GATE_NAME;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_NAME;
+
+public abstract class AbstractGroupAction implements QualityGatesWsAction {
+  protected final DbClient dbClient;
+  protected final QualityGatesWsSupport wsSupport;
+
+  protected AbstractGroupAction(DbClient dbClient, QualityGatesWsSupport wsSupport) {
+    this.dbClient = dbClient;
+    this.wsSupport = wsSupport;
+  }
+
+  protected void defineGateAndGroupParameters(WebService.NewAction action) {
+    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);
+      apply(dbSession, qualityGateDto, group);
+    }
+    response.noContent();
+  }
+
+  protected abstract void apply(DbSession dbSession, QualityGateDto qualityGate, GroupDto group);
+
+  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();
+  }
+}
index c3cfa0c7c6b642bc2031cf7528a1c1b3ab100203..2924ac68ca9f53c70f5c53c8050142b6bbff6d23 100644 (file)
  */
 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;
@@ -31,21 +27,14 @@ 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;
+public class AddGroupAction extends AbstractGroupAction {
   private final UuidFactory uuidFactory;
-  private final QualityGatesWsSupport wsSupport;
 
   public AddGroupAction(DbClient dbClient, UuidFactory uuidFactory, QualityGatesWsSupport wsSupport) {
-    this.dbClient = dbClient;
+    super(dbClient, wsSupport);
     this.uuidFactory = uuidFactory;
-    this.wsSupport = wsSupport;
   }
 
   @Override
@@ -63,41 +52,11 @@ public class AddGroupAction implements QualityGatesWsAction {
       .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");
-
+    super.defineGateAndGroupParameters(action);
   }
 
   @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) {
+  protected void apply(DbSession dbSession, QualityGateDto qualityGate, GroupDto group) {
     if (dbClient.qualityGateGroupPermissionsDao().exists(dbSession, qualityGate, group)) {
       return;
     }
index 1a37844f61adbc095f0a605d2066cd5fe044bb69..a8b3afc1d3a543c19e592071dfd75885ba5d78e5 100644 (file)
@@ -25,27 +25,28 @@ public class QualityGateWsModule extends Module {
   @Override
   protected void configureModule() {
     add(
+      AddGroupAction.class,
       AddUserAction.class,
-      QualityGatesWsSupport.class,
-      QualityGatesWs.class,
-      ListAction.class,
-      SearchAction.class,
-      ShowAction.class,
-      CreateAction.class,
-      RenameAction.class,
       CopyAction.class,
-      DestroyAction.class,
-      SetAsDefaultAction.class,
-      SelectAction.class,
-      DeselectAction.class,
+      CreateAction.class,
       CreateConditionAction.class,
       DeleteConditionAction.class,
-      UpdateConditionAction.class,
-      ProjectStatusAction.class,
+      DeselectAction.class,
+      DestroyAction.class,
       GetByProjectAction.class,
-      AddGroupAction.class,
+      ListAction.class,
+      ProjectStatusAction.class,
+      QualityGatesWs.class,
+      QualityGatesWsSupport.class,
+      RemoveGroupAction.class,
+      RenameAction.class,
+      SearchAction.class,
       SearchGroupsAction.class,
-      SearchUsersAction.class
+      SearchUsersAction.class,
+      SelectAction.class,
+      SetAsDefaultAction.class,
+      ShowAction.class,
+      UpdateConditionAction.class
     );
   }
 }
index 202714cd08ad2ebe32cea5f25af16c9406f83c20..dd4e5825aafdb0be81ae5cdfc44b46045193606b 100644 (file)
@@ -31,6 +31,7 @@ public class QualityGatesWsParameters {
   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 ACTION_REMOVE_GROUP = "remove_group";
   public static final String ACTION_SEARCH_GROUPS = "search_groups";
   public static final String ACTION_SEARCH_USERS = "search_users";
 
@@ -55,5 +56,4 @@ public class QualityGatesWsParameters {
   private QualityGatesWsParameters() {
     // prevent instantiation
   }
-
 }
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/RemoveGroupAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/RemoveGroupAction.java
new file mode 100644 (file)
index 0000000..ccdf7b3
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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 org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.db.user.GroupDto;
+
+import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.ACTION_REMOVE_GROUP;
+
+public class RemoveGroupAction extends AbstractGroupAction {
+
+  public RemoveGroupAction(DbClient dbClient, QualityGatesWsSupport wsSupport) {
+    super(dbClient, wsSupport);
+  }
+
+  @Override
+  public void define(WebService.NewController context) {
+    WebService.NewAction action = context
+      .createAction(ACTION_REMOVE_GROUP)
+      .setDescription("Remove the ability from a group 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");
+
+    super.defineGateAndGroupParameters(action);
+  }
+
+  @Override
+  protected void apply(DbSession dbSession, QualityGateDto qualityGate, GroupDto group) {
+    if (!dbClient.qualityGateGroupPermissionsDao().exists(dbSession, qualityGate, group)) {
+      return;
+    }
+    dbClient.qualityGateGroupPermissionsDao().deleteByQualityGateAndGroup(dbSession, qualityGate, group);
+    dbSession.commit();
+  }
+}
index ec01f5a680ba4cdf7247d1acbe6740c414b5528a..f3748dd3ed67f66c053ea8c4b54d2e1e0ed7602d 100644 (file)
@@ -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 + 21);
+    assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 22);
   }
 
 }
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/RemoveGroupActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/RemoveGroupActionTest.java
new file mode 100644 (file)
index 0000000..bbb5ec3
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * 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 org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.WebService;
+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.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_GATE_NAME;
+import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_GROUP_NAME;
+
+public class RemoveGroupActionTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+  @Rule
+  public DbTester db = DbTester.create();
+
+  private final DbClient dbClient = db.getDbClient();
+  private final QualityGatesWsSupport wsSupport = new QualityGatesWsSupport(dbClient, userSession, TestComponentFinder.from(db));
+  private final WsActionTester ws = new WsActionTester(new RemoveGroupAction(dbClient, wsSupport));
+
+  @Test
+  public void test_definition() {
+    WebService.Action def = ws.getDef();
+    assertThat(def.key()).isEqualTo("remove_group");
+    assertThat(def.isPost()).isTrue();
+    assertThat(def.isInternal()).isTrue();
+    assertThat(def.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("groupName", "gateName");
+  }
+
+  @Test
+  public void remove_group() {
+    QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+    GroupDto group = db.users().insertGroup();
+    db.qualityGates().addGroupPermission(qualityGate, group);
+    userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES);
+
+    TestResponse response = ws.newRequest()
+      .setParam(PARAM_GATE_NAME, qualityGate.getName())
+      .setParam(PARAM_GROUP_NAME, group.getName())
+      .execute();
+
+    assertThat(response.getStatus()).isEqualTo(204);
+    assertThat(dbClient.qualityGateGroupPermissionsDao().exists(db.getSession(), qualityGate, group)).isFalse();
+  }
+
+  @Test
+  public void does_nothing_when_group_cannot_edit_gate() {
+    QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+    GroupDto group = db.users().insertGroup();
+
+    assertThat(dbClient.qualityGateGroupPermissionsDao().exists(db.getSession(), qualityGate, group)).isFalse();
+
+    userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES);
+
+    ws.newRequest()
+      .setParam(PARAM_GATE_NAME, qualityGate.getName())
+      .setParam(PARAM_GROUP_NAME, group.getName())
+      .execute();
+
+    assertThat(dbClient.qualityGateGroupPermissionsDao().exists(db.getSession(), qualityGate, group)).isFalse();
+  }
+
+  @Test
+  public void qg_administrators_can_remove_group() {
+    QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+    GroupDto group = db.users().insertGroup();
+    db.qualityGates().addGroupPermission(qualityGate, group);
+    userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES);
+
+    ws.newRequest()
+      .setParam(PARAM_GATE_NAME, qualityGate.getName())
+      .setParam(PARAM_GROUP_NAME, group.getName())
+      .execute();
+
+    assertThat(dbClient.qualityGateGroupPermissionsDao().exists(db.getSession(), qualityGate, group)).isFalse();
+  }
+
+  @Test
+  public void qg_editors_can_remove_group() {
+    QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+    GroupDto group = db.users().insertGroup();
+    db.qualityGates().addGroupPermission(qualityGate, group);
+    UserDto userAllowedToEditGate = db.users().insertUser();
+    db.qualityGates().addUserPermission(qualityGate, userAllowedToEditGate);
+    userSession.logIn(userAllowedToEditGate);
+
+    ws.newRequest()
+      .setParam(PARAM_GATE_NAME, qualityGate.getName())
+      .setParam(PARAM_GROUP_NAME, group.getName())
+      .execute();
+
+    assertThat(dbClient.qualityGateGroupPermissionsDao().exists(db.getSession(), qualityGate, group)).isFalse();
+  }
+
+  @Test
+  public void fail_when_group_does_not_exist() {
+    QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+    userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES);
+
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage("Group with name 'unknown' is not found");
+
+    ws.newRequest()
+      .setParam(PARAM_GATE_NAME, qualityGate.getName())
+      .setParam(PARAM_GROUP_NAME, "unknown")
+      .execute();
+  }
+
+  @Test
+  public void fail_when_qgate_does_not_exist() {
+    GroupDto group = db.users().insertGroup();
+    userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES);
+
+    expectedException.expect(NotFoundException.class);
+    expectedException.expectMessage(String.format("No quality gate has been found for name unknown"));
+
+    ws.newRequest()
+      .setParam(PARAM_GATE_NAME, "unknown")
+      .setParam(PARAM_GROUP_NAME, group.getName())
+      .execute();
+  }
+
+  @Test
+  public void fail_when_qg_is_built_in() {
+    GroupDto group = db.users().insertGroup();
+    QualityGateDto qualityGate = db.qualityGates().insertQualityGate(qg -> qg.setBuiltIn(true));
+    userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES);
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage(String.format("Operation forbidden for built-in Quality Gate '%s'", qualityGate.getName()));
+
+    ws.newRequest()
+      .setParam(PARAM_GATE_NAME, qualityGate.getName())
+      .setParam(PARAM_GROUP_NAME, group.getName())
+      .execute();
+  }
+
+  @Test
+  public void fail_when_not_enough_permission() {
+    QualityGateDto qualityGate = db.qualityGates().insertQualityGate();
+    GroupDto group = db.users().insertGroup();
+    userSession.logIn(db.users().insertUser()).addPermission(GlobalPermission.ADMINISTER_QUALITY_PROFILES);
+
+    expectedException.expect(ForbiddenException.class);
+
+    ws.newRequest()
+      .setParam(PARAM_GATE_NAME, qualityGate.getName())
+      .setParam(PARAM_GROUP_NAME, group.getName())
+      .execute();
+  }
+}