]> source.dussan.org Git - sonarqube.git/blob
2b68cec4651a2e1773c18299d3ac9510511e31fe
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2019 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.qualityprofile.ws;
21
22 import java.net.HttpURLConnection;
23 import org.junit.Rule;
24 import org.junit.Test;
25 import org.junit.rules.ExpectedException;
26 import org.sonar.api.resources.Languages;
27 import org.sonar.api.server.ws.WebService;
28 import org.sonar.api.server.ws.WebService.Param;
29 import org.sonar.api.utils.System2;
30 import org.sonar.core.util.UuidFactoryFast;
31 import org.sonar.db.DbClient;
32 import org.sonar.db.DbSession;
33 import org.sonar.db.DbTester;
34 import org.sonar.db.component.ComponentDto;
35 import org.sonar.db.organization.OrganizationDto;
36 import org.sonar.db.qualityprofile.QProfileDto;
37 import org.sonar.db.user.UserDto;
38 import org.sonar.server.exceptions.BadRequestException;
39 import org.sonar.server.exceptions.ForbiddenException;
40 import org.sonar.server.exceptions.NotFoundException;
41 import org.sonar.server.exceptions.UnauthorizedException;
42 import org.sonar.server.language.LanguageTesting;
43 import org.sonar.server.organization.TestDefaultOrganizationProvider;
44 import org.sonar.server.qualityprofile.QProfileFactoryImpl;
45 import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
46 import org.sonar.server.tester.UserSessionRule;
47 import org.sonar.server.ws.TestResponse;
48 import org.sonar.server.ws.WsActionTester;
49
50 import static org.assertj.core.api.Assertions.assertThat;
51 import static org.mockito.Mockito.mock;
52 import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
53 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY;
54 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
55 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_ORGANIZATION;
56 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_QUALITY_PROFILE;
57
58 public class DeleteActionTest {
59
60   private static final String A_LANGUAGE = "xoo";
61
62   @Rule
63   public DbTester db = DbTester.create(System2.INSTANCE);
64   @Rule
65   public ExpectedException expectedException = ExpectedException.none();
66   @Rule
67   public UserSessionRule userSession = UserSessionRule.standalone();
68
69   private DbClient dbClient = db.getDbClient();
70   private DbSession dbSession = db.getSession();
71   private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class);
72
73   private DeleteAction underTest = new DeleteAction(
74     new Languages(LanguageTesting.newLanguage(A_LANGUAGE)),
75     new QProfileFactoryImpl(dbClient, UuidFactoryFast.getInstance(), System2.INSTANCE, activeRuleIndexer), dbClient, userSession,
76     new QProfileWsSupport(dbClient, userSession, TestDefaultOrganizationProvider.from(db)));
77   private WsActionTester ws = new WsActionTester(underTest);
78
79   @Test
80   public void delete_profile_by_key() {
81     OrganizationDto organization = db.organizations().insert();
82     ComponentDto project = db.components().insertPrivateProject(organization);
83     QProfileDto profile1 = createProfile(organization);
84     QProfileDto profile2 = createProfile(organization);
85     db.qualityProfiles().associateWithProject(project, profile1);
86
87     logInAsQProfileAdministrator(organization);
88
89     TestResponse response = ws.newRequest()
90       .setMethod("POST")
91       .setParam(PARAM_KEY, profile1.getKee())
92       .execute();
93     assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT);
94
95     verifyProfileDoesNotExist(profile1, organization);
96     verifyProfileExists(profile2);
97   }
98
99   @Test
100   public void delete_profile_by_language_and_name_in_default_organization() {
101     OrganizationDto organization = db.getDefaultOrganization();
102     ComponentDto project = db.components().insertPrivateProject(organization);
103     QProfileDto profile1 = createProfile(organization);
104     QProfileDto profile2 = createProfile(organization);
105     db.qualityProfiles().associateWithProject(project, profile1);
106
107     logInAsQProfileAdministrator(organization);
108
109     TestResponse response = ws.newRequest()
110       .setMethod("POST")
111       .setParam(PARAM_LANGUAGE, profile1.getLanguage())
112       .setParam(PARAM_QUALITY_PROFILE, profile1.getName())
113       .execute();
114
115     assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT);
116
117     verifyProfileDoesNotExist(profile1, organization);
118     verifyProfileExists(profile2);
119   }
120
121   @Test
122   public void delete_profile_by_language_and_name_in_specified_organization() {
123     OrganizationDto organization = db.organizations().insert();
124     ComponentDto project = db.components().insertPrivateProject(organization);
125     QProfileDto profile1 = createProfile(organization);
126     QProfileDto profile2 = createProfile(organization);
127     db.qualityProfiles().associateWithProject(project, profile1);
128     logInAsQProfileAdministrator(organization);
129
130     TestResponse response = ws.newRequest()
131       .setMethod("POST")
132       .setParam(PARAM_ORGANIZATION, organization.getKey())
133       .setParam(PARAM_LANGUAGE, profile1.getLanguage())
134       .setParam(PARAM_QUALITY_PROFILE, profile1.getName())
135       .execute();
136     assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT);
137
138     verifyProfileDoesNotExist(profile1, organization);
139     verifyProfileExists(profile2);
140   }
141
142   @Test
143   public void as_qprofile_editor() {
144     OrganizationDto organization = db.organizations().insert();
145     QProfileDto profile = createProfile(organization);
146     UserDto user = db.users().insertUser();
147     db.qualityProfiles().addUserPermission(profile, user);
148     userSession.logIn(user);
149
150     TestResponse response = ws.newRequest()
151       .setMethod("POST")
152       .setParam(PARAM_ORGANIZATION, organization.getKey())
153       .setParam(PARAM_LANGUAGE, profile.getLanguage())
154       .setParam(PARAM_QUALITY_PROFILE, profile.getName())
155       .execute();
156     assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT);
157
158     verifyProfileDoesNotExist(profile, organization);
159   }
160
161   @Test
162   public void fail_if_built_in_profile() {
163     OrganizationDto organization = db.organizations().insert();
164     QProfileDto profile1 = db.qualityProfiles().insert(organization, p -> p.setIsBuiltIn(true));
165     logInAsQProfileAdministrator(organization);
166
167     expectedException.expect(BadRequestException.class);
168
169     ws.newRequest()
170       .setMethod("POST")
171       .setParam(PARAM_KEY, profile1.getKee())
172       .execute();
173   }
174
175   @Test
176   public void fail_if_not_profile_administrator() {
177     OrganizationDto organization = db.organizations().insert();
178     QProfileDto qprofile = createProfile(organization);
179     userSession.logIn(db.users().insertUser());
180
181     expectedException.expect(ForbiddenException.class);
182     expectedException.expectMessage("Insufficient privileges");
183
184     ws.newRequest()
185       .setMethod("POST")
186       .setParam(PARAM_KEY, qprofile.getKee())
187       .execute();
188   }
189
190   @Test
191   public void fail_if_not_logged_in() {
192     QProfileDto profile = createProfile(db.getDefaultOrganization());
193
194     expectedException.expect(UnauthorizedException.class);
195
196     ws.newRequest()
197       .setMethod("POST")
198       .setParam(PARAM_KEY, profile.getKee())
199       .execute();
200   }
201
202   @Test
203   public void fail_if_missing_parameters() {
204     userSession.logIn();
205
206     expectedException.expect(IllegalArgumentException.class);
207     expectedException.expectMessage("If 'key' is not specified, 'qualityProfile' and 'language' must be set");
208
209     ws.newRequest()
210       .setMethod("POST")
211       .execute();
212   }
213
214   @Test
215   public void fail_if_missing_language_parameter() {
216     OrganizationDto organization = db.organizations().insert();
217     QProfileDto profile = createProfile(organization);
218     logInAsQProfileAdministrator(organization);
219
220     expectedException.expect(IllegalArgumentException.class);
221     expectedException.expectMessage("If 'key' is not specified, 'qualityProfile' and 'language' must be set");
222
223     ws.newRequest()
224       .setMethod("POST")
225       .setParam(PARAM_ORGANIZATION, organization.getKey())
226       .setParam("profileName", profile.getName())
227       .execute();
228   }
229
230   @Test
231   public void fail_if_missing_name_parameter() {
232     OrganizationDto organization = db.organizations().insert();
233     QProfileDto profile = createProfile(organization);
234     logInAsQProfileAdministrator(organization);
235
236     expectedException.expect(IllegalArgumentException.class);
237     expectedException.expectMessage("If 'key' is not specified, 'qualityProfile' and 'language' must be set");
238
239     ws.newRequest()
240       .setMethod("POST")
241       .setParam(PARAM_ORGANIZATION, organization.getKey())
242       .setParam(PARAM_LANGUAGE, profile.getLanguage())
243       .execute();
244   }
245
246   @Test
247   public void fail_if_too_many_parameters_to_reference_profile() {
248     OrganizationDto organization = db.organizations().insert();
249     QProfileDto profile = createProfile(organization);
250     logInAsQProfileAdministrator(organization);
251
252     expectedException.expect(IllegalArgumentException.class);
253     expectedException.expectMessage("When a quality profile key is set, 'organization' 'language' and 'qualityProfile' can't be set");
254
255     ws.newRequest()
256       .setMethod("POST")
257       .setParam(PARAM_ORGANIZATION, organization.getKey())
258       .setParam(PARAM_LANGUAGE, profile.getLanguage())
259       .setParam("profileName", profile.getName())
260       .setParam(PARAM_KEY, profile.getKee())
261       .execute();
262   }
263
264   @Test
265   public void fail_if_profile_does_not_exist() {
266     userSession.logIn();
267
268     expectedException.expect(NotFoundException.class);
269     expectedException.expectMessage("Quality Profile with key 'does_not_exist' does not exist");
270
271     ws.newRequest()
272       .setMethod("POST")
273       .setParam(PARAM_KEY, "does_not_exist")
274       .execute();
275   }
276
277   @Test
278   public void fail_if_deleting_default_profile() {
279     OrganizationDto organization = db.organizations().insert();
280     QProfileDto profile = createProfile(organization);
281     db.qualityProfiles().setAsDefault(profile);
282     logInAsQProfileAdministrator(organization);
283
284     expectedException.expect(IllegalArgumentException.class);
285     expectedException.expectMessage("Profile '" + profile.getName() + "' cannot be deleted because it is marked as default");
286
287     ws.newRequest()
288       .setMethod("POST")
289       .setParam(PARAM_KEY, profile.getKee())
290       .execute();
291   }
292
293   @Test
294   public void fail_if_a_descendant_is_marked_as_default() {
295     OrganizationDto organization = db.organizations().insert();
296     QProfileDto parentProfile = createProfile(organization);
297     QProfileDto childProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage(A_LANGUAGE).setParentKee(parentProfile.getKee()));
298     db.qualityProfiles().setAsDefault(childProfile);
299     logInAsQProfileAdministrator(organization);
300
301     expectedException.expect(IllegalArgumentException.class);
302     expectedException.expectMessage("Profile '" + parentProfile.getName() + "' cannot be deleted because its descendant named '" + childProfile.getName() +
303       "' is marked as default");
304
305     ws.newRequest()
306       .setMethod("POST")
307       .setParam(PARAM_KEY, parentProfile.getKee())
308       .execute();
309   }
310
311   @Test
312   public void definition() {
313     WebService.Action definition = ws.getDef();
314
315     assertThat(definition.isPost()).isTrue();
316     assertThat(definition.params()).extracting(Param::key).containsExactlyInAnyOrder("language", "organization", "key", "qualityProfile");
317     Param key = definition.param("key");
318     assertThat(key.deprecatedKey()).isEqualTo("profileKey");
319     assertThat(key.deprecatedSince()).isEqualTo("6.6");
320     Param profileName = definition.param("qualityProfile");
321     assertThat(profileName.deprecatedSince()).isNullOrEmpty();
322     Param language = definition.param("language");
323     assertThat(language.deprecatedSince()).isNullOrEmpty();
324   }
325
326   private void logInAsQProfileAdministrator(OrganizationDto organization) {
327     userSession
328       .logIn(db.users().insertUser())
329       .addPermission(ADMINISTER_QUALITY_PROFILES, organization);
330   }
331
332   private void verifyProfileDoesNotExist(QProfileDto profile, OrganizationDto organization) {
333     assertThat(dbClient.qualityProfileDao().selectByUuid(dbSession, profile.getKee())).isNull();
334     assertThat(dbClient.qualityProfileDao().selectSelectedProjects(dbSession, organization, profile, null)).isEmpty();
335   }
336
337   private void verifyProfileExists(QProfileDto profile) {
338     assertThat(dbClient.qualityProfileDao().selectByUuid(dbSession, profile.getKee())).isNotNull();
339   }
340
341   private QProfileDto createProfile(OrganizationDto organization) {
342     return db.qualityProfiles().insert(organization, p -> p.setLanguage(A_LANGUAGE));
343   }
344 }