]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10945 Active rules search is only for member on paid organizations
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Fri, 6 Jul 2018 12:25:13 +0000 (14:25 +0200)
committerSonarTech <sonartech@sonarsource.com>
Wed, 11 Jul 2018 18:21:22 +0000 (20:21 +0200)
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeactivateRulesAction.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/ShowAction.java
server/sonar-server/src/main/resources/org/sonar/server/rule/ws/app-example.json
server/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java

index aea1c6848a78a46803f8055c2108c294dd18d1f2..3b6a8dbb71fb088e156d68e6b535b8b1dd4bb46c 100644 (file)
@@ -36,7 +36,7 @@ import org.sonar.server.user.UserSession;
 import static org.sonar.core.util.Uuids.UUID_EXAMPLE_03;
 import static org.sonar.server.qualityprofile.ws.BulkChangeWsResponse.writeResponse;
 import static org.sonar.server.qualityprofile.ws.QProfileReference.fromKey;
-import static org.sonar.server.rule.ws.SearchAction.defineGenericRuleSearchParameters;
+import static org.sonar.server.rule.ws.RuleWsSupport.defineGenericRuleSearchParameters;
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ACTIVATE_RULES;
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_KEY;
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_SEVERITY;
index b561083f9176f00b3e21936835ac237cfe64f33b..8f55070c3823006024f3d2469da6ee4655992db4 100644 (file)
@@ -34,12 +34,11 @@ import org.sonar.server.user.UserSession;
 
 import static org.sonar.core.util.Uuids.UUID_EXAMPLE_04;
 import static org.sonar.server.qualityprofile.ws.BulkChangeWsResponse.writeResponse;
-import static org.sonar.server.rule.ws.SearchAction.defineGenericRuleSearchParameters;
+import static org.sonar.server.rule.ws.RuleWsSupport.defineGenericRuleSearchParameters;
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_DEACTIVATE_RULES;
 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_KEY;
 
 public class DeactivateRulesAction implements QProfileWsAction {
-  public static final String SEVERITY = "activation_severity";
 
   private final RuleQueryFactory ruleQueryFactory;
   private final UserSession userSession;
index 0df84c49176aa3bc242dc266e0947292982bccf2..c96ae59ab490628067f2d678d5f80b72a8a3eca1 100644 (file)
@@ -88,8 +88,6 @@ public class RuleQueryFactory {
     Date availableSince = request.paramAsDate(PARAM_AVAILABLE_SINCE);
     query.setAvailableSince(availableSince != null ? availableSince.getTime() : null);
     query.setStatuses(toEnums(request.paramAsStrings(PARAM_STATUSES), RuleStatus.class));
-    Boolean activation = request.paramAsBoolean(PARAM_ACTIVATION);
-    query.setActivation(activation);
 
     // Order is important : 1. Load profile, 2. Load organization either from parameter or from profile, 3. Load compare to profile
     setProfile(dbSession, query, request);
@@ -97,7 +95,9 @@ public class RuleQueryFactory {
     setCompareToProfile(dbSession, query, request);
     QProfileDto profile = query.getQProfile();
     query.setLanguages(profile == null ? request.paramAsStrings(PARAM_LANGUAGES) : ImmutableList.of(profile.getLanguage()));
-
+    if (wsSupport.areActiveRulesVisible(query.getOrganization())) {
+      query.setActivation(request.paramAsBoolean(PARAM_ACTIVATION));
+    }
     query.setTags(request.paramAsStrings(PARAM_TAGS));
     query.setInheritance(request.paramAsStrings(PARAM_INHERITANCE));
     query.setActiveSeverities(request.paramAsStrings(PARAM_ACTIVE_SEVERITIES));
@@ -139,7 +139,6 @@ public class RuleQueryFactory {
       checkArgument(organization.getUuid().equals(inputOrganization.getUuid()),
         format("The specified quality profile '%s' is not part of the specified organization '%s'", profile.getKee(), organizationKey));
     }
-    wsSupport.checkMembershipOnPaidOrganization(organization);
     query.setOrganization(organization);
   }
 
index a54dea9813002f22038f783b9396f8141e688441..e9d529117f5c7e0590d04ba4b48afe802827e39e 100644 (file)
@@ -25,19 +25,47 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import javax.annotation.Nullable;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.ServerSide;
+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.rule.RuleDto;
 import org.sonar.db.user.UserDto;
 import org.sonar.server.organization.DefaultOrganizationProvider;
+import org.sonar.server.qualityprofile.ActiveRuleInheritance;
+import org.sonar.server.rule.index.RuleIndexDefinition;
 import org.sonar.server.user.UserSession;
 
+import static org.sonar.api.server.ws.WebService.Param.ASCENDING;
+import static org.sonar.api.server.ws.WebService.Param.SORT;
+import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
+import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
+import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
 import static org.sonar.core.util.stream.MoreCollectors.toSet;
 import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 import static org.sonar.db.organization.OrganizationDto.Subscription.PAID;
 import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVATION;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_SEVERITIES;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_AVAILABLE_SINCE;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_COMPARE_TO_PROFILE;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_INCLUDE_EXTERNAL;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_INHERITANCE;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_TEMPLATE;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ORGANIZATION;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_QPROFILE;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_REPOSITORIES;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_RULE_KEY;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_SEVERITIES;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_STATUSES;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TAGS;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TEMPLATE_KEY;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TYPES;
 import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
 
 @ServerSide
@@ -65,7 +93,6 @@ public class RuleWsSupport {
     OrganizationDto organization = checkFoundWithOptional(
       dbClient.organizationDao().selectByKey(dbSession, organizationOrDefaultKey),
       "No organization with key '%s'", organizationOrDefaultKey);
-    checkMembershipOnPaidOrganization(organization);
     return organization;
   }
 
@@ -74,11 +101,136 @@ public class RuleWsSupport {
     return dbClient.userDao().selectByUuids(dbSession, userUuids).stream().collect(uniqueIndex(UserDto::getUuid));
   }
 
-  void checkMembershipOnPaidOrganization(OrganizationDto organization) {
+  boolean areActiveRulesVisible(OrganizationDto organization) {
     if (!organization.getSubscription().equals(PAID)) {
-      return;
+      return true;
     }
-    userSession.checkMembership(organization);
+    return userSession.hasMembership(organization);
   }
 
+  public static void defineGenericRuleSearchParameters(WebService.NewAction action) {
+    action
+      .createParam(TEXT_QUERY)
+      .setMinimumLength(2)
+      .setDescription("UTF-8 search query")
+      .setExampleValue("xpath");
+
+    action
+      .createParam(PARAM_RULE_KEY)
+      .setDescription("Key of rule to search for")
+      .setExampleValue("squid:S001");
+
+    action
+      .createParam(PARAM_REPOSITORIES)
+      .setDescription("Comma-separated list of repositories")
+      .setExampleValue("checkstyle,findbugs");
+
+    action
+      .createParam(PARAM_SEVERITIES)
+      .setDescription("Comma-separated list of default severities. Not the same than severity of rules in Quality profiles.")
+      .setPossibleValues(Severity.ALL)
+      .setExampleValue("CRITICAL,BLOCKER");
+
+    action
+      .createParam(PARAM_LANGUAGES)
+      .setDescription("Comma-separated list of languages")
+      .setExampleValue("java,js");
+
+    action
+      .createParam(PARAM_STATUSES)
+      .setDescription("Comma-separated list of status codes")
+      .setPossibleValues(RuleStatus.values())
+      .setExampleValue(RuleStatus.READY);
+
+    action
+      .createParam(PARAM_AVAILABLE_SINCE)
+      .setDescription("Filters rules added since date. Format is yyyy-MM-dd")
+      .setExampleValue("2014-06-22");
+
+    action
+      .createParam(PARAM_TAGS)
+      .setDescription("Comma-separated list of tags. Returned rules match any of the tags (OR operator)")
+      .setExampleValue("security,java8");
+
+    action
+      .createParam(PARAM_TYPES)
+      .setSince("5.5")
+      .setDescription("Comma-separated list of types. Returned rules match any of the tags (OR operator)")
+      .setPossibleValues(RuleType.values())
+      .setExampleValue(RuleType.BUG);
+
+    action
+      .createParam(PARAM_ACTIVATION)
+      .setDescription("Filter rules that are activated or deactivated on the selected Quality profile. Ignored if " +
+        "the parameter '" + PARAM_QPROFILE + "' is not set.")
+      .setBooleanPossibleValues();
+
+    action
+      .createParam(PARAM_QPROFILE)
+      .setDescription("Quality profile key to filter on. Used only if the parameter '" +
+        PARAM_ACTIVATION + "' is set.")
+      .setExampleValue(UUID_EXAMPLE_01);
+
+    action.createParam(PARAM_COMPARE_TO_PROFILE)
+      .setDescription("Quality profile key to filter rules that are activated. Meant to compare easily to profile set in '%s'", PARAM_QPROFILE)
+      .setInternal(true)
+      .setSince("6.5")
+      .setExampleValue(UUID_EXAMPLE_02);
+
+    action
+      .createParam(PARAM_INHERITANCE)
+      .setDescription("Comma-separated list of values of inheritance for a rule within a quality profile. Used only if the parameter '" +
+        PARAM_ACTIVATION + "' is set.")
+      .setPossibleValues(ActiveRuleInheritance.NONE.name(),
+        ActiveRuleInheritance.INHERITED.name(),
+        ActiveRuleInheritance.OVERRIDES.name())
+      .setExampleValue(ActiveRuleInheritance.INHERITED.name() + "," +
+        ActiveRuleInheritance.OVERRIDES.name());
+
+    action
+      .createParam(PARAM_ACTIVE_SEVERITIES)
+      .setDescription("Comma-separated list of activation severities, i.e the severity of rules in Quality profiles.")
+      .setPossibleValues(Severity.ALL)
+      .setExampleValue("CRITICAL,BLOCKER");
+
+    action
+      .createParam(PARAM_IS_TEMPLATE)
+      .setDescription("Filter template rules")
+      .setBooleanPossibleValues();
+
+    action
+      .createParam(PARAM_TEMPLATE_KEY)
+      .setDescription("Key of the template rule to filter on. Used to search for the custom rules based on this template.")
+      .setExampleValue("java:S001");
+
+    action
+      .createParam(SORT)
+      .setDescription("Sort field")
+      .setPossibleValues(RuleIndexDefinition.SORT_FIELDS)
+      .setExampleValue(RuleIndexDefinition.SORT_FIELDS.iterator().next());
+
+    action
+      .createParam(ASCENDING)
+      .setDescription("Ascending sort")
+      .setBooleanPossibleValues()
+      .setDefaultValue(true);
+
+    action.createParam(PARAM_ORGANIZATION)
+      .setDescription("Organization key")
+      .setRequired(false)
+      .setInternal(true)
+      .setExampleValue("my-org")
+      .setSince("6.4");
+  }
+
+  static void defineIsExternalParam(WebService.NewAction action) {
+    action
+      .createParam(PARAM_INCLUDE_EXTERNAL)
+      .setDescription("Include external engine rules in the results")
+      .setDefaultValue(false)
+      .setBooleanPossibleValues()
+      .setSince("7.2");
+  }
+
+
 }
index 0027b0542faec3826b9248613030db2342192c28..d2d9fa4a388fb3a03b5ae5171a86a7d02acd2630 100644 (file)
@@ -36,7 +36,6 @@ import java.util.Objects;
 import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
-import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.ws.Change;
@@ -53,9 +52,7 @@ import org.sonar.db.user.UserDto;
 import org.sonar.server.es.Facets;
 import org.sonar.server.es.SearchIdResult;
 import org.sonar.server.es.SearchOptions;
-import org.sonar.server.qualityprofile.ActiveRuleInheritance;
 import org.sonar.server.rule.index.RuleIndex;
-import org.sonar.server.rule.index.RuleIndexDefinition;
 import org.sonar.server.rule.index.RuleQuery;
 import org.sonarqube.ws.Common;
 import org.sonarqube.ws.Rules.SearchResponse;
@@ -66,10 +63,6 @@ import static org.sonar.api.server.ws.WebService.Param.FACETS;
 import static org.sonar.api.server.ws.WebService.Param.FIELDS;
 import static org.sonar.api.server.ws.WebService.Param.PAGE;
 import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
-import static org.sonar.api.server.ws.WebService.Param.SORT;
-import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
-import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
-import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
 import static org.sonar.server.es.SearchOptions.MAX_LIMIT;
 import static org.sonar.server.rule.index.RuleIndex.ALL_STATUSES_EXCEPT_REMOVED;
 import static org.sonar.server.rule.index.RuleIndex.FACET_ACTIVE_SEVERITIES;
@@ -81,22 +74,12 @@ import static org.sonar.server.rule.index.RuleIndex.FACET_STATUSES;
 import static org.sonar.server.rule.index.RuleIndex.FACET_TAGS;
 import static org.sonar.server.rule.index.RuleIndex.FACET_TYPES;
 import static org.sonar.server.rule.ws.RulesWsParameters.OPTIONAL_FIELDS;
-import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVATION;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_SEVERITIES;
-import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_AVAILABLE_SINCE;
-import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_COMPARE_TO_PROFILE;
-import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_INCLUDE_EXTERNAL;
-import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_INHERITANCE;
-import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_TEMPLATE;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES;
-import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ORGANIZATION;
-import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_QPROFILE;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_REPOSITORIES;
-import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_RULE_KEY;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_SEVERITIES;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_STATUSES;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TAGS;
-import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TEMPLATE_KEY;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TYPES;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
 
@@ -159,7 +142,23 @@ public class SearchAction implements RulesWsAction {
 
     Iterator<String> it = OPTIONAL_FIELDS.iterator();
     paramFields.setExampleValue(format("%s,%s", it.next(), it.next()));
-    doDefinition(action);
+    action.setDescription("Search for a collection of relevant rules matching a specified query.<br/>" +
+      "Since 5.5, following fields in the response have been deprecated :" +
+      "<ul>" +
+      "<li>\"effortToFixDescription\" becomes \"gapDescription\"</li>" +
+      "<li>\"debtRemFnCoeff\" becomes \"remFnGapMultiplier\"</li>" +
+      "<li>\"defaultDebtRemFnCoeff\" becomes \"defaultRemFnGapMultiplier\"</li>" +
+      "<li>\"debtRemFnOffset\" becomes \"remFnBaseEffort\"</li>" +
+      "<li>\"defaultDebtRemFnOffset\" becomes \"defaultRemFnBaseEffort\"</li>" +
+      "<li>\"debtOverloaded\" becomes \"remFnOverloaded\"</li>" +
+      "</ul>")
+      .setResponseExample(getClass().getResource("search-example.json"))
+      .setSince("4.4")
+      .setHandler(this);
+
+    // Rule-specific search parameters
+    RuleWsSupport.defineGenericRuleSearchParameters(action);
+    RuleWsSupport.defineIsExternalParam(action);
   }
 
   @Override
@@ -190,150 +189,6 @@ public class SearchAction implements RulesWsAction {
     response.setPs(context.getLimit());
   }
 
-  private void doDefinition(WebService.NewAction action) {
-    action.setDescription("Search for a collection of relevant rules matching a specified query.<br/>" +
-      "Since 5.5, following fields in the response have been deprecated :" +
-      "<ul>" +
-      "<li>\"effortToFixDescription\" becomes \"gapDescription\"</li>" +
-      "<li>\"debtRemFnCoeff\" becomes \"remFnGapMultiplier\"</li>" +
-      "<li>\"defaultDebtRemFnCoeff\" becomes \"defaultRemFnGapMultiplier\"</li>" +
-      "<li>\"debtRemFnOffset\" becomes \"remFnBaseEffort\"</li>" +
-      "<li>\"defaultDebtRemFnOffset\" becomes \"defaultRemFnBaseEffort\"</li>" +
-      "<li>\"debtOverloaded\" becomes \"remFnOverloaded\"</li>" +
-      "</ul>")
-      .setResponseExample(getClass().getResource("search-example.json"))
-      .setSince("4.4")
-      .setHandler(this);
-
-    // Rule-specific search parameters
-    defineGenericRuleSearchParameters(action);
-    defineIsExternalParam(action);
-  }
-
-  static void defineIsExternalParam(WebService.NewAction action) {
-    action
-      .createParam(PARAM_INCLUDE_EXTERNAL)
-      .setDescription("Include external engine rules in the results")
-      .setDefaultValue(false)
-      .setBooleanPossibleValues()
-      .setSince("7.2");
-  }
-
-  public static void defineGenericRuleSearchParameters(WebService.NewAction action) {
-    action
-      .createParam(TEXT_QUERY)
-      .setMinimumLength(2)
-      .setDescription("UTF-8 search query")
-      .setExampleValue("xpath");
-
-    action
-      .createParam(PARAM_RULE_KEY)
-      .setDescription("Key of rule to search for")
-      .setExampleValue("squid:S001");
-
-    action
-      .createParam(PARAM_REPOSITORIES)
-      .setDescription("Comma-separated list of repositories")
-      .setExampleValue("checkstyle,findbugs");
-
-    action
-      .createParam(PARAM_SEVERITIES)
-      .setDescription("Comma-separated list of default severities. Not the same than severity of rules in Quality profiles.")
-      .setPossibleValues(Severity.ALL)
-      .setExampleValue("CRITICAL,BLOCKER");
-
-    action
-      .createParam(PARAM_LANGUAGES)
-      .setDescription("Comma-separated list of languages")
-      .setExampleValue("java,js");
-
-    action
-      .createParam(PARAM_STATUSES)
-      .setDescription("Comma-separated list of status codes")
-      .setPossibleValues(RuleStatus.values())
-      .setExampleValue(RuleStatus.READY);
-
-    action
-      .createParam(PARAM_AVAILABLE_SINCE)
-      .setDescription("Filters rules added since date. Format is yyyy-MM-dd")
-      .setExampleValue("2014-06-22");
-
-    action
-      .createParam(PARAM_TAGS)
-      .setDescription("Comma-separated list of tags. Returned rules match any of the tags (OR operator)")
-      .setExampleValue("security,java8");
-
-    action
-      .createParam(PARAM_TYPES)
-      .setSince("5.5")
-      .setDescription("Comma-separated list of types. Returned rules match any of the tags (OR operator)")
-      .setPossibleValues(RuleType.values())
-      .setExampleValue(RuleType.BUG);
-
-    action
-      .createParam(PARAM_ACTIVATION)
-      .setDescription("Filter rules that are activated or deactivated on the selected Quality profile. Ignored if " +
-        "the parameter '" + PARAM_QPROFILE + "' is not set.")
-      .setBooleanPossibleValues();
-
-    action
-      .createParam(PARAM_QPROFILE)
-      .setDescription("Quality profile key to filter on. Used only if the parameter '" +
-        PARAM_ACTIVATION + "' is set.")
-      .setExampleValue(UUID_EXAMPLE_01);
-
-    action.createParam(PARAM_COMPARE_TO_PROFILE)
-      .setDescription("Quality profile key to filter rules that are activated. Meant to compare easily to profile set in '%s'", PARAM_QPROFILE)
-      .setInternal(true)
-      .setSince("6.5")
-      .setExampleValue(UUID_EXAMPLE_02);
-
-    action
-      .createParam(PARAM_INHERITANCE)
-      .setDescription("Comma-separated list of values of inheritance for a rule within a quality profile. Used only if the parameter '" +
-        PARAM_ACTIVATION + "' is set.")
-      .setPossibleValues(ActiveRuleInheritance.NONE.name(),
-        ActiveRuleInheritance.INHERITED.name(),
-        ActiveRuleInheritance.OVERRIDES.name())
-      .setExampleValue(ActiveRuleInheritance.INHERITED.name() + "," +
-        ActiveRuleInheritance.OVERRIDES.name());
-
-    action
-      .createParam(PARAM_ACTIVE_SEVERITIES)
-      .setDescription("Comma-separated list of activation severities, i.e the severity of rules in Quality profiles.")
-      .setPossibleValues(Severity.ALL)
-      .setExampleValue("CRITICAL,BLOCKER");
-
-    action
-      .createParam(PARAM_IS_TEMPLATE)
-      .setDescription("Filter template rules")
-      .setBooleanPossibleValues();
-
-    action
-      .createParam(PARAM_TEMPLATE_KEY)
-      .setDescription("Key of the template rule to filter on. Used to search for the custom rules based on this template.")
-      .setExampleValue("java:S001");
-
-    action
-      .createParam(SORT)
-      .setDescription("Sort field")
-      .setPossibleValues(RuleIndexDefinition.SORT_FIELDS)
-      .setExampleValue(RuleIndexDefinition.SORT_FIELDS.iterator().next());
-
-    action
-      .createParam(ASCENDING)
-      .setDescription("Ascending sort")
-      .setBooleanPossibleValues()
-      .setDefaultValue(true);
-
-    action.createParam(PARAM_ORGANIZATION)
-      .setDescription("Organization key")
-      .setRequired(false)
-      .setInternal(true)
-      .setExampleValue("my-org")
-      .setSince("6.4");
-  }
-
   private void writeRules(DbSession dbSession, SearchResponse.Builder response, SearchResult result, SearchOptions context) {
     Map<String, UserDto> usersByUuid = ruleWsSupport.getUsersByUuid(dbSession, result.rules);
     result.rules.forEach(rule -> response.addRules(mapper.toWsRule(rule.getDefinition(), result, context.getFields(), rule.getMetadata(), usersByUuid)));
@@ -396,7 +251,7 @@ public class SearchAction implements RulesWsAction {
   private void doContextResponse(DbSession dbSession, SearchRequest request, SearchResult result, SearchResponse.Builder response, RuleQuery query) {
     SearchOptions contextForResponse = loadCommonContext(request);
     writeRules(dbSession, response, result, contextForResponse);
-    if (contextForResponse.getFields().contains("actives")) {
+    if (contextForResponse.getFields().contains("actives") && ruleWsSupport.areActiveRulesVisible(query.getOrganization())) {
       activeRuleCompleter.completeSearch(dbSession, query, result.rules, response);
     }
   }
index bd374a495f772a10963f17ede4efaea5a5364478..fd860930aa42067a310753c39768a383fa97088b 100644 (file)
@@ -127,7 +127,7 @@ public class ShowAction implements RulesWsAction {
     RuleDto rule = searchResult.getRules().get(0);
     responseBuilder.setRule(mapper.toWsRule(rule.getDefinition(), searchResult, Collections.emptySet(), rule.getMetadata(),
       ruleWsSupport.getUsersByUuid(dbSession, searchResult.getRules())));
-    if (request.mandatoryParamAsBoolean(PARAM_ACTIVES)) {
+    if (request.mandatoryParamAsBoolean(PARAM_ACTIVES) && ruleWsSupport.areActiveRulesVisible(organization)) {
       activeRuleCompleter.completeShow(dbSession, organization, rule.getDefinition()).forEach(responseBuilder::addActives);
     }
     return responseBuilder.build();
index cbd432356679a79d866ef3c78481757519f07f33..b8dc5cbc67c4b1d9a1ef2788b3f926d693cdd655 100644 (file)
@@ -1,31 +1,5 @@
 {
   "canWrite": false,
-  "qualityprofiles": [
-    {
-      "key": "java-top-profile-without-formatting-conventions-50037",
-      "name": "Default - Top",
-      "lang": "java",
-      "isBuiltIn": false
-    },
-    {
-      "key": "java-sonar-way-80423",
-      "name": "Sonar way",
-      "lang": "java",
-      "isBuiltIn": true
-    },
-    {
-      "key": "js-sonar-way",
-      "name": "Sonar way",
-      "lang": "js",
-      "isBuiltIn": true
-    },
-    {
-      "key": "php-sonar-way-05548",
-      "name": "Sonar way",
-      "lang": "php",
-      "isBuiltIn": true
-    }
-  ],
   "languages": {
     "js": "JavaScript",
     "java": "Java",
index d2e73661f756573384f2136d9797e139b6316f39..f181578280722d112b1b1f588dc832a845632cfa 100644 (file)
@@ -30,20 +30,15 @@ import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.permission.OrganizationPermission;
 import org.sonar.db.rule.RuleRepositoryDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.language.LanguageTesting;
 import org.sonar.server.organization.DefaultOrganizationProvider;
 import org.sonar.server.organization.TestDefaultOrganizationProvider;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.WsActionTester;
-import org.sonarqube.ws.Rules;
 
-import static java.lang.String.format;
 import static java.util.Arrays.asList;
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.db.organization.OrganizationDto.Subscription.PAID;
 import static org.sonar.test.JsonAssert.assertJson;
 
 public class AppActionTest {
@@ -110,24 +105,6 @@ public class AppActionTest {
       "}");
   }
 
-  @Test
-  public void response_on_paid_organization() {
-    OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
-    UserDto user = db.users().insertUser();
-    userSession.logIn(user).addMembership(organization);
-
-    String json = ws.newRequest()
-      .setParam("organization", organization.getKey())
-      .execute().getInput();;
-
-    assertJson(json).isSimilarTo("{" +
-      "\"languages\": {" +
-      "    \"xoo\": \"Xoo\"," +
-      "    \"ws\": \"Whitespace\"" +
-      "  }" +
-      "}");
-  }
-
   @Test
   public void canWrite_is_true_if_user_is_profile_administrator_of_default_organization() {
     userSession.addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, db.getDefaultOrganization());
@@ -182,19 +159,6 @@ public class AppActionTest {
       .execute();
   }
 
-  @Test
-  public void fail_on_paid_organization_when_not_member() {
-    OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
-    db.rules().insert();
-
-    expectedException.expect(ForbiddenException.class);
-    expectedException.expectMessage(format("You're not member of organization '%s'", organization.getKey()));
-
-    ws.newRequest()
-      .setParam("organization", organization.getKey())
-      .executeProtobuf(Rules.SearchResponse.class);
-  }
-
   private void insertRules() {
     RuleRepositoryDto repo1 = new RuleRepositoryDto("xoo", "xoo", "SonarQube");
     RuleRepositoryDto repo2 = new RuleRepositoryDto("squid", "ws", "SonarQube");
index d18c61f35fcfc7176c4e40d6b2e3c16be6d7d23b..58cb0ad500533c0fbb8630a8080146d71ba37f75 100644 (file)
@@ -31,8 +31,6 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.qualityprofile.QProfileDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.organization.TestDefaultOrganizationProvider;
 import org.sonar.server.rule.index.RuleQuery;
@@ -41,7 +39,6 @@ import org.sonar.server.ws.TestRequest;
 import org.sonar.server.ws.WsAction;
 import org.sonar.server.ws.WsActionTester;
 
-import static java.lang.String.format;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.api.rule.RuleStatus.DEPRECATED;
 import static org.sonar.api.rule.RuleStatus.READY;
@@ -56,6 +53,7 @@ import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
 import static org.sonar.db.organization.OrganizationDto.Subscription.PAID;
 import static org.sonar.db.qualityprofile.ActiveRuleDto.INHERITED;
 import static org.sonar.db.qualityprofile.ActiveRuleDto.OVERRIDES;
+import static org.sonar.server.rule.ws.RuleWsSupport.defineGenericRuleSearchParameters;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVATION;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_SEVERITIES;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_AVAILABLE_SINCE;
@@ -73,7 +71,6 @@ import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_STATUSES;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TAGS;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TEMPLATE_KEY;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TYPES;
-import static org.sonar.server.rule.ws.SearchAction.defineGenericRuleSearchParameters;
 
 public class RuleQueryFactoryTest {
 
@@ -257,27 +254,28 @@ public class RuleQueryFactoryTest {
   }
 
   @Test
-  public void filter_by_qprofile_when_subscription_is_paid_and_user_is_member() {
+  public void activation_is_kept_when_member_of_paid_organization() {
     OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
-    QProfileDto qualityProfile = db.qualityProfiles().insert(organization);
-    UserDto user = db.users().insertUser();
-    userSession.logIn(user).addMembership(organization);
+    QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setName("Sonar way").setLanguage("xoo").setKee("sonar-way"));
+    userSession.logIn(db.users().insertUser()).addMembership(organization);
 
-    RuleQuery result = execute(PARAM_QPROFILE, qualityProfile.getKee());
+    RuleQuery result = execute(
+      PARAM_ACTIVATION, "true",
+      PARAM_QPROFILE, profile.getKee());
 
-    assertThat(result.getOrganization().getUuid()).isEqualTo(organization.getUuid());
+    assertThat(result.getActivation()).isTrue();
   }
 
   @Test
-  public void filter_by_organization_when_subscription_is_paid_and_user_is_member() {
+  public void activation_is_set_to_null_when_not_member_of_paid_organization() {
     OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
-    QProfileDto qualityProfile = db.qualityProfiles().insert(organization);
-    UserDto user = db.users().insertUser();
-    userSession.logIn(user).addMembership(organization);
+    QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setName("Sonar way").setLanguage("xoo").setKee("sonar-way"));
 
-    RuleQuery result = execute(PARAM_ORGANIZATION, organization.getKey());
+    RuleQuery result = execute(
+      PARAM_ACTIVATION, "true",
+      PARAM_QPROFILE, profile.getKee());
 
-    assertThat(result.getOrganization().getUuid()).isEqualTo(organization.getUuid());
+    assertThat(result.getActivation()).isNull();
   }
 
   @Test
@@ -347,27 +345,6 @@ public class RuleQueryFactoryTest {
       PARAM_COMPARE_TO_PROFILE, "unknown");
   }
 
-  @Test
-  public void fail_when_searching_by_organization_when_subscription_is_paid_and_user_is_not_member() {
-    OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
-
-    expectedException.expect(ForbiddenException.class);
-    expectedException.expectMessage(format("You're not member of organization '%s'", organization.getKey()));
-
-    execute(PARAM_ORGANIZATION, organization.getKey());
-  }
-
-  @Test
-  public void fail_when_searching_by_qprofile_when_subscription_is_paid_and_user_is_not_member() {
-    OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
-    QProfileDto qualityProfile = db.qualityProfiles().insert(organization);
-
-    expectedException.expect(ForbiddenException.class);
-    expectedException.expectMessage(format("You're not member of organization '%s'", organization.getKey()));
-
-    execute(PARAM_QPROFILE, qualityProfile.getKee());
-  }
-
   private void assertResult(RuleQuery result, QProfileDto qualityProfile, QProfileDto compareToQualityProfile) {
     assertThat(result.getKey()).isEqualTo("ruleKey");
 
index 6114ac6ab6eeb0b4418ace7bdd51e0a833a8fac4..1176a9efa1d3f6ee0716b3334e3388702e1b2bf5 100644 (file)
@@ -45,7 +45,6 @@ import org.sonar.db.rule.RuleMetadataDto;
 import org.sonar.db.rule.RuleParamDto;
 import org.sonar.db.user.UserDto;
 import org.sonar.server.es.EsTester;
-import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.language.LanguageTesting;
 import org.sonar.server.organization.DefaultOrganizationProvider;
@@ -70,7 +69,6 @@ import org.sonarqube.ws.Rules;
 import org.sonarqube.ws.Rules.Rule;
 import org.sonarqube.ws.Rules.SearchResponse;
 
-import static java.lang.String.format;
 import static java.util.Arrays.asList;
 import static java.util.Arrays.stream;
 import static java.util.Collections.singleton;
@@ -83,6 +81,7 @@ import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.sonar.api.rule.Severity.BLOCKER;
+import static org.sonar.api.server.ws.WebService.Param.FIELDS;
 import static org.sonar.db.organization.OrganizationDto.Subscription.PAID;
 import static org.sonar.db.rule.RuleTesting.setSystemTags;
 import static org.sonar.db.rule.RuleTesting.setTags;
@@ -159,8 +158,8 @@ public class SearchActionTest {
 
   @Test
   public void return_all_rules() {
-    RuleDefinitionDto rule1 = createJavaRule();
-    RuleDefinitionDto rule2 = createJavaRule();
+    RuleDefinitionDto rule1 = db.rules().insert(r1 -> r1.setLanguage("java"));
+    RuleDefinitionDto rule2 = db.rules().insert(r1 -> r1.setLanguage("java"));
     indexRules();
 
     verify(r -> {
@@ -192,8 +191,8 @@ public class SearchActionTest {
 
   @Test
   public void filter_by_rule_key() {
-    RuleDefinitionDto rule1 = createJavaRule();
-    RuleDefinitionDto rule2 = createJavaRule();
+    RuleDefinitionDto rule1 = db.rules().insert(r1 -> r1.setLanguage("java"));
+    RuleDefinitionDto rule2 = db.rules().insert(r1 -> r1.setLanguage("java"));
     indexRules();
 
     verify(r -> r.setParam(PARAM_RULE_KEY, rule1.getKey().toString()), rule1);
@@ -263,7 +262,7 @@ public class SearchActionTest {
 
   @Test
   public void return_all_rule_fields_by_default() {
-    RuleDefinitionDto rule = createJavaRule();
+    RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java"));
     indexRules();
 
     Rules.SearchResponse response = ws.newRequest().executeProtobuf(Rules.SearchResponse.class);
@@ -282,7 +281,7 @@ public class SearchActionTest {
 
   @Test
   public void return_subset_of_fields() {
-    RuleDefinitionDto rule = createJavaRule();
+    RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java"));
     indexRules();
 
     Rules.SearchResponse response = ws.newRequest()
@@ -311,9 +310,9 @@ public class SearchActionTest {
   @Test
   public void should_filter_on_organization_specific_tags() {
     OrganizationDto organization = db.organizations().insert();
-    RuleDefinitionDto rule1 = createJavaRule();
+    RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("java"));
     RuleMetadataDto metadata1 = insertMetadata(organization, rule1, setTags("tag1", "tag2"));
-    RuleDefinitionDto rule2 = createJavaRule();
+    RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("java"));
     RuleMetadataDto metadata2 = insertMetadata(organization, rule2);
     indexRules();
 
@@ -327,13 +326,13 @@ public class SearchActionTest {
   @Test
   public void when_searching_for_several_tags_combine_them_with_OR() {
     OrganizationDto organization = db.organizations().insert();
-    RuleDefinitionDto bothTagsRule = createJavaRule();
+    RuleDefinitionDto bothTagsRule = db.rules().insert(r -> r.setLanguage("java"));
     insertMetadata(organization, bothTagsRule, setTags("tag1", "tag2"));
-    RuleDefinitionDto oneTagRule = createJavaRule();
+    RuleDefinitionDto oneTagRule = db.rules().insert(r -> r.setLanguage("java"));
     insertMetadata(organization, oneTagRule, setTags("tag1"));
-    RuleDefinitionDto otherTagRule = createJavaRule();
+    RuleDefinitionDto otherTagRule = db.rules().insert(r -> r.setLanguage("java"));
     insertMetadata(organization, otherTagRule, setTags("tag2"));
-    RuleDefinitionDto noTagRule = createJavaRule();
+    RuleDefinitionDto noTagRule = db.rules().insert(r -> r.setLanguage("java"));
     insertMetadata(organization, noTagRule, setTags());
     indexRules();
 
@@ -406,7 +405,7 @@ public class SearchActionTest {
   @Test
   public void should_return_organization_specific_tags() {
     OrganizationDto organization = db.organizations().insert();
-    RuleDefinitionDto rule = createJavaRule();
+    RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java"));
     RuleMetadataDto metadata = insertMetadata(organization, rule, setTags("tag1", "tag2"));
     indexRules();
 
@@ -444,7 +443,7 @@ public class SearchActionTest {
 
   @Test
   public void should_return_specified_fields() {
-    RuleDefinitionDto rule = createJavaRule();
+    RuleDefinitionDto rule = db.rules().insert(r1 -> r1.setLanguage("java"));
     indexRules();
 
     checkField(rule, "repo", Rule::getRepo, rule.getRepositoryKey());
@@ -632,14 +631,13 @@ public class SearchActionTest {
   public void search_all_active_rules() {
     OrganizationDto organization = db.organizations().insert();
     QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage("java"));
-    RuleDefinitionDto rule = createJavaRule();
+    RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java"));
     RuleActivation activation = RuleActivation.create(rule.getId(), BLOCKER, null);
     qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation));
 
     indexRules();
 
     SearchResponse result = ws.newRequest()
-      .setParam("f", "")
       .setParam("q", rule.getName())
       .setParam("activation", "true")
       .setParam("organization", organization.getKey())
@@ -658,9 +656,7 @@ public class SearchActionTest {
     OrganizationDto organization = db.organizations().insert();
     QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage("java"));
     QProfileDto waterproofProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage("java"));
-
-    RuleDefinitionDto rule = createJavaRule();
-
+    RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java"));
     RuleParamDto ruleParam1 = db.rules().insertRuleParam(rule, p -> p.setDefaultValue("some value")
       .setType("STRING")
       .setDescription("My small description")
@@ -680,11 +676,7 @@ public class SearchActionTest {
     RuleActivation activation = RuleActivation.create(rule.getId());
     List<ActiveRuleChange> activeRuleChanges1 = qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation));
     qProfileRules.activateAndCommit(db.getSession(), waterproofProfile, singleton(activation));
-
     assertThat(activeRuleChanges1).hasSize(1);
-
-    db.commit();
-
     indexRules();
     indexActiveRules();
 
@@ -701,9 +693,8 @@ public class SearchActionTest {
     assertThat(result.getActives().getActives().get(rule.getKey().toString())).isNotNull();
     assertThat(result.getActives().getActives().get(rule.getKey().toString()).getActiveListList()).hasSize(1);
 
-    Rules.Active activeList = result.getActives().getActives().get(rule.getKey().toString()).getActiveList(0);
-
     // The rule without value is not inserted
+    Rules.Active activeList = result.getActives().getActives().get(rule.getKey().toString()).getActiveList(0);
     assertThat(activeList.getParamsCount()).isEqualTo(2);
     assertThat(activeList.getParamsList()).extracting("key", "value").containsExactlyInAnyOrder(
       tuple(ruleParam1.getName(), ruleParam1.getDefaultValue()),
@@ -724,7 +715,7 @@ public class SearchActionTest {
     OrganizationDto organization = db.organizations().insert();
     QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage("java"));
 
-    RuleDefinitionDto rule = createJavaRule();
+    RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java"));
 
     RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setDefaultValue("some value")
       .setType("STRING")
@@ -922,34 +913,92 @@ public class SearchActionTest {
   }
 
   @Test
-  public void returns_rules_on_paid_organization() {
+  public void active_rules_are_returned_when_member_of_paid_organization() {
     OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
-    RuleDefinitionDto rule = db.rules().insert();
+    QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage("java"));
+    RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java"));
+    RuleActivation activation = RuleActivation.create(rule.getId(), BLOCKER, null);
+    qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation));
+    userSession.logIn(db.users().insertUser()).addMembership(organization);
+
     indexRules();
-    UserDto user = db.users().insertUser();
-    userSession.logIn(user).addMembership(organization);
 
     SearchResponse result = ws.newRequest()
-      .setParam("organization", organization.getKey())
+      .setParam(FIELDS, "actives")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
       .executeProtobuf(SearchResponse.class);
 
-    assertThat(result.getRulesList())
-      .extracting(Rule::getKey)
-      .containsExactlyInAnyOrder(rule.getKey().toString());
+    assertThat(result.getRulesCount()).isEqualTo(1);
+    assertThat(result.getActives().getActivesMap()).isNotEmpty();
   }
 
   @Test
-  public void fail_on_paid_organization_when_not_member() {
+  public void active_rules_are_not_returned_when_not_member_of_paid_organization() {
     OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
-    db.rules().insert();
+    QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage("java"));
+    RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("java"));
+    RuleActivation activation = RuleActivation.create(rule.getId(), BLOCKER, null);
+    qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation));
+
     indexRules();
 
-    expectedException.expect(ForbiddenException.class);
-    expectedException.expectMessage(format("You're not member of organization '%s'", organization.getKey()));
+    SearchResponse result = ws.newRequest()
+      .setParam(FIELDS, "actives")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
+      .executeProtobuf(SearchResponse.class);
 
-    ws.newRequest()
-      .setParam("organization", organization.getKey())
+    assertThat(result.getRulesCount()).isEqualTo(1);
+    assertThat(result.getActives().getActivesMap()).isEmpty();
+  }
+
+  @Test
+  public void search_for_active_rules_when_member_of_paid_organization() {
+    OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
+    QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage("java"));
+    // Rule1 is activated on profile
+    RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("java"));
+    RuleActivation activation = RuleActivation.create(rule1.getId(), BLOCKER, null);
+    qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation));
+    // Rule2 is not activated
+    RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("java"));
+    userSession.logIn(db.users().insertUser()).addMembership(organization);
+
+    indexRules();
+
+    SearchResponse result = ws.newRequest()
+      .setParam(FIELDS, "actives")
+      .setParam(PARAM_QPROFILE, profile.getKee())
+      .setParam(PARAM_ACTIVATION, "true")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
       .executeProtobuf(SearchResponse.class);
+
+    assertThat(result.getRulesList()).extracting(Rule::getKey)
+      .containsExactlyInAnyOrder(rule1.getKey().toString());
+  }
+
+  @Test
+  public void search_for_active_rules_is_ignored_when_not_member_of_paid_organization() {
+    OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
+    QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage("java"));
+    // Rule1 is activated on profile
+    RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("java"));
+    RuleActivation activation = RuleActivation.create(rule1.getId(), BLOCKER, null);
+    qProfileRules.activateAndCommit(db.getSession(), profile, singleton(activation));
+    // Rule2 is not activated
+    RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("java"));
+
+    indexRules();
+
+    SearchResponse result = ws.newRequest()
+      .setParam(FIELDS, "actives")
+      .setParam(PARAM_QPROFILE, profile.getKee())
+      .setParam(PARAM_ACTIVATION, "true")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
+      .executeProtobuf(SearchResponse.class);
+
+    // the 2 rules are returned as filter on profile is ignored
+    assertThat(result.getRulesList()).extracting(Rule::getKey)
+      .containsExactlyInAnyOrder(rule1.getKey().toString(), rule2.getKey().toString());
   }
 
   @SafeVarargs
@@ -995,7 +1044,4 @@ public class SearchActionTest {
     activeRuleIndexer.indexOnStartup(activeRuleIndexer.getIndexTypes());
   }
 
-  private RuleDefinitionDto createJavaRule() {
-    return db.rules().insert(r -> r.setLanguage("java"));
-  }
 }
index 3b860357eebd087cd5fdb9bba533fb86a386b476..a3f3d7b87971e1f3d53ce15946d1daeb38424b75 100644 (file)
@@ -51,6 +51,7 @@ import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.sonar.db.organization.OrganizationDto.Subscription.PAID;
 import static org.sonar.db.rule.RuleDto.Format.MARKDOWN;
 import static org.sonar.db.rule.RuleTesting.newCustomRule;
 import static org.sonar.db.rule.RuleTesting.newTemplateRule;
@@ -358,6 +359,39 @@ public class ShowActionTest {
     assertThat(result.getActivesList()).isEmpty();
   }
 
+  @Test
+  public void active_rules_are_returned_when_member_of_paid_organization() {
+    OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
+    RuleDefinitionDto rule = db.rules().insert();
+    QProfileDto qProfile = db.qualityProfiles().insert(organization);
+    ActiveRuleDto activeRule = db.qualityProfiles().activateRule(qProfile, rule);
+    userSession.logIn(db.users().insertUser()).addMembership(organization);
+
+    ShowResponse result = ws.newRequest()
+      .setParam(PARAM_KEY, rule.getKey().toString())
+      .setParam(PARAM_ACTIVES, "true")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
+      .executeProtobuf(ShowResponse.class);
+
+    assertThat(result.getActivesList()).isNotEmpty();
+  }
+
+  @Test
+  public void active_rules_are_not_returned_when_not_member_of_paid_organization() {
+    OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
+    RuleDefinitionDto rule = db.rules().insert();
+    QProfileDto qProfile = db.qualityProfiles().insert(organization);
+    ActiveRuleDto activeRule = db.qualityProfiles().activateRule(qProfile, rule);
+
+    ShowResponse result = ws.newRequest()
+      .setParam(PARAM_KEY, rule.getKey().toString())
+      .setParam(PARAM_ACTIVES, "true")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
+      .executeProtobuf(ShowResponse.class);
+
+    assertThat(result.getActivesList()).isEmpty();
+  }
+
   @Test
   public void throw_NotFoundException_if_organization_cannot_be_found() {
     RuleDefinitionDto rule = db.rules().insert();