]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8857 add organization parameter to api/qualityprofiles/restore_built_in
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Wed, 15 Mar 2017 10:58:12 +0000 (11:58 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 23 Mar 2017 16:38:34 +0000 (17:38 +0100)
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileReset.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileResetImpl.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInAction.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileResetMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfilesWsTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/RestoreBuiltInActionTest.java

index 46ddd1fc49d02aa2596f6bdae737c8ea52128b50..c6c29b3cf55ba8244a4d744c6c687a165a8bd49f 100644 (file)
@@ -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
index 4c509b65c0116f8aa6658639a05de2543255745e..0e884329816c9fc4cc2f898f2079747c4c419bc5 100644 (file)
  */
 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<QProfileName, RulesProfile> profilesByName = loadDefinitionsGroupedByName(language);
-    for (Map.Entry<QProfileName, Collection<RulesProfile>> entry : profilesByName.asMap().entrySet()) {
-      QProfileName profileName = entry.getKey();
-      QualityProfileDto profile = factory.getOrCreate(dbSession, qProfileWsSupport.getDefaultOrganization(dbSession), profileName);
-      List<RuleActivation> 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<RuleActivation> 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<RuleActivation> activations) {
-    Preconditions.checkNotNull(profile.getId(), "Quality profile must be persisted");
-    BulkChangeResult result = new BulkChangeResult();
-    Set<RuleKey> 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<ActiveRuleChange> 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<ActiveRuleChange> 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<QProfileName, RulesProfile> loadDefinitionsGroupedByName(String language) {
-    ListMultimap<QProfileName, RulesProfile> 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<RuleActivation> 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 (file)
index 0000000..62b6df3
--- /dev/null
@@ -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<QProfileName, RulesProfile> profilesByName = loadDefinitionsGroupedByName(language);
+    for (Map.Entry<QProfileName, Collection<RulesProfile>> entry : profilesByName.asMap().entrySet()) {
+      QProfileName profileName = entry.getKey();
+      QualityProfileDto profile = factory.getOrCreate(dbSession, organization, profileName);
+      List<RuleActivation> 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<RuleActivation> 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<RuleActivation> activations) {
+    Preconditions.checkNotNull(profile.getId(), "Quality profile must be persisted");
+    BulkChangeResult result = new BulkChangeResult();
+    Set<RuleKey> 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<ActiveRuleChange> 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<ActiveRuleChange> 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<QProfileName, RulesProfile> loadDefinitionsGroupedByName(String language) {
+    ListMultimap<QProfileName, RulesProfile> 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());
+  }
+}
index 5c5f0872921a4eba56341cf03de8f342586da55b..05ea696751b35f61159b7609ad963ba033777f3b 100644 (file)
@@ -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();
   }
index ab4103e713d25a960454ab6e2d90119a64ccc7f2..1ac983d31e5439c2f335490308bc2d65fa089a36 100644 (file)
@@ -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);
index fc0b537bd0f896be42a98f630cf7ab3a3048e676..76cf2fa0d4f0c446b92a5ed540bda6e3b6b38dca 100644 (file)
@@ -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");
index b30c13a7eabcbbb10f6dc5b5c27710a51261c49c..9dcd8772b040a3899b72156329618c9dc690e7a9 100644 (file)
@@ -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<OrganizationDto> 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<OrganizationDto> 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());
   }
 }