From e9787d42617b60e80bb74bacd0ea70fbf64330dd Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Fri, 6 Jun 2014 18:04:04 +0200 Subject: [PATCH] SONAR-5361 Create WS to delete a custom rule (need to remove active rules to be finished) --- .../server/platform/ServerComponents.java | 146 ++---------------- .../org/sonar/server/rule/RuleDeleter.java | 58 +++++++ .../org/sonar/server/rule/RuleService.java | 22 ++- .../sonar/server/rule/ws/DeleteAction.java | 63 ++++++++ .../sonar/server/rule/ws/RulesWebService.java | 5 +- .../server/rule/RuleDeleterMediumTest.java | 104 +++++++++++++ .../server/rule/RuleServiceMediumTest.java | 57 ++++--- .../sonar/server/rule/ws/AppActionTest.java | 2 +- .../server/rule/ws/DeleteActionTest.java | 56 +++++++ .../server/rule/ws/RulesWebServiceTest.java | 3 +- 10 files changed, 358 insertions(+), 158 deletions(-) create mode 100644 sonar-server/src/main/java/org/sonar/server/rule/RuleDeleter.java create mode 100644 sonar-server/src/main/java/org/sonar/server/rule/ws/DeleteAction.java create mode 100644 sonar-server/src/test/java/org/sonar/server/rule/RuleDeleterMediumTest.java create mode 100644 sonar-server/src/test/java/org/sonar/server/rule/ws/DeleteActionTest.java diff --git a/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index 359550f191e..35a2803784f 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -52,13 +52,7 @@ import org.sonar.core.measure.db.MeasureFilterDao; import org.sonar.core.metric.DefaultMetricFinder; import org.sonar.core.notification.DefaultNotificationManager; import org.sonar.core.permission.PermissionFacade; -import org.sonar.core.persistence.DaoUtils; -import org.sonar.core.persistence.DatabaseVersion; -import org.sonar.core.persistence.DefaultDatabase; -import org.sonar.core.persistence.MyBatis; -import org.sonar.core.persistence.PreviewDatabaseFactory; -import org.sonar.core.persistence.SemaphoreUpdater; -import org.sonar.core.persistence.SemaphoresImpl; +import org.sonar.core.persistence.*; import org.sonar.core.preview.PreviewCache; import org.sonar.core.profiling.Profiling; import org.sonar.core.purge.PurgeProfiler; @@ -92,33 +86,11 @@ import org.sonar.server.db.DbClient; import org.sonar.server.db.EmbeddedDatabaseFactory; import org.sonar.server.db.migrations.DatabaseMigrations; import org.sonar.server.db.migrations.DatabaseMigrator; -import org.sonar.server.debt.DebtCharacteristicsXMLImporter; -import org.sonar.server.debt.DebtModelBackup; -import org.sonar.server.debt.DebtModelLookup; -import org.sonar.server.debt.DebtModelOperations; -import org.sonar.server.debt.DebtModelPluginRepository; -import org.sonar.server.debt.DebtModelService; -import org.sonar.server.debt.DebtModelXMLExporter; -import org.sonar.server.debt.DebtRulesXMLImporter; +import org.sonar.server.debt.*; import org.sonar.server.duplication.ws.DuplicationsParser; import org.sonar.server.duplication.ws.DuplicationsWriter; import org.sonar.server.duplication.ws.DuplicationsWs; -import org.sonar.server.issue.ActionService; -import org.sonar.server.issue.AssignAction; -import org.sonar.server.issue.CommentAction; -import org.sonar.server.issue.DefaultIssueFinder; -import org.sonar.server.issue.InternalRubyIssueService; -import org.sonar.server.issue.IssueBulkChangeService; -import org.sonar.server.issue.IssueChangelogFormatter; -import org.sonar.server.issue.IssueChangelogService; -import org.sonar.server.issue.IssueCommentService; -import org.sonar.server.issue.IssueService; -import org.sonar.server.issue.IssueStatsFinder; -import org.sonar.server.issue.PlanAction; -import org.sonar.server.issue.PublicRubyIssueService; -import org.sonar.server.issue.ServerIssueStorage; -import org.sonar.server.issue.SetSeverityAction; -import org.sonar.server.issue.TransitionAction; +import org.sonar.server.issue.*; import org.sonar.server.issue.actionplan.ActionPlanService; import org.sonar.server.issue.actionplan.ActionPlanWs; import org.sonar.server.issue.filter.IssueFilterService; @@ -147,81 +119,22 @@ import org.sonar.server.platform.ws.L10nWs; import org.sonar.server.platform.ws.RestartHandler; import org.sonar.server.platform.ws.ServerWs; import org.sonar.server.platform.ws.SystemWs; -import org.sonar.server.plugins.BatchWs; -import org.sonar.server.plugins.InstalledPluginReferentialFactory; -import org.sonar.server.plugins.PluginDownloader; -import org.sonar.server.plugins.ServerExtensionInstaller; -import org.sonar.server.plugins.ServerPluginJarInstaller; -import org.sonar.server.plugins.ServerPluginJarsInstaller; -import org.sonar.server.plugins.ServerPluginRepository; -import org.sonar.server.plugins.UpdateCenterClient; -import org.sonar.server.plugins.UpdateCenterMatrixFactory; +import org.sonar.server.plugins.*; import org.sonar.server.qualitygate.QgateProjectFinder; import org.sonar.server.qualitygate.QualityGates; import org.sonar.server.qualitygate.RegisterQualityGates; -import org.sonar.server.qualitygate.ws.QGatesAppAction; -import org.sonar.server.qualitygate.ws.QGatesCopyAction; -import org.sonar.server.qualitygate.ws.QGatesCreateAction; -import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction; -import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction; -import org.sonar.server.qualitygate.ws.QGatesDeselectAction; -import org.sonar.server.qualitygate.ws.QGatesDestroyAction; -import org.sonar.server.qualitygate.ws.QGatesListAction; -import org.sonar.server.qualitygate.ws.QGatesRenameAction; -import org.sonar.server.qualitygate.ws.QGatesSearchAction; -import org.sonar.server.qualitygate.ws.QGatesSelectAction; -import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction; -import org.sonar.server.qualitygate.ws.QGatesShowAction; -import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction; -import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction; -import org.sonar.server.qualitygate.ws.QGatesWs; -import org.sonar.server.qualityprofile.BuiltInProfiles; -import org.sonar.server.qualityprofile.ProfilesManager; -import org.sonar.server.qualityprofile.QProfileBackuper; -import org.sonar.server.qualityprofile.QProfileCopier; -import org.sonar.server.qualityprofile.QProfileLookup; -import org.sonar.server.qualityprofile.QProfileOperations; -import org.sonar.server.qualityprofile.QProfileProjectLookup; -import org.sonar.server.qualityprofile.QProfileProjectOperations; -import org.sonar.server.qualityprofile.QProfileRepositoryExporter; -import org.sonar.server.qualityprofile.QProfileReset; -import org.sonar.server.qualityprofile.QProfileService; -import org.sonar.server.qualityprofile.QProfiles; -import org.sonar.server.qualityprofile.RegisterQualityProfiles; -import org.sonar.server.qualityprofile.RuleActivationContextFactory; -import org.sonar.server.qualityprofile.RuleActivator; +import org.sonar.server.qualitygate.ws.*; +import org.sonar.server.qualityprofile.*; import org.sonar.server.qualityprofile.db.ActiveRuleDao; import org.sonar.server.qualityprofile.index.ActiveRuleIndex; import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer; -import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions; -import org.sonar.server.qualityprofile.ws.ProfilesWs; -import org.sonar.server.qualityprofile.ws.QProfileRecreateBuiltInAction; -import org.sonar.server.qualityprofile.ws.QProfilesWs; -import org.sonar.server.qualityprofile.ws.RuleActivationActions; -import org.sonar.server.rule.DeprecatedRulesDefinition; -import org.sonar.server.rule.RegisterRules; -import org.sonar.server.rule.RubyRuleService; -import org.sonar.server.rule.RuleCreator; -import org.sonar.server.rule.RuleDefinitionsLoader; -import org.sonar.server.rule.RuleOperations; -import org.sonar.server.rule.RuleRepositories; -import org.sonar.server.rule.RuleService; -import org.sonar.server.rule.RuleUpdater; +import org.sonar.server.qualityprofile.ws.*; +import org.sonar.server.rule.*; import org.sonar.server.rule.db.RuleDao; import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.rule.index.RuleNormalizer; -import org.sonar.server.rule.ws.ActiveRuleCompleter; -import org.sonar.server.rule.ws.AppAction; -import org.sonar.server.rule.ws.RuleMapping; -import org.sonar.server.rule.ws.RulesWebService; -import org.sonar.server.rule.ws.SearchAction; -import org.sonar.server.rule.ws.TagsAction; -import org.sonar.server.rule.ws.UpdateAction; -import org.sonar.server.search.ESNode; -import org.sonar.server.search.IndexClient; -import org.sonar.server.search.IndexQueue; -import org.sonar.server.search.IndexQueueWorker; -import org.sonar.server.search.IndexSynchronizer; +import org.sonar.server.rule.ws.*; +import org.sonar.server.search.*; import org.sonar.server.source.CodeColorizers; import org.sonar.server.source.DeprecatedSourceDecorator; import org.sonar.server.source.HtmlSourceDecorator; @@ -230,27 +143,9 @@ import org.sonar.server.source.ws.ScmAction; import org.sonar.server.source.ws.ScmWriter; import org.sonar.server.source.ws.ShowAction; import org.sonar.server.source.ws.SourcesWs; -import org.sonar.server.startup.CleanPreviewAnalysisCache; -import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules; -import org.sonar.server.startup.GeneratePluginIndex; -import org.sonar.server.startup.GwtPublisher; -import org.sonar.server.startup.JdbcDriverDeployer; -import org.sonar.server.startup.LogServerId; -import org.sonar.server.startup.RegisterDashboards; -import org.sonar.server.startup.RegisterDebtModel; -import org.sonar.server.startup.RegisterMetrics; -import org.sonar.server.startup.RegisterNewMeasureFilters; -import org.sonar.server.startup.RegisterPermissionTemplates; -import org.sonar.server.startup.RegisterServletFilters; -import org.sonar.server.startup.RenameDeprecatedPropertyKeys; -import org.sonar.server.startup.ServerMetadataPersister; +import org.sonar.server.startup.*; import org.sonar.server.test.CoverageService; -import org.sonar.server.test.ws.CoverageShowAction; -import org.sonar.server.test.ws.CoverageWs; -import org.sonar.server.test.ws.TestsCoveredFilesAction; -import org.sonar.server.test.ws.TestsShowAction; -import org.sonar.server.test.ws.TestsTestCasesAction; -import org.sonar.server.test.ws.TestsWs; +import org.sonar.server.test.ws.*; import org.sonar.server.text.MacroInterpreter; import org.sonar.server.text.RubyTextService; import org.sonar.server.ui.JRubyI18n; @@ -258,20 +153,9 @@ import org.sonar.server.ui.JRubyProfiling; import org.sonar.server.ui.PageDecorations; import org.sonar.server.ui.Views; import org.sonar.server.updatecenter.ws.UpdateCenterWs; -import org.sonar.server.user.DefaultUserService; -import org.sonar.server.user.DoPrivileged; -import org.sonar.server.user.GroupMembershipFinder; -import org.sonar.server.user.GroupMembershipService; -import org.sonar.server.user.NewUserNotifier; -import org.sonar.server.user.SecurityRealmFactory; +import org.sonar.server.user.*; import org.sonar.server.user.ws.UsersWs; -import org.sonar.server.util.BooleanTypeValidation; -import org.sonar.server.util.FloatTypeValidation; -import org.sonar.server.util.IntegerTypeValidation; -import org.sonar.server.util.StringListTypeValidation; -import org.sonar.server.util.StringTypeValidation; -import org.sonar.server.util.TextTypeValidation; -import org.sonar.server.util.TypeValidations; +import org.sonar.server.util.*; import org.sonar.server.ws.ListingWs; import org.sonar.server.ws.WebServiceEngine; @@ -454,11 +338,13 @@ class ServerComponents { pico.addSingleton(RuleService.class); pico.addSingleton(RuleUpdater.class); pico.addSingleton(RuleCreator.class); + pico.addSingleton(RuleDeleter.class); pico.addSingleton(UpdateAction.class); pico.addSingleton(RulesWebService.class); pico.addSingleton(SearchAction.class); pico.addSingleton(org.sonar.server.rule.ws.ShowAction.class); pico.addSingleton(org.sonar.server.rule.ws.CreateAction.class); + pico.addSingleton(DeleteAction.class); pico.addSingleton(TagsAction.class); pico.addSingleton(RuleMapping.class); pico.addSingleton(ActiveRuleCompleter.class); diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RuleDeleter.java b/sonar-server/src/main/java/org/sonar/server/rule/RuleDeleter.java new file mode 100644 index 00000000000..7ed4104d3fb --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/rule/RuleDeleter.java @@ -0,0 +1,58 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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; + +import org.sonar.api.ServerComponent; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.rule.RuleDto; +import org.sonar.server.db.DbClient; +import org.sonar.server.qualityprofile.QProfileService; + +public class RuleDeleter implements ServerComponent { + + private final DbClient dbClient; + private final QProfileService profileService; + + public RuleDeleter(DbClient dbClient, QProfileService profileService) { + this.dbClient = dbClient; + this.profileService = profileService; + } + + public void delete(RuleKey ruleKey) { + DbSession dbSession = dbClient.openSession(false); + try { + RuleDto rule = dbClient.ruleDao().getByKey(dbSession, ruleKey); + if (rule.getParentId() == null) { + throw new IllegalStateException("Only custom rules can be deleted"); + } + // TODO call profileService to deactivate active rules on the rule + + rule.setStatus(RuleStatus.REMOVED); + dbClient.ruleDao().update(dbSession, rule); + + dbSession.commit(); + } finally { + dbSession.close(); + } + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/rule/RuleService.java b/sonar-server/src/main/java/org/sonar/server/rule/RuleService.java index 8e7d84bef0c..17276441954 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/RuleService.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/RuleService.java @@ -30,6 +30,7 @@ import org.sonar.server.search.QueryOptions; import org.sonar.server.user.UserSession; import javax.annotation.CheckForNull; + import java.util.Set; /** @@ -40,11 +41,13 @@ public class RuleService implements ServerComponent { private final RuleIndex index; private final RuleUpdater ruleUpdater; private final RuleCreator ruleCreator; + private final RuleDeleter ruleDeleter; - public RuleService(RuleIndex index, RuleUpdater ruleUpdater, RuleCreator ruleCreator) { + public RuleService(RuleIndex index, RuleUpdater ruleUpdater, RuleCreator ruleCreator, RuleDeleter ruleDeleter) { this.index = index; this.ruleUpdater = ruleUpdater; this.ruleCreator = ruleCreator; + this.ruleDeleter = ruleDeleter; } @CheckForNull @@ -69,18 +72,23 @@ public class RuleService implements ServerComponent { } public void update(RuleUpdate update) { - UserSession userSession = UserSession.get(); - userSession.checkLoggedIn(); - userSession.checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN); - + checkPermission(); ruleUpdater.update(update, UserSession.get()); } public RuleKey create(NewRule newRule) { + checkPermission(); + return ruleCreator.create(newRule); + } + + public void delete(RuleKey ruleKey) { + checkPermission(); + ruleDeleter.delete(ruleKey); + } + + private void checkPermission() { UserSession userSession = UserSession.get(); userSession.checkLoggedIn(); userSession.checkGlobalPermission(GlobalPermissions.QUALITY_PROFILE_ADMIN); - - return ruleCreator.create(newRule); } } diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ws/DeleteAction.java b/sonar-server/src/main/java/org/sonar/server/rule/ws/DeleteAction.java new file mode 100644 index 00000000000..b81a8bdb6f9 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/rule/ws/DeleteAction.java @@ -0,0 +1,63 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.sonar.api.rule.RuleKey; +import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.RequestHandler; +import org.sonar.api.server.ws.Response; +import org.sonar.api.server.ws.WebService; +import org.sonar.server.rule.RuleService; + +/** + * @since 4.4 + */ +public class DeleteAction implements RequestHandler { + + public static final String PARAM_KEY = "key"; + + private final RuleService service; + + public DeleteAction(RuleService service) { + this.service = service; + } + + void define(WebService.NewController controller) { + WebService.NewAction action = controller + .createAction("delete") + .setDescription("Delete custom rule or manual rule") + .setSince("4.4") + .setPost(true) + .setHandler(this); + + action + .createParam(PARAM_KEY) + .setDescription("Rule key") + .setRequired(true) + .setExampleValue("squid:XPath_1402065390816"); + } + + @Override + public void handle(Request request, Response response) { + RuleKey key = RuleKey.parse(request.mandatoryParam(PARAM_KEY)); + service.delete(key); + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWebService.java b/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWebService.java index 3bb48bd4ed0..b4a9ffc9cb4 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWebService.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/ws/RulesWebService.java @@ -29,15 +29,17 @@ public class RulesWebService implements WebService { private final CreateAction create; private final AppAction app; private final UpdateAction update; + private final DeleteAction delete; public RulesWebService(SearchAction search, ShowAction show, TagsAction tags, CreateAction create, - AppAction app, UpdateAction update) { + AppAction app, UpdateAction update, DeleteAction delete) { this.search = search; this.show = show; this.tags = tags; this.create = create; this.app = app; this.update = update; + this.delete = delete; } @Override @@ -52,6 +54,7 @@ public class RulesWebService implements WebService { app.define(controller); update.define(controller); create.define(controller); + delete.define(controller); controller.done(); } diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RuleDeleterMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule/RuleDeleterMediumTest.java new file mode 100644 index 00000000000..769c8f0f171 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/rule/RuleDeleterMediumTest.java @@ -0,0 +1,104 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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; + +import com.google.common.collect.ImmutableMap; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rule.Severity; +import org.sonar.check.Cardinality; +import org.sonar.core.persistence.DbSession; +import org.sonar.server.db.DbClient; +import org.sonar.server.rule.db.RuleDao; +import org.sonar.server.rule.index.RuleIndex; +import org.sonar.server.tester.ServerTester; + +import static org.fest.assertions.Assertions.assertThat; + +public class RuleDeleterMediumTest { + + @ClassRule + public static ServerTester tester = new ServerTester(); + + RuleDao dao = tester.get(RuleDao.class); + RuleIndex index = tester.get(RuleIndex.class); + RuleCreator creator = tester.get(RuleCreator.class); + RuleDeleter deleter = tester.get(RuleDeleter.class); + DbSession dbSession; + + @Before + public void before() { + tester.clearDbAndIndexes(); + dbSession = tester.get(DbClient.class).openSession(false); + } + + @After + public void after() { + dbSession.close(); + } + + @Test + public void delete_custom_rule() throws Exception { + // Create template rule + RuleKey templateRuleKey = RuleKey.of("java", "S001"); + dao.insert(dbSession, RuleTesting.newDto(templateRuleKey).setCardinality(Cardinality.MULTIPLE)); + dbSession.commit(); + + // Create custom rule + NewRule newRule = new NewRule() + .setTemplateKey(templateRuleKey) + .setName("My custom") + .setHtmlDescription("Some description") + .setSeverity(Severity.MAJOR) + .setStatus(RuleStatus.READY) + .setParameters(ImmutableMap.of("regex", "a.*")); + RuleKey customRuleKey = creator.create(newRule); + + // Delete custom rule + deleter.delete(customRuleKey); + + Rule customRuleReloaded = index.getByKey(customRuleKey); + assertThat(customRuleReloaded).isNotNull(); + assertThat(customRuleReloaded.status()).isEqualTo(RuleStatus.REMOVED); + + // TODO check active rules are removed + } + + @Test + public void fail_to_delete_if_not_custom() throws Exception { + // Create rule + RuleKey ruleKey = RuleKey.of("java", "S001"); + dao.insert(dbSession, RuleTesting.newDto(ruleKey)); + dbSession.commit(); + + try { + // Delete rule + deleter.delete(ruleKey); + } catch (Exception e){ + assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Only custom rules can be deleted"); + } + } + +} diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java index 60ac8b0430a..0f5b80eb841 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java @@ -44,7 +44,6 @@ import java.util.Collections; import java.util.Set; import static org.fest.assertions.Assertions.assertThat; -import static org.fest.assertions.Fail.fail; public class RuleServiceMediumTest { @@ -112,7 +111,7 @@ public class RuleServiceMediumTest { assertThat(rule.getNoteUserLogin()).isEqualTo("me"); } - @Test + @Test(expected = UnauthorizedException.class) public void do_not_update_if_not_granted() throws Exception { MockUserSession.set().setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); @@ -123,23 +122,18 @@ public class RuleServiceMediumTest { .setSystemTags(Sets.newHashSet("java8", "javadoc"))); dbSession.commit(); - try { - RuleUpdate update = new RuleUpdate(key).setMarkdownNote("my *note*"); - service.update(update); - fail(); - } catch (UnauthorizedException e) { - // ok - } + RuleUpdate update = new RuleUpdate(key).setMarkdownNote("my *note*"); + service.update(update); } @Test - public void create_rule() throws Exception { + public void create_custom_rule() throws Exception { MockUserSession.set() .setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN) .setLogin("me"); + // Create template rule RuleKey templateRuleKey = RuleKey.of("java", "S001"); - dao.insert(dbSession, RuleTesting.newDto(templateRuleKey).setCardinality(Cardinality.MULTIPLE)); dbSession.commit(); @@ -159,15 +153,42 @@ public class RuleServiceMediumTest { assertThat(rule).isNotNull(); } - @Test + @Test(expected = UnauthorizedException.class) public void do_not_create_if_not_granted() throws Exception { MockUserSession.set().setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); - try { - service.create(new NewRule()); - fail(); - } catch (UnauthorizedException e) { - // ok - } + service.create(new NewRule()); + } + + @Test + public void delete_custom_rule() throws Exception { + MockUserSession.set() + .setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN) + .setLogin("me"); + + // Create template rule + RuleKey templateRuleKey = RuleKey.of("java", "S001"); + dao.insert(dbSession, RuleTesting.newDto(templateRuleKey).setCardinality(Cardinality.MULTIPLE)); + dbSession.commit(); + + // Create custom rule + NewRule newRule = new NewRule() + .setTemplateKey(templateRuleKey) + .setName("My custom") + .setHtmlDescription("Some description") + .setSeverity(Severity.MAJOR) + .setStatus(RuleStatus.READY) + .setParameters(ImmutableMap.of("regex", "a.*")); + RuleKey customRuleKey = service.create(newRule); + + // Delete custom rule + service.delete(customRuleKey); + } + + @Test(expected = UnauthorizedException.class) + public void do_not_delete_if_not_granted() throws Exception { + MockUserSession.set().setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); + + service.delete(RuleKey.of("java", "S001")); } } diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java index 58e7c280e5e..e188fd9c2f0 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java @@ -69,7 +69,7 @@ public class AppActionTest { AppAction app = new AppAction(languages, ruleRepositories, i18n, debtModel, qualityProfileService); WsTester tester = new WsTester(new RulesWebService( mock(SearchAction.class), mock(ShowAction.class), mock(TagsAction.class), mock(CreateAction.class), - app, mock(UpdateAction.class))); + app, mock(UpdateAction.class), mock(DeleteAction.class))); MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN); diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/DeleteActionTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/DeleteActionTest.java new file mode 100644 index 00000000000..d497363eaea --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/DeleteActionTest.java @@ -0,0 +1,56 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.api.rule.RuleKey; +import org.sonar.server.rule.RuleService; +import org.sonar.server.ws.WsTester; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +@RunWith(MockitoJUnitRunner.class) +public class DeleteActionTest { + + WsTester tester; + + @Mock + RuleService ruleService; + + @Before + public void setUp() throws Exception { + tester = new WsTester(new RulesWebService(mock(SearchAction.class), mock(ShowAction.class), mock(TagsAction.class), mock(CreateAction.class), mock(AppAction.class), + mock(UpdateAction.class), new DeleteAction(ruleService))); + } + + @Test + public void delete_custom_rule() throws Exception { + WsTester.TestRequest request = tester.newGetRequest("api/rules", "delete").setParam("key", "squid:XPath_1402065390816"); + request.execute(); + + verify(ruleService).delete(RuleKey.of("squid", "XPath_1402065390816")); + } +} diff --git a/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceTest.java b/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceTest.java index a3ab5339dd5..3e59379a90f 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceTest.java @@ -87,12 +87,13 @@ public class RulesWebServiceTest { WebService.Controller controller = context.controller(API_ENDPOINT); assertThat(controller).isNotNull(); - assertThat(controller.actions()).hasSize(6); + assertThat(controller.actions()).hasSize(7); assertThat(controller.action(API_SEARCH_METHOD)).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("app")).isNotNull(); } -- 2.39.5