3 * Copyright (C) 2009-2016 SonarSource SA
4 * mailto:contact 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;
22 import java.io.IOException;
23 import javax.annotation.Nullable;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.junit.rules.ExpectedException;
28 import org.sonar.api.resources.Qualifiers;
29 import org.sonar.api.utils.System2;
30 import org.sonar.api.web.UserRole;
31 import org.sonar.core.permission.GlobalPermissions;
32 import org.sonar.db.DbClient;
33 import org.sonar.db.DbSession;
34 import org.sonar.db.DbTester;
35 import org.sonar.db.component.ComponentDto;
36 import org.sonar.db.component.ResourceTypesRule;
37 import org.sonar.db.user.GroupDto;
38 import org.sonar.db.user.GroupRoleDto;
39 import org.sonar.db.user.UserDto;
40 import org.sonar.db.user.UserRoleDto;
41 import org.sonar.server.component.ComponentFinder;
42 import org.sonar.server.exceptions.ForbiddenException;
43 import org.sonar.server.exceptions.UnauthorizedException;
44 import org.sonar.server.i18n.I18nRule;
45 import org.sonar.server.tester.UserSessionRule;
46 import org.sonar.server.usergroups.ws.UserGroupFinder;
47 import org.sonar.server.ws.TestResponse;
48 import org.sonar.server.ws.WsActionTester;
49 import org.sonarqube.ws.MediaTypes;
50 import org.sonarqube.ws.WsPermissions.SearchProjectPermissionsWsResponse;
52 import static org.assertj.core.api.Assertions.assertThat;
53 import static org.sonar.api.server.ws.WebService.Param.PAGE;
54 import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
55 import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
56 import static org.sonar.db.component.ComponentTesting.newDeveloper;
57 import static org.sonar.db.component.ComponentTesting.newProjectCopy;
58 import static org.sonar.db.component.ComponentTesting.newProjectDto;
59 import static org.sonar.db.component.ComponentTesting.newView;
60 import static org.sonar.db.user.GroupTesting.newGroupDto;
61 import static org.sonar.db.user.UserTesting.newUserDto;
62 import static org.sonar.test.JsonAssert.assertJson;
63 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID;
64 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER;
67 public class SearchProjectPermissionsActionTest {
69 public ExpectedException expectedException = ExpectedException.none();
71 public UserSessionRule userSession = UserSessionRule.standalone();
73 public DbTester db = DbTester.create(System2.INSTANCE);
76 I18nRule i18n = new I18nRule();
77 DbClient dbClient = db.getDbClient();
78 final DbSession dbSession = db.getSession();
79 ResourceTypesRule resourceTypes = new ResourceTypesRule();
80 SearchProjectPermissionsDataLoader dataLoader;
82 SearchProjectPermissionsAction underTest;
86 resourceTypes.setRootQualifiers(Qualifiers.PROJECT, Qualifiers.VIEW, "DEV");
87 ComponentFinder componentFinder = new ComponentFinder(dbClient);
88 PermissionDependenciesFinder finder = new PermissionDependenciesFinder(dbClient, componentFinder, new UserGroupFinder(dbClient), resourceTypes);
89 i18n.setProjectPermissions();
91 dataLoader = new SearchProjectPermissionsDataLoader(dbClient, finder, resourceTypes);
92 underTest = new SearchProjectPermissionsAction(dbClient, userSession, i18n, resourceTypes, dataLoader);
94 ws = new WsActionTester(underTest);
96 userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
100 public void search_project_permissions() {
101 UserDto user1 = insertUser(newUserDto());
102 UserDto user2 = insertUser(newUserDto());
103 UserDto user3 = insertUser(newUserDto());
105 ComponentDto jdk7 = insertJdk7();
106 ComponentDto project2 = insertClang();
107 ComponentDto dev = insertDeveloper();
108 ComponentDto view = insertView();
109 insertProjectInView(jdk7, view);
111 insertUserRole(UserRole.ISSUE_ADMIN, user1.getId(), jdk7.getId());
112 insertUserRole(UserRole.ADMIN, user1.getId(), jdk7.getId());
113 insertUserRole(UserRole.ADMIN, user2.getId(), jdk7.getId());
114 insertUserRole(UserRole.ADMIN, user3.getId(), jdk7.getId());
115 insertUserRole(UserRole.ISSUE_ADMIN, user1.getId(), project2.getId());
116 insertUserRole(UserRole.ISSUE_ADMIN, user1.getId(), dev.getId());
117 insertUserRole(UserRole.ISSUE_ADMIN, user1.getId(), view.getId());
119 insertUserRole(GlobalPermissions.SYSTEM_ADMIN, user1.getId(), null);
121 GroupDto group1 = insertGroup(newGroupDto());
122 GroupDto group2 = insertGroup(newGroupDto());
123 GroupDto group3 = insertGroup(newGroupDto());
125 insertGroupRole(UserRole.ADMIN, jdk7.getId(), null);
126 insertGroupRole(UserRole.ADMIN, jdk7.getId(), group1.getId());
127 insertGroupRole(UserRole.ADMIN, jdk7.getId(), group2.getId());
128 insertGroupRole(UserRole.ADMIN, jdk7.getId(), group3.getId());
129 insertGroupRole(UserRole.ADMIN, dev.getId(), group2.getId());
130 insertGroupRole(UserRole.ADMIN, view.getId(), group2.getId());
134 String result = ws.newRequest().execute().getInput();
137 .ignoreFields("permissions")
138 .isSimilarTo(getClass().getResource("search_project_permissions-example.json"));
142 public void empty_result() {
143 String result = ws.newRequest().execute().getInput();
146 .ignoreFields("permissions")
147 .isSimilarTo(getClass().getResource("SearchProjectPermissionsActionTest/empty.json"));
151 public void search_project_permissions_with_project_permission() {
152 userSession.login().addProjectUuidPermissions(UserRole.ADMIN, "project-uuid");
153 insertComponent(newProjectDto("project-uuid"));
156 String result = ws.newRequest()
157 .setParam(PARAM_PROJECT_ID, "project-uuid")
158 .execute().getInput();
160 assertThat(result).contains("project-uuid");
164 public void has_projects_ordered_by_name() {
165 for (int i = 9; i >= 1; i--) {
166 insertComponent(newProjectDto()
167 .setName("project-name-" + i));
171 String result = ws.newRequest()
173 .setParam(PAGE_SIZE, "3")
174 .execute().getInput();
177 .contains("project-name-1", "project-name-2", "project-name-3")
178 .doesNotContain("project-name-4");
182 public void search_by_query_on_name() {
183 insertComponent(newProjectDto().setName("project-name"));
184 insertComponent(newProjectDto().setName("another-name"));
187 String result = ws.newRequest()
188 .setParam(TEXT_QUERY, "project")
189 .execute().getInput();
191 assertThat(result).contains("project-name")
192 .doesNotContain("another-name");
196 public void search_by_query_on_key() {
197 insertComponent(newProjectDto().setKey("project-key"));
198 insertComponent(newProjectDto().setKey("another-key"));
201 String result = ws.newRequest()
202 .setParam(TEXT_QUERY, "project")
203 .execute().getInput();
205 assertThat(result).contains("project-key")
206 .doesNotContain("another-key");
210 public void handle_more_than_1000_projects() {
211 for (int i = 1; i <= 1001; i++) {
212 insertComponent(newProjectDto("project-uuid-" + i));
216 String result = ws.newRequest()
217 .setParam(TEXT_QUERY, "project")
218 .setParam(PAGE_SIZE, "1001")
219 .execute().getInput();
221 assertThat(result).contains("project-uuid-1", "project-uuid-999", "project-uuid-1001");
225 public void result_depends_of_root_types() {
226 resourceTypes.setRootQualifiers(Qualifiers.PROJECT);
227 insertComponent(newView("view-uuid"));
228 insertComponent(newDeveloper("developer-name"));
229 insertComponent(newProjectDto("project-uuid"));
231 dataLoader = new SearchProjectPermissionsDataLoader(dbClient,
232 new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient), new UserGroupFinder(dbClient), resourceTypes),
234 underTest = new SearchProjectPermissionsAction(dbClient, userSession, i18n, resourceTypes, dataLoader);
235 ws = new WsActionTester(underTest);
237 String result = ws.newRequest().execute().getInput();
239 assertThat(result).contains("project-uuid")
240 .doesNotContain("view-uuid")
241 .doesNotContain("developer-name");
245 public void filter_by_qualifier() throws IOException {
246 insertComponent(newView("view-uuid"));
247 insertComponent(newDeveloper("developer-name"));
248 insertComponent(newProjectDto("project-uuid"));
251 TestResponse wsResponse = ws.newRequest()
252 .setMediaType(MediaTypes.PROTOBUF)
253 .setParam(PARAM_QUALIFIER, Qualifiers.PROJECT)
255 SearchProjectPermissionsWsResponse result = SearchProjectPermissionsWsResponse.parseFrom(wsResponse.getInputStream());
257 assertThat(result.getProjectsList())
259 .contains("project-uuid")
260 .doesNotContain("view-uuid")
261 .doesNotContain("developer-name");
265 public void fail_if_not_logged_in() {
266 expectedException.expect(UnauthorizedException.class);
267 userSession.anonymous();
269 ws.newRequest().execute();
273 public void fail_if_not_admin() {
274 expectedException.expect(ForbiddenException.class);
277 ws.newRequest().execute();
281 public void display_all_project_permissions() {
282 String result = ws.newRequest().execute().getInput();
285 .ignoreFields("permissions")
286 .isSimilarTo(getClass().getResource("SearchProjectPermissionsActionTest/display_all_project_permissions.json"));
289 private ComponentDto insertView() {
290 return insertComponent(newView()
291 .setUuid("752d8bfd-420c-4a83-a4e5-8ab19b13c8fc")
296 private ComponentDto insertProjectInView(ComponentDto project, ComponentDto view) {
297 return insertComponent(newProjectCopy("project-in-view-uuid", project, view));
300 private ComponentDto insertDeveloper() {
301 return insertComponent(newDeveloper("Simon Brandhof")
302 .setUuid("4e607bf9-7ed0-484a-946d-d58ba7dab2fb")
303 .setKey("simon-brandhof"));
306 private ComponentDto insertClang() {
307 return insertComponent(newProjectDto("project-uuid-2")
310 .setUuid("ce4c03d6-430f-40a9-b777-ad877c00aa4d"));
313 private ComponentDto insertJdk7() {
314 return insertComponent(newProjectDto("project-uuid-1")
316 .setKey("net.java.openjdk:jdk7")
317 .setUuid("0bd7b1e7-91d6-439e-a607-4a3a9aad3c6a"));
320 private UserDto insertUser(UserDto user) {
321 return dbClient.userDao().insert(dbSession, user.setActive(true));
324 private void insertUserRole(String permission, long userId, @Nullable Long resourceId) {
325 dbClient.roleDao().insertUserRole(dbSession, new UserRoleDto()
328 .setResourceId(resourceId));
331 private GroupDto insertGroup(GroupDto group) {
332 return dbClient.groupDao().insert(dbSession, group);
335 private void insertGroupRole(String permission, @Nullable Long resourceId, @Nullable Long groupId) {
336 dbClient.roleDao().insertGroupRole(dbSession, new GroupRoleDto().setRole(permission).setResourceId(resourceId).setGroupId(groupId));
339 private ComponentDto insertComponent(ComponentDto component) {
340 dbClient.componentDao().insert(dbSession, component.setEnabled(true));
341 return dbClient.componentDao().selectOrFailByUuid(dbSession, component.uuid());
344 private void commit() {