import org.sonar.server.rule.index.RuleIndexer;
import org.sonar.server.util.TypeValidations;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Lists.newArrayList;
import static java.lang.String.format;
import static org.sonar.server.ws.WsUtils.checkRequest;
public RuleKey create(DbSession dbSession, NewCustomRule newRule) {
RuleKey templateKey = newRule.templateKey();
- if (templateKey == null) {
- throw new IllegalArgumentException("Rule template key should not be null");
- }
+ checkArgument(templateKey != null, "Rule template key should not be null");
String defaultOrganizationUuid = defaultOrganizationProvider.get().getUuid();
OrganizationDto defaultOrganization = dbClient.organizationDao().selectByUuid(dbSession, defaultOrganizationUuid)
.orElseThrow(() -> new IllegalStateException(String.format("Could not find default organization for uuid '%s'", defaultOrganizationUuid)));
RuleDto templateRule = dbClient.ruleDao().selectOrFailByKey(dbSession, defaultOrganization, templateKey);
- if (!templateRule.isTemplate()) {
- throw new IllegalArgumentException("This rule is not a template rule: " + templateKey.toString());
- }
+ checkArgument(templateRule.isTemplate(), "This rule is not a template rule: %s", templateKey.toString());
validateCustomRule(newRule, dbSession, templateKey);
RuleKey customRuleKey = RuleKey.of(templateRule.getRepositoryKey(), newRule.ruleKey());
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rule.Severity;
+import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
public void define(WebService.NewController controller) {
WebService.NewAction action = controller
.createAction("create")
- .setDescription("Create a custom rule. <br/>" +
- "Since 5.5, it's no more possible to create manual rule." +
- "Custom rules are currently not supported, if the organization feature is enabled. In that case, the webservice will fail.")
+ .setDescription("Create a custom rule")
.setSince("4.4")
+ .setChangelog(
+ new Change("5.5", "Creating manual rule is not more possible"),
+ new Change("6.4", "Creating custom rules are not supported if the organization feature is enabled. In that case, the webservice will fail"))
.setPost(true)
.setHandler(this);
List<RuleDefinitionDto> templateRules = new ArrayList<>();
if (rule.getTemplateId() != null) {
Optional<RuleDefinitionDto> templateRule = dbClient.ruleDao().selectDefinitionById(rule.getTemplateId(), dbSession);
- if (templateRule.isPresent()) {
- templateRules.add(templateRule.get());
- }
+ templateRule.ifPresent(templateRules::add);
}
List<RuleParamDto> ruleParameters = dbClient.ruleDao().selectRuleParamsByRuleIds(dbSession, singletonList(rule.getId()));
SearchAction.SearchResult searchResult = new SearchAction.SearchResult()
.setTemplateRules(templateRules)
.setTotal(1L);
return Rules.CreateResponse.newBuilder()
- .setRule(ruleMapper.toWsRule(rule, searchResult, Collections.<String>emptySet()))
+ .setRule(ruleMapper.toWsRule(rule, searchResult, Collections.emptySet()))
.build();
}
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.rule.ws;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.rule.Severity;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.rule.RuleDao;
-import org.sonar.db.rule.RuleDto;
-import org.sonar.db.rule.RuleParamDto;
-import org.sonar.db.rule.RuleTesting;
-import org.sonar.server.organization.DefaultOrganization;
-import org.sonar.server.organization.DefaultOrganizationProvider;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-@RunWith(MockitoJUnitRunner.class)
-public class CreateActionMediumTest {
-
- @ClassRule
- public static ServerTester tester = new ServerTester().withEsIndexes();
-
- @Rule
- public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester).logIn().setSystemAdministrator();
-
- private WsTester wsTester;
- private RuleDao ruleDao;
- private DbSession session;
- private OrganizationDto defaultOrganization;
-
- @Before
- public void setUp() {
- tester.clearDbAndIndexes();
- wsTester = tester.get(WsTester.class);
- ruleDao = tester.get(RuleDao.class);
- DbClient dbClient = tester.get(DbClient.class);
- session = dbClient.openSession(false);
- DefaultOrganization defaultOrganization = tester.get(DefaultOrganizationProvider.class).get();
- this.defaultOrganization = dbClient.organizationDao().selectByUuid(session, defaultOrganization.getUuid()).get();
- }
-
- @After
- public void after() {
- session.close();
- }
-
- @Test
- public void create_custom_rule() throws Exception {
- // Template rule
- RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001"), defaultOrganization);
- ruleDao.insert(session, templateRule.getDefinition());
- ruleDao.insertOrUpdate(session, templateRule.getMetadata().setRuleId(templateRule.getId()));
- RuleParamDto param = RuleParamDto.createFor(templateRule.getDefinition()).setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue(".*");
- ruleDao.insertRuleParam(session, templateRule.getDefinition(), param);
- session.commit();
-
- WsTester.TestRequest request = wsTester.newPostRequest("api/rules", "create")
- .setParam("custom_key", "MY_CUSTOM")
- .setParam("template_key", templateRule.getKey().toString())
- .setParam("name", "My custom rule")
- .setParam("markdown_description", "Description")
- .setParam("severity", "MAJOR")
- .setParam("status", "BETA")
- .setParam("params", "regex=a.*");
- request.execute().assertJson(getClass(), "create_custom_rule.json");
- }
-
- @Test
- public void create_custom_rule_with_prevent_reactivation_param_to_true() throws Exception {
- RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001"));
- ruleDao.insert(session, templateRule.getDefinition());
-
- // insert a removed rule
- RuleDto customRule = RuleTesting.newCustomRule(templateRule)
- .setRuleKey("MY_CUSTOM")
- .setStatus(RuleStatus.REMOVED)
- .setName("My custom rule")
- .setDescription("Description")
- .setDescriptionFormat(RuleDto.Format.MARKDOWN)
- .setSeverity(Severity.MAJOR);
- tester.get(RuleDao.class).insert(session, customRule.getDefinition());
- session.commit();
-
- WsTester.TestRequest request = wsTester.newPostRequest("api/rules", "create")
- .setParam("custom_key", "MY_CUSTOM")
- .setParam("template_key", templateRule.getKey().toString())
- .setParam("name", "My custom rule")
- .setParam("markdown_description", "Description")
- .setParam("severity", "MAJOR")
- .setParam("prevent_reactivation", "true");
- request.execute()
- .assertJson(getClass(), "create_rule_with_prevent_reactivation_param_to_true.json")
- .assertStatus(409);
- }
-
-}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.rule.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.config.MapSettings;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.db.rule.RuleDto;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.organization.TestDefaultOrganizationProvider;
+import org.sonar.server.organization.TestOrganizationFlags;
+import org.sonar.server.rule.RuleCreator;
+import org.sonar.server.rule.index.RuleIndexDefinition;
+import org.sonar.server.rule.index.RuleIndexer;
+import org.sonar.server.text.MacroInterpreter;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.AdditionalAnswers.returnsFirstArg;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.sonar.db.rule.RuleTesting.newCustomRule;
+import static org.sonar.db.rule.RuleTesting.newTemplateRule;
+import static org.sonar.server.util.TypeValidationsTesting.newFullTypeValidations;
+import static org.sonar.test.JsonAssert.assertJson;
+
+public class CreateActionTest {
+
+ private System2 system2 = mock(System2.class);
+
+ @Rule
+ public DbTester db = DbTester.create(system2);
+
+ @Rule
+ public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings()));
+
+ private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
+
+ private WsActionTester wsTester = new WsActionTester(new CreateAction(db.getDbClient(),
+ new RuleCreator(system2, new RuleIndexer(es.client(), db.getDbClient()), db.getDbClient(), newFullTypeValidations(),
+ TestDefaultOrganizationProvider.from(db)),
+ new RuleMapper(new Languages(), createMacroInterpreter()), organizationFlags));
+
+ @Test
+ public void create_custom_rule() {
+ // Template rule
+ RuleDto templateRule = newTemplateRule(RuleKey.of("java", "S001"), db.getDefaultOrganization());
+ db.rules().insert(templateRule.getDefinition());
+ db.rules().insertOrUpdateMetadata(templateRule.getMetadata().setRuleId(templateRule.getId()));
+ db.rules().insertRuleParam(templateRule.getDefinition(), param -> param.setName("regex").setType("STRING").setDescription("Reg ex").setDefaultValue(".*"));
+
+ String result = wsTester.newRequest()
+ .setParam("custom_key", "MY_CUSTOM")
+ .setParam("template_key", templateRule.getKey().toString())
+ .setParam("name", "My custom rule")
+ .setParam("markdown_description", "Description")
+ .setParam("severity", "MAJOR")
+ .setParam("status", "BETA")
+ .setParam("params", "regex=a.*")
+ .execute().getInput();
+
+ assertJson(result).isSimilarTo("{\n" +
+ " \"rule\": {\n" +
+ " \"key\": \"java:MY_CUSTOM\",\n" +
+ " \"repo\": \"java\",\n" +
+ " \"name\": \"My custom rule\",\n" +
+ " \"htmlDesc\": \"Description\",\n" +
+ " \"severity\": \"MAJOR\",\n" +
+ " \"status\": \"BETA\",\n" +
+ " \"internalKey\": \"InternalKeyS001\",\n" +
+ " \"isTemplate\": false,\n" +
+ " \"templateKey\": \"java:S001\",\n" +
+ " \"sysTags\": [\"systag1\", \"systag2\"],\n" +
+ " \"lang\": \"js\",\n" +
+ " \"params\": [\n" +
+ " {\n" +
+ " \"key\": \"regex\",\n" +
+ " \"htmlDesc\": \"Reg ex\",\n" +
+ " \"defaultValue\": \"a.*\",\n" +
+ " \"type\": \"STRING\"\n" +
+ " }\n" +
+ " ]\n" +
+ " }\n" +
+ "}\n");
+ }
+
+ @Test
+ public void create_custom_rule_with_prevent_reactivation_param_to_true() {
+ RuleDefinitionDto templateRule = newTemplateRule(RuleKey.of("java", "S001")).getDefinition();
+ db.rules().insert(templateRule);
+ // insert a removed rule
+ RuleDefinitionDto customRule = newCustomRule(templateRule)
+ .setRuleKey("MY_CUSTOM")
+ .setStatus(RuleStatus.REMOVED)
+ .setName("My custom rule")
+ .setDescription("Description")
+ .setDescriptionFormat(RuleDto.Format.MARKDOWN)
+ .setSeverity(Severity.MAJOR);
+ db.rules().insert(customRule);
+
+ TestResponse response = wsTester.newRequest()
+ .setParam("custom_key", "MY_CUSTOM")
+ .setParam("template_key", templateRule.getKey().toString())
+ .setParam("name", "My custom rule")
+ .setParam("markdown_description", "Description")
+ .setParam("severity", "MAJOR")
+ .setParam("prevent_reactivation", "true")
+ .execute();
+
+ assertThat(response.getStatus()).isEqualTo(409);
+ assertJson(response.getInput()).isSimilarTo("{\n" +
+ " \"rule\": {\n" +
+ " \"key\": \"java:MY_CUSTOM\",\n" +
+ " \"repo\": \"java\",\n" +
+ " \"name\": \"My custom rule\",\n" +
+ " \"htmlDesc\": \"Description\",\n" +
+ " \"severity\": \"MAJOR\",\n" +
+ " \"status\": \"REMOVED\",\n" +
+ " \"isTemplate\": false\n" +
+ " }\n" +
+ "}\n");
+ }
+
+ private static MacroInterpreter createMacroInterpreter() {
+ MacroInterpreter macroInterpreter = mock(MacroInterpreter.class);
+ doAnswer(returnsFirstArg()).when(macroInterpreter).interpret(anyString());
+ return macroInterpreter;
+ }
+
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.rule.ws;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.tester.UserSessionRule;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class RulesWsMediumTest {
-
- @ClassRule
- public static ServerTester tester = new ServerTester().withEsIndexes();
-
- @Rule
- public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
-
- private static final String API_ENDPOINT = "api/rules";
- private static final String API_SHOW_METHOD = "show";
- private static final String API_TAGS_METHOD = "tags";
-
- private RulesWs ws;
- private DbSession session;
-
- @Before
- public void setUp() {
- tester.clearDbAndIndexes();
- ws = tester.get(RulesWs.class);
- session = tester.get(DbClient.class).openSession(false);
- }
-
- @After
- public void after() {
- session.close();
- }
-
- @Test
- public void define() {
- WebService.Context context = new WebService.Context();
- ws.define(context);
-
- WebService.Controller controller = context.controller(API_ENDPOINT);
-
- assertThat(controller).isNotNull();
- assertThat(controller.actions()).hasSize(9);
- assertThat(controller.action("search")).isNotNull();
- assertThat(controller.action(API_SHOW_METHOD)).isNotNull();
- assertThat(controller.action(API_TAGS_METHOD)).isNotNull();
- assertThat(controller.action("update")).isNotNull();
- assertThat(controller.action("create")).isNotNull();
- assertThat(controller.action("delete")).isNotNull();
- assertThat(controller.action("repositories")).isNotNull();
- assertThat(controller.action("app")).isNotNull();
- }
-}
+++ /dev/null
-{
- "rule": {
- "key": "java:MY_CUSTOM",
- "repo": "java",
- "name": "My custom rule",
- "htmlDesc": "Description",
- "severity": "MAJOR",
- "status": "BETA",
- "internalKey": "InternalKeyS001",
- "isTemplate": false,
- "templateKey": "java:S001",
- "sysTags": ["systag1", "systag2"],
- "lang": "js",
- "params": [
- {
- "key": "regex",
- "htmlDesc": "Reg ex",
- "defaultValue": "a.*",
- "type": "STRING"
- }
- ]
- }
-}
+++ /dev/null
-{
- "rule": {
- "key": "java:MY_CUSTOM",
- "repo": "java",
- "name": "My custom rule",
- "htmlDesc": "Description",
- "severity": "MAJOR",
- "status": "REMOVED",
- "isTemplate": false
- }
-}