3 * Copyright (C) 2009-2021 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.index;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.List;
26 import java.util.function.Function;
27 import org.assertj.core.api.Assertions;
28 import org.junit.Before;
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.sonar.api.utils.System2;
32 import org.sonar.core.util.Uuids;
33 import org.sonar.core.util.stream.MoreCollectors;
34 import org.sonar.db.DbClient;
35 import org.sonar.db.DbSession;
36 import org.sonar.db.DbTester;
37 import org.sonar.db.component.ComponentDbTester;
38 import org.sonar.db.component.ComponentDto;
39 import org.sonar.db.permission.GroupPermissionDto;
40 import org.sonar.db.user.GroupDto;
41 import org.sonar.db.user.UserDbTester;
42 import org.sonar.db.user.UserDto;
44 import static java.util.Arrays.asList;
45 import static java.util.Collections.singletonList;
46 import static org.assertj.core.api.Assertions.assertThat;
47 import static org.sonar.api.resources.Qualifiers.APP;
48 import static org.sonar.api.resources.Qualifiers.PROJECT;
49 import static org.sonar.api.resources.Qualifiers.VIEW;
50 import static org.sonar.api.web.UserRole.ADMIN;
51 import static org.sonar.api.web.UserRole.USER;
53 public class PermissionIndexerDaoTest {
56 public DbTester dbTester = DbTester.create(System2.INSTANCE);
58 private final DbClient dbClient = dbTester.getDbClient();
59 private final DbSession dbSession = dbTester.getSession();
60 private final ComponentDbTester componentDbTester = new ComponentDbTester(dbTester);
61 private final UserDbTester userDbTester = new UserDbTester(dbTester);
63 private ComponentDto publicProject;
64 private ComponentDto privateProject1;
65 private ComponentDto privateProject2;
66 private ComponentDto view1;
67 private ComponentDto view2;
68 private ComponentDto application;
69 private UserDto user1;
70 private UserDto user2;
71 private GroupDto group;
73 private final PermissionIndexerDao underTest = new PermissionIndexerDao();
77 publicProject = componentDbTester.insertPublicProject();
78 privateProject1 = componentDbTester.insertPrivateProject();
79 privateProject2 = componentDbTester.insertPrivateProject();
80 view1 = componentDbTester.insertPublicPortfolio();
81 view2 = componentDbTester.insertPublicPortfolio();
82 application = componentDbTester.insertPublicApplication();
83 user1 = userDbTester.insertUser();
84 user2 = userDbTester.insertUser();
85 group = userDbTester.insertGroup();
89 public void select_all() {
90 insertTestDataForProjectsAndViews();
92 Collection<IndexPermissions> dtos = underTest.selectAll(dbClient, dbSession);
93 Assertions.assertThat(dtos).hasSize(6);
95 IndexPermissions publicProjectAuthorization = getByProjectUuid(publicProject.uuid(), dtos);
96 isPublic(publicProjectAuthorization, PROJECT);
98 IndexPermissions view1Authorization = getByProjectUuid(view1.uuid(), dtos);
99 isPublic(view1Authorization, VIEW);
101 IndexPermissions applicationAuthorization = getByProjectUuid(application.uuid(), dtos);
102 isPublic(applicationAuthorization, APP);
104 IndexPermissions privateProject1Authorization = getByProjectUuid(privateProject1.uuid(), dtos);
105 assertThat(privateProject1Authorization.getGroupUuids()).containsOnly(group.getUuid());
106 assertThat(privateProject1Authorization.isAllowAnyone()).isFalse();
107 assertThat(privateProject1Authorization.getUserUuids()).containsOnly(user1.getUuid(), user2.getUuid());
108 assertThat(privateProject1Authorization.getQualifier()).isEqualTo(PROJECT);
110 IndexPermissions privateProject2Authorization = getByProjectUuid(privateProject2.uuid(), dtos);
111 assertThat(privateProject2Authorization.getGroupUuids()).isEmpty();
112 assertThat(privateProject2Authorization.isAllowAnyone()).isFalse();
113 assertThat(privateProject2Authorization.getUserUuids()).containsOnly(user1.getUuid());
114 assertThat(privateProject2Authorization.getQualifier()).isEqualTo(PROJECT);
116 IndexPermissions view2Authorization = getByProjectUuid(view2.uuid(), dtos);
117 isPublic(view2Authorization, VIEW);
121 public void selectByUuids() {
122 insertTestDataForProjectsAndViews();
124 Map<String, IndexPermissions> dtos = underTest
125 .selectByUuids(dbClient, dbSession, asList(publicProject.uuid(), privateProject1.uuid(), privateProject2.uuid(), view1.uuid(), view2.uuid(), application.uuid()))
127 .collect(MoreCollectors.uniqueIndex(IndexPermissions::getProjectUuid, Function.identity()));
128 Assertions.assertThat(dtos).hasSize(6);
130 IndexPermissions publicProjectAuthorization = dtos.get(publicProject.uuid());
131 isPublic(publicProjectAuthorization, PROJECT);
133 IndexPermissions view1Authorization = dtos.get(view1.uuid());
134 isPublic(view1Authorization, VIEW);
136 IndexPermissions applicationAuthorization = dtos.get(application.uuid());
137 isPublic(applicationAuthorization, APP);
139 IndexPermissions privateProject1Authorization = dtos.get(privateProject1.uuid());
140 assertThat(privateProject1Authorization.getGroupUuids()).containsOnly(group.getUuid());
141 assertThat(privateProject1Authorization.isAllowAnyone()).isFalse();
142 assertThat(privateProject1Authorization.getUserUuids()).containsOnly(user1.getUuid(), user2.getUuid());
143 assertThat(privateProject1Authorization.getQualifier()).isEqualTo(PROJECT);
145 IndexPermissions privateProject2Authorization = dtos.get(privateProject2.uuid());
146 assertThat(privateProject2Authorization.getGroupUuids()).isEmpty();
147 assertThat(privateProject2Authorization.isAllowAnyone()).isFalse();
148 assertThat(privateProject2Authorization.getUserUuids()).containsOnly(user1.getUuid());
149 assertThat(privateProject2Authorization.getQualifier()).isEqualTo(PROJECT);
151 IndexPermissions view2Authorization = dtos.get(view2.uuid());
152 isPublic(view2Authorization, VIEW);
156 public void selectByUuids_returns_empty_list_when_project_does_not_exist() {
157 insertTestDataForProjectsAndViews();
159 List<IndexPermissions> dtos = underTest.selectByUuids(dbClient, dbSession, singletonList("missing"));
160 Assertions.assertThat(dtos).isEmpty();
164 public void select_by_projects_with_high_number_of_projects() {
165 List<String> projectUuids = new ArrayList<>();
166 for (int i = 0; i < 3500; i++) {
167 ComponentDto project = dbTester.components().insertPrivateProject(Integer.toString(i));
168 projectUuids.add(project.uuid());
169 GroupPermissionDto dto = new GroupPermissionDto()
170 .setUuid(Uuids.createFast())
171 .setGroupUuid(group.getUuid())
172 .setGroupName(group.getName())
174 .setComponentUuid(project.uuid())
175 .setComponentName(project.name());
176 dbClient.groupPermissionDao().insert(dbSession, dto, project);
180 assertThat(underTest.selectByUuids(dbClient, dbSession, projectUuids))
182 .extracting(IndexPermissions::getProjectUuid)
183 .containsAll(projectUuids);
187 public void return_private_project_without_any_permission_when_no_permission_in_DB() {
188 List<IndexPermissions> dtos = underTest.selectByUuids(dbClient, dbSession, singletonList(privateProject1.uuid()));
191 Assertions.assertThat(dtos).hasSize(1);
192 IndexPermissions dto = dtos.get(0);
193 assertThat(dto.getGroupUuids()).isEmpty();
194 assertThat(dto.getUserUuids()).isEmpty();
195 assertThat(dto.isAllowAnyone()).isFalse();
196 assertThat(dto.getProjectUuid()).isEqualTo(privateProject1.uuid());
197 assertThat(dto.getQualifier()).isEqualTo(privateProject1.qualifier());
201 public void return_public_project_with_only_AllowAnyone_true_when_no_permission_in_DB() {
202 List<IndexPermissions> dtos = underTest.selectByUuids(dbClient, dbSession, singletonList(publicProject.uuid()));
204 Assertions.assertThat(dtos).hasSize(1);
205 IndexPermissions dto = dtos.get(0);
206 assertThat(dto.getGroupUuids()).isEmpty();
207 assertThat(dto.getUserUuids()).isEmpty();
208 assertThat(dto.isAllowAnyone()).isTrue();
209 assertThat(dto.getProjectUuid()).isEqualTo(publicProject.uuid());
210 assertThat(dto.getQualifier()).isEqualTo(publicProject.qualifier());
214 public void return_private_project_with_AllowAnyone_false_and_user_id_when_user_is_granted_USER_permission_directly() {
215 dbTester.users().insertProjectPermissionOnUser(user1, USER, privateProject1);
216 List<IndexPermissions> dtos = underTest.selectByUuids(dbClient, dbSession, singletonList(privateProject1.uuid()));
218 Assertions.assertThat(dtos).hasSize(1);
219 IndexPermissions dto = dtos.get(0);
220 assertThat(dto.getGroupUuids()).isEmpty();
221 assertThat(dto.getUserUuids()).containsOnly(user1.getUuid());
222 assertThat(dto.isAllowAnyone()).isFalse();
223 assertThat(dto.getProjectUuid()).isEqualTo(privateProject1.uuid());
224 assertThat(dto.getQualifier()).isEqualTo(privateProject1.qualifier());
228 public void return_private_project_with_AllowAnyone_false_and_group_id_but_not_user_id_when_user_is_granted_USER_permission_through_group() {
229 dbTester.users().insertMember(group, user1);
230 dbTester.users().insertProjectPermissionOnGroup(group, USER, privateProject1);
231 List<IndexPermissions> dtos = underTest.selectByUuids(dbClient, dbSession, singletonList(privateProject1.uuid()));
233 Assertions.assertThat(dtos).hasSize(1);
234 IndexPermissions dto = dtos.get(0);
235 assertThat(dto.getGroupUuids()).containsOnly(group.getUuid());
236 assertThat(dto.getUserUuids()).isEmpty();
237 assertThat(dto.isAllowAnyone()).isFalse();
238 assertThat(dto.getProjectUuid()).isEqualTo(privateProject1.uuid());
239 assertThat(dto.getQualifier()).isEqualTo(privateProject1.qualifier());
242 private void isPublic(IndexPermissions view1Authorization, String qualifier) {
243 assertThat(view1Authorization.getGroupUuids()).isEmpty();
244 assertThat(view1Authorization.isAllowAnyone()).isTrue();
245 assertThat(view1Authorization.getUserUuids()).isEmpty();
246 assertThat(view1Authorization.getQualifier()).isEqualTo(qualifier);
249 private static IndexPermissions getByProjectUuid(String projectUuid, Collection<IndexPermissions> dtos) {
250 return dtos.stream().filter(dto -> dto.getProjectUuid().equals(projectUuid)).findFirst().orElseThrow(IllegalArgumentException::new);
253 private void insertTestDataForProjectsAndViews() {
254 // user1 has USER access on both private projects
255 userDbTester.insertProjectPermissionOnUser(user1, ADMIN, publicProject);
256 userDbTester.insertProjectPermissionOnUser(user1, USER, privateProject1);
257 userDbTester.insertProjectPermissionOnUser(user1, USER, privateProject2);
258 userDbTester.insertProjectPermissionOnUser(user1, ADMIN, view1);
259 userDbTester.insertProjectPermissionOnUser(user1, ADMIN, application);
261 // user2 has USER access on privateProject1 only
262 userDbTester.insertProjectPermissionOnUser(user2, USER, privateProject1);
263 userDbTester.insertProjectPermissionOnUser(user2, ADMIN, privateProject2);
265 // group1 has USER access on privateProject1 only
266 userDbTester.insertProjectPermissionOnGroup(group, USER, privateProject1);
267 userDbTester.insertProjectPermissionOnGroup(group, ADMIN, privateProject1);
268 userDbTester.insertProjectPermissionOnGroup(group, ADMIN, view1);
269 userDbTester.insertProjectPermissionOnGroup(group, ADMIN, application);