From 3890514fac821836778dfa34e29f62bd21730a85 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Wed, 15 Mar 2017 11:58:12 +0100 Subject: [PATCH] SONAR-8857 add organization parameter to api/qualityprofiles/restore_built_in --- .../platformlevel/PlatformLevel4.java | 4 +- .../server/qualityprofile/QProfileReset.java | 147 +--------------- .../qualityprofile/QProfileResetImpl.java | 164 ++++++++++++++++++ .../ws/RestoreBuiltInAction.java | 22 ++- .../QProfileResetMediumTest.java | 13 +- .../qualityprofile/ws/QProfilesWsTest.java | 9 - .../ws/RestoreBuiltInActionTest.java | 93 ++++++++-- 7 files changed, 278 insertions(+), 174 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileResetImpl.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index 46ddd1fc49d..c6c29b3cf55 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -148,7 +148,7 @@ import org.sonar.server.qualityprofile.QProfileFactory; import org.sonar.server.qualityprofile.QProfileLoader; import org.sonar.server.qualityprofile.QProfileLookup; import org.sonar.server.qualityprofile.QProfileProjectOperations; -import org.sonar.server.qualityprofile.QProfileReset; +import org.sonar.server.qualityprofile.QProfileResetImpl; import org.sonar.server.qualityprofile.QProfileService; import org.sonar.server.qualityprofile.RuleActivator; import org.sonar.server.qualityprofile.RuleActivatorContextFactory; @@ -276,7 +276,7 @@ public class PlatformLevel4 extends PlatformLevel { QProfileFactory.class, QProfileCopier.class, QProfileBackuperImpl.class, - QProfileReset.class, + QProfileResetImpl.class, QProfilesWsModule.class, // rule diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileReset.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileReset.java index 4c509b65c01..0e884329816 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileReset.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileReset.java @@ -19,156 +19,19 @@ */ package org.sonar.server.qualityprofile; -import com.google.common.base.Preconditions; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.ListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.sonar.api.profiles.ProfileDefinition; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rules.ActiveRule; -import org.sonar.api.rules.ActiveRuleParam; -import org.sonar.api.server.ServerSide; -import org.sonar.api.utils.ValidationMessages; -import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.organization.OrganizationDto; -import org.sonar.db.qualityprofile.ActiveRuleDto; -import org.sonar.db.qualityprofile.ActiveRuleKey; -import org.sonar.db.qualityprofile.QualityProfileDto; -import org.sonar.db.rule.RuleParamDto; -import org.sonar.server.exceptions.BadRequestException; -import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; -import org.sonar.server.qualityprofile.ws.QProfileWsSupport; - -import static org.sonar.server.ws.WsUtils.checkRequest; - -@ServerSide -public class QProfileReset { - - private final DbClient db; - private final QProfileFactory factory; - private final RuleActivator activator; - private final ActiveRuleIndexer activeRuleIndexer; - private final QProfileWsSupport qProfileWsSupport; - private final ProfileDefinition[] definitions; - - public QProfileReset(DbClient db, RuleActivator activator, ActiveRuleIndexer activeRuleIndexer, QProfileFactory factory, QProfileWsSupport qProfileWsSupport, - ProfileDefinition... definitions) { - this.db = db; - this.activator = activator; - this.activeRuleIndexer = activeRuleIndexer; - this.factory = factory; - this.qProfileWsSupport = qProfileWsSupport; - this.definitions = definitions; - } - - public QProfileReset(DbClient db, RuleActivator activator, ActiveRuleIndexer activeRuleIndexer, QProfileFactory factory, - QProfileWsSupport qProfileWsSupport) { - this(db, activator, activeRuleIndexer, factory, qProfileWsSupport, new ProfileDefinition[0]); - } +public interface QProfileReset { /** - * Reset built-in profiles for the given language. Missing profiles are created and - * existing ones are updated. + * Restore the built-in profiles provided by plugins for the specified language. + * Missing profiles are created and existing ones are updated. */ - public void resetLanguage(DbSession dbSession, String language) { - ListMultimap profilesByName = loadDefinitionsGroupedByName(language); - for (Map.Entry> entry : profilesByName.asMap().entrySet()) { - QProfileName profileName = entry.getKey(); - QualityProfileDto profile = factory.getOrCreate(dbSession, qProfileWsSupport.getDefaultOrganization(dbSession), profileName); - List activations = Lists.newArrayList(); - for (RulesProfile def : entry.getValue()) { - for (ActiveRule activeRule : def.getActiveRules()) { - RuleActivation activation = new RuleActivation(RuleKey.of(activeRule.getRepositoryKey(), activeRule.getRuleKey())); - activation.setSeverity(activeRule.getSeverity().name()); - if (!activeRule.getActiveRuleParams().isEmpty()) { - for (ActiveRuleParam param : activeRule.getActiveRuleParams()) { - activation.setParameter(param.getParamKey(), param.getValue()); - } - } else { - for (RuleParamDto param : db.ruleDao().selectRuleParamsByRuleKey(dbSession, activeRule.getRule().ruleKey())) { - activation.setParameter(param.getName(), param.getDefaultValue()); - } - } - activations.add(activation); - } - } - doReset(dbSession, profile, activations); - } - } + void resetLanguage(DbSession dbSession, OrganizationDto organization, String language); /** * Reset the profile, which is created if it does not exist */ - QProfileRestoreSummary reset(DbSession dbSession, OrganizationDto organization, QProfileName profileName, Collection activations) { - QualityProfileDto profile = factory.getOrCreate(dbSession, organization, profileName); - BulkChangeResult ruleChanges = doReset(dbSession, profile, activations); - return new QProfileRestoreSummary(organization, profile, ruleChanges); - } - - /** - * @param dbSession - * @param profile must exist - */ - private BulkChangeResult doReset(DbSession dbSession, QualityProfileDto profile, Collection activations) { - Preconditions.checkNotNull(profile.getId(), "Quality profile must be persisted"); - BulkChangeResult result = new BulkChangeResult(); - Set ruleToBeDeactivated = Sets.newHashSet(); - // Keep reference to all the activated rules before backup restore - for (ActiveRuleDto activeRuleDto : db.activeRuleDao().selectByProfileKey(dbSession, profile.getKee())) { - if (activeRuleDto.getInheritance() == null) { - // inherited rules can't be deactivated - ruleToBeDeactivated.add(activeRuleDto.getKey().ruleKey()); - } - } - - for (RuleActivation activation : activations) { - try { - List changes = activator.activate(dbSession, activation, profile.getKey()); - ruleToBeDeactivated.remove(activation.getRuleKey()); - result.incrementSucceeded(); - result.addChanges(changes); - } catch (BadRequestException e) { - result.incrementFailed(); - result.getErrors().addAll(e.errors()); - } - } - - List changes = new ArrayList<>(); - changes.addAll(result.getChanges()); - for (RuleKey ruleKey : ruleToBeDeactivated) { - try { - changes.addAll(activator.deactivate(dbSession, ActiveRuleKey.of(profile.getKee(), ruleKey))); - } catch (BadRequestException e) { - // ignore, probably a rule inherited from parent that can't be deactivated - } - } - dbSession.commit(); - activeRuleIndexer.index(changes); - return result; - } - - private ListMultimap loadDefinitionsGroupedByName(String language) { - ListMultimap profilesByName = ArrayListMultimap.create(); - for (ProfileDefinition definition : definitions) { - ValidationMessages validation = ValidationMessages.create(); - RulesProfile profile = definition.createProfile(validation); - if (language.equals(profile.getLanguage())) { - processValidationMessages(validation); - profilesByName.put(new QProfileName(profile.getLanguage(), profile.getName()), profile); - } - } - return profilesByName; - } - - private void processValidationMessages(ValidationMessages messages) { - checkRequest(messages.getErrors().isEmpty(), messages.getErrors()); - } + QProfileRestoreSummary reset(DbSession dbSession, OrganizationDto organization, QProfileName profileName, Collection activations); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileResetImpl.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileResetImpl.java new file mode 100644 index 00000000000..62b6df3a3b8 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileResetImpl.java @@ -0,0 +1,164 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualityprofile; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.sonar.api.profiles.ProfileDefinition; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rules.ActiveRule; +import org.sonar.api.rules.ActiveRuleParam; +import org.sonar.api.server.ServerSide; +import org.sonar.api.utils.ValidationMessages; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.qualityprofile.ActiveRuleDto; +import org.sonar.db.qualityprofile.ActiveRuleKey; +import org.sonar.db.qualityprofile.QualityProfileDto; +import org.sonar.db.rule.RuleParamDto; +import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; + +import static org.sonar.server.ws.WsUtils.checkRequest; + +@ServerSide +public class QProfileResetImpl implements QProfileReset { + + private final DbClient db; + private final QProfileFactory factory; + private final RuleActivator activator; + private final ActiveRuleIndexer activeRuleIndexer; + private final ProfileDefinition[] definitions; + + public QProfileResetImpl(DbClient db, RuleActivator activator, ActiveRuleIndexer activeRuleIndexer, QProfileFactory factory, ProfileDefinition... definitions) { + this.db = db; + this.activator = activator; + this.activeRuleIndexer = activeRuleIndexer; + this.factory = factory; + this.definitions = definitions; + } + + public QProfileResetImpl(DbClient db, RuleActivator activator, ActiveRuleIndexer activeRuleIndexer, QProfileFactory factory) { + this(db, activator, activeRuleIndexer, factory, new ProfileDefinition[0]); + } + + @Override + public void resetLanguage(DbSession dbSession, OrganizationDto organization, String language) { + ListMultimap profilesByName = loadDefinitionsGroupedByName(language); + for (Map.Entry> entry : profilesByName.asMap().entrySet()) { + QProfileName profileName = entry.getKey(); + QualityProfileDto profile = factory.getOrCreate(dbSession, organization, profileName); + List activations = Lists.newArrayList(); + for (RulesProfile def : entry.getValue()) { + for (ActiveRule activeRule : def.getActiveRules()) { + RuleActivation activation = new RuleActivation(RuleKey.of(activeRule.getRepositoryKey(), activeRule.getRuleKey())); + activation.setSeverity(activeRule.getSeverity().name()); + if (!activeRule.getActiveRuleParams().isEmpty()) { + for (ActiveRuleParam param : activeRule.getActiveRuleParams()) { + activation.setParameter(param.getParamKey(), param.getValue()); + } + } else { + for (RuleParamDto param : db.ruleDao().selectRuleParamsByRuleKey(dbSession, activeRule.getRule().ruleKey())) { + activation.setParameter(param.getName(), param.getDefaultValue()); + } + } + activations.add(activation); + } + } + doReset(dbSession, profile, activations); + } + } + + @Override + public QProfileRestoreSummary reset(DbSession dbSession, OrganizationDto organization, QProfileName profileName, Collection activations) { + QualityProfileDto profile = factory.getOrCreate(dbSession, organization, profileName); + BulkChangeResult ruleChanges = doReset(dbSession, profile, activations); + return new QProfileRestoreSummary(organization, profile, ruleChanges); + } + + /** + * @param dbSession + * @param profile must exist + */ + private BulkChangeResult doReset(DbSession dbSession, QualityProfileDto profile, Collection activations) { + Preconditions.checkNotNull(profile.getId(), "Quality profile must be persisted"); + BulkChangeResult result = new BulkChangeResult(); + Set ruleToBeDeactivated = Sets.newHashSet(); + // Keep reference to all the activated rules before backup restore + for (ActiveRuleDto activeRuleDto : db.activeRuleDao().selectByProfileKey(dbSession, profile.getKee())) { + if (activeRuleDto.getInheritance() == null) { + // inherited rules can't be deactivated + ruleToBeDeactivated.add(activeRuleDto.getKey().ruleKey()); + } + } + + for (RuleActivation activation : activations) { + try { + List changes = activator.activate(dbSession, activation, profile.getKey()); + ruleToBeDeactivated.remove(activation.getRuleKey()); + result.incrementSucceeded(); + result.addChanges(changes); + } catch (BadRequestException e) { + result.incrementFailed(); + result.getErrors().addAll(e.errors()); + } + } + + List changes = new ArrayList<>(); + changes.addAll(result.getChanges()); + for (RuleKey ruleKey : ruleToBeDeactivated) { + try { + changes.addAll(activator.deactivate(dbSession, ActiveRuleKey.of(profile.getKee(), ruleKey))); + } catch (BadRequestException e) { + // ignore, probably a rule inherited from parent that can't be deactivated + } + } + dbSession.commit(); + activeRuleIndexer.index(changes); + return result; + } + + private ListMultimap loadDefinitionsGroupedByName(String language) { + ListMultimap profilesByName = ArrayListMultimap.create(); + for (ProfileDefinition definition : definitions) { + ValidationMessages validation = ValidationMessages.create(); + RulesProfile profile = definition.createProfile(validation); + if (language.equals(profile.getLanguage())) { + processValidationMessages(validation); + profilesByName.put(new QProfileName(profile.getLanguage(), profile.getName()), profile); + } + } + return profilesByName; + } + + private static void processValidationMessages(ValidationMessages messages) { + checkRequest(messages.getErrors().isEmpty(), messages.getErrors()); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInAction.java index 5c5f0872921..05ea696751b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInAction.java @@ -25,47 +25,57 @@ import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.permission.OrganizationPermission; import org.sonar.server.qualityprofile.QProfileReset; +import org.sonar.server.user.UserSession; import static org.sonar.server.util.LanguageParamUtils.getExampleValue; import static org.sonar.server.util.LanguageParamUtils.getLanguageKeys; +import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION; public class RestoreBuiltInAction implements QProfileWsAction { private final DbClient dbClient; private final QProfileReset reset; private final Languages languages; + private final UserSession userSession; private final QProfileWsSupport qProfileWsSupport; - public RestoreBuiltInAction(DbClient dbClient, QProfileReset reset, Languages languages, QProfileWsSupport qProfileWsSupport) { + public RestoreBuiltInAction(DbClient dbClient, QProfileReset reset, Languages languages, UserSession userSession, QProfileWsSupport qProfileWsSupport) { this.dbClient = dbClient; this.reset = reset; this.languages = languages; + this.userSession = userSession; this.qProfileWsSupport = qProfileWsSupport; } @Override public void define(WebService.NewController controller) { - WebService.NewAction restoreDefault = controller.createAction("restore_built_in") + WebService.NewAction action = controller.createAction("restore_built_in") .setDescription("Restore built-in profiles from the definitions declared by plugins. " + "Missing profiles are created, existing ones are updated.") .setSince("4.4") .setPost(true) .setHandler(this); - restoreDefault.createParam("language") + action.createParam("language") .setDescription("Restore the built-in profiles defined for this language") .setExampleValue(getExampleValue(languages)) .setPossibleValues(getLanguageKeys(languages)) .setRequired(true); + + QProfileWsSupport.createOrganizationParam(action).setSince("6.4"); } @Override public void handle(Request request, Response response) { - qProfileWsSupport.checkQProfileAdminPermission(); + userSession.checkLoggedIn(); - String language = request.mandatoryParam("language"); try (DbSession dbSession = dbClient.openSession(false)) { - reset.resetLanguage(dbSession, language); + OrganizationDto organization = qProfileWsSupport.getOrganizationByKey(dbSession, request.param(PARAM_ORGANIZATION)); + userSession.checkPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization); + + reset.resetLanguage(dbSession, organization, request.mandatoryParam("language")); } response.noContent(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileResetMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileResetMediumTest.java index ab4103e713d..1ac983d31e5 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileResetMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileResetMediumTest.java @@ -36,6 +36,7 @@ import org.sonar.api.server.rule.RulesDefinition; import org.sonar.api.utils.ValidationMessages; import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.organization.OrganizationDto; import org.sonar.db.qualityprofile.ActiveRuleDao; import org.sonar.db.qualityprofile.ActiveRuleDto; import org.sonar.db.qualityprofile.ActiveRuleKey; @@ -67,9 +68,9 @@ public class QProfileResetMediumTest { @Rule public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester); - DbClient db; - DbSession dbSession; - QProfileReset reset; + private DbClient db; + private DbSession dbSession; + private QProfileReset reset; @Before public void before() { @@ -139,7 +140,8 @@ public class QProfileResetMediumTest { assertThat(activeRuleParamDtos.get(0).getKey()).isEqualTo("acceptWhitespace"); assertThat(activeRuleParamDtos.get(0).getValue()).isEqualTo("false"); - reset.resetLanguage(dbSession, ServerTester.Xoo.KEY); + OrganizationDto organization = db.organizationDao().selectByUuid(dbSession, profile.getOrganizationUuid()).get(); + reset.resetLanguage(dbSession, organization, ServerTester.Xoo.KEY); dbSession.commit(); // Severity and parameter value come back to origin after reset @@ -188,7 +190,8 @@ public class QProfileResetMediumTest { } }, defProfile); - reset.resetLanguage(dbSession, ServerTester.Xoo.KEY); + OrganizationDto organization = db.organizationDao().selectByUuid(dbSession, profile.getOrganizationUuid()).get(); + reset.resetLanguage(dbSession, organization, ServerTester.Xoo.KEY); // Parameter value come back to origin after reset ActiveRuleDto activeRuleDto = tester.get(ActiveRuleDao.class).selectOrFailByKey(dbSession, activeRuleKey); diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java index fc0b537bd0f..76cf2fa0d4f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java @@ -69,7 +69,6 @@ public class QProfilesWsTest { new RemoveProjectAction(projectAssociationParameters, null, null, dbClient), new CreateAction(null, null, null, languages, wsSupport, userSessionRule, null, importers), new ImportersAction(importers), - new RestoreBuiltInAction(dbClient, null, languages, wsSupport), new SearchAction(null, languages), new SetDefaultAction(languages, null, null, wsSupport), new ProjectsAction(null, userSessionRule), @@ -109,14 +108,6 @@ public class QProfilesWsTest { assertThat(controller.actions()).isNotEmpty(); } - @Test - public void define_restore_built_action() { - WebService.Action restoreProfiles = controller.action("restore_built_in"); - assertThat(restoreProfiles).isNotNull(); - assertThat(restoreProfiles.isPost()).isTrue(); - assertThat(restoreProfiles.params()).hasSize(1); - } - @Test public void define_search() { WebService.Action search = controller.action("search"); diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInActionTest.java index b30c13a7eab..9dcd8772b04 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInActionTest.java @@ -22,10 +22,14 @@ package org.sonar.server.qualityprofile.ws; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.mockito.ArgumentCaptor; import org.sonar.api.resources.Languages; +import org.sonar.api.server.ws.WebService; import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import org.sonar.db.organization.OrganizationDto; import org.sonar.server.exceptions.ForbiddenException; +import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.exceptions.UnauthorizedException; import org.sonar.server.language.LanguageTesting; import org.sonar.server.organization.DefaultOrganizationProvider; @@ -54,29 +58,82 @@ public class RestoreBuiltInActionTest { private QProfileReset reset = mock(QProfileReset.class); private Languages languages = LanguageTesting.newLanguages("xoo"); - private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.fromUuid("ORG1"); + private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); private QProfileWsSupport wsSupport = new QProfileWsSupport(db.getDbClient(), userSession, defaultOrganizationProvider); + private RestoreBuiltInAction underTest = new RestoreBuiltInAction(db.getDbClient(), reset, languages, userSession, wsSupport); + private WsActionTester tester = new WsActionTester(underTest); - private WsActionTester tester = new WsActionTester(new RestoreBuiltInAction(db.getDbClient(), reset, languages, wsSupport)); + @Test + public void test_definition() { + WebService.Action action = tester.getDef(); + + assertThat(action.key()).isEqualTo("restore_built_in"); + assertThat(action.isPost()).isTrue(); + assertThat(action.responseExampleAsString()).isNull(); + + // parameters + assertThat(action.params()).hasSize(2); + WebService.Param languageParam = action.param("language"); + assertThat(languageParam.isRequired()).isTrue(); + assertThat(languageParam.since()).isNull();//introduced at the same time than the web service + + WebService.Param organizationParam = action.param("organization"); + assertThat(organizationParam.isRequired()).isFalse(); + assertThat(organizationParam.since()).isEqualTo("6.4"); + } @Test - public void return_empty_result_when_no_info_or_warning() { - logInAsQProfileAdministrator(); + public void restore_built_in_profiles_on_default_organization() { + OrganizationDto organization = db.getDefaultOrganization(); + logInAsQProfileAdministrator(organization); TestResponse response = tester.newRequest().setParam("language", "xoo").execute(); - verify(reset).resetLanguage(any(DbSession.class), eq("xoo")); + ArgumentCaptor organizationArgument = ArgumentCaptor.forClass(OrganizationDto.class); + verify(reset).resetLanguage(any(DbSession.class), organizationArgument.capture(), eq("xoo")); + assertThat(organizationArgument.getValue().getUuid()).isEqualTo(organization.getUuid()); + assertThat(response.getStatus()).isEqualTo(204); + } + + @Test + public void restore_built_in_profiles_on_specified_organization() { + OrganizationDto organization = db.organizations().insert(); + logInAsQProfileAdministrator(organization); + TestResponse response = tester.newRequest() + .setParam("language", "xoo") + .setParam("organization", organization.getKey()) + .execute(); + + ArgumentCaptor organizationArgument = ArgumentCaptor.forClass(OrganizationDto.class); + verify(reset).resetLanguage(any(DbSession.class), organizationArgument.capture(), eq("xoo")); + assertThat(organizationArgument.getValue().getUuid()).isEqualTo(organization.getUuid()); assertThat(response.getStatus()).isEqualTo(204); } @Test - public void fail_on_unknown_language() throws Exception { - logInAsQProfileAdministrator(); + public void throw_IAE_if_language_does_not_exist() throws Exception { + logInAsQProfileAdministrator(db.getDefaultOrganization()); + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Value of parameter 'language' (unknown) must be one of: [xoo]"); + tester.newRequest().setParam("language", "unknown").execute(); } @Test - public void throw_ForbiddenException_if_not_profile_administrator() throws Exception { + public void throw_NotFoundException_if_organization_does_not_exist() throws Exception { + userSession.logIn(); + + expectedException.expect(NotFoundException.class); + expectedException.expectMessage("No organization with key 'does_not_exist'"); + + tester.newRequest() + .setParam("language", "unknown") + .setParam("organization", "does_not_exist") + .execute(); + } + + @Test + public void throw_ForbiddenException_if_not_profile_administrator_of_default_organization() throws Exception { userSession.logIn(); expectedException.expect(ForbiddenException.class); @@ -85,17 +142,33 @@ public class RestoreBuiltInActionTest { tester.newRequest().setParam("language", "xoo").execute(); } + @Test + public void throw_ForbiddenException_if_not_profile_administrator_of_specified_organization() throws Exception { + OrganizationDto org = db.organizations().insert(); + userSession.logIn().addPermission(ADMINISTER_QUALITY_PROFILES, db.getDefaultOrganization()); + + expectedException.expect(ForbiddenException.class); + expectedException.expectMessage("Insufficient privileges"); + + tester.newRequest() + .setParam("language", "xoo") + .setParam("organization", org.getKey()) + .execute(); + } + @Test public void throw_UnauthorizedException_if_not_logged_in() throws Exception { + userSession.anonymous(); + expectedException.expect(UnauthorizedException.class); expectedException.expectMessage("Authentication is required"); tester.newRequest().setParam("language", "xoo").execute(); } - private void logInAsQProfileAdministrator() { + private void logInAsQProfileAdministrator(OrganizationDto organization) { userSession .logIn() - .addPermission(ADMINISTER_QUALITY_PROFILES, defaultOrganizationProvider.get().getUuid()); + .addPermission(ADMINISTER_QUALITY_PROFILES, organization.getUuid()); } } -- 2.39.5