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.common.github.permissions;
22 import java.util.List;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.sonar.core.util.SequenceUuidFactory;
28 import org.sonar.core.util.UuidFactory;
29 import org.sonar.db.DbSession;
30 import org.sonar.db.DbTester;
31 import org.sonar.db.audit.AuditPersister;
32 import org.sonar.db.provisioning.GithubPermissionsMappingDao;
33 import org.sonar.db.provisioning.GithubPermissionsMappingDto;
34 import org.sonar.server.common.permission.Operation;
35 import org.sonar.server.exceptions.NotFoundException;
37 import static org.assertj.core.api.Assertions.assertThat;
38 import static org.assertj.core.api.Assertions.assertThatThrownBy;
39 import static org.mockito.Mockito.mock;
40 import static org.sonar.server.common.github.permissions.GithubPermissionsMappingService.ADMIN_GITHUB_ROLE;
41 import static org.sonar.server.common.github.permissions.GithubPermissionsMappingService.MAINTAIN_GITHUB_ROLE;
42 import static org.sonar.server.common.github.permissions.GithubPermissionsMappingService.READ_GITHUB_ROLE;
43 import static org.sonar.server.common.github.permissions.GithubPermissionsMappingService.TRIAGE_GITHUB_ROLE;
44 import static org.sonar.server.common.github.permissions.GithubPermissionsMappingService.WRITE_GITHUB_ROLE;
46 public class GithubPermissionsMappingServiceIT {
48 private static final String CUSTOM_ROLE_NAME = "customRole1";
50 private static final SonarqubePermissions NO_SQ_PERMISSIONS = new SonarqubePermissions(false, false, false, false, false, false);
53 public DbTester db = DbTester.create();
54 private final DbSession dbSession = db.getSession();
56 private final AuditPersister auditPersister = mock();
57 private final GithubPermissionsMappingDao githubPermissionsMappingDao = new GithubPermissionsMappingDao(auditPersister);
59 private final UuidFactory uuidFactory = new SequenceUuidFactory();
61 private final GithubPermissionsMappingService underTest = new GithubPermissionsMappingService(db.getDbClient(), githubPermissionsMappingDao, uuidFactory);
64 public void getPermissionsMapping_whenMappingNotDefined_returnMappingEntirelyFalse() {
65 List<GithubPermissionsMapping> actualPermissionsMapping = underTest.getPermissionsMapping();
67 List<GithubPermissionsMapping> expectedPermissionsMapping = List.of(
68 new GithubPermissionsMapping(READ_GITHUB_ROLE, true, NO_SQ_PERMISSIONS),
69 new GithubPermissionsMapping(TRIAGE_GITHUB_ROLE, true, NO_SQ_PERMISSIONS),
70 new GithubPermissionsMapping(WRITE_GITHUB_ROLE, true, NO_SQ_PERMISSIONS),
71 new GithubPermissionsMapping(MAINTAIN_GITHUB_ROLE, true, NO_SQ_PERMISSIONS),
72 new GithubPermissionsMapping(ADMIN_GITHUB_ROLE, true, NO_SQ_PERMISSIONS));
74 assertThat(actualPermissionsMapping).containsAll(expectedPermissionsMapping);
78 public void getPermissionsMapping_whenMappingDefined_returnMapping() {
79 Map<String, Set<String>> githubRolesToSqPermissions = Map.of(
80 CUSTOM_ROLE_NAME, Set.of("user"),
81 READ_GITHUB_ROLE, Set.of("user", "codeviewer"),
82 WRITE_GITHUB_ROLE, Set.of("user", "codeviewer", "issueadmin", "securityhotspotadmin", "admin", "scan"));
83 persistGithubPermissionsMapping(githubRolesToSqPermissions);
85 List<GithubPermissionsMapping> actualPermissionsMapping = underTest.getPermissionsMapping();
87 List<GithubPermissionsMapping> expectedPermissionsMapping = List.of(
88 new GithubPermissionsMapping(CUSTOM_ROLE_NAME, false, new SonarqubePermissions(true, false, false, false, false, false)),
89 new GithubPermissionsMapping(READ_GITHUB_ROLE, true, new SonarqubePermissions(true, true, false, false, false, false)),
90 new GithubPermissionsMapping(TRIAGE_GITHUB_ROLE, true, NO_SQ_PERMISSIONS),
91 new GithubPermissionsMapping(WRITE_GITHUB_ROLE, true, new SonarqubePermissions(true, true, true, true, true, true)),
92 new GithubPermissionsMapping(MAINTAIN_GITHUB_ROLE, true, NO_SQ_PERMISSIONS),
93 new GithubPermissionsMapping(ADMIN_GITHUB_ROLE, true, NO_SQ_PERMISSIONS));
95 assertThat(actualPermissionsMapping).containsAll(expectedPermissionsMapping);
98 private void persistGithubPermissionsMapping(Map<String, Set<String>> githubRolesToSonarqubePermissions) {
99 for (Map.Entry<String, Set<String>> githubRoleToSonarqubePermissions : githubRolesToSonarqubePermissions.entrySet()) {
100 String githubRole = githubRoleToSonarqubePermissions.getKey();
101 githubRoleToSonarqubePermissions.getValue()
102 .forEach(permission -> githubPermissionsMappingDao.insert(
104 new GithubPermissionsMappingDto("uuid_" + githubRole + "_" + permission, githubRole, permission)));
110 public void updatePermissionsMappings_onBaseRole_shouldAddAndRemovePermissions() {
111 Map<String, Set<String>> githubRolesToSqPermissions = Map.of(READ_GITHUB_ROLE, Set.of("user", "codeviewer"));
112 persistGithubPermissionsMapping(githubRolesToSqPermissions);
114 PermissionMappingChange permToAdd1 = new PermissionMappingChange(READ_GITHUB_ROLE, "issueadmin", Operation.ADD);
115 PermissionMappingChange permToAdd2 = new PermissionMappingChange(READ_GITHUB_ROLE, "scan", Operation.ADD);
116 PermissionMappingChange permToRemove1 = new PermissionMappingChange(READ_GITHUB_ROLE, "user", Operation.REMOVE);
117 PermissionMappingChange permToRemove2 = new PermissionMappingChange(READ_GITHUB_ROLE, "codeviewer", Operation.REMOVE);
119 underTest.updatePermissionsMappings(Set.of(permToAdd1, permToAdd2, permToRemove1, permToRemove2));
121 GithubPermissionsMapping updatedPermissionsMapping = underTest.getPermissionsMappingForGithubRole(READ_GITHUB_ROLE);
123 SonarqubePermissions expectedSqPermissions = new SonarqubePermissions(false, false, true, false, false, true);
124 GithubPermissionsMapping expectedPermissionsMapping = new GithubPermissionsMapping(READ_GITHUB_ROLE, true, expectedSqPermissions);
125 assertThat(updatedPermissionsMapping).isEqualTo(expectedPermissionsMapping);
129 public void updatePermissionsMappings_onCustomRole_shouldAddAndRemovePermissions() {
130 Map<String, Set<String>> githubRolesToSqPermissions = Map.of(CUSTOM_ROLE_NAME, Set.of("user", "codeviewer"));
131 persistGithubPermissionsMapping(githubRolesToSqPermissions);
133 PermissionMappingChange permToAdd1 = new PermissionMappingChange(CUSTOM_ROLE_NAME, "issueadmin", Operation.ADD);
134 PermissionMappingChange permToRemove1 = new PermissionMappingChange(CUSTOM_ROLE_NAME, "user", Operation.REMOVE);
136 underTest.updatePermissionsMappings(Set.of(permToAdd1, permToRemove1));
138 GithubPermissionsMapping updatedPermissionsMapping = underTest.getPermissionsMappingForGithubRole(CUSTOM_ROLE_NAME);
140 SonarqubePermissions expectedSqPermissions = new SonarqubePermissions(false, true, true, false, false, false);
141 GithubPermissionsMapping expectedPermissionsMapping = new GithubPermissionsMapping(CUSTOM_ROLE_NAME, false, expectedSqPermissions);
142 assertThat(updatedPermissionsMapping).isEqualTo(expectedPermissionsMapping);
146 public void updatePermissionsMappings_whenRemovingNonExistingPermission_isNoOp() {
147 PermissionMappingChange permToRemove1 = new PermissionMappingChange(READ_GITHUB_ROLE, "user", Operation.REMOVE);
149 underTest.updatePermissionsMappings(Set.of(permToRemove1));
151 GithubPermissionsMapping updatedPermissionsMapping = underTest.getPermissionsMappingForGithubRole(READ_GITHUB_ROLE);
153 GithubPermissionsMapping expectedPermissionsMapping = new GithubPermissionsMapping(READ_GITHUB_ROLE, true, NO_SQ_PERMISSIONS);
154 assertThat(updatedPermissionsMapping).isEqualTo(expectedPermissionsMapping);
158 public void updatePermissionsMappings_whenAddingAlreadyExistingPermission_isNoOp() {
159 Map<String, Set<String>> githubRolesToSqPermissions = Map.of(READ_GITHUB_ROLE, Set.of("user", "codeviewer"));
160 persistGithubPermissionsMapping(githubRolesToSqPermissions);
161 PermissionMappingChange permToAdd1 = new PermissionMappingChange(READ_GITHUB_ROLE, "user", Operation.ADD);
163 underTest.updatePermissionsMappings(Set.of(permToAdd1));
165 GithubPermissionsMapping updatedPermissionsMapping = underTest.getPermissionsMappingForGithubRole(READ_GITHUB_ROLE);
167 SonarqubePermissions expectedSqPermissions = new SonarqubePermissions(true, true, false, false, false, false);
168 GithubPermissionsMapping expectedPermissionsMapping = new GithubPermissionsMapping(READ_GITHUB_ROLE, true, expectedSqPermissions);
169 assertThat(updatedPermissionsMapping).isEqualTo(expectedPermissionsMapping);
173 public void updatePermissionsMappings_handlesUpdatesForDifferentRoles() {
174 PermissionMappingChange permToAdd1 = new PermissionMappingChange(READ_GITHUB_ROLE, "user", Operation.ADD);
175 PermissionMappingChange permToAdd2 = new PermissionMappingChange(WRITE_GITHUB_ROLE, "user", Operation.ADD);
177 underTest.updatePermissionsMappings(Set.of(permToAdd1, permToAdd2));
179 SonarqubePermissions userOnlySqPermission = new SonarqubePermissions(true, false, false, false, false, false);
181 GithubPermissionsMapping updatedPermissionsMapping = underTest.getPermissionsMappingForGithubRole(READ_GITHUB_ROLE);
182 assertThat(updatedPermissionsMapping).isEqualTo(new GithubPermissionsMapping(READ_GITHUB_ROLE, true, userOnlySqPermission));
184 updatedPermissionsMapping = underTest.getPermissionsMappingForGithubRole(WRITE_GITHUB_ROLE);
185 assertThat(updatedPermissionsMapping).isEqualTo(new GithubPermissionsMapping(WRITE_GITHUB_ROLE, true, userOnlySqPermission));
189 public void getPermissionsMappingForGithubRole_onBaseRole_shouldReturnMappingOnlyForRole() {
190 Map<String, Set<String>> githubRolesToSqPermissions = Map.of(
191 READ_GITHUB_ROLE, Set.of("user", "codeviewer"),
192 WRITE_GITHUB_ROLE, Set.of("user", "codeviewer", "issueadmin", "securityhotspotadmin", "admin", "scan"));
193 persistGithubPermissionsMapping(githubRolesToSqPermissions);
195 GithubPermissionsMapping actualPermissionsMapping = underTest.getPermissionsMappingForGithubRole(READ_GITHUB_ROLE);
197 SonarqubePermissions expectedSqPermissions = new SonarqubePermissions(true, true, false, false, false, false);
198 GithubPermissionsMapping expectedPermissionsMapping = new GithubPermissionsMapping(READ_GITHUB_ROLE, true, expectedSqPermissions);
200 assertThat(actualPermissionsMapping).isEqualTo(expectedPermissionsMapping);
204 public void getPermissionsMappingForGithubRole_onCustomRole_shouldReturnMappingOnlyForRole() {
205 Map<String, Set<String>> githubRolesToSqPermissions = Map.of(
206 CUSTOM_ROLE_NAME, Set.of("admin"),
207 WRITE_GITHUB_ROLE, Set.of("user", "codeviewer", "issueadmin", "securityhotspotadmin", "admin", "scan"));
208 persistGithubPermissionsMapping(githubRolesToSqPermissions);
210 GithubPermissionsMapping actualPermissionsMapping = underTest.getPermissionsMappingForGithubRole(CUSTOM_ROLE_NAME);
212 SonarqubePermissions expectedSqPermissions = new SonarqubePermissions(false, false, false, false, true, false);
213 GithubPermissionsMapping expectedPermissionsMapping = new GithubPermissionsMapping(CUSTOM_ROLE_NAME, false, expectedSqPermissions);
215 assertThat(actualPermissionsMapping).isEqualTo(expectedPermissionsMapping);
219 public void deletePermissionMappings_whenTryingToDeleteForBaseRole_shouldThrow() {
220 assertThatThrownBy(() -> underTest.deletePermissionMappings(READ_GITHUB_ROLE))
221 .isInstanceOf(IllegalArgumentException.class)
222 .hasMessage("Deleting permission mapping for GitHub base role '" + READ_GITHUB_ROLE + "' is not allowed.");
226 public void deletePermissionMappings_whenNoMappingsExistForGithubRole_shouldThrow() {
227 assertThatThrownBy(() -> underTest.deletePermissionMappings(CUSTOM_ROLE_NAME))
228 .isInstanceOf(NotFoundException.class)
229 .hasMessage("Role '" + CUSTOM_ROLE_NAME + "' not found.");
233 public void deletePermissionMappings_whenTryingToDeleteForCustomRole_shouldDeleteMapping() {
234 Map<String, Set<String>> githubRolesToSqPermissions = Map.of(
235 READ_GITHUB_ROLE, Set.of("user", "codeviewer"),
236 WRITE_GITHUB_ROLE, Set.of("user", "codeviewer", "issueadmin", "securityhotspotadmin", "admin", "scan"),
237 CUSTOM_ROLE_NAME, Set.of("user", "codeviewer", "scan"),
238 "customRole2", Set.of("user", "codeviewer"));
240 persistGithubPermissionsMapping(githubRolesToSqPermissions);
241 underTest.deletePermissionMappings("customRole2");
243 List<GithubPermissionsMapping> allPermissionMappings = underTest.getPermissionsMapping();
245 assertThat(allPermissionMappings)
246 .containsExactlyInAnyOrder(
247 new GithubPermissionsMapping(READ_GITHUB_ROLE, true, new SonarqubePermissions(true, true, false, false, false, false)),
248 new GithubPermissionsMapping(WRITE_GITHUB_ROLE, true, new SonarqubePermissions(true, true, true, true, true, true)),
249 new GithubPermissionsMapping(TRIAGE_GITHUB_ROLE, true, NO_SQ_PERMISSIONS),
250 new GithubPermissionsMapping(MAINTAIN_GITHUB_ROLE, true, NO_SQ_PERMISSIONS),
251 new GithubPermissionsMapping(ADMIN_GITHUB_ROLE, true, NO_SQ_PERMISSIONS),
252 new GithubPermissionsMapping(CUSTOM_ROLE_NAME, false, new SonarqubePermissions(true, true, false, false, false, true)));