From 44eaa37244f20ca311a1a797c961c80706b35251 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 20 Jun 2017 08:35:37 +0200 Subject: [PATCH] SONAR-9442 Send email to profile admin on each qprofile update --- it/it-plugins/foo-plugin-v1/pom.xml | 75 ++++++++ .../src/main/java/org/sonar/foo/Foo.java | 43 +++++ .../main/java/org/sonar/foo/FooPlugin.java | 39 ++++ .../main/java/org/sonar/foo/package-info.java | 23 +++ .../org/sonar/foo/rule/FooBasicProfile.java | 41 ++++ .../sonar/foo/rule/FooRulesDefinition.java | 46 +++++ .../java/org/sonar/foo/rule/package-info.java | 23 +++ it/it-plugins/foo-plugin-v2/pom.xml | 75 ++++++++ .../src/main/java/org/sonar/foo/Foo.java | 43 +++++ .../main/java/org/sonar/foo/FooPlugin.java | 39 ++++ .../main/java/org/sonar/foo/package-info.java | 23 +++ .../org/sonar/foo/rule/FooBasicProfile.java | 42 +++++ .../sonar/foo/rule/FooRulesDefinition.java | 46 +++++ .../java/org/sonar/foo/rule/package-info.java | 23 +++ .../sonar/db/permission/AuthorizationDao.java | 6 + .../db/permission/AuthorizationMapper.java | 2 + .../db/permission/AuthorizationMapper.xml | 18 ++ .../db/permission/AuthorizationDaoTest.java | 47 ++++- .../notification/NotificationModule.java | 13 +- .../notification/ws/NotificationWsModule.java | 34 ++++ .../platformlevel/PlatformLevel4.java | 2 + .../platformlevel/PlatformLevelStartup.java | 9 + .../BuiltInQualityProfilesNotification.java | 41 ++++ ...QualityProfilesNotificationDispatcher.java | 59 ++++++ ...InQualityProfilesNotificationTemplate.java | 42 +++++ .../RegisterQualityProfiles.java | 7 +- .../notification/NotificationModuleTest.java | 2 +- .../ws/NotificationWsModuleTest.java | 34 ++++ ...ityProfilesNotificationDispatcherTest.java | 61 ++++++ .../RegisterQualityProfilesTest.java | 35 +++- tests/plugins/foo-plugin-v1/pom.xml | 75 ++++++++ .../src/main/java/org/sonar/foo/Foo.java | 43 +++++ .../main/java/org/sonar/foo/FooPlugin.java | 39 ++++ .../main/java/org/sonar/foo/package-info.java | 23 +++ .../org/sonar/foo/rule/FooBasicProfile.java | 41 ++++ .../sonar/foo/rule/FooRulesDefinition.java | 46 +++++ .../java/org/sonar/foo/rule/package-info.java | 23 +++ tests/plugins/foo-plugin-v2/pom.xml | 75 ++++++++ .../src/main/java/org/sonar/foo/Foo.java | 43 +++++ .../main/java/org/sonar/foo/FooPlugin.java | 39 ++++ .../main/java/org/sonar/foo/package-info.java | 23 +++ .../org/sonar/foo/rule/FooBasicProfile.java | 42 +++++ .../sonar/foo/rule/FooRulesDefinition.java | 46 +++++ .../java/org/sonar/foo/rule/package-info.java | 23 +++ tests/plugins/pom.xml | 2 + .../org/sonarqube/tests/Category5Suite.java | 8 +- ...uiltInQualityProfilesNotificationTest.java | 176 ++++++++++++++++++ tests/src/test/java/util/ItUtils.java | 2 +- 48 files changed, 1739 insertions(+), 23 deletions(-) create mode 100644 it/it-plugins/foo-plugin-v1/pom.xml create mode 100644 it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/Foo.java create mode 100644 it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/FooPlugin.java create mode 100644 it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/package-info.java create mode 100644 it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooBasicProfile.java create mode 100644 it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java create mode 100644 it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/package-info.java create mode 100644 it/it-plugins/foo-plugin-v2/pom.xml create mode 100644 it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/Foo.java create mode 100644 it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/FooPlugin.java create mode 100644 it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/package-info.java create mode 100644 it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooBasicProfile.java create mode 100644 it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java create mode 100644 it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/package-info.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/notification/ws/NotificationWsModule.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotification.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotificationDispatcher.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotificationTemplate.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/notification/ws/NotificationWsModuleTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotificationDispatcherTest.java create mode 100644 tests/plugins/foo-plugin-v1/pom.xml create mode 100644 tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/Foo.java create mode 100644 tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/FooPlugin.java create mode 100644 tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/package-info.java create mode 100644 tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooBasicProfile.java create mode 100644 tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java create mode 100644 tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/package-info.java create mode 100644 tests/plugins/foo-plugin-v2/pom.xml create mode 100644 tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/Foo.java create mode 100644 tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/FooPlugin.java create mode 100644 tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/package-info.java create mode 100644 tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooBasicProfile.java create mode 100644 tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java create mode 100644 tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/package-info.java create mode 100644 tests/src/test/java/org/sonarqube/tests/qualityProfile/BuiltInQualityProfilesNotificationTest.java diff --git a/it/it-plugins/foo-plugin-v1/pom.xml b/it/it-plugins/foo-plugin-v1/pom.xml new file mode 100644 index 00000000000..e34322baece --- /dev/null +++ b/it/it-plugins/foo-plugin-v1/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + org.sonarsource.sonarqube + sonarqube + 6.5-SNAPSHOT + ../.. + + foo-plugin-v1 + SonarQube :: Plugins :: Foo (V1) + sonar-plugin + Sample of plugin to document and test available APIs + + + true + + + + + com.google.guava + guava + + + commons-io + commons-io + + + commons-lang + commons-lang + + + com.google.code.findbugs + jsr305 + provided + + + org.sonarsource.sonarqube + sonar-plugin-api + provided + + + + + junit + junit + test + + + org.assertj + assertj-core + test + + + org.mockito + mockito-core + test + + + + + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + + foo + Foo + org.sonar.foo.FooPlugin + + + + + diff --git a/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/Foo.java b/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/Foo.java new file mode 100644 index 00000000000..522bc81483d --- /dev/null +++ b/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/Foo.java @@ -0,0 +1,43 @@ +/* + * 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.foo; + +import org.sonar.api.resources.Language; + +public class Foo implements Language { + + public static final String KEY = "foo"; + public static final String NAME = "foo"; + + @Override + public String getKey() { + return KEY; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String[] getFileSuffixes() { + return new String[0]; + } +} diff --git a/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/FooPlugin.java b/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/FooPlugin.java new file mode 100644 index 00000000000..17677e0acb2 --- /dev/null +++ b/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/FooPlugin.java @@ -0,0 +1,39 @@ +/* + * 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.foo; + +import org.sonar.api.Plugin; +import org.sonar.foo.rule.FooBasicProfile; +import org.sonar.foo.rule.FooRulesDefinition; + +/** + * Plugin entry-point, as declared in pom.xml. + */ +public class FooPlugin implements Plugin { + + @Override + public void define(Context context) { + context.addExtensions( + Foo.class, + FooRulesDefinition.class, + FooBasicProfile.class); + } + +} diff --git a/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/package-info.java b/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/package-info.java new file mode 100644 index 00000000000..24613bbdaf7 --- /dev/null +++ b/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.foo; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooBasicProfile.java b/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooBasicProfile.java new file mode 100644 index 00000000000..3a53e9293ff --- /dev/null +++ b/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooBasicProfile.java @@ -0,0 +1,41 @@ +/* + * 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.foo.rule; + +import org.sonar.api.profiles.ProfileDefinition; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.rules.Rule; +import org.sonar.api.utils.ValidationMessages; + +import static org.sonar.api.rules.RulePriority.MAJOR; +import static org.sonar.foo.Foo.KEY; +import static org.sonar.foo.rule.FooRulesDefinition.FOO_REPOSITORY; + +public class FooBasicProfile extends ProfileDefinition { + + @Override + public RulesProfile createProfile(ValidationMessages validation) { + final RulesProfile profile = RulesProfile.create("Basic", KEY); + profile.activateRule(Rule.create(FOO_REPOSITORY, "UnchangedRule"), MAJOR); + profile.activateRule(Rule.create(FOO_REPOSITORY, "ChangedRule"), MAJOR); + profile.activateRule(Rule.create(FOO_REPOSITORY, "RemovedRule"), MAJOR); + return profile; + } +} diff --git a/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java b/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java new file mode 100644 index 00000000000..7257dd72681 --- /dev/null +++ b/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java @@ -0,0 +1,46 @@ +/* + * 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.foo.rule; + +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.foo.Foo; + +public class FooRulesDefinition implements RulesDefinition { + + public static final String FOO_REPOSITORY = "foo"; + + @Override + public void define(Context context) { + defineRulesXoo(context); + } + + private static void defineRulesXoo(Context context) { + NewRepository repo = context.createRepository(FOO_REPOSITORY, Foo.KEY).setName("Foo"); + createRule(repo, "UnchangedRule"); + createRule(repo, "ChangedRule"); + createRule(repo, "RemovedRule"); + repo.done(); + } + + private static NewRule createRule(NewRepository repo, String key) { + return repo.createRule(key).setName(key).setHtmlDescription(key); + } + +} diff --git a/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/package-info.java b/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/package-info.java new file mode 100644 index 00000000000..b3209c8ac96 --- /dev/null +++ b/it/it-plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.foo.rule; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/it/it-plugins/foo-plugin-v2/pom.xml b/it/it-plugins/foo-plugin-v2/pom.xml new file mode 100644 index 00000000000..db2fc2c5916 --- /dev/null +++ b/it/it-plugins/foo-plugin-v2/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + org.sonarsource.sonarqube + sonarqube + 6.5-SNAPSHOT + ../.. + + foo-plugin-v2 + SonarQube :: Plugins :: Foo (V2) + sonar-plugin + Sample of plugin to document and test available APIs + + + true + + + + + com.google.guava + guava + + + commons-io + commons-io + + + commons-lang + commons-lang + + + com.google.code.findbugs + jsr305 + provided + + + org.sonarsource.sonarqube + sonar-plugin-api + provided + + + + + junit + junit + test + + + org.assertj + assertj-core + test + + + org.mockito + mockito-core + test + + + + + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + + foo + Foo + org.sonar.foo.FooPlugin + + + + + diff --git a/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/Foo.java b/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/Foo.java new file mode 100644 index 00000000000..522bc81483d --- /dev/null +++ b/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/Foo.java @@ -0,0 +1,43 @@ +/* + * 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.foo; + +import org.sonar.api.resources.Language; + +public class Foo implements Language { + + public static final String KEY = "foo"; + public static final String NAME = "foo"; + + @Override + public String getKey() { + return KEY; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String[] getFileSuffixes() { + return new String[0]; + } +} diff --git a/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/FooPlugin.java b/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/FooPlugin.java new file mode 100644 index 00000000000..17677e0acb2 --- /dev/null +++ b/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/FooPlugin.java @@ -0,0 +1,39 @@ +/* + * 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.foo; + +import org.sonar.api.Plugin; +import org.sonar.foo.rule.FooBasicProfile; +import org.sonar.foo.rule.FooRulesDefinition; + +/** + * Plugin entry-point, as declared in pom.xml. + */ +public class FooPlugin implements Plugin { + + @Override + public void define(Context context) { + context.addExtensions( + Foo.class, + FooRulesDefinition.class, + FooBasicProfile.class); + } + +} diff --git a/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/package-info.java b/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/package-info.java new file mode 100644 index 00000000000..24613bbdaf7 --- /dev/null +++ b/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.foo; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooBasicProfile.java b/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooBasicProfile.java new file mode 100644 index 00000000000..1c2d051f7cf --- /dev/null +++ b/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooBasicProfile.java @@ -0,0 +1,42 @@ +/* + * 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.foo.rule; + +import org.sonar.api.profiles.ProfileDefinition; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.rules.Rule; +import org.sonar.api.utils.ValidationMessages; + +import static org.sonar.api.rules.RulePriority.MAJOR; +import static org.sonar.api.rules.RulePriority.MINOR; +import static org.sonar.foo.Foo.KEY; +import static org.sonar.foo.rule.FooRulesDefinition.FOO_REPOSITORY; + +public class FooBasicProfile extends ProfileDefinition { + + @Override + public RulesProfile createProfile(ValidationMessages validation) { + final RulesProfile profile = RulesProfile.create("Basic", KEY); + profile.activateRule(Rule.create(FOO_REPOSITORY, "UnchangedRule"), MAJOR); + profile.activateRule(Rule.create(FOO_REPOSITORY, "ChangedRule"), MINOR); + profile.activateRule(Rule.create(FOO_REPOSITORY, "NewRule"), MAJOR); + return profile; + } +} diff --git a/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java b/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java new file mode 100644 index 00000000000..aacc2335262 --- /dev/null +++ b/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java @@ -0,0 +1,46 @@ +/* + * 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.foo.rule; + +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.foo.Foo; + +public class FooRulesDefinition implements RulesDefinition { + + public static final String FOO_REPOSITORY = "foo"; + + @Override + public void define(Context context) { + defineRulesXoo(context); + } + + private static void defineRulesXoo(Context context) { + NewRepository repo = context.createRepository(FOO_REPOSITORY, Foo.KEY).setName("Foo"); + createRule(repo, "UnchangedRule"); + createRule(repo, "ChangedRule"); + createRule(repo, "NewRule"); + repo.done(); + } + + private static NewRule createRule(NewRepository repo, String key) { + return repo.createRule(key).setName(key).setHtmlDescription(key); + } + +} diff --git a/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/package-info.java b/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/package-info.java new file mode 100644 index 00000000000..b3209c8ac96 --- /dev/null +++ b/it/it-plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.foo.rule; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/permission/AuthorizationDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/permission/AuthorizationDao.java index 2e0c94c29af..44afc088c09 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/permission/AuthorizationDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/permission/AuthorizationDao.java @@ -20,6 +20,7 @@ package org.sonar.db.permission; import java.util.Collection; +import java.util.List; import java.util.Set; import javax.annotation.Nullable; import org.sonar.db.Dao; @@ -27,6 +28,7 @@ import org.sonar.db.DbSession; import static org.sonar.db.DatabaseUtils.executeLargeInputs; import static org.sonar.db.DatabaseUtils.executeLargeInputsIntoSet; +import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES; /** * The SQL requests used to verify authorization (the permissions @@ -163,6 +165,10 @@ public class AuthorizationDao implements Dao { partitionSize -> partitionSize / 3); } + public List selectQualityProfileAdministratorLogins(DbSession dbSession) { + return mapper(dbSession).selectQualityProfileAdministratorLogins(ADMINISTER_QUALITY_PROFILES.getKey()); + } + private static AuthorizationMapper mapper(DbSession dbSession) { return dbSession.getMapper(AuthorizationMapper.class); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/permission/AuthorizationMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/permission/AuthorizationMapper.java index e60588cf1bd..5c76c4ea5d4 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/permission/AuthorizationMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/permission/AuthorizationMapper.java @@ -60,4 +60,6 @@ public interface AuthorizationMapper { Set selectProjectPermissions(@Param("projectUuid") String projectUuid, @Param("userId") long userId); Set selectProjectPermissionsOfAnonymous(@Param("projectUuid") String projectUuid); + + List selectQualityProfileAdministratorLogins(@Param("permission") String permission); } diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/permission/AuthorizationMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/permission/AuthorizationMapper.xml index 181292874bb..76dd716a1f5 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/permission/AuthorizationMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/permission/AuthorizationMapper.xml @@ -378,4 +378,22 @@ and p.organization_uuid = gr.organization_uuid and gr.group_id is null + + diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/permission/AuthorizationDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/permission/AuthorizationDaoTest.java index 9ffad60746c..c3a099c4f8a 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/permission/AuthorizationDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/permission/AuthorizationDaoTest.java @@ -46,7 +46,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.core.permission.GlobalPermissions.QUALITY_GATE_ADMIN; import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; +import static org.sonar.db.permission.OrganizationPermission.ADMINISTER; import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_GATES; +import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES; import static org.sonar.db.permission.OrganizationPermission.SCAN; public class AuthorizationDaoTest { @@ -691,7 +693,6 @@ public class AuthorizationDaoTest { users.stream().map(UserDto::getId).collect(Collectors.toSet()), "user", PROJECT_ID)).isEmpty(); } - @Test public void countUsersWithGlobalPermissionExcludingGroupMember() { // u1 has the direct permission, u2 and u3 have the permission through their group @@ -958,6 +959,50 @@ public class AuthorizationDaoTest { .containsOnly(publicProject.uuid()); assertThat(underTest.keepAuthorizedProjectUuids(dbSession, newHashSet(publicProject.uuid()), null, UserRole.ADMIN)) .isEmpty(); + } + + @Test + public void selectQualityProfileAdministratorLogins_return_users_with_quality_profile_administrator_permission() { + OrganizationDto organization1 = db.organizations().insert(); + UserDto user1 = db.users().insertUser(); + db.users().insertPermissionOnUser(organization1, user1, ADMINISTER_QUALITY_PROFILES); + OrganizationDto organization2 = db.organizations().insert(); + UserDto user2 = db.users().insertUser(); + db.users().insertPermissionOnUser(organization2, user2, ADMINISTER_QUALITY_PROFILES); + List logins = underTest.selectQualityProfileAdministratorLogins(dbSession); + + assertThat(logins).containsExactlyInAnyOrder(user1.getLogin(), user2.getLogin()); } + + @Test + public void selectQualityProfileAdministratorLogins_return_users_within_quality_profile_administrator_group() { + OrganizationDto organization1 = db.organizations().insert(); + GroupDto qualityProfileAdministratorGroup1 = db.users().insertGroup(organization1); + db.users().insertPermissionOnGroup(qualityProfileAdministratorGroup1, ADMINISTER_QUALITY_PROFILES); + UserDto user1 = db.users().insertUser(); + db.users().insertMember(qualityProfileAdministratorGroup1, user1); + OrganizationDto organization2 = db.organizations().insert(); + GroupDto qualityProfileAdministratorGroup2 = db.users().insertGroup(organization2); + db.users().insertPermissionOnGroup(qualityProfileAdministratorGroup2, ADMINISTER_QUALITY_PROFILES); + UserDto user2 = db.users().insertUser(); + db.users().insertMember(qualityProfileAdministratorGroup2, user2); + + List logins = underTest.selectQualityProfileAdministratorLogins(dbSession); + + assertThat(logins).containsExactlyInAnyOrder(user1.getLogin(), user2.getLogin()); + } + + @Test + public void selectQualityProfileAdministratorLogins_does_not_return_non_quality_profile_administrator_logins() { + OrganizationDto organization1 = db.organizations().insert(); + UserDto user1 = db.users().insertUser(); + db.users().insertPermissionOnUser(organization1, user1, ADMINISTER); + db.users().insertUser(); + + List logins = underTest.selectQualityProfileAdministratorLogins(dbSession); + + assertThat(logins).isEmpty(); + } + } diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationModule.java b/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationModule.java index a7e88a63c9a..555da5d7249 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationModule.java @@ -21,12 +21,7 @@ package org.sonar.server.notification; import org.sonar.api.config.EmailSettings; import org.sonar.core.platform.Module; -import org.sonar.server.notification.email.AlertsEmailTemplate; import org.sonar.server.notification.email.EmailNotificationChannel; -import org.sonar.server.notification.ws.AddAction; -import org.sonar.server.notification.ws.ListAction; -import org.sonar.server.notification.ws.NotificationsWs; -import org.sonar.server.notification.ws.RemoveAction; public class NotificationModule extends Module { @Override @@ -38,12 +33,6 @@ public class NotificationModule extends Module { NotificationUpdater.class, DefaultNotificationManager.class, NotificationDaemon.class, - AlertsEmailTemplate.class, - EmailNotificationChannel.class, - // WS - NotificationsWs.class, - AddAction.class, - RemoveAction.class, - ListAction.class); + EmailNotificationChannel.class); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/NotificationWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/NotificationWsModule.java new file mode 100644 index 00000000000..968af6912a5 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/NotificationWsModule.java @@ -0,0 +1,34 @@ +/* + * 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.notification.ws; + +import org.sonar.core.platform.Module; + +public class NotificationWsModule extends Module { + @Override + protected void configureModule() { + add( + // WS + NotificationsWs.class, + AddAction.class, + RemoveAction.class, + ListAction.class); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index 8321a4ba0ff..3056d5bdde8 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -84,6 +84,7 @@ import org.sonar.server.metric.CoreCustomMetrics; import org.sonar.server.metric.DefaultMetricFinder; import org.sonar.server.metric.ws.MetricsWsModule; import org.sonar.server.notification.NotificationModule; +import org.sonar.server.notification.ws.NotificationWsModule; import org.sonar.server.organization.BillingValidationsProxyImpl; import org.sonar.server.organization.OrganizationCreationImpl; import org.sonar.server.organization.OrganizationValidationImpl; @@ -434,6 +435,7 @@ public class PlatformLevel4 extends PlatformLevel { // Notifications NotificationModule.class, + NotificationWsModule.class, EmailsWsModule.class, // Tests diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java index d627e3c40ab..39c20db53c7 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java @@ -21,6 +21,7 @@ package org.sonar.server.platform.platformlevel; import org.sonar.server.app.ProcessCommandWrapper; import org.sonar.server.es.IndexerStartupTask; +import org.sonar.server.notification.NotificationModule; import org.sonar.server.organization.DefaultOrganizationEnforcer; import org.sonar.server.platform.ServerLifecycleNotifier; import org.sonar.server.platform.web.RegisterServletFilters; @@ -28,6 +29,9 @@ import org.sonar.server.qualitygate.RegisterQualityGates; import org.sonar.server.qualityprofile.BuiltInQProfileInsertImpl; import org.sonar.server.qualityprofile.BuiltInQProfileLoader; import org.sonar.server.qualityprofile.BuiltInQProfileUpdateImpl; +import org.sonar.server.qualityprofile.BuiltInQualityProfilesNotification; +import org.sonar.server.qualityprofile.BuiltInQualityProfilesNotificationDispatcher; +import org.sonar.server.qualityprofile.BuiltInQualityProfilesNotificationTemplate; import org.sonar.server.qualityprofile.RegisterQualityProfiles; import org.sonar.server.rule.RegisterRules; import org.sonar.server.rule.WebServerRuleFinder; @@ -58,6 +62,11 @@ public class PlatformLevelStartup extends PlatformLevel { RegisterRules.class); add(BuiltInQProfileLoader.class); addIfStartupLeader( + // TODO Should we put it in level 2 ? + NotificationModule.class, + BuiltInQualityProfilesNotificationDispatcher.class, + BuiltInQualityProfilesNotificationTemplate.class, + BuiltInQualityProfilesNotification.class, BuiltInQProfileInsertImpl.class, BuiltInQProfileUpdateImpl.class, RegisterQualityProfiles.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotification.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotification.java new file mode 100644 index 00000000000..cdc2b657748 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotification.java @@ -0,0 +1,41 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.qualityprofile; + +import org.sonar.api.notifications.Notification; +import org.sonar.server.notification.NotificationManager; + +public class BuiltInQualityProfilesNotification { + + static final String BUILT_IN_QUALITY_PROFILES = "built-in-quality-profiles"; + + private final NotificationManager notificationManager; + + public BuiltInQualityProfilesNotification(NotificationManager notificationManager) { + this.notificationManager = notificationManager; + } + + void send() { + notificationManager.scheduleForSending( + new Notification(BUILT_IN_QUALITY_PROFILES) + .setDefaultMessage("This is a test message from SonarQube")); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotificationDispatcher.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotificationDispatcher.java new file mode 100644 index 00000000000..5fab56c976d --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotificationDispatcher.java @@ -0,0 +1,59 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualityprofile; + +import java.util.List; +import org.sonar.api.notifications.Notification; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.server.notification.NotificationDispatcher; +import org.sonar.server.notification.email.EmailNotificationChannel; + +import static org.sonar.server.qualityprofile.BuiltInQualityProfilesNotification.BUILT_IN_QUALITY_PROFILES; + +public class BuiltInQualityProfilesNotificationDispatcher extends NotificationDispatcher { + + public static final String KEY = "BuiltInQP"; + + private final EmailNotificationChannel emailNotificationChannel; + private final DbClient dbClient; + + public BuiltInQualityProfilesNotificationDispatcher(EmailNotificationChannel emailNotificationChannel, DbClient dbClient) { + super(BUILT_IN_QUALITY_PROFILES); + this.emailNotificationChannel = emailNotificationChannel; + this.dbClient = dbClient; + } + + @Override + public String getKey() { + return KEY; + } + + @Override + public void dispatch(Notification notification, Context context) { + getRecipients().forEach(login -> context.addUser(login, emailNotificationChannel)); + } + + private List getRecipients() { + try (DbSession session = dbClient.openSession(false)) { + return dbClient.authorizationDao().selectQualityProfileAdministratorLogins(session); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotificationTemplate.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotificationTemplate.java new file mode 100644 index 00000000000..b15c4f7046f --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotificationTemplate.java @@ -0,0 +1,42 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualityprofile; + +import org.sonar.api.notifications.Notification; +import org.sonar.plugins.emailnotifications.api.EmailMessage; +import org.sonar.plugins.emailnotifications.api.EmailTemplate; + +import static org.sonar.server.qualityprofile.BuiltInQualityProfilesNotification.BUILT_IN_QUALITY_PROFILES; + +public class BuiltInQualityProfilesNotificationTemplate extends EmailTemplate { + + @Override + public EmailMessage format(Notification notification) { + if (!BUILT_IN_QUALITY_PROFILES.equals(notification.getType())) { + return null; + } + // And finally return the email that will be sent + return new EmailMessage() + .setMessageId(BUILT_IN_QUALITY_PROFILES) + .setSubject("empty") + .setMessage("This is a test message from SonarQube"); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RegisterQualityProfiles.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RegisterQualityProfiles.java index c6b9593f13b..89c900f9a10 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RegisterQualityProfiles.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/RegisterQualityProfiles.java @@ -45,13 +45,16 @@ public class RegisterQualityProfiles { private final DbClient dbClient; private final BuiltInQProfileInsert builtInQProfileInsert; private final BuiltInQProfileUpdate builtInQProfileUpdate; + private final BuiltInQualityProfilesNotification builtInQualityProfilesNotification; public RegisterQualityProfiles(BuiltInQProfileRepository builtInQProfileRepository, - DbClient dbClient, BuiltInQProfileInsert builtInQProfileInsert, BuiltInQProfileUpdate builtInQProfileUpdate) { + DbClient dbClient, BuiltInQProfileInsert builtInQProfileInsert, BuiltInQProfileUpdate builtInQProfileUpdate, + BuiltInQualityProfilesNotification builtInQualityProfilesNotification) { this.builtInQProfileRepository = builtInQProfileRepository; this.dbClient = dbClient; this.builtInQProfileInsert = builtInQProfileInsert; this.builtInQProfileUpdate = builtInQProfileUpdate; + this.builtInQualityProfilesNotification = builtInQualityProfilesNotification; } public void start() { @@ -95,6 +98,8 @@ public class RegisterQualityProfiles { LOGGER.info("Update profile {}", builtIn.getQProfileName()); builtInQProfileUpdate.update(dbSession, builtIn, ruleProfile); + + builtInQualityProfilesNotification.send(); } /** diff --git a/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationModuleTest.java index 187df6f7b7b..3c29ccf4822 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationModuleTest.java @@ -29,6 +29,6 @@ public class NotificationModuleTest { public void verify_count_of_added_components() { ComponentContainer container = new ComponentContainer(); new NotificationModule().configure(container); - assertThat(container.size()).isEqualTo(12 + 2); + assertThat(container.size()).isEqualTo(7 + 2); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/notification/ws/NotificationWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/NotificationWsModuleTest.java new file mode 100644 index 00000000000..fe37e926afd --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/NotificationWsModuleTest.java @@ -0,0 +1,34 @@ +/* + * 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.notification.ws; + +import org.junit.Test; +import org.sonar.core.platform.ComponentContainer; + +import static org.assertj.core.api.Assertions.assertThat; + +public class NotificationWsModuleTest { + @Test + public void verify_count_of_added_components() { + ComponentContainer container = new ComponentContainer(); + new NotificationWsModule().configure(container); + assertThat(container.size()).isEqualTo(4 + 2); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotificationDispatcherTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotificationDispatcherTest.java new file mode 100644 index 00000000000..9290e130489 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQualityProfilesNotificationDispatcherTest.java @@ -0,0 +1,61 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.qualityprofile; + +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.notifications.Notification; +import org.sonar.db.DbTester; +import org.sonar.db.permission.OrganizationPermission; +import org.sonar.db.user.UserDto; +import org.sonar.server.notification.NotificationDispatcher.Context; +import org.sonar.server.notification.email.EmailNotificationChannel; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; + +public class BuiltInQualityProfilesNotificationDispatcherTest { + + @Rule + public DbTester dbTester = DbTester.create(); + private Context context = mock(Context.class); + private EmailNotificationChannel channel = mock(EmailNotificationChannel.class); + private BuiltInQualityProfilesNotificationDispatcher underTest = new BuiltInQualityProfilesNotificationDispatcher(channel, dbTester.getDbClient()); + + @Test + public void send_email_to_quality_profile_administrator() { + UserDto profileAdmin = dbTester.users().insertUser(); + dbTester.users().insertPermissionOnUser(profileAdmin, OrganizationPermission.ADMINISTER_QUALITY_PROFILES); + + underTest.dispatch(mock(Notification.class), context); + + verify(context).addUser(profileAdmin.getLogin(), channel); + } + + @Test + public void does_not_send_email_to_user_that_is_not_quality_profile_administrator() { + dbTester.users().insertUser(); + + underTest.dispatch(mock(Notification.class), context); + + verifyZeroInteractions(context); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesTest.java index b8aa907ad31..205b2939863 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/RegisterQualityProfilesTest.java @@ -38,6 +38,9 @@ import org.sonar.server.language.LanguageTesting; import org.sonar.server.tester.UserSessionRule; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.sonar.db.qualityprofile.QualityProfileTesting.newRuleProfileDto; public class RegisterQualityProfilesTest { @@ -58,10 +61,11 @@ public class RegisterQualityProfilesTest { private DbClient dbClient = db.getDbClient(); private DummyBuiltInQProfileInsert insert = new DummyBuiltInQProfileInsert(); private DummyBuiltInQProfileUpdate update = new DummyBuiltInQProfileUpdate(); + private BuiltInQualityProfilesNotification builtInQualityProfilesNotification = mock(BuiltInQualityProfilesNotification.class); private RegisterQualityProfiles underTest = new RegisterQualityProfiles( builtInQProfileRepositoryRule, dbClient, - insert, update); + insert, update, builtInQualityProfilesNotification); @Test public void start_fails_if_BuiltInQProfileRepository_has_not_been_initialized() { @@ -133,15 +137,38 @@ public class RegisterQualityProfilesTest { assertThat(logTester.logs(LoggerLevel.INFO)).contains("Update profile foo/Sonar way"); } + @Test + public void does_not_send_notification_on_new_profile() { + builtInQProfileRepositoryRule.add(FOO_LANGUAGE, "Sonar way"); + builtInQProfileRepositoryRule.initialize(); + + underTest.start(); + + verifyZeroInteractions(builtInQualityProfilesNotification); + } + + @Test + public void send_notification_when_built_in_profile_is_updated() { + RulesProfileDto ruleProfile = newRuleProfileDto(rp -> rp.setIsBuiltIn(true).setName("Sonar way").setLanguage(FOO_LANGUAGE.getKey())); + db.getDbClient().qualityProfileDao().insert(db.getSession(), ruleProfile); + db.commit(); + builtInQProfileRepositoryRule.add(FOO_LANGUAGE, ruleProfile.getName(), false); + builtInQProfileRepositoryRule.initialize(); + + underTest.start(); + + verify(builtInQualityProfilesNotification).send(); + } + private String selectPersistedName(QProfileDto profile) { return db.qualityProfiles().selectByUuid(profile.getKee()).get().getName(); } private void insertRulesProfile(BuiltInQProfile builtIn) { RulesProfileDto dto = newRuleProfileDto(rp -> rp - .setIsBuiltIn(true) - .setLanguage(builtIn.getLanguage()) - .setName(builtIn.getName())); + .setIsBuiltIn(true) + .setLanguage(builtIn.getLanguage()) + .setName(builtIn.getName())); dbClient.qualityProfileDao().insert(db.getSession(), dto); db.commit(); } diff --git a/tests/plugins/foo-plugin-v1/pom.xml b/tests/plugins/foo-plugin-v1/pom.xml new file mode 100644 index 00000000000..e34322baece --- /dev/null +++ b/tests/plugins/foo-plugin-v1/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + org.sonarsource.sonarqube + sonarqube + 6.5-SNAPSHOT + ../.. + + foo-plugin-v1 + SonarQube :: Plugins :: Foo (V1) + sonar-plugin + Sample of plugin to document and test available APIs + + + true + + + + + com.google.guava + guava + + + commons-io + commons-io + + + commons-lang + commons-lang + + + com.google.code.findbugs + jsr305 + provided + + + org.sonarsource.sonarqube + sonar-plugin-api + provided + + + + + junit + junit + test + + + org.assertj + assertj-core + test + + + org.mockito + mockito-core + test + + + + + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + + foo + Foo + org.sonar.foo.FooPlugin + + + + + diff --git a/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/Foo.java b/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/Foo.java new file mode 100644 index 00000000000..522bc81483d --- /dev/null +++ b/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/Foo.java @@ -0,0 +1,43 @@ +/* + * 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.foo; + +import org.sonar.api.resources.Language; + +public class Foo implements Language { + + public static final String KEY = "foo"; + public static final String NAME = "foo"; + + @Override + public String getKey() { + return KEY; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String[] getFileSuffixes() { + return new String[0]; + } +} diff --git a/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/FooPlugin.java b/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/FooPlugin.java new file mode 100644 index 00000000000..17677e0acb2 --- /dev/null +++ b/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/FooPlugin.java @@ -0,0 +1,39 @@ +/* + * 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.foo; + +import org.sonar.api.Plugin; +import org.sonar.foo.rule.FooBasicProfile; +import org.sonar.foo.rule.FooRulesDefinition; + +/** + * Plugin entry-point, as declared in pom.xml. + */ +public class FooPlugin implements Plugin { + + @Override + public void define(Context context) { + context.addExtensions( + Foo.class, + FooRulesDefinition.class, + FooBasicProfile.class); + } + +} diff --git a/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/package-info.java b/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/package-info.java new file mode 100644 index 00000000000..24613bbdaf7 --- /dev/null +++ b/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.foo; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooBasicProfile.java b/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooBasicProfile.java new file mode 100644 index 00000000000..3a53e9293ff --- /dev/null +++ b/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooBasicProfile.java @@ -0,0 +1,41 @@ +/* + * 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.foo.rule; + +import org.sonar.api.profiles.ProfileDefinition; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.rules.Rule; +import org.sonar.api.utils.ValidationMessages; + +import static org.sonar.api.rules.RulePriority.MAJOR; +import static org.sonar.foo.Foo.KEY; +import static org.sonar.foo.rule.FooRulesDefinition.FOO_REPOSITORY; + +public class FooBasicProfile extends ProfileDefinition { + + @Override + public RulesProfile createProfile(ValidationMessages validation) { + final RulesProfile profile = RulesProfile.create("Basic", KEY); + profile.activateRule(Rule.create(FOO_REPOSITORY, "UnchangedRule"), MAJOR); + profile.activateRule(Rule.create(FOO_REPOSITORY, "ChangedRule"), MAJOR); + profile.activateRule(Rule.create(FOO_REPOSITORY, "RemovedRule"), MAJOR); + return profile; + } +} diff --git a/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java b/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java new file mode 100644 index 00000000000..7257dd72681 --- /dev/null +++ b/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java @@ -0,0 +1,46 @@ +/* + * 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.foo.rule; + +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.foo.Foo; + +public class FooRulesDefinition implements RulesDefinition { + + public static final String FOO_REPOSITORY = "foo"; + + @Override + public void define(Context context) { + defineRulesXoo(context); + } + + private static void defineRulesXoo(Context context) { + NewRepository repo = context.createRepository(FOO_REPOSITORY, Foo.KEY).setName("Foo"); + createRule(repo, "UnchangedRule"); + createRule(repo, "ChangedRule"); + createRule(repo, "RemovedRule"); + repo.done(); + } + + private static NewRule createRule(NewRepository repo, String key) { + return repo.createRule(key).setName(key).setHtmlDescription(key); + } + +} diff --git a/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/package-info.java b/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/package-info.java new file mode 100644 index 00000000000..b3209c8ac96 --- /dev/null +++ b/tests/plugins/foo-plugin-v1/src/main/java/org/sonar/foo/rule/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.foo.rule; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/tests/plugins/foo-plugin-v2/pom.xml b/tests/plugins/foo-plugin-v2/pom.xml new file mode 100644 index 00000000000..db2fc2c5916 --- /dev/null +++ b/tests/plugins/foo-plugin-v2/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + org.sonarsource.sonarqube + sonarqube + 6.5-SNAPSHOT + ../.. + + foo-plugin-v2 + SonarQube :: Plugins :: Foo (V2) + sonar-plugin + Sample of plugin to document and test available APIs + + + true + + + + + com.google.guava + guava + + + commons-io + commons-io + + + commons-lang + commons-lang + + + com.google.code.findbugs + jsr305 + provided + + + org.sonarsource.sonarqube + sonar-plugin-api + provided + + + + + junit + junit + test + + + org.assertj + assertj-core + test + + + org.mockito + mockito-core + test + + + + + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + + foo + Foo + org.sonar.foo.FooPlugin + + + + + diff --git a/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/Foo.java b/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/Foo.java new file mode 100644 index 00000000000..522bc81483d --- /dev/null +++ b/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/Foo.java @@ -0,0 +1,43 @@ +/* + * 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.foo; + +import org.sonar.api.resources.Language; + +public class Foo implements Language { + + public static final String KEY = "foo"; + public static final String NAME = "foo"; + + @Override + public String getKey() { + return KEY; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String[] getFileSuffixes() { + return new String[0]; + } +} diff --git a/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/FooPlugin.java b/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/FooPlugin.java new file mode 100644 index 00000000000..17677e0acb2 --- /dev/null +++ b/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/FooPlugin.java @@ -0,0 +1,39 @@ +/* + * 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.foo; + +import org.sonar.api.Plugin; +import org.sonar.foo.rule.FooBasicProfile; +import org.sonar.foo.rule.FooRulesDefinition; + +/** + * Plugin entry-point, as declared in pom.xml. + */ +public class FooPlugin implements Plugin { + + @Override + public void define(Context context) { + context.addExtensions( + Foo.class, + FooRulesDefinition.class, + FooBasicProfile.class); + } + +} diff --git a/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/package-info.java b/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/package-info.java new file mode 100644 index 00000000000..24613bbdaf7 --- /dev/null +++ b/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.foo; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooBasicProfile.java b/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooBasicProfile.java new file mode 100644 index 00000000000..1c2d051f7cf --- /dev/null +++ b/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooBasicProfile.java @@ -0,0 +1,42 @@ +/* + * 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.foo.rule; + +import org.sonar.api.profiles.ProfileDefinition; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.rules.Rule; +import org.sonar.api.utils.ValidationMessages; + +import static org.sonar.api.rules.RulePriority.MAJOR; +import static org.sonar.api.rules.RulePriority.MINOR; +import static org.sonar.foo.Foo.KEY; +import static org.sonar.foo.rule.FooRulesDefinition.FOO_REPOSITORY; + +public class FooBasicProfile extends ProfileDefinition { + + @Override + public RulesProfile createProfile(ValidationMessages validation) { + final RulesProfile profile = RulesProfile.create("Basic", KEY); + profile.activateRule(Rule.create(FOO_REPOSITORY, "UnchangedRule"), MAJOR); + profile.activateRule(Rule.create(FOO_REPOSITORY, "ChangedRule"), MINOR); + profile.activateRule(Rule.create(FOO_REPOSITORY, "NewRule"), MAJOR); + return profile; + } +} diff --git a/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java b/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java new file mode 100644 index 00000000000..aacc2335262 --- /dev/null +++ b/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/FooRulesDefinition.java @@ -0,0 +1,46 @@ +/* + * 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.foo.rule; + +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.foo.Foo; + +public class FooRulesDefinition implements RulesDefinition { + + public static final String FOO_REPOSITORY = "foo"; + + @Override + public void define(Context context) { + defineRulesXoo(context); + } + + private static void defineRulesXoo(Context context) { + NewRepository repo = context.createRepository(FOO_REPOSITORY, Foo.KEY).setName("Foo"); + createRule(repo, "UnchangedRule"); + createRule(repo, "ChangedRule"); + createRule(repo, "NewRule"); + repo.done(); + } + + private static NewRule createRule(NewRepository repo, String key) { + return repo.createRule(key).setName(key).setHtmlDescription(key); + } + +} diff --git a/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/package-info.java b/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/package-info.java new file mode 100644 index 00000000000..b3209c8ac96 --- /dev/null +++ b/tests/plugins/foo-plugin-v2/src/main/java/org/sonar/foo/rule/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.foo.rule; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/tests/plugins/pom.xml b/tests/plugins/pom.xml index 2f41319fe52..e66f838108f 100644 --- a/tests/plugins/pom.xml +++ b/tests/plugins/pom.xml @@ -41,6 +41,8 @@ batch-plugin extension-lifecycle-plugin fake-billing-plugin + foo-plugin-v1 + foo-plugin-v2 global-property-change-plugin issue-filter-plugin l10n-fr-pack diff --git a/tests/src/test/java/org/sonarqube/tests/Category5Suite.java b/tests/src/test/java/org/sonarqube/tests/Category5Suite.java index 283aea49471..5335ef37b3b 100644 --- a/tests/src/test/java/org/sonarqube/tests/Category5Suite.java +++ b/tests/src/test/java/org/sonarqube/tests/Category5Suite.java @@ -19,6 +19,9 @@ */ package org.sonarqube.tests; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.sonarqube.tests.qualityProfile.BuiltInQualityProfilesNotificationTest; import org.sonarqube.tests.serverSystem.ClusterTest; import org.sonarqube.tests.serverSystem.RestartTest; import org.sonarqube.tests.serverSystem.ServerSystemRestartingOrchestrator; @@ -28,8 +31,6 @@ import org.sonarqube.tests.updateCenter.UpdateCenterTest; import org.sonarqube.tests.user.OnboardingTest; import org.sonarqube.tests.user.RealmAuthenticationTest; import org.sonarqube.tests.user.SsoAuthenticationTest; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; /** * This suite is reserved to the tests that start their own instance of Orchestrator. @@ -47,7 +48,8 @@ import org.junit.runners.Suite; UpdateCenterTest.class, RealmAuthenticationTest.class, SsoAuthenticationTest.class, - OnboardingTest.class + OnboardingTest.class, + BuiltInQualityProfilesNotificationTest.class }) public class Category5Suite { diff --git a/tests/src/test/java/org/sonarqube/tests/qualityProfile/BuiltInQualityProfilesNotificationTest.java b/tests/src/test/java/org/sonarqube/tests/qualityProfile/BuiltInQualityProfilesNotificationTest.java new file mode 100644 index 00000000000..9960e8b7c42 --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/qualityProfile/BuiltInQualityProfilesNotificationTest.java @@ -0,0 +1,176 @@ +/* + * 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.sonarqube.tests.qualityProfile; + +import com.sonar.orchestrator.Orchestrator; +import java.io.File; +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sonarqube.ws.WsUsers; +import org.sonarqube.ws.client.PostRequest; +import org.sonarqube.ws.client.WsClient; +import org.sonarqube.ws.client.permission.AddGroupWsRequest; +import org.sonarqube.ws.client.permission.AddUserWsRequest; +import org.subethamail.wiser.Wiser; +import org.subethamail.wiser.WiserMessage; +import util.ItUtils; +import util.user.UserRule; + +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; +import static org.assertj.core.api.Assertions.assertThat; +import static util.ItUtils.pluginArtifact; + +public class BuiltInQualityProfilesNotificationTest { + + private static Orchestrator orchestrator; + private static Wiser smtpServer; + private static UserRule userRule; + + @Before + public void init() throws Exception { + smtpServer = new Wiser(0); + smtpServer.start(); + } + + @After + public void tearDown() throws Exception { + if (orchestrator != null) { + orchestrator.stop(); + } + if (smtpServer != null) { + smtpServer.stop(); + } + } + + @Test + public void does_not_send_mail_if_no_quality_profile_is_updated() throws Exception { + orchestrator = Orchestrator.builderEnv() + .addPlugin(pluginArtifact("foo-plugin-v1")) + .setServerProperty("email.smtp_host.secured", "localhost") + .setServerProperty("email.smtp_port.secured", Integer.toString(smtpServer.getServer().getPort())) + // .setServerProperty("sonar.web.javaAdditionalOpts", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005")// FIXME + // remove web debugging + .build(); + orchestrator.start(); + + userRule = UserRule.from(orchestrator); + + WsUsers.CreateWsResponse.User profileAdmin1 = userRule.generate(); + WsClient wsClient = ItUtils.newAdminWsClient(orchestrator); + wsClient.permissions().addUser(new AddUserWsRequest().setLogin(profileAdmin1.getLogin()).setPermission("profileadmin")); + + WsUsers.CreateWsResponse.User profileAdmin2 = userRule.generate(); + String groupName = randomAlphanumeric(20); + wsClient.wsConnector().call(new PostRequest("api/user_groups/create").setParam("name", groupName)).failIfNotSuccessful(); + wsClient.permissions().addGroup(new AddGroupWsRequest().setPermission("profileadmin").setGroupName(groupName)); + wsClient.wsConnector().call(new PostRequest("api/user_groups/add_user").setParam("name", groupName).setParam("login", profileAdmin2.getLogin())).failIfNotSuccessful(); + + WsUsers.CreateWsResponse.User noProfileAdmin = userRule.generate(); + + orchestrator.restartServer(); + + waitUntilAllNotificationsAreDelivered(1, 10, 100); + assertThat(smtpServer.getMessages()).isEmpty(); + } + + @Test + public void send_mail_if_quality_profile_is_updated() throws Exception { + orchestrator = Orchestrator.builderEnv() + .addPlugin(pluginArtifact("foo-plugin-v1")) + .setServerProperty("email.smtp_host.secured", "localhost") + .setServerProperty("email.smtp_port.secured", Integer.toString(smtpServer.getServer().getPort())) + // .setServerProperty("sonar.web.javaAdditionalOpts", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005")// FIXME + // remove web debugging + .build(); + orchestrator.start(); + + userRule = UserRule.from(orchestrator); + + WsUsers.CreateWsResponse.User profileAdmin1 = userRule.generate(); + WsClient wsClient = ItUtils.newAdminWsClient(orchestrator); + wsClient.permissions().addUser(new AddUserWsRequest().setLogin(profileAdmin1.getLogin()).setPermission("profileadmin")); + + WsUsers.CreateWsResponse.User profileAdmin2 = userRule.generate(); + String groupName = randomAlphanumeric(20); + wsClient.wsConnector().call(new PostRequest("api/user_groups/create").setParam("name", groupName)).failIfNotSuccessful(); + wsClient.permissions().addGroup(new AddGroupWsRequest().setPermission("profileadmin").setGroupName(groupName)); + wsClient.wsConnector().call(new PostRequest("api/user_groups/add_user").setParam("name", groupName).setParam("login", profileAdmin2.getLogin())).failIfNotSuccessful(); + + WsUsers.CreateWsResponse.User noProfileAdmin = userRule.generate(); + + // uninstall plugin V1 + wsClient.wsConnector().call(new PostRequest("api/plugins/uninstall").setParam("key", "foo")).failIfNotSuccessful(); + + // install plugin V2 + File pluginsDir = new File(orchestrator.getServer().getHome() + "/extensions/plugins"); + orchestrator.getConfiguration().fileSystem().copyToDirectory(pluginArtifact("foo-plugin-v2"), pluginsDir); + + orchestrator.restartServer(); + + waitUntilAllNotificationsAreDelivered(2, 10, 1_000); + assertThat(smtpServer.getMessages()) + .extracting(this::getMimeMessage) + .extracting(this::getAllRecipients) + .containsOnly("<" + profileAdmin1.getEmail() + ">", "<" + profileAdmin2.getEmail() + ">"); + assertThat(smtpServer.getMessages()) + .extracting(this::getMimeMessage) + .extracting(this::getContent) + .extracting(m -> m.contains("This is a test message from SonarQube")) + .containsOnly(true); + } + + private MimeMessage getMimeMessage(WiserMessage msg) { + try { + return msg.getMimeMessage(); + } catch (MessagingException e) { + throw new RuntimeException(e); + } + } + + private String getContent(MimeMessage mimeMessage1) { + try { + return mimeMessage1.getContent().toString(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private String getAllRecipients(MimeMessage mimeMessage) { + try { + return mimeMessage.getHeader("To", null); + } catch (MessagingException e) { + throw new RuntimeException(e); + } + } + + private static void waitUntilAllNotificationsAreDelivered(int expectedNumberOfEmails, int pollNumber, int pollMillis) throws InterruptedException { + for (int i = 0; i < pollNumber; i++) { + if (smtpServer.getMessages().size() == expectedNumberOfEmails) { + break; + } + Thread.sleep(pollMillis); + } + } + +} diff --git a/tests/src/test/java/util/ItUtils.java b/tests/src/test/java/util/ItUtils.java index 3ef0d275549..7c41cb2ab34 100644 --- a/tests/src/test/java/util/ItUtils.java +++ b/tests/src/test/java/util/ItUtils.java @@ -146,7 +146,6 @@ public class ItUtils { * Locate the artifact of a fake plugin stored in it/plugins. * * @param dirName the directory of it/plugins, for example "sonar-fake-plugin". - * It assumes that version is 1.0-SNAPSHOT */ public static FileLocation pluginArtifact(String dirName) { return FileLocation.byWildcardMavenFilename(new File("plugins/" + dirName + "/target"), dirName + "-*.jar"); @@ -495,6 +494,7 @@ public class ItUtils { public static void expectMissingError(Runnable runnable) { expectHttpError(404, runnable); } + /** * Missing permissions */ -- 2.39.5