]> source.dussan.org Git - sonarqube.git/blob
dd0282d50798e1e0b7ee3c7dd5ff6008801161de
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2023 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.server.v2.api.github.permissions.controller;
21
22 import com.google.gson.Gson;
23 import com.google.gson.GsonBuilder;
24 import java.util.List;
25 import java.util.Set;
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;
41
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;
55
56 public class DefaultGithubPermissionsControllerTest {
57
58   public static final String GITHUB_ROLE = "role1";
59   private static final Gson gson = new GsonBuilder().create();
60
61   @Rule
62   public UserSessionRule userSession = UserSessionRule.standalone();
63   private final GithubPermissionsMappingService githubPermissionsMappingService = mock();
64   private final MockMvc mockMvc = ControllerTester.getMockMvc(new DefaultGithubPermissionsController(userSession, githubPermissionsMappingService));
65
66   @Test
67   public void fetchMapping_whenUserIsNotAdministrator_shouldReturnForbidden() throws Exception {
68     userSession.logIn().setNonSystemAdministrator();
69
70     mockMvc.perform(get(GITHUB_PERMISSIONS_ENDPOINT))
71       .andExpectAll(
72         status().isForbidden(),
73         content().json("{\"message\":\"Insufficient privileges\"}"));
74   }
75
76   @Test
77   public void fetchMapping_whenMappingSet_shouldReturnMapping() throws Exception {
78     userSession.logIn().setSystemAdministrator();
79
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);
84
85     MvcResult mvcResult = mockMvc.perform(get(GITHUB_PERMISSIONS_ENDPOINT))
86       .andExpect(status().isOk())
87       .andReturn();
88
89     GithubPermissionsMappingRestResponse response = gson.fromJson(mvcResult.getResponse().getContentAsString(), GithubPermissionsMappingRestResponse.class);
90     assertThat(response.githubPermissionsMappings()).isEqualTo(toRestResources(mapping));
91   }
92
93   private static List<RestGithubPermissionsMapping> toRestResources(List<GithubPermissionsMapping> permissionsMapping) {
94     return permissionsMapping.stream()
95       .map(DefaultGithubPermissionsControllerTest::toRestGithubPermissionMapping)
96       .toList();
97   }
98
99   private static RestGithubPermissionsMapping toRestGithubPermissionMapping(GithubPermissionsMapping permissionMapping) {
100     return new RestGithubPermissionsMapping(permissionMapping.roleName(), permissionMapping.roleName(), permissionMapping.isBaseRole(), permissionMapping.permissions());
101   }
102
103   @Test
104   public void updateMapping_whenUserIsNotAdministrator_shouldReturnForbidden() throws Exception {
105     userSession.logIn().setNonSystemAdministrator();
106
107     mockMvc.perform(
108       patch(GITHUB_PERMISSIONS_ENDPOINT + "/" + GITHUB_ROLE)
109         .contentType(JSON_MERGE_PATCH_CONTENT_TYPE)
110         .content("""
111           {
112               "user": true,
113               "codeViewer": false,
114               "admin": true
115           }
116           """))
117       .andExpectAll(
118         status().isForbidden(),
119         content().json("{\"message\":\"Insufficient privileges\"}"));
120   }
121
122   @Test
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));
126
127     when(githubPermissionsMappingService.getPermissionsMappingForGithubRole(GITHUB_ROLE)).thenReturn(updatedRolePermissions);
128
129     MvcResult mvcResult = mockMvc.perform(
130       patch(GITHUB_PERMISSIONS_ENDPOINT + "/" + GITHUB_ROLE)
131         .contentType(JSON_MERGE_PATCH_CONTENT_TYPE)
132         .content("""
133           {
134             "permissions": {
135               "user": true,
136               "codeViewer": false,
137               "admin": true
138             }
139           }
140           """))
141       .andExpect(status().isOk())
142       .andReturn();
143
144     RestGithubPermissionsMapping response = gson.fromJson(mvcResult.getResponse().getContentAsString(), RestGithubPermissionsMapping.class);
145
146     RestGithubPermissionsMapping expectedResponse = new RestGithubPermissionsMapping(GITHUB_ROLE, GITHUB_ROLE, false,
147       new SonarqubePermissions(true, false, false, true, true, false));
148     assertThat(response).isEqualTo(expectedResponse);
149
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));
157   }
158
159   @Test
160   public void deleteMapping_whenUserIsNotAdministrator_shouldReturnForbidden() throws Exception {
161     userSession.logIn().setNonSystemAdministrator();
162     mockMvc
163       .perform(delete(GITHUB_PERMISSIONS_ENDPOINT + "/" + READ_GITHUB_ROLE))
164       .andExpectAll(
165         status().isForbidden(),
166         content().json("{\"message\":\"Insufficient privileges\"}"));
167   }
168
169   @Test
170   public void deleteMapping_whenTryingToDeleteBaseRole_shouldReturnBadRequest() throws Exception {
171     userSession.logIn().setSystemAdministrator();
172     doThrow(new IllegalArgumentException("Bad request")).when(githubPermissionsMappingService).deletePermissionMappings(READ_GITHUB_ROLE);
173     mockMvc
174       .perform(delete(GITHUB_PERMISSIONS_ENDPOINT + "/" + READ_GITHUB_ROLE))
175       .andExpectAll(
176         status().isBadRequest(),
177         content().json("{\"message\":\"Bad request\"}"));
178   }
179
180   @Test
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);
184     mockMvc
185       .perform(delete(GITHUB_PERMISSIONS_ENDPOINT + "/" + READ_GITHUB_ROLE))
186       .andExpectAll(
187         status().isNotFound(),
188         content().json("{\"message\":\"Role not found\"}"));
189   }
190
191   @Test
192   public void deleteMapping_whenTryingToDeleteCustomRole_shouldReturnNoContent() throws Exception {
193     userSession.logIn().setSystemAdministrator();
194     mockMvc
195       .perform(delete(GITHUB_PERMISSIONS_ENDPOINT + "/" + GITHUB_ROLE))
196       .andExpect(
197         status().isNoContent());
198
199     verify(githubPermissionsMappingService).deletePermissionMappings(GITHUB_ROLE);
200   }
201
202 }