3 * Copyright (C) 2009-2023 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.permission.ws.template;
22 import java.util.stream.IntStream;
23 import javax.annotation.Nullable;
24 import org.junit.Test;
25 import org.sonar.api.resources.Qualifiers;
26 import org.sonar.api.resources.ResourceTypes;
27 import org.sonar.api.server.ws.WebService;
28 import org.sonar.api.web.UserRole;
29 import org.sonar.core.permission.GlobalPermissions;
30 import org.sonar.db.component.ResourceTypesRule;
31 import org.sonar.db.permission.template.PermissionTemplateDto;
32 import org.sonar.db.permission.template.PermissionTemplateGroupDto;
33 import org.sonar.db.user.GroupDto;
34 import org.sonar.server.exceptions.BadRequestException;
35 import org.sonar.server.exceptions.ForbiddenException;
36 import org.sonar.server.exceptions.NotFoundException;
37 import org.sonar.server.exceptions.UnauthorizedException;
38 import org.sonar.server.permission.PermissionService;
39 import org.sonar.server.permission.PermissionServiceImpl;
40 import org.sonar.server.permission.RequestValidator;
41 import org.sonar.server.permission.ws.BasePermissionWsTest;
42 import org.sonar.server.permission.ws.WsParameters;
43 import org.sonarqube.ws.Permissions.WsGroupsResponse;
45 import static org.assertj.core.api.Assertions.assertThat;
46 import static org.assertj.core.api.Assertions.assertThatThrownBy;
47 import static org.sonar.api.server.ws.WebService.Param.PAGE;
48 import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
49 import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
50 import static org.sonar.api.web.UserRole.ADMIN;
51 import static org.sonar.api.web.UserRole.CODEVIEWER;
52 import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
53 import static org.sonar.api.web.UserRole.USER;
54 import static org.sonar.db.permission.PermissionQuery.DEFAULT_PAGE_SIZE;
55 import static org.sonar.db.permission.template.PermissionTemplateTesting.newPermissionTemplateGroupDto;
56 import static org.sonar.db.user.GroupTesting.newGroupDto;
57 import static org.sonar.test.JsonAssert.assertJson;
58 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION;
59 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_ID;
60 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_TEMPLATE_NAME;
62 public class TemplateGroupsActionTest extends BasePermissionWsTest<TemplateGroupsAction> {
64 private final ResourceTypes resourceTypes = new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT);
65 private final PermissionService permissionService = new PermissionServiceImpl(resourceTypes);
66 private final WsParameters wsParameters = new WsParameters(permissionService);
67 private final RequestValidator requestValidator = new RequestValidator(permissionService);
70 protected TemplateGroupsAction buildWsAction() {
71 return new TemplateGroupsAction(db.getDbClient(), userSession, newPermissionWsSupport(), wsParameters, requestValidator);
75 public void define_template_groups() {
76 WebService.Action action = wsTester.getDef();
78 assertThat(action).isNotNull();
79 assertThat(action.key()).isEqualTo("template_groups");
80 assertThat(action.isPost()).isFalse();
81 assertThat(action.isInternal()).isTrue();
82 assertThat(action.since()).isEqualTo("5.2");
86 public void template_groups_of_json_example() {
87 GroupDto adminGroup = insertGroup("sonar-administrators", "System administrators");
88 GroupDto userGroup = insertGroup("sonar-users", "Every authenticated user automatically belongs to this group");
90 PermissionTemplateDto template = addTemplate();
91 addGroupToTemplate(newPermissionTemplateGroup(ISSUE_ADMIN, template.getUuid(), adminGroup.getUuid()), template.getName());
92 addGroupToTemplate(newPermissionTemplateGroup(ISSUE_ADMIN, template.getUuid(), userGroup.getUuid()), template.getName());
94 addGroupToTemplate(newPermissionTemplateGroup(USER, template.getUuid(), null), template.getName());
95 addGroupToTemplate(newPermissionTemplateGroup(ISSUE_ADMIN, template.getUuid(), null), template.getName());
98 String response = newRequest()
99 .setParam(PARAM_PERMISSION, ISSUE_ADMIN)
100 .setParam(PARAM_TEMPLATE_ID, template.getUuid())
106 .withStrictArrayOrder()
107 .isSimilarTo(getClass().getResource("template_groups-example.json"));
111 public void return_all_permissions_of_matching_groups() {
112 PermissionTemplateDto template = addTemplate();
114 GroupDto group1 = db.users().insertGroup("group-1-name");
115 addGroupToTemplate(newPermissionTemplateGroup(CODEVIEWER, template.getUuid(), group1.getUuid()), template.getName());
116 addGroupToTemplate(newPermissionTemplateGroup(ADMIN, template.getUuid(), group1.getUuid()), template.getName());
118 GroupDto group2 = db.users().insertGroup("group-2-name");
119 addGroupToTemplate(newPermissionTemplateGroup(USER, template.getUuid(), group2.getUuid()), template.getName());
120 addGroupToTemplate(newPermissionTemplateGroup(ADMIN, template.getUuid(), group2.getUuid()), template.getName());
122 GroupDto group3 = db.users().insertGroup("group-3-name");
125 addGroupToTemplate(newPermissionTemplateGroup(USER, template.getUuid(), null), template.getName());
126 addGroupToTemplate(newPermissionTemplateGroup(ISSUE_ADMIN, template.getUuid(), null), template.getName());
128 PermissionTemplateDto anotherTemplate = addTemplate();
129 GroupDto group4 = db.users().insertGroup("group-4-name");
130 addGroupToTemplate(newPermissionTemplateGroup(ADMIN, anotherTemplate.getUuid(), group3.getUuid()), anotherTemplate.getName());
131 addGroupToTemplate(newPermissionTemplateGroup(ADMIN, anotherTemplate.getUuid(), group4.getUuid()), anotherTemplate.getName());
134 WsGroupsResponse response = newRequest()
135 .setParam(PARAM_TEMPLATE_ID, template.getUuid())
136 .executeProtobuf(WsGroupsResponse.class);
138 assertThat(response.getGroupsList()).extracting("name").containsExactly("Anyone", "group-1-name", "group-2-name", "group-3-name", "group-4-name");
139 assertThat(response.getGroups(0).getPermissionsList()).containsOnly("user", "issueadmin");
140 assertThat(response.getGroups(1).getPermissionsList()).containsOnly("codeviewer", "admin");
141 assertThat(response.getGroups(2).getPermissionsList()).containsOnly("user", "admin");
142 assertThat(response.getGroups(3).getPermissionsList()).isEmpty();
146 public void search_by_permission() {
147 PermissionTemplateDto template = addTemplate();
149 GroupDto group1 = db.users().insertGroup("group-1-name");
150 addGroupToTemplate(newPermissionTemplateGroup(USER, template.getUuid(), group1.getUuid()), template.getName());
151 addGroupToTemplate(newPermissionTemplateGroup(CODEVIEWER, template.getUuid(), group1.getUuid()), template.getName());
153 GroupDto group2 = db.users().insertGroup("group-2-name");
154 addGroupToTemplate(newPermissionTemplateGroup(ADMIN, template.getUuid(), group2.getUuid()), template.getName());
156 GroupDto group3 = db.users().insertGroup("group-3-name");
159 addGroupToTemplate(newPermissionTemplateGroup(USER, template.getUuid(), null), template.getName());
161 PermissionTemplateDto anotherTemplate = addTemplate();
162 addGroupToTemplate(newPermissionTemplateGroup(ADMIN, anotherTemplate.getUuid(), group3.getUuid()), anotherTemplate.getName());
165 WsGroupsResponse response = newRequest()
166 .setParam(PARAM_PERMISSION, USER)
167 .setParam(PARAM_TEMPLATE_ID, template.getUuid())
168 .executeProtobuf(WsGroupsResponse.class);
170 assertThat(response.getGroupsList()).extracting("name").containsExactly("Anyone", "group-1-name");
171 assertThat(response.getGroups(0).getPermissionsList()).containsOnly("user");
172 assertThat(response.getGroups(1).getPermissionsList()).containsOnly("user", "codeviewer");
176 public void search_by_template_name() {
177 GroupDto group1 = db.users().insertGroup("group-1-name");
178 GroupDto group2 = db.users().insertGroup("group-2-name");
179 GroupDto group3 = db.users().insertGroup("group-3-name");
181 PermissionTemplateDto template = addTemplate();
182 addGroupToTemplate(newPermissionTemplateGroup(USER, template.getUuid(), group1.getUuid()), template.getName());
183 addGroupToTemplate(newPermissionTemplateGroup(ADMIN, template.getUuid(), group2.getUuid()), template.getName());
184 addGroupToTemplate(newPermissionTemplateGroup(USER, template.getUuid(), null), template.getName());
186 PermissionTemplateDto anotherTemplate = addTemplate();
187 addGroupToTemplate(newPermissionTemplateGroup(USER, anotherTemplate.getUuid(), group1.getUuid()), anotherTemplate.getName());
190 WsGroupsResponse response = newRequest()
191 .setParam(PARAM_TEMPLATE_NAME, template.getName())
192 .executeProtobuf(WsGroupsResponse.class);
194 assertThat(response.getGroupsList()).extracting("name").containsExactly("Anyone", "group-1-name", "group-2-name", "group-3-name");
198 public void search_with_pagination() {
199 PermissionTemplateDto template = addTemplate();
200 GroupDto group1 = db.users().insertGroup("group-1-name");
201 addGroupToTemplate(newPermissionTemplateGroup(USER, template.getUuid(), group1.getUuid()), template.getName());
202 GroupDto group2 = db.users().insertGroup("group-2-name");
203 addGroupToTemplate(newPermissionTemplateGroup(USER, template.getUuid(), group2.getUuid()), template.getName());
206 WsGroupsResponse response = newRequest()
207 .setParam(PARAM_PERMISSION, USER)
208 .setParam(PARAM_TEMPLATE_NAME, template.getName())
210 .setParam(PAGE_SIZE, "1")
211 .executeProtobuf(WsGroupsResponse.class);
213 assertThat(response.getGroupsList()).extracting("name").containsExactly("group-2-name");
217 public void search_with_text_query() {
218 PermissionTemplateDto template = addTemplate();
219 GroupDto group1 = db.users().insertGroup("group-1-name");
220 addGroupToTemplate(newPermissionTemplateGroup(USER, template.getUuid(), group1.getUuid()), template.getName());
221 GroupDto group2 = db.users().insertGroup("group-2-name");
222 GroupDto group3 = db.users().insertGroup("group-3");
225 WsGroupsResponse response = newRequest()
226 .setParam(PARAM_TEMPLATE_NAME, template.getName())
227 .setParam(TEXT_QUERY, "-nam")
228 .executeProtobuf(WsGroupsResponse.class);
230 assertThat(response.getGroupsList()).extracting("name").containsExactly("group-1-name", "group-2-name");
234 public void search_with_text_query_return_all_groups_even_when_no_permission_set() {
235 PermissionTemplateDto template = addTemplate();
236 db.users().insertGroup("group-1-name");
237 db.users().insertGroup("group-2-name");
238 db.users().insertGroup("group-3-name");
241 WsGroupsResponse response = newRequest()
242 .setParam(PARAM_TEMPLATE_ID, template.getUuid())
243 .setParam(TEXT_QUERY, "-name")
244 .executeProtobuf(WsGroupsResponse.class);
246 assertThat(response.getGroupsList()).extracting("name").containsExactly("group-1-name", "group-2-name", "group-3-name");
247 assertThat(response.getGroups(0).getPermissionsList()).isEmpty();
248 assertThat(response.getGroups(1).getPermissionsList()).isEmpty();
249 assertThat(response.getGroups(2).getPermissionsList()).isEmpty();
253 public void search_with_text_query_return_anyone_group_even_when_no_permission_set() {
254 PermissionTemplateDto template = addTemplate();
255 GroupDto group = db.users().insertGroup("group");
256 addGroupToTemplate(newPermissionTemplateGroup(USER, template.getUuid(), group.getUuid()), template.getName());
259 WsGroupsResponse response = newRequest()
260 .setParam(PARAM_TEMPLATE_ID, template.getUuid())
261 .setParam(TEXT_QUERY, "nyo")
262 .executeProtobuf(WsGroupsResponse.class);
264 assertThat(response.getGroupsList()).extracting("name").containsExactly("Anyone");
265 assertThat(response.getGroups(0).getPermissionsList()).isEmpty();
269 public void search_ignores_other_template_and_is_ordered_by_groups_with_permission_then_by_name_when_many_groups() {
270 PermissionTemplateDto template = addTemplate();
271 PermissionTemplateDto otherTemplate = db.permissionTemplates().insertTemplate();
272 IntStream.rangeClosed(1, DEFAULT_PAGE_SIZE + 1).forEach(i -> {
273 GroupDto group = db.users().insertGroup("Group-" + i);
274 db.permissionTemplates().addGroupToTemplate(otherTemplate, group, UserRole.USER);
276 String lastGroupName = "Group-" + (DEFAULT_PAGE_SIZE + 1);
277 db.permissionTemplates().addGroupToTemplate(template, db.users().selectGroup(lastGroupName).get(), UserRole.USER);
280 WsGroupsResponse response = newRequest()
281 .setParam(PARAM_TEMPLATE_ID, template.getUuid())
282 .executeProtobuf(WsGroupsResponse.class);
284 assertThat(response.getGroupsList())
286 .hasSize(DEFAULT_PAGE_SIZE)
287 .startsWith("Anyone", lastGroupName, "Group-1");
291 public void fail_if_not_logged_in() {
292 PermissionTemplateDto template1 = addTemplate();
293 userSession.anonymous();
295 assertThatThrownBy(() -> {
297 .setParam(PARAM_PERMISSION, USER)
298 .setParam(PARAM_TEMPLATE_ID, template1.getUuid())
301 .isInstanceOf(UnauthorizedException.class);
305 public void fail_if_insufficient_privileges() {
306 PermissionTemplateDto template1 = addTemplate();
309 assertThatThrownBy(() -> {
311 .setParam(PARAM_PERMISSION, USER)
312 .setParam(PARAM_TEMPLATE_ID, template1.getUuid())
315 .isInstanceOf(ForbiddenException.class);
319 public void fail_if_template_uuid_and_name_provided() {
320 PermissionTemplateDto template1 = addTemplate();
323 assertThatThrownBy(() -> {
325 .setParam(PARAM_PERMISSION, USER)
326 .setParam(PARAM_TEMPLATE_ID, template1.getUuid())
327 .setParam(PARAM_TEMPLATE_NAME, template1.getName())
330 .isInstanceOf(BadRequestException.class);
334 public void fail_if_template_uuid_nor_name_provided() {
337 assertThatThrownBy(() -> {
339 .setParam(PARAM_PERMISSION, USER)
342 .isInstanceOf(BadRequestException.class);
346 public void fail_if_template_is_not_found() {
349 assertThatThrownBy(() -> {
351 .setParam(PARAM_PERMISSION, USER)
352 .setParam(PARAM_TEMPLATE_ID, "unknown-uuid")
355 .isInstanceOf(NotFoundException.class);
359 public void fail_if_not_a_project_permission() {
361 PermissionTemplateDto template1 = addTemplate();
363 assertThatThrownBy(() -> {
365 .setParam(PARAM_PERMISSION, GlobalPermissions.QUALITY_GATE_ADMIN)
366 .setParam(PARAM_TEMPLATE_ID, template1.getUuid())
369 .isInstanceOf(IllegalArgumentException.class);
372 private GroupDto insertGroup(String name, String description) {
373 return db.users().insertGroup(newGroupDto().setName(name).setDescription(description));
376 private void addGroupToTemplate(PermissionTemplateGroupDto permissionTemplateGroup, String templateName) {
377 db.getDbClient().permissionTemplateDao().insertGroupPermission(db.getSession(), permissionTemplateGroup, templateName);
381 private static PermissionTemplateGroupDto newPermissionTemplateGroup(String permission, String templateUuid, @Nullable String groupUuid) {
382 return newPermissionTemplateGroupDto()
383 .setPermission(permission)
384 .setTemplateUuid(templateUuid)
385 .setGroupUuid(groupUuid);