From 364fc3b7439e8241ed4094837f9dd835375d09cc Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Fri, 6 Jul 2018 14:25:13 +0200 Subject: [PATCH] SONAR-10945 Active rules search is only for member on paid organizations --- .../ws/ActivateRulesAction.java | 2 +- .../ws/DeactivateRulesAction.java | 3 +- .../server/rule/ws/RuleQueryFactory.java | 7 +- .../sonar/server/rule/ws/RuleWsSupport.java | 160 +++++++++++++++- .../sonar/server/rule/ws/SearchAction.java | 181 ++---------------- .../org/sonar/server/rule/ws/ShowAction.java | 2 +- .../org/sonar/server/rule/ws/app-example.json | 26 --- .../sonar/server/rule/ws/AppActionTest.java | 36 ---- .../server/rule/ws/RuleQueryFactoryTest.java | 51 ++--- .../server/rule/ws/SearchActionTest.java | 136 ++++++++----- .../sonar/server/rule/ws/ShowActionTest.java | 34 ++++ 11 files changed, 319 insertions(+), 319 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java index aea1c6848a7..3b6a8dbb71f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ActivateRulesAction.java @@ -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; diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeactivateRulesAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeactivateRulesAction.java index b561083f917..8f55070c382 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeactivateRulesAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeactivateRulesAction.java @@ -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; diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java index 0df84c49176..c96ae59ab49 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleQueryFactory.java @@ -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); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java index a54dea98130..e9d529117f5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java @@ -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"); + } + + } diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java index 0027b0542fa..d2d9fa4a388 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java @@ -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 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.
" + + "Since 5.5, following fields in the response have been deprecated :" + + "") + .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.
" + - "Since 5.5, following fields in the response have been deprecated :" + - "") - .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 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); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/ShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/ShowAction.java index bd374a495f7..fd860930aa4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/ShowAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/ShowAction.java @@ -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(); diff --git a/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/app-example.json b/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/app-example.json index cbd43235667..b8dc5cbc67c 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/app-example.json +++ b/server/sonar-server/src/main/resources/org/sonar/server/rule/ws/app-example.json @@ -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", diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java index d2e73661f75..f1815782807 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java @@ -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"); diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java index d18c61f35fc..58cb0ad5005 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/RuleQueryFactoryTest.java @@ -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"); diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java index 6114ac6ab6e..1176a9efa1d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java @@ -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 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")); - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java index 3b860357eeb..a3f3d7b8797 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java @@ -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(); -- 2.39.5