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.v2.api.github.permissions.controller;
22 import com.google.gson.Gson;
23 import com.google.gson.GsonBuilder;
24 import java.util.List;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.mockito.ArgumentCaptor;
29 import org.sonar.server.common.github.permissions.GithubPermissionsMapping;
30 import org.sonar.server.common.github.permissions.GithubPermissionsMappingService;
31 import org.sonar.server.common.github.permissions.PermissionMappingChange;
32 import org.sonar.server.common.github.permissions.SonarqubePermissions;
33 import org.sonar.server.common.permission.Operation;
34 import org.sonar.server.exceptions.NotFoundException;
35 import org.sonar.server.tester.UserSessionRule;
36 import org.sonar.server.v2.api.ControllerTester;
37 import org.sonar.server.v2.api.github.permissions.model.RestGithubPermissionsMapping;
38 import org.sonar.server.v2.api.github.permissions.response.GithubPermissionsMappingRestResponse;
39 import org.springframework.test.web.servlet.MockMvc;
40 import org.springframework.test.web.servlet.MvcResult;
42 import static org.assertj.core.api.Assertions.assertThat;
43 import static org.mockito.Mockito.doThrow;
44 import static org.mockito.Mockito.mock;
45 import static org.mockito.Mockito.verify;
46 import static org.mockito.Mockito.when;
47 import static org.sonar.server.common.github.permissions.GithubPermissionsMappingService.READ_GITHUB_ROLE;
48 import static org.sonar.server.v2.WebApiEndpoints.GITHUB_PERMISSIONS_ENDPOINT;
49 import static org.sonar.server.v2.WebApiEndpoints.JSON_MERGE_PATCH_CONTENT_TYPE;
50 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
51 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
52 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
53 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
54 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
56 public class DefaultGithubPermissionsControllerTest {
58 public static final String GITHUB_ROLE = "role1";
59 private static final Gson gson = new GsonBuilder().create();
62 public UserSessionRule userSession = UserSessionRule.standalone();
63 private final GithubPermissionsMappingService githubPermissionsMappingService = mock();
64 private final MockMvc mockMvc = ControllerTester.getMockMvc(new DefaultGithubPermissionsController(userSession, githubPermissionsMappingService));
67 public void fetchMapping_whenUserIsNotAdministrator_shouldReturnForbidden() throws Exception {
68 userSession.logIn().setNonSystemAdministrator();
70 mockMvc.perform(get(GITHUB_PERMISSIONS_ENDPOINT))
72 status().isForbidden(),
73 content().json("{\"message\":\"Insufficient privileges\"}"));
77 public void fetchMapping_whenMappingSet_shouldReturnMapping() throws Exception {
78 userSession.logIn().setSystemAdministrator();
80 List<GithubPermissionsMapping> mapping = List.of(
81 new GithubPermissionsMapping(GITHUB_ROLE, false, new SonarqubePermissions(true, false, true, false, true, false)),
82 new GithubPermissionsMapping("role2", true, new SonarqubePermissions(false, true, false, true, false, true)));
83 when(githubPermissionsMappingService.getPermissionsMapping()).thenReturn(mapping);
85 MvcResult mvcResult = mockMvc.perform(get(GITHUB_PERMISSIONS_ENDPOINT))
86 .andExpect(status().isOk())
89 GithubPermissionsMappingRestResponse response = gson.fromJson(mvcResult.getResponse().getContentAsString(), GithubPermissionsMappingRestResponse.class);
90 assertThat(response.githubPermissionsMappings()).isEqualTo(toRestResources(mapping));
93 private static List<RestGithubPermissionsMapping> toRestResources(List<GithubPermissionsMapping> permissionsMapping) {
94 return permissionsMapping.stream()
95 .map(DefaultGithubPermissionsControllerTest::toRestGithubPermissionMapping)
99 private static RestGithubPermissionsMapping toRestGithubPermissionMapping(GithubPermissionsMapping permissionMapping) {
100 return new RestGithubPermissionsMapping(permissionMapping.roleName(), permissionMapping.roleName(), permissionMapping.isBaseRole(), permissionMapping.permissions());
104 public void updateMapping_whenUserIsNotAdministrator_shouldReturnForbidden() throws Exception {
105 userSession.logIn().setNonSystemAdministrator();
108 patch(GITHUB_PERMISSIONS_ENDPOINT + "/" + GITHUB_ROLE)
109 .contentType(JSON_MERGE_PATCH_CONTENT_TYPE)
118 status().isForbidden(),
119 content().json("{\"message\":\"Insufficient privileges\"}"));
123 public void updateMapping_shouldUpdateMapping() throws Exception {
124 userSession.logIn().setSystemAdministrator();
125 GithubPermissionsMapping updatedRolePermissions = new GithubPermissionsMapping(GITHUB_ROLE, false, new SonarqubePermissions(true, false, false, true, true, false));
127 when(githubPermissionsMappingService.getPermissionsMappingForGithubRole(GITHUB_ROLE)).thenReturn(updatedRolePermissions);
129 MvcResult mvcResult = mockMvc.perform(
130 patch(GITHUB_PERMISSIONS_ENDPOINT + "/" + GITHUB_ROLE)
131 .contentType(JSON_MERGE_PATCH_CONTENT_TYPE)
141 .andExpect(status().isOk())
144 RestGithubPermissionsMapping response = gson.fromJson(mvcResult.getResponse().getContentAsString(), RestGithubPermissionsMapping.class);
146 RestGithubPermissionsMapping expectedResponse = new RestGithubPermissionsMapping(GITHUB_ROLE, GITHUB_ROLE, false,
147 new SonarqubePermissions(true, false, false, true, true, false));
148 assertThat(response).isEqualTo(expectedResponse);
150 ArgumentCaptor<Set<PermissionMappingChange>> permissionMappingChangesCaptor = ArgumentCaptor.forClass(Set.class);
151 verify(githubPermissionsMappingService).updatePermissionsMappings(permissionMappingChangesCaptor.capture());
152 assertThat(permissionMappingChangesCaptor.getValue())
153 .containsExactlyInAnyOrder(
154 new PermissionMappingChange(GITHUB_ROLE, "codeviewer", Operation.REMOVE),
155 new PermissionMappingChange(GITHUB_ROLE, "user", Operation.ADD),
156 new PermissionMappingChange(GITHUB_ROLE, "admin", Operation.ADD));
160 public void deleteMapping_whenUserIsNotAdministrator_shouldReturnForbidden() throws Exception {
161 userSession.logIn().setNonSystemAdministrator();
163 .perform(delete(GITHUB_PERMISSIONS_ENDPOINT + "/" + READ_GITHUB_ROLE))
165 status().isForbidden(),
166 content().json("{\"message\":\"Insufficient privileges\"}"));
170 public void deleteMapping_whenTryingToDeleteBaseRole_shouldReturnBadRequest() throws Exception {
171 userSession.logIn().setSystemAdministrator();
172 doThrow(new IllegalArgumentException("Bad request")).when(githubPermissionsMappingService).deletePermissionMappings(READ_GITHUB_ROLE);
174 .perform(delete(GITHUB_PERMISSIONS_ENDPOINT + "/" + READ_GITHUB_ROLE))
176 status().isBadRequest(),
177 content().json("{\"message\":\"Bad request\"}"));
181 public void deleteMapping_whenNoMappingsExistForACustomRole_shouldReturnNotFound() throws Exception {
182 userSession.logIn().setSystemAdministrator();
183 doThrow(new NotFoundException("Role not found")).when(githubPermissionsMappingService).deletePermissionMappings(READ_GITHUB_ROLE);
185 .perform(delete(GITHUB_PERMISSIONS_ENDPOINT + "/" + READ_GITHUB_ROLE))
187 status().isNotFound(),
188 content().json("{\"message\":\"Role not found\"}"));
192 public void deleteMapping_whenTryingToDeleteCustomRole_shouldReturnNoContent() throws Exception {
193 userSession.logIn().setSystemAdministrator();
195 .perform(delete(GITHUB_PERMISSIONS_ENDPOINT + "/" + GITHUB_ROLE))
197 status().isNoContent());
199 verify(githubPermissionsMappingService).deletePermissionMappings(GITHUB_ROLE);