From: Zipeng WU Date: Tue, 19 Oct 2021 15:52:51 +0000 (+0200) Subject: SONAR-15541 Create api/qualitygates/remove_user service X-Git-Tag: 9.2.0.49834~116 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=090fd5e9cd9bd868256d83217d82d87e0f8ca2a4;p=sonarqube.git SONAR-15541 Create api/qualitygates/remove_user service --- diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDao.java index 5d383b5f5b8..18c9440a847 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDao.java @@ -64,6 +64,10 @@ public class QualityGateUserPermissionsDao implements Dao { return mapper(dbSession).countByQuery(query); } + public void deleteByQualityGateAndUser(DbSession dbSession, QualityGateDto qualityGate, UserDto user) { + mapper(dbSession).delete(qualityGate.getUuid(), user.getUuid()); + } + public void deleteByUser(DbSession dbSession, UserDto user) { mapper(dbSession).deleteByUser(user.getUuid()); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsMapper.java index 8f3a7c8e268..5edf1c3aa13 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsMapper.java @@ -35,6 +35,8 @@ public interface QualityGateUserPermissionsMapper { int countByQuery(@Param("query") SearchPermissionQuery query); + void delete(@Param("qualityGateUuid") String qualityGateUuid, @Param("userUuid") String userUuid); + void deleteByUser(@Param("userUuid") String userUuid); void deleteByQualityGate(@Param("qualityGateUuid") String qualityGateUuid); diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateUserPermissionsMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateUserPermissionsMapper.xml index 628a828f1f7..149fc766cfb 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateUserPermissionsMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateUserPermissionsMapper.xml @@ -92,6 +92,12 @@ + + delete from qgate_user_permissions + where quality_gate_uuid = #{qualityGateUuid} + and user_uuid = #{userUuid} + + delete from qgate_user_permissions where user_uuid = #{userUuid} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDaoTest.java index 048be73e898..0c956d9bdca 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDaoTest.java @@ -207,6 +207,19 @@ public class QualityGateUserPermissionsDaoTest { .containsExactly(user1.getUuid(), user2.getUuid(), user3.getUuid()); } + @Test + public void deleteByQualityGateAndUser() { + QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); + UserDto user = db.users().insertUser(); + db.qualityGates().addUserPermission(qualityGate, user); + + assertThat(underTest.exists(dbSession, qualityGate, user)).isTrue(); + + underTest.deleteByQualityGateAndUser(dbSession, qualityGate, user); + + assertThat(underTest.exists(dbSession, qualityGate, user)).isFalse(); + } + @Test public void deleteByUser() { QualityGateDto qualityGateDto1 = db.qualityGates().insertQualityGate(); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AbstractUserAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AbstractUserAction.java new file mode 100644 index 00000000000..046a11314e1 --- /dev/null +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AbstractUserAction.java @@ -0,0 +1,78 @@ +/* + * 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.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.UserDto; + +import static org.sonar.server.exceptions.NotFoundException.checkFound; +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.user.UsersWsParameters.PARAM_LOGIN; + +public abstract class AbstractUserAction implements QualityGatesWsAction { + protected final DbClient dbClient; + protected final QualityGatesWsSupport wsSupport; + + protected AbstractUserAction(DbClient dbClient, QualityGatesWsSupport wsSupport) { + this.dbClient = dbClient; + this.wsSupport = wsSupport; + } + + protected void defineGateAndUserParameters(WebService.NewAction action) { + action.createParam(PARAM_GATE_NAME) + .setDescription("Quality Gate name") + .setRequired(true) + .setMaximumLength(NAME_MAXIMUM_LENGTH) + .setExampleValue("SonarSource Way"); + + action.createParam(PARAM_LOGIN) + .setDescription("User login") + .setRequired(true) + .setExampleValue("john.doe"); + } + + @Override + public void handle(Request request, Response response) throws Exception { + final String login = request.mandatoryParam(PARAM_LOGIN); + final String qualityGateName = request.mandatoryParam(PARAM_GATE_NAME); + + try (DbSession dbSession = dbClient.openSession(false)) { + QualityGateDto qualityGateDto = wsSupport.getByName(dbSession, qualityGateName); + wsSupport.checkCanLimitedEdit(dbSession, qualityGateDto); + UserDto user = getUser(dbSession, login); + apply(dbSession, qualityGateDto, user); + } + response.noContent(); + } + + private UserDto getUser(DbSession dbSession, String login) { + UserDto user = dbClient.userDao().selectByLogin(dbSession, login); + checkFound(user, "User with login '%s' is not found", login); + return user; + } + + protected abstract void apply(DbSession dbSession, QualityGateDto qualityGate, UserDto user); +} diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddUserAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddUserAction.java index c71e858085d..6ce85ae1092 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddUserAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddUserAction.java @@ -19,8 +19,6 @@ */ package org.sonar.server.qualitygate.ws; -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; @@ -29,22 +27,15 @@ import org.sonar.db.qualitygate.QualityGateDto; import org.sonar.db.qualitygate.QualityGateUserPermissionsDto; import org.sonar.db.user.UserDto; -import static org.sonar.server.exceptions.NotFoundException.checkFound; -import static org.sonar.server.qualitygate.ws.CreateAction.NAME_MAXIMUM_LENGTH; import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.ACTION_ADD_USER; -import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_GATE_NAME; -import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_LOGIN; -public class AddUserAction implements QualityGatesWsAction { +public class AddUserAction extends AbstractUserAction { - private final DbClient dbClient; private final UuidFactory uuidFactory; - private final QualityGatesWsSupport wsSupport; public AddUserAction(DbClient dbClient, UuidFactory uuidFactory, QualityGatesWsSupport wsSupport) { - this.dbClient = dbClient; + super(dbClient, wsSupport); this.uuidFactory = uuidFactory; - this.wsSupport = wsSupport; } @Override @@ -62,40 +53,11 @@ public class AddUserAction 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_LOGIN) - .setDescription("User login") - .setRequired(true) - .setExampleValue("john.doe"); - + super.defineGateAndUserParameters(action); } @Override - public void handle(Request request, Response response) throws Exception { - final String login = request.mandatoryParam(PARAM_LOGIN); - final String qualityGateName = request.mandatoryParam(PARAM_GATE_NAME); - - try (DbSession dbSession = dbClient.openSession(false)) { - QualityGateDto qualityGateDto = wsSupport.getByName(dbSession, qualityGateName); - wsSupport.checkCanLimitedEdit(dbSession, qualityGateDto); - UserDto user = getUser(dbSession, login); - addUser(dbSession, qualityGateDto, user); - } - response.noContent(); - } - - private UserDto getUser(DbSession dbSession, String login) { - UserDto user = dbClient.userDao().selectByLogin(dbSession, login); - checkFound(user, "User with login '%s' is not found", login); - return user; - } - - private void addUser(DbSession dbSession, QualityGateDto qualityGate, UserDto user) { + protected void apply(DbSession dbSession, QualityGateDto qualityGate, UserDto user) { if (dbClient.qualityGateUserPermissionDao().exists(dbSession, qualityGate, user)) { return; } 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 a8b3afc1d3a..9523165f140 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 @@ -39,6 +39,7 @@ public class QualityGateWsModule extends Module { QualityGatesWs.class, QualityGatesWsSupport.class, RemoveGroupAction.class, + RemoveUserAction.class, RenameAction.class, SearchAction.class, SearchGroupsAction.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 dd4e5825aaf..341c053bd87 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 @@ -32,6 +32,7 @@ public class QualityGatesWsParameters { 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_REMOVE_USER = "remove_user"; public static final String ACTION_SEARCH_GROUPS = "search_groups"; public static final String ACTION_SEARCH_USERS = "search_users"; diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/RemoveUserAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/RemoveUserAction.java new file mode 100644 index 00000000000..f1cbb81cba3 --- /dev/null +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/RemoveUserAction.java @@ -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.UserDto; + +import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.ACTION_REMOVE_USER; + +public class RemoveUserAction extends AbstractUserAction { + + public RemoveUserAction(DbClient dbClient, QualityGatesWsSupport wsSupport) { + super(dbClient, wsSupport); + } + + @Override + public void define(WebService.NewController context) { + WebService.NewAction action = context + .createAction(ACTION_REMOVE_USER) + .setDescription("Remove the ability from an user to edit a Quality Gate.
" + + "Requires one of the following permissions:" + + "") + .setHandler(this) + .setPost(true) + .setInternal(true) + .setSince("9.2"); + + super.defineGateAndUserParameters(action); + } + + @Override + protected void apply(DbSession dbSession, QualityGateDto qualityGate, UserDto user) { + if (!dbClient.qualityGateUserPermissionDao().exists(dbSession, qualityGate, user)) { + return; + } + dbClient.qualityGateUserPermissionDao().deleteByQualityGateAndUser(dbSession, qualityGate, user); + dbSession.commit(); + } +} 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 f3748dd3ed6..5a6f375475b 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 + 22); + assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 23); } } diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/RemoveUserActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/RemoveUserActionTest.java new file mode 100644 index 00000000000..15b338692c7 --- /dev/null +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/qualitygate/ws/RemoveUserActionTest.java @@ -0,0 +1,184 @@ +/* + * 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.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.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.user.UsersWsParameters.PARAM_LOGIN; + +public class RemoveUserActionTest { + + @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 RemoveUserAction(dbClient, wsSupport)); + + @Test + public void test_definition() { + WebService.Action def = ws.getDef(); + assertThat(def.key()).isEqualTo("remove_user"); + assertThat(def.isPost()).isTrue(); + assertThat(def.isInternal()).isTrue(); + assertThat(def.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("login", "gateName"); + } + + @Test + public void remove_user() { + QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); + UserDto user = db.users().insertUser(); + db.qualityGates().addUserPermission(qualityGate, user); + userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES); + + TestResponse response = ws.newRequest() + .setParam(PARAM_GATE_NAME, qualityGate.getName()) + .setParam(PARAM_LOGIN, user.getLogin()) + .execute(); + + assertThat(response.getStatus()).isEqualTo(204); + assertThat(dbClient.qualityGateUserPermissionDao().exists(db.getSession(), qualityGate, user)).isFalse(); + } + + @Test + public void does_nothing_when_user_cannot_edit_gate() { + QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); + UserDto user = db.users().insertUser(); + + assertThat(dbClient.qualityGateUserPermissionDao().exists(db.getSession(), qualityGate, user)).isFalse(); + + userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES); + + ws.newRequest() + .setParam(PARAM_GATE_NAME, qualityGate.getName()) + .setParam(PARAM_LOGIN, user.getLogin()) + .execute(); + + assertThat(dbClient.qualityGateUserPermissionDao().exists(db.getSession(), qualityGate, user)).isFalse(); + } + + @Test + public void qg_administrators_can_remove_user() { + QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); + UserDto user = db.users().insertUser(); + db.qualityGates().addUserPermission(qualityGate, user); + userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES); + + ws.newRequest() + .setParam(PARAM_GATE_NAME, qualityGate.getName()) + .setParam(PARAM_LOGIN, user.getLogin()) + .execute(); + + assertThat(dbClient.qualityGateUserPermissionDao().exists(db.getSession(), qualityGate, user)).isFalse(); + } + + @Test + public void qg_editors_can_remove_user() { + QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); + UserDto user = db.users().insertUser(); + db.qualityGates().addUserPermission(qualityGate, user); + UserDto userAllowedToEditGate = db.users().insertUser(); + db.qualityGates().addUserPermission(qualityGate, userAllowedToEditGate); + userSession.logIn(userAllowedToEditGate); + + ws.newRequest() + .setParam(PARAM_GATE_NAME, qualityGate.getName()) + .setParam(PARAM_LOGIN, user.getLogin()) + .execute(); + + assertThat(dbClient.qualityGateUserPermissionDao().exists(db.getSession(), qualityGate, user)).isFalse(); + } + + @Test + public void fail_when_user_does_not_exist() { + QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); + userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES); + + final TestRequest request = ws.newRequest() + .setParam(PARAM_GATE_NAME, qualityGate.getName()) + .setParam(PARAM_LOGIN, "unknown"); + + assertThatThrownBy(() -> request.execute()) + .isInstanceOf(NotFoundException.class) + .hasMessage("User with login 'unknown' is not found"); + } + + @Test + public void fail_when_qgate_does_not_exist() { + UserDto user = db.users().insertUser(); + userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES); + + final TestRequest request = ws.newRequest() + .setParam(PARAM_GATE_NAME, "unknown") + .setParam(PARAM_LOGIN, user.getLogin()); + + assertThatThrownBy(() -> request.execute()) + .isInstanceOf(NotFoundException.class) + .hasMessage("No quality gate has been found for name unknown"); + } + + @Test + public void fail_when_qg_is_built_in() { + UserDto user = db.users().insertUser(); + QualityGateDto qualityGate = db.qualityGates().insertQualityGate(qg -> qg.setBuiltIn(true)); + userSession.logIn().addPermission(GlobalPermission.ADMINISTER_QUALITY_GATES); + + final TestRequest request = ws.newRequest() + .setParam(PARAM_GATE_NAME, qualityGate.getName()) + .setParam(PARAM_LOGIN, user.getLogin()); + + assertThatThrownBy(() -> request.execute()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(String.format("Operation forbidden for built-in Quality Gate '%s'", qualityGate.getName())); + } + + @Test + public void fail_when_not_enough_permission() { + QualityGateDto qualityGate = db.qualityGates().insertQualityGate(); + UserDto user = db.users().insertUser(); + userSession.logIn(db.users().insertUser()); + + final TestRequest request = ws.newRequest() + .setParam(PARAM_GATE_NAME, qualityGate.getName()) + .setParam(PARAM_LOGIN, user.getLogin()); + + assertThatThrownBy(() -> request.execute()) + .isInstanceOf(ForbiddenException.class); + } +}