]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-23649 Conditions mismatch notification should be enabled by default for Quality...
authorLéo Geoffroy <leo.geoffroy@sonarsource.com>
Fri, 22 Nov 2024 16:06:53 +0000 (17:06 +0100)
committersonartech <sonartech@sonarsource.com>
Tue, 26 Nov 2024 20:02:51 +0000 (20:02 +0000)
20 files changed:
server/sonar-db-dao/src/it/java/org/sonar/db/property/PropertiesDaoIT.java
server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/property/PropertiesMapper.java
server/sonar-db-dao/src/main/resources/org/sonar/db/property/PropertiesMapper.xml
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/notification/NotificationDbTester.java
server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/QualityGateMetricsUpdateNotificationHandler.java
server/sonar-server-common/src/main/java/org/sonar/server/notification/DefaultNotificationManager.java
server/sonar-server-common/src/main/java/org/sonar/server/notification/NotificationDispatcherMetadata.java
server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/QualityGateMetricsUpdateNotificationHandlerTest.java
server/sonar-server-common/src/test/java/org/sonar/server/notification/DefaultNotificationManagerTest.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/notification/ws/AddActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/notification/ws/ListActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/notification/ws/RemoveActionIT.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/notification/ws/Dispatchers.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/notification/ws/DispatchersImpl.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/notification/ws/ListAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/notification/ws/NotificationCenter.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/notification/ws/NotificationUpdater.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/notification/ws/DispatchersImplTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/notification/ws/NotificationCenterTest.java

index 67da5d6523a9902ee89c67e581afbbf5b860cae3..6e2b57f5ad4e9aeb6f3a8049f2de258b6ff9d913 100644 (file)
@@ -36,13 +36,13 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.MethodSource;
 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
-import org.sonar.db.component.ComponentQualifiers;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.EmailSubscriberDto;
 import org.sonar.db.audit.AuditPersister;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentQualifiers;
 import org.sonar.db.portfolio.PortfolioDto;
 import org.sonar.db.project.ProjectDto;
 import org.sonar.db.user.UserDto;
@@ -94,7 +94,6 @@ class PropertiesDaoIT {
     String projectKey = secure().nextAlphabetic(4);
     String projectName = secure().nextAlphabetic(4);
 
-
     // global subscription
     insertProperty("notification.DispatcherWithGlobalSubscribers.Email", "true", null,
       user2.getUuid(), user2.getLogin(), null, null);
@@ -126,10 +125,10 @@ class PropertiesDaoIT {
     // Global + Project subscribers
     assertThat(underTest.hasProjectNotificationSubscribersForDispatchers(projectUuid, singletonList(
       "DispatcherWithGlobalAndProjectSubscribers")))
-      .isTrue();
+        .isTrue();
     assertThat(underTest.hasProjectNotificationSubscribersForDispatchers("PROJECT_B", singletonList(
       "DispatcherWithGlobalAndProjectSubscribers")))
-      .isTrue();
+        .isTrue();
   }
 
   @Test
@@ -139,7 +138,7 @@ class PropertiesDaoIT {
     String channelKey = secure().nextAlphabetic(6);
     String projectKey = secure().nextAlphabetic(7);
 
-    Set<EmailSubscriberDto> subscribers = underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey,
+    Set<EmailSubscriberDto> subscribers = underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey,
       projectKey);
 
     assertThat(subscribers).isEmpty();
@@ -153,14 +152,14 @@ class PropertiesDaoIT {
     String projectKey = secure().nextAlphabetic(7);
     Set<String> logins = of("user1", "user2");
 
-    Set<EmailSubscriberDto> subscribers = underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey,
+    Set<EmailSubscriberDto> subscribers = underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey,
       projectKey, logins);
 
     assertThat(subscribers).isEmpty();
   }
 
   @Test
-  void findEmailRecipientsForNotification_finds_only_globally_subscribed_users_if_projectKey_is_null() {
+  void findEnabledEmailSubscribersForNotification_finds_only_globally_subscribed_users_if_projectKey_is_null() {
     UserDto user1 = db.users().insertUser(withEmail("user1"));
     UserDto user2 = db.users().insertUser(withEmail("user2"));
     UserDto user3 = db.users().insertUser(withEmail("user3"));
@@ -185,19 +184,19 @@ class PropertiesDaoIT {
     insertProperty(propertyKeyOf(dispatcherKey, channelKey), "false", project.getUuid(), user4.getUuid(), user4.getLogin(),
       project.getKey(), project.getName());
 
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null))
       .containsOnly(EmailSubscriberDto.create("user1", true, emailOf("user1")), EmailSubscriberDto.create("user2", true, emailOf("user2")));
 
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, otherChannelKey, null))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, otherChannelKey, null))
       .isEmpty();
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), otherDispatcherKey, channelKey, null))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), otherDispatcherKey, channelKey, null))
       .isEmpty();
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), channelKey, dispatcherKey, null))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), channelKey, dispatcherKey, null))
       .isEmpty();
   }
 
   @Test
-  void findEmailRecipientsForNotification_with_logins_finds_only_globally_subscribed_specified_users_if_projectKey_is_null() {
+  void findEnabledEmailSubscribersForNotification_with_logins_finds_only_globally_subscribed_specified_users_if_projectKey_is_null() {
     UserDto user1 = db.users().insertUser(withEmail("user1"));
     UserDto user2 = db.users().insertUser(withEmail("user2"));
     UserDto user3 = db.users().insertUser(withEmail("user3"));
@@ -223,22 +222,22 @@ class PropertiesDaoIT {
       project.getKey(), project.getName());
     Set<String> allLogins = of("user1", "user2", "user3", "user4");
 
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, allLogins))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, allLogins))
       .containsOnly(EmailSubscriberDto.create("user1", true, emailOf("user1")), EmailSubscriberDto.create("user2", true, emailOf("user2")));
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, of("user1", "user2")))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, of("user1", "user2")))
       .containsOnly(EmailSubscriberDto.create("user1", true, emailOf("user1")), EmailSubscriberDto.create("user2", true, emailOf("user2")));
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, of("user2")))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, of("user2")))
       .containsOnly(EmailSubscriberDto.create("user2", true, emailOf("user2")));
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, of("user1")))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, of("user1")))
       .containsOnly(EmailSubscriberDto.create("user1", true, emailOf("user1")));
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, of()))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, of()))
       .isEmpty();
 
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, otherChannelKey, null, allLogins))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, otherChannelKey, null, allLogins))
       .isEmpty();
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), otherDispatcherKey, channelKey, null, allLogins))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), otherDispatcherKey, channelKey, null, allLogins))
       .isEmpty();
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), channelKey, dispatcherKey, null, allLogins))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), channelKey, dispatcherKey, null, allLogins))
       .isEmpty();
   }
 
@@ -271,7 +270,7 @@ class PropertiesDaoIT {
   }
 
   @Test
-  void findEmailRecipientsForNotification_finds_global_and_project_subscribed_users_when_projectKey_is_non_null() {
+  void findEnabledEmailSubscribersForNotification_finds_global_and_project_subscribed_users_when_projectKey_is_non_null() {
     UserDto user1 = db.users().insertUser(withEmail("user1"));
     UserDto user2 = db.users().insertUser(withEmail("user2"));
     UserDto user3 = db.users().insertUser(withEmail("user3"));
@@ -298,24 +297,24 @@ class PropertiesDaoIT {
     insertProperty(propertyKeyOf(dispatcherKey, channelKey), "false", project.getUuid(), user4.getUuid(), user4.getLogin(),
       project.getKey(), project.getName());
 
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey))
       .containsOnly(
         EmailSubscriberDto.create("user1", true, emailOf("user1")),
         EmailSubscriberDto.create("user2", true, emailOf("user2")), EmailSubscriberDto.create("user2", false, "user2@foo"),
         EmailSubscriberDto.create("user3", false, emailOf("user3")));
 
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, otherProjectKey))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, otherProjectKey))
       .containsOnly(
         EmailSubscriberDto.create("user1", true, emailOf("user1")),
         EmailSubscriberDto.create("user2", true, emailOf("user2")));
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, otherChannelKey, otherProjectKey))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, otherChannelKey, otherProjectKey))
       .isEmpty();
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), otherDispatcherKey, channelKey, otherProjectKey))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), otherDispatcherKey, channelKey, otherProjectKey))
       .isEmpty();
   }
 
   @Test
-  void findEmailRecipientsForNotification_with_logins_finds_global_and_project_subscribed_specified_users_when_projectKey_is_non_null() {
+  void findEnabledEmailSubscribersForNotification_with_logins_finds_global_and_project_subscribed_specified_users_when_projectKey_is_non_null() {
     UserDto user1 = db.users().insertUser(withEmail("user1"));
     UserDto user2 = db.users().insertUser(withEmail("user2"));
     UserDto user3 = db.users().insertUser(withEmail("user3"));
@@ -343,38 +342,58 @@ class PropertiesDaoIT {
       project.getKey(), project.getName());
     Set<String> allLogins = of("user1", "user2", "user3", "user4");
 
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, allLogins))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, allLogins))
       .containsOnly(
         EmailSubscriberDto.create("user1", true, emailOf("user1")),
         EmailSubscriberDto.create("user2", true, emailOf("user2")), EmailSubscriberDto.create("user2", false, "user2@foo"),
         EmailSubscriberDto.create("user3", false, emailOf("user3")));
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of("user1")))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of("user1")))
       .containsOnly(
         EmailSubscriberDto.create("user1", true, emailOf("user1")));
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of("user2")))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of("user2")))
       .containsOnly(
         EmailSubscriberDto.create("user2", true, emailOf("user2")), EmailSubscriberDto.create("user2", false, "user2@foo"));
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of("user3")))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of("user3")))
       .containsOnly(EmailSubscriberDto.create("user3", false, emailOf("user3")));
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of()))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of()))
       .isEmpty();
 
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, otherProjectKey, allLogins))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, otherProjectKey, allLogins))
       .containsOnly(
         EmailSubscriberDto.create("user1", true, emailOf("user1")),
         EmailSubscriberDto.create("user2", true, emailOf("user2")));
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, otherChannelKey, otherProjectKey, allLogins))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, otherChannelKey, otherProjectKey, allLogins))
       .isEmpty();
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), otherDispatcherKey, channelKey, otherProjectKey, allLogins))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), otherDispatcherKey, channelKey, otherProjectKey, allLogins))
       .isEmpty();
   }
 
   @Test
-  void findEmailRecipientsForNotification_ignores_subscribed_users_without_email() {
+  void findDisabledEmailSubscribersForNotification_shouldReturnDisabledNotificationForUser() {
+    UserDto user1 = db.users().insertUser(withEmail("user1"));
+    UserDto user2 = db.users().insertUser(withEmail("user2"));
+    String projectKey = secure().nextAlphabetic(3);
+    insertPrivateProject(projectKey);
+    String dispatcherKey = secure().nextAlphabetic(4);
+    String channelKey = secure().nextAlphabetic(5);
+    // user1 and user2 subscribed on project and globally
+    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "false", null, user1.getUuid(), user1.getLogin(),
+      null, null);
+    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, user2.getUuid(), user2.getLogin(),
+      null, null);
+
+    assertThat(underTest.findDisabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, of("user1", "user2")))
+      .containsOnly(
+        EmailSubscriberDto.create("user1", true, emailOf("user1")));
+  }
+
+  @Test
+  void findEnabledEmailSubscribersForNotification_with_logins_ignores_subscribed_users_without_email() {
     UserDto user1 = db.users().insertUser(withEmail("user1"));
     UserDto user2 = db.users().insertUser(noEmail("user2"));
     UserDto user3 = db.users().insertUser(withEmail("user3"));
     UserDto user4 = db.users().insertUser(noEmail("user4"));
+    Set<String> allLogins = of("user1", "user2", "user3");
     String projectKey = secure().nextAlphabetic(3);
     ProjectDto project = insertPrivateProject(projectKey);
     String dispatcherKey = secure().nextAlphabetic(4);
@@ -385,27 +404,27 @@ class PropertiesDaoIT {
     insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", project.getUuid(), user1.getUuid(), user1.getLogin(),
       project.getKey(), project.getName());
     insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, user2.getUuid(), user2.getLogin(),
-      null, null);
+      project.getKey(), null);
     insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", project.getUuid(), user2.getUuid(), user2.getLogin(),
       project.getKey(), project.getName());
     // user3 and user4 subscribed only globally
     insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, user3.getUuid(), user3.getLogin(),
-      null, null);
+      project.getKey(), null);
     insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, user4.getUuid(), user4.getLogin(),
       null, null);
 
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, allLogins))
       .containsOnly(
         EmailSubscriberDto.create("user1", true, emailOf("user1")), EmailSubscriberDto.create("user1", false, emailOf("user1")),
         EmailSubscriberDto.create("user3", true, emailOf("user3")));
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null))
+    assertThat(underTest.findEnabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, allLogins))
       .containsOnly(
         EmailSubscriberDto.create("user1", true, emailOf("user1")),
         EmailSubscriberDto.create("user3", true, emailOf("user3")));
   }
 
   @Test
-  void findEmailRecipientsForNotification_with_logins_ignores_subscribed_users_without_email() {
+  void findDisabledEmailSubscribersForNotification_() {
     UserDto user1 = db.users().insertUser(withEmail("user1"));
     UserDto user2 = db.users().insertUser(noEmail("user2"));
     UserDto user3 = db.users().insertUser(withEmail("user3"));
@@ -416,25 +435,25 @@ class PropertiesDaoIT {
     String dispatcherKey = secure().nextAlphabetic(4);
     String channelKey = secure().nextAlphabetic(5);
     // user1 and user2 subscribed on project and globally
-    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, user1.getUuid(), user1.getLogin(),
+    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "false", null, user1.getUuid(), user1.getLogin(),
       null, null);
-    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", project.getUuid(), user1.getUuid(), user1.getLogin(),
+    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "false", project.getUuid(), user1.getUuid(), user1.getLogin(),
       project.getKey(), project.getName());
-    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, user2.getUuid(), user2.getLogin(),
+    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "false", null, user2.getUuid(), user2.getLogin(),
       project.getKey(), null);
-    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", project.getUuid(), user2.getUuid(), user2.getLogin(),
+    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "false", project.getUuid(), user2.getUuid(), user2.getLogin(),
       project.getKey(), project.getName());
     // user3 and user4 subscribed only globally
-    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, user3.getUuid(), user3.getLogin(),
+    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "false", null, user3.getUuid(), user3.getLogin(),
       project.getKey(), null);
-    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "true", null, user4.getUuid(), user4.getLogin(),
+    insertProperty(propertyKeyOf(dispatcherKey, channelKey), "false", null, user4.getUuid(), user4.getLogin(),
       null, null);
 
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, allLogins))
+    assertThat(underTest.findDisabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, projectKey, allLogins))
       .containsOnly(
         EmailSubscriberDto.create("user1", true, emailOf("user1")), EmailSubscriberDto.create("user1", false, emailOf("user1")),
         EmailSubscriberDto.create("user3", true, emailOf("user3")));
-    assertThat(underTest.findEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, allLogins))
+    assertThat(underTest.findDisabledEmailSubscribersForNotification(db.getSession(), dispatcherKey, channelKey, null, allLogins))
       .containsOnly(
         EmailSubscriberDto.create("user1", true, emailOf("user1")),
         EmailSubscriberDto.create("user3", true, emailOf("user3")));
@@ -517,7 +536,7 @@ class PropertiesDaoIT {
   }
 
   private static Object[][] allValuesForSelect() {
-    return new Object[][]{
+    return new Object[][] {
       {null, ""},
       {"", ""},
       {"some value", "some value"},
@@ -622,10 +641,10 @@ class PropertiesDaoIT {
         tuple(key, project2.getUuid()));
     assertThat(underTest.selectPropertiesByKeysAndEntityUuids(session, newHashSet(key, anotherKey), newHashSet(project.getUuid(),
       project2.getUuid())))
-      .extracting(PropertyDto::getKey, PropertyDto::getEntityUuid).containsOnly(
-        tuple(key, project.getUuid()),
-        tuple(key, project2.getUuid()),
-        tuple(anotherKey, project2.getUuid()));
+        .extracting(PropertyDto::getKey, PropertyDto::getEntityUuid).containsOnly(
+          tuple(key, project.getUuid()),
+          tuple(key, project2.getUuid()),
+          tuple(anotherKey, project2.getUuid()));
 
     assertThat(underTest.selectPropertiesByKeysAndEntityUuids(session, newHashSet("unknown"), newHashSet(project.getUuid()))).isEmpty();
     assertThat(underTest.selectPropertiesByKeysAndEntityUuids(session, newHashSet("key"), newHashSet("uuid123456789"))).isEmpty();
@@ -830,7 +849,7 @@ class PropertiesDaoIT {
   }
 
   static Object[][] valueUpdatesDataProvider() {
-    return new Object[][]{
+    return new Object[][] {
       {null, null},
       {null, ""},
       {null, "some value"},
@@ -915,8 +934,8 @@ class PropertiesDaoIT {
 
     assertThat(db.select("select prop_key as \"key\", text_value as \"value\", entity_uuid as \"projectUuid\", user_uuid as \"userUuid\" " +
       "from properties"))
-      .extracting((row) -> row.get("key"), (row) -> row.get("value"), (row) -> row.get("projectUuid"), (row) -> row.get("userUuid"))
-      .containsOnly(tuple("KEY", "ANOTHER_VALUE", null, null), tuple("ANOTHER_KEY", "VALUE", project.uuid(), "100"));
+        .extracting((row) -> row.get("key"), (row) -> row.get("value"), (row) -> row.get("projectUuid"), (row) -> row.get("userUuid"))
+        .containsOnly(tuple("KEY", "ANOTHER_VALUE", null, null), tuple("ANOTHER_KEY", "VALUE", project.uuid(), "100"));
   }
 
   private static Map<String, String> mapOf(String... values) {
index e921e12bab345f3fc3642e086acee6433aec1e5d..4db1a4cda5cd4fa85284a914a7b3852c7d11413b 100644 (file)
@@ -63,13 +63,24 @@ public class PropertiesDao implements Dao {
     this.auditPersister = auditPersister;
   }
 
-  public Set<EmailSubscriberDto> findEmailSubscribersForNotification(DbSession dbSession, String notificationDispatcherKey, String notificationChannelKey,
+  public Set<EmailSubscriberDto> findEnabledEmailSubscribersForNotification(DbSession dbSession, String notificationDispatcherKey, String notificationChannelKey,
     @Nullable String projectKey) {
-    return getMapper(dbSession).findEmailRecipientsForNotification(NOTIFICATION_PREFIX + notificationDispatcherKey + "." + notificationChannelKey, projectKey, null);
+    return getMapper(dbSession).findEmailRecipientsForNotification(NOTIFICATION_PREFIX + notificationDispatcherKey + "." + notificationChannelKey, projectKey, null,
+      Boolean.toString(true));
   }
 
-  public Set<EmailSubscriberDto> findEmailSubscribersForNotification(DbSession dbSession, String notificationDispatcherKey, String notificationChannelKey,
+  public Set<EmailSubscriberDto> findEnabledEmailSubscribersForNotification(DbSession dbSession, String notificationDispatcherKey, String notificationChannelKey,
+    @Nullable String projectKey, Set<String> logins) {
+    return findEmailSubscribersForNotification(dbSession, notificationDispatcherKey, notificationChannelKey, projectKey, logins, true);
+  }
+
+  public Set<EmailSubscriberDto> findDisabledEmailSubscribersForNotification(DbSession dbSession, String notificationDispatcherKey, String notificationChannelKey,
     @Nullable String projectKey, Set<String> logins) {
+    return findEmailSubscribersForNotification(dbSession, notificationDispatcherKey, notificationChannelKey, projectKey, logins, false);
+  }
+
+  public Set<EmailSubscriberDto> findEmailSubscribersForNotification(DbSession dbSession, String notificationDispatcherKey, String notificationChannelKey,
+    @Nullable String projectKey, Set<String> logins, boolean enabled) {
     if (logins.isEmpty()) {
       return Collections.emptySet();
     }
@@ -78,7 +89,7 @@ public class PropertiesDao implements Dao {
       logins,
       loginsPartition -> {
         String notificationKey = NOTIFICATION_PREFIX + notificationDispatcherKey + "." + notificationChannelKey;
-        return getMapper(dbSession).findEmailRecipientsForNotification(notificationKey, projectKey, loginsPartition);
+        return getMapper(dbSession).findEmailRecipientsForNotification(notificationKey, projectKey, loginsPartition, Boolean.toString(enabled));
       },
       partitionSize -> projectKey == null ? partitionSize : (partitionSize / 2));
   }
index e5a17a9a846350c31f2323ec1252ea3ddcefe057..6689fe4f62cc0aa3e200cf828fca02172f542c6a 100644 (file)
@@ -28,7 +28,7 @@ import org.sonar.db.EmailSubscriberDto;
 public interface PropertiesMapper {
 
   Set<EmailSubscriberDto> findEmailRecipientsForNotification(@Param("notifKey") String notificationKey, @Nullable @Param("projectKey") String projectKey,
-    @Nullable @Param("logins") List<String> logins);
+    @Nullable @Param("logins") List<String> logins, @Param("notifValue") String notificationValue);
 
   List<PropertyDto> selectGlobalProperties();
 
index a430fb9253a8dd469706d6b5ae7658e11405836b..110d99e50e3250477e9431f2fa3ff18521b4272a 100644 (file)
@@ -13,7 +13,7 @@
     INNER JOIN properties p ON
       p.user_uuid = u.uuid
       and p.prop_key = #{notifKey,jdbcType=VARCHAR}
-      and p.text_value = 'true'
+      and p.text_value = #{notifValue,jdbcType=VARCHAR}
       and p.entity_uuid IS NULL
     WHERE
       u.email is not null
@@ -35,7 +35,7 @@
       INNER JOIN properties p ON
         p.user_uuid = u.uuid
         and p.prop_key = #{notifKey,jdbcType=VARCHAR}
-        and p.text_value = 'true'
+        and p.text_value = #{notifValue,jdbcType=VARCHAR}
         and p.entity_uuid = proj.uuid
       WHERE
         u.email is not null
index 3db9b97f1e5026dce7eb47e10da526d3e12cec34..ecd58371e511dbe82945a2fbd7df38fd041b9518 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.db.notification;
 import java.util.List;
 import javax.annotation.Nullable;
 import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.project.ProjectDto;
 import org.sonar.db.property.PropertyDto;
@@ -41,16 +40,16 @@ public class NotificationDbTester {
     this.db = db;
   }
 
-  public void assertExists(String channel, String dispatcher, String userUuid, @Nullable ProjectDto project) {
+  public void assertExists(String channel, String dispatcher, String userUuid, @Nullable ProjectDto project, boolean enabled) {
     List<PropertyDto> result = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder()
-        .setKey(String.join(".", PROP_NOTIFICATION_PREFIX, dispatcher, channel))
-        .setEntityUuid(project == null ? null : project.getUuid())
-        .setUserUuid(userUuid)
-        .build(), db.getSession()).stream()
+      .setKey(String.join(".", PROP_NOTIFICATION_PREFIX, dispatcher, channel))
+      .setEntityUuid(project == null ? null : project.getUuid())
+      .setUserUuid(userUuid)
+      .build(), db.getSession()).stream()
       .filter(prop -> project == null ? prop.getEntityUuid() == null : prop.getEntityUuid() != null)
       .toList();
     assertThat(result).hasSize(1);
-    assertThat(result.get(0).getValue()).isEqualTo("true");
+    assertThat(result.get(0).getValue()).isEqualTo(Boolean.toString(enabled));
   }
 
   public void assertDoesNotExist(String channel, String dispatcher, String userUuid, @Nullable ProjectDto project) {
index 8508662fddbf9f0c7159644ccb5579400529975d..ffd0bae69fee2339069698bf9aa7c6d525030866 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Set;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.EmailSubscriberDto;
+import org.sonar.db.permission.GlobalPermission;
 import org.sonar.server.notification.EmailNotificationHandler;
 import org.sonar.server.notification.NotificationDispatcherMetadata;
 import org.sonar.server.notification.email.EmailNotificationChannel;
@@ -35,7 +36,9 @@ public class QualityGateMetricsUpdateNotificationHandler extends EmailNotificati
   static final String KEY = "QualityGateConditionsMismatch";
   private static final NotificationDispatcherMetadata METADATA = NotificationDispatcherMetadata.create(KEY)
     .setProperty(NotificationDispatcherMetadata.GLOBAL_NOTIFICATION, String.valueOf(true))
-    .setProperty(NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION, String.valueOf(false));
+    .setProperty(NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION, String.valueOf(false))
+    .setProperty(NotificationDispatcherMetadata.ENABLED_BY_DEFAULT_NOTIFICATION, String.valueOf(true))
+    .setProperty(NotificationDispatcherMetadata.PERMISSION_RESTRICTION, GlobalPermission.ADMINISTER_QUALITY_GATES.getKey());
 
   private final DbClient dbClient;
 
@@ -48,21 +51,24 @@ public class QualityGateMetricsUpdateNotificationHandler extends EmailNotificati
   protected Set<EmailNotificationChannel.EmailDeliveryRequest> toEmailDeliveryRequests(Collection<QualityGateMetricsUpdateNotification> notifications) {
     try (DbSession session = dbClient.openSession(false)) {
 
-      Set<String> logins = dbClient.authorizationDao()
-        .selectQualityGateAdministratorLogins(session).stream()
-        .map(EmailSubscriberDto::getLogin)
-        .collect(toSet());
+      Set<EmailSubscriberDto> subscriptions = dbClient.authorizationDao()
+        .selectQualityGateAdministratorLogins(session);
 
-      if (logins.isEmpty()) {
+      if (subscriptions.isEmpty()) {
         return Set.of();
       }
 
-      Set<EmailSubscriberDto> emailSubscribers = dbClient.propertiesDao().findEmailSubscribersForNotification(
-        session, KEY, EmailNotificationChannel.class.getSimpleName(), null, logins);
+      Set<String> disabledLogins = dbClient.propertiesDao().findDisabledEmailSubscribersForNotification(
+        session, KEY, EmailNotificationChannel.class.getSimpleName(), null,
+        subscriptions.stream().map(EmailSubscriberDto::getLogin).collect(toSet()))
+        .stream()
+        .map(EmailSubscriberDto::getLogin)
+        .collect(toSet());
 
-      return emailSubscribers
+      return subscriptions
         .stream()
-        .flatMap(t -> notifications.stream().map(notification -> new EmailNotificationChannel.EmailDeliveryRequest(t.getEmail(), notification)))
+        .filter(s -> !disabledLogins.contains(s.getLogin()))
+        .flatMap(s -> notifications.stream().map(notification -> new EmailNotificationChannel.EmailDeliveryRequest(s.getEmail(), notification)))
         .collect(toSet());
     }
   }
index 191c2ff3eb2f4155d483cb274a84d0702e7bd151..50e4a7f9f76090ffbe5ec7e5638de37e0429ea7d 100644 (file)
@@ -115,7 +115,7 @@ public class DefaultNotificationManager implements NotificationManager {
     verifyProjectKey(projectKey);
 
     try (DbSession dbSession = dbClient.openSession(false)) {
-      Set<EmailSubscriberDto> emailSubscribers = dbClient.propertiesDao().findEmailSubscribersForNotification(
+      Set<EmailSubscriberDto> emailSubscribers = dbClient.propertiesDao().findEnabledEmailSubscribersForNotification(
         dbSession, dispatcherKey, EmailNotificationChannel.class.getSimpleName(), projectKey);
 
       return keepAuthorizedEmailSubscribers(dbSession, projectKey, subscriberPermissionsOnProject, emailSubscribers);
@@ -132,7 +132,7 @@ public class DefaultNotificationManager implements NotificationManager {
     }
 
     try (DbSession dbSession = dbClient.openSession(false)) {
-      Set<EmailSubscriberDto> emailSubscribers = dbClient.propertiesDao().findEmailSubscribersForNotification(
+      Set<EmailSubscriberDto> emailSubscribers = dbClient.propertiesDao().findEnabledEmailSubscribersForNotification(
         dbSession, dispatcherKey, EmailNotificationChannel.class.getSimpleName(), projectKey, logins);
 
       return keepAuthorizedEmailSubscribers(dbSession, projectKey, subscriberPermissionsOnProject, emailSubscribers);
index a087d3490703d6db7a7c7e75f38cfab7bff236c6..5bc5afe88ce12fcd3ae6e778b65b70e696c65c10 100644 (file)
@@ -37,6 +37,8 @@ public final class NotificationDispatcherMetadata {
 
   public static final String GLOBAL_NOTIFICATION = "globalNotification";
   public static final String PER_PROJECT_NOTIFICATION = "perProjectNotification";
+  public static final String ENABLED_BY_DEFAULT_NOTIFICATION = "enabledByDefaultNotification";
+  public static final String PERMISSION_RESTRICTION = "permissionRestriction";
 
   private String dispatcherKey;
   private Map<String, String> properties;
index bb691f638dd253cf77112e1d13f35a90f434fa04..305bb9b4aebd29a27cf066a16233edd3a85cb036 100644 (file)
@@ -60,8 +60,10 @@ class QualityGateMetricsUpdateNotificationHandlerTest {
     when(authorizationDao.selectQualityGateAdministratorLogins(dbSession))
       .thenReturn(Set.of(new EmailSubscriberDto().setLogin("login1").setEmail("email@email.com"), new EmailSubscriberDto().setLogin("login2").setEmail("email2@email.com")));
 
-    when(propertiesDao.findEmailSubscribersForNotification(eq(dbSession), eq(QualityGateMetricsUpdateNotificationHandler.KEY), any(), isNull(), eq(Set.of("login1", "login2"))))
-      .thenReturn(Set.of(new EmailSubscriberDto().setLogin("login1").setEmail("email@email.com"), new EmailSubscriberDto().setLogin("login2").setEmail("email2@email.com")));
+    when(
+      propertiesDao.findDisabledEmailSubscribersForNotification(eq(dbSession), eq(QualityGateMetricsUpdateNotificationHandler.KEY), any(), isNull(),
+        eq(Set.of("login1", "login2"))))
+          .thenReturn(Set.of());
 
     Assertions.assertThat(underTest.toEmailDeliveryRequests(List.of(new QualityGateMetricsUpdateNotification(true))))
       .extracting(EmailNotificationChannel.EmailDeliveryRequest::recipientEmail, EmailNotificationChannel.EmailDeliveryRequest::notification)
@@ -70,12 +72,12 @@ class QualityGateMetricsUpdateNotificationHandlerTest {
   }
 
   @Test
-  void toEmailDeliveryRequests_whenHasAdminsButNotSubscribed_shouldNotSendExpectedNotification() {
+  void toEmailDeliveryRequests_whenHasAdminsButHasUnsubscribe_shouldNotSendExpectedNotification() {
     when(authorizationDao.selectQualityGateAdministratorLogins(dbSession))
       .thenReturn(Set.of(new EmailSubscriberDto().setLogin("login1").setEmail("email@email.com")));
 
-    when(propertiesDao.findEmailSubscribersForNotification(eq(dbSession), eq(QualityGateMetricsUpdateNotificationHandler.KEY), any(), isNull(), eq(Set.of("login1"))))
-      .thenReturn(Set.of());
+    when(propertiesDao.findDisabledEmailSubscribersForNotification(eq(dbSession), eq(QualityGateMetricsUpdateNotificationHandler.KEY), any(), isNull(), eq(Set.of("login1"))))
+      .thenReturn(Set.of(new EmailSubscriberDto().setLogin("login1").setEmail("email@email.com")));
 
     Assertions.assertThat(underTest.toEmailDeliveryRequests(List.of(new QualityGateMetricsUpdateNotification(true))))
       .isEmpty();
index f9b0ebe070ba2132f7088845e913a419daf3e2ca..b687dc0e7cb6de442ceab68c32a080e8a9aca156 100644 (file)
@@ -178,7 +178,7 @@ public class DefaultNotificationManagerTest {
     String globalPermission = secure().nextAlphanumeric(4);
     String projectPermission = secure().nextAlphanumeric(5);
     String projectKey = secure().nextAlphabetic(6);
-    when(propertiesDao.findEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey))
+    when(propertiesDao.findEnabledEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey))
       .thenReturn(Collections.emptySet());
 
     Set<EmailRecipient> emailRecipients = underTest.findSubscribedEmailRecipients(dispatcherKey, projectKey,
@@ -197,7 +197,7 @@ public class DefaultNotificationManagerTest {
     Set<String> logins = IntStream.range(0, 1 + new Random().nextInt(10))
       .mapToObj(i -> "login_" + i)
       .collect(Collectors.toSet());
-    when(propertiesDao.findEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey, logins))
+    when(propertiesDao.findEnabledEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey, logins))
       .thenReturn(Collections.emptySet());
 
     Set<EmailRecipient> emailRecipients = underTest.findSubscribedEmailRecipients(dispatcherKey, projectKey, logins,
@@ -213,7 +213,7 @@ public class DefaultNotificationManagerTest {
     String globalPermission = secure().nextAlphanumeric(4);
     String projectPermission = secure().nextAlphanumeric(5);
     String projectKey = secure().nextAlphabetic(6);
-    when(propertiesDao.findEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey))
+    when(propertiesDao.findEnabledEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey))
       .thenReturn(
         newHashSet(EmailSubscriberDto.create("user1", false, "user1@foo"), EmailSubscriberDto.create("user3", false, "user3@foo"),
           EmailSubscriberDto.create("user3", true, "user3@foo")));
@@ -239,7 +239,7 @@ public class DefaultNotificationManagerTest {
     String projectPermission = secure().nextAlphanumeric(5);
     String projectKey = secure().nextAlphabetic(6);
     Set<String> logins = ImmutableSet.of("user1", "user2", "user3");
-    when(propertiesDao.findEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey, logins))
+    when(propertiesDao.findEnabledEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey, logins))
       .thenReturn(
         newHashSet(EmailSubscriberDto.create("user1", false, "user1@foo"), EmailSubscriberDto.create("user3", false, "user3@foo"),
           EmailSubscriberDto.create("user3", true, "user3@foo")));
@@ -268,7 +268,7 @@ public class DefaultNotificationManagerTest {
       .mapToObj(i -> EmailSubscriberDto.create("user" + i, true, "user" + i + "@sonarsource.com"))
       .collect(Collectors.toSet());
     Set<String> logins = subscribers.stream().map(EmailSubscriberDto::getLogin).collect(Collectors.toSet());
-    when(propertiesDao.findEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey))
+    when(propertiesDao.findEnabledEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey))
       .thenReturn(subscribers);
     when(authorizationDao.keepAuthorizedLoginsOnEntity(dbSession, logins, projectKey, globalPermission))
       .thenReturn(logins);
@@ -293,7 +293,7 @@ public class DefaultNotificationManagerTest {
       .mapToObj(i -> EmailSubscriberDto.create("user" + i, true, "user" + i + "@sonarsource.com"))
       .collect(Collectors.toSet());
     Set<String> logins = subscribers.stream().map(EmailSubscriberDto::getLogin).collect(Collectors.toSet());
-    when(propertiesDao.findEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey, logins))
+    when(propertiesDao.findEnabledEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey, logins))
       .thenReturn(subscribers);
     when(authorizationDao.keepAuthorizedLoginsOnEntity(dbSession, logins, projectKey, globalPermission))
       .thenReturn(logins);
@@ -318,7 +318,7 @@ public class DefaultNotificationManagerTest {
       .mapToObj(i -> EmailSubscriberDto.create("user" + i, false, "user" + i + "@sonarsource.com"))
       .collect(Collectors.toSet());
     Set<String> logins = subscribers.stream().map(EmailSubscriberDto::getLogin).collect(Collectors.toSet());
-    when(propertiesDao.findEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey))
+    when(propertiesDao.findEnabledEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey))
       .thenReturn(subscribers);
     when(authorizationDao.keepAuthorizedLoginsOnEntity(dbSession, logins, projectKey, projectPermission))
       .thenReturn(logins);
@@ -343,7 +343,7 @@ public class DefaultNotificationManagerTest {
       .mapToObj(i -> EmailSubscriberDto.create("user" + i, false, "user" + i + "@sonarsource.com"))
       .collect(Collectors.toSet());
     Set<String> logins = subscribers.stream().map(EmailSubscriberDto::getLogin).collect(Collectors.toSet());
-    when(propertiesDao.findEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey, logins))
+    when(propertiesDao.findEnabledEmailSubscribersForNotification(dbSession, dispatcherKey, "EmailNotificationChannel", projectKey, logins))
       .thenReturn(subscribers);
     when(authorizationDao.keepAuthorizedLoginsOnEntity(dbSession, logins, projectKey, projectPermission))
       .thenReturn(logins);
index b5506ef52ed843d8942eb4d6e3de81fbf446cd44..efe44ee17909a83dbd651111d9ce49416dfe33c1 100644 (file)
@@ -78,7 +78,7 @@ class AddActionIT {
   private final WsActionTester ws = new WsActionTester(new AddAction(new NotificationCenter(
     new NotificationDispatcherMetadata[] {},
     new NotificationChannel[] {emailChannel, twitterChannel, defaultChannel}),
-    new NotificationUpdater(dbClient), dispatchers, dbClient, TestComponentFinder.from(db), userSession));
+    new NotificationUpdater(dbClient, dispatchers), dispatchers, dbClient, TestComponentFinder.from(db), userSession));
 
   @Test
   void add_to_email_channel_by_default() {
@@ -88,7 +88,7 @@ class AddActionIT {
 
     call(NOTIF_MY_NEW_ISSUES, null, null, null);
 
-    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), null);
+    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), null, true);
   }
 
   @Test
@@ -99,7 +99,7 @@ class AddActionIT {
 
     call(NOTIF_NEW_QUALITY_GATE_STATUS, twitterChannel.getKey(), null, null);
 
-    db.notifications().assertExists(twitterChannel.getKey(), NOTIF_NEW_QUALITY_GATE_STATUS, userSession.getUuid(), null);
+    db.notifications().assertExists(twitterChannel.getKey(), NOTIF_NEW_QUALITY_GATE_STATUS, userSession.getUuid(), null, true);
   }
 
   @Test
@@ -113,7 +113,7 @@ class AddActionIT {
 
     call(NOTIF_MY_NEW_ISSUES, null, project.getKey(), null);
 
-    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), project);
+    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), project, true);
   }
 
   @Test
@@ -127,7 +127,7 @@ class AddActionIT {
 
     call(NOTIF_MY_NEW_ISSUES, null, project.getKey(), null);
 
-    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), project);
+    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), project, true);
   }
 
   @Test
@@ -142,8 +142,8 @@ class AddActionIT {
 
     call(NOTIF_MY_NEW_ISSUES, null, null, null);
 
-    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), project);
-    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), null);
+    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), project, true);
+    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), null, true);
   }
 
   @Test
@@ -158,8 +158,8 @@ class AddActionIT {
     userSession.addProjectPermission(USER, project);
     call(NOTIF_MY_NEW_ISSUES, null, project.getKey(), null);
 
-    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), project);
-    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), null);
+    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), project, true);
+    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), null, true);
   }
 
   @Test
@@ -174,8 +174,8 @@ class AddActionIT {
 
     call(NOTIF_MY_NEW_ISSUES, null, project.getKey(), null);
 
-    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), project);
-    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), null);
+    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), project, true);
+    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUuid(), null, true);
   }
 
   @Test
@@ -197,7 +197,7 @@ class AddActionIT {
 
     call(NOTIF_MY_NEW_ISSUES, null, null, user.getLogin());
 
-    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user.getUuid(), null);
+    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user.getUuid(), null, true);
   }
 
   @Test
index e3ebaef25f88b7e00f86181c0b366621b5afcfeb..1e94bfc62e38a8321a10dc7a5f9aabbefbb7f9ef 100644 (file)
  */
 package org.sonar.server.notification.ws;
 
-import org.junit.Rule;
-import org.junit.Test;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ProjectData;
+import org.sonar.db.permission.GlobalPermission;
 import org.sonar.db.project.ProjectDto;
 import org.sonar.db.user.UserDto;
 import org.sonar.server.exceptions.ForbiddenException;
@@ -49,14 +51,15 @@ import static org.sonar.api.web.UserRole.USER;
 import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
 import static org.sonar.test.JsonAssert.assertJson;
 
-public class ListActionIT {
+class ListActionIT {
   private static final String NOTIF_MY_NEW_ISSUES = "MyNewIssues";
   private static final String NOTIF_NEW_ISSUES = "NewIssues";
   private static final String NOTIF_NEW_QUALITY_GATE_STATUS = "NewQualityGateStatus";
+  private static final String NOTIF_CONDITIONS_MISMATCH = "QualityGateConditionsMismatch";
 
-  @Rule
+  @RegisterExtension
   public final UserSessionRule userSession = UserSessionRule.standalone();
-  @Rule
+  @RegisterExtension
   public final DbTester db = DbTester.create();
 
   private final DbClient dbClient = db.getDbClient();
@@ -65,8 +68,8 @@ public class ListActionIT {
   private final NotificationChannel emailChannel = new FakeNotificationChannel("EmailChannel");
   private final NotificationChannel twitterChannel = new FakeNotificationChannel("TwitterChannel");
 
-  private final NotificationUpdater notificationUpdater = new NotificationUpdater(dbClient);
   private final Dispatchers dispatchers = mock(Dispatchers.class);
+  private final NotificationUpdater notificationUpdater = new NotificationUpdater(dbClient, dispatchers);
 
   private final WsActionTester ws = new WsActionTester(new ListAction(new NotificationCenter(
     new NotificationDispatcherMetadata[] {},
@@ -74,7 +77,7 @@ public class ListActionIT {
     dbClient, userSession, dispatchers));
 
   @Test
-  public void channels() {
+  void channels() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
 
@@ -84,18 +87,18 @@ public class ListActionIT {
   }
 
   @Test
-  public void overall_dispatchers() {
+  void overall_dispatchers() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
-    when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
-
+    when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS, NOTIF_CONDITIONS_MISMATCH));
+    when(dispatchers.getEnabledByDefaultDispatchers()).thenReturn(singletonList(NOTIF_CONDITIONS_MISMATCH));
     ListResponse result = call();
 
-    assertThat(result.getGlobalTypesList()).containsExactly(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS);
+    assertThat(result.getGlobalTypesList()).containsExactly(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS, NOTIF_CONDITIONS_MISMATCH);
   }
 
   @Test
-  public void per_project_dispatchers() {
+  void per_project_dispatchers() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
@@ -106,7 +109,7 @@ public class ListActionIT {
   }
 
   @Test
-  public void filter_unauthorized_projects() {
+  void filter_unauthorized_projects() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -124,7 +127,7 @@ public class ListActionIT {
   }
 
   @Test
-  public void filter_channels() {
+  void filter_channels() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
@@ -138,7 +141,7 @@ public class ListActionIT {
   }
 
   @Test
-  public void filter_overall_dispatchers() {
+  void filter_overall_dispatchers() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
@@ -152,7 +155,102 @@ public class ListActionIT {
   }
 
   @Test
-  public void filter_per_project_dispatchers() {
+  void filter_enabled_by_default_dispatchers() {
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user);
+    when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS, NOTIF_CONDITIONS_MISMATCH));
+    when(dispatchers.getEnabledByDefaultDispatchers()).thenReturn(singletonList(NOTIF_CONDITIONS_MISMATCH));
+    notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
+    notificationUpdater.add(dbSession, emailChannel.getKey(), "Unknown Notification", user, null);
+    dbSession.commit();
+
+    ListResponse result = call();
+
+    assertThat(result.getNotificationsList()).extracting(Notification::getType).containsOnly(NOTIF_MY_NEW_ISSUES, NOTIF_CONDITIONS_MISMATCH);
+  }
+
+  @Test
+  void filter_whenDispatcherEnabledByDefaultAndRemoved_shouldNotShowNotification() {
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user);
+    when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_CONDITIONS_MISMATCH));
+    when(dispatchers.getEnabledByDefaultDispatchers()).thenReturn(singletonList(NOTIF_CONDITIONS_MISMATCH));
+    notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
+    notificationUpdater.remove(dbSession, emailChannel.getKey(), NOTIF_CONDITIONS_MISMATCH, user, null);
+    notificationUpdater.remove(dbSession, twitterChannel.getKey(), NOTIF_CONDITIONS_MISMATCH, user, null);
+    dbSession.commit();
+
+    ListResponse result = call();
+
+    assertThat(result.getNotificationsList()).extracting(Notification::getType).containsOnly(NOTIF_MY_NEW_ISSUES);
+  }
+
+  @Test
+  void filter_whenUserHasPermissionToDispatcher_shouldShowNotifications() {
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user);
+    db.users().insertGlobalPermissionOnUser(user, GlobalPermission.ADMINISTER_QUALITY_GATES);
+    when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_CONDITIONS_MISMATCH));
+    when(dispatchers.getPermissionRestrictedDispatchers()).thenReturn(Map.of(NOTIF_CONDITIONS_MISMATCH, GlobalPermission.ADMINISTER_QUALITY_GATES.getKey()));
+
+    notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
+    notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_CONDITIONS_MISMATCH, user, null);
+
+    dbSession.commit();
+
+    ListResponse result = call();
+
+    assertThat(result.getGlobalTypesList()).containsOnly(NOTIF_MY_NEW_ISSUES, NOTIF_CONDITIONS_MISMATCH);
+    assertThat(result.getNotificationsList()).extracting(Notification::getType).containsOnly(NOTIF_MY_NEW_ISSUES, NOTIF_CONDITIONS_MISMATCH);
+  }
+
+  @Test
+  void filter_whenAdminAndUserHasNoPermission_shouldNotShowNotifications() {
+    UserDto admin = db.users().insertUser();
+    db.users().insertGlobalPermissionOnUser(admin, GlobalPermission.ADMINISTER_QUALITY_GATES);
+    userSession.logIn(admin).setSystemAdministrator();
+
+    UserDto user = db.users().insertUser();
+
+    when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_CONDITIONS_MISMATCH));
+    when(dispatchers.getPermissionRestrictedDispatchers()).thenReturn(Map.of(NOTIF_CONDITIONS_MISMATCH, GlobalPermission.ADMINISTER_QUALITY_GATES.getKey()));
+
+    notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
+    notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_CONDITIONS_MISMATCH, user, null);
+
+    dbSession.commit();
+
+    ListResponse result = call(user.getLogin());
+
+    assertThat(result.getGlobalTypesList()).containsOnly(NOTIF_MY_NEW_ISSUES);
+    assertThat(result.getNotificationsList()).extracting(Notification::getType).containsOnly(NOTIF_MY_NEW_ISSUES);
+  }
+
+  @Test
+  void filter_whenUserHasNotPermissions_shouldNotShowNotifications() {
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user);
+
+    when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_CONDITIONS_MISMATCH, NOTIF_NEW_QUALITY_GATE_STATUS));
+
+    when(dispatchers.getPermissionRestrictedDispatchers()).thenReturn(Map.of(NOTIF_CONDITIONS_MISMATCH, GlobalPermission.ADMINISTER_QUALITY_GATES.getKey(),
+      NOTIF_NEW_QUALITY_GATE_STATUS, GlobalPermission.ADMINISTER_QUALITY_GATES.getKey()));
+
+    when(dispatchers.getEnabledByDefaultDispatchers()).thenReturn(singletonList(NOTIF_CONDITIONS_MISMATCH));
+
+    notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
+    notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_NEW_QUALITY_GATE_STATUS, user, null);
+
+    dbSession.commit();
+
+    ListResponse result = call();
+
+    assertThat(result.getGlobalTypesList()).containsOnly(NOTIF_MY_NEW_ISSUES);
+    assertThat(result.getNotificationsList()).extracting(Notification::getType).containsOnly(NOTIF_MY_NEW_ISSUES);
+  }
+
+  @Test
+  void filter_per_project_dispatchers() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -170,7 +268,7 @@ public class ListActionIT {
   }
 
   @Test
-  public void order_with_global_then_by_channel_and_dispatcher() {
+  void order_with_global_then_by_channel_and_dispatcher() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
@@ -199,7 +297,7 @@ public class ListActionIT {
   }
 
   @Test
-  public void list_user_notifications_as_system_admin() {
+  void list_user_notifications_as_system_admin() {
     UserDto user = db.users().insertUser();
     when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
     userSession.logIn(user).setSystemAdministrator();
@@ -215,7 +313,7 @@ public class ListActionIT {
   }
 
   @Test
-  public void fail_if_login_and_not_system_admin() {
+  void fail_if_login_and_not_system_admin() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user).setNonSystemAdministrator();
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -228,7 +326,7 @@ public class ListActionIT {
   }
 
   @Test
-  public void fail_if_login_is_provided_and_unknown() {
+  void fail_if_login_is_provided_and_unknown() {
     userSession.logIn().setSystemAdministrator();
 
     assertThatThrownBy(() -> call("LOGIN 404"))
@@ -237,7 +335,7 @@ public class ListActionIT {
   }
 
   @Test
-  public void json_example() {
+  void json_example() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
@@ -261,7 +359,7 @@ public class ListActionIT {
   }
 
   @Test
-  public void definition() {
+  void definition() {
     WebService.Action definition = ws.getDef();
 
     assertThat(definition.key()).isEqualTo("list");
@@ -276,7 +374,7 @@ public class ListActionIT {
   }
 
   @Test
-  public void fail_when_not_authenticated() {
+  void fail_when_not_authenticated() {
     userSession.anonymous();
 
     assertThatThrownBy(this::call)
index 938f06189e92c60895ac0d625f68a53f89f5210b..6015c1adb2e4b3c8f054fc13eed7be7a3b7876f1 100644 (file)
@@ -19,8 +19,8 @@
  */
 package org.sonar.server.notification.ws;
 
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 import org.sonar.api.notifications.Notification;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
@@ -55,13 +55,13 @@ import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_L
 import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_PROJECT;
 import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_TYPE;
 
-public class RemoveActionIT {
+class RemoveActionIT {
   private static final String NOTIF_MY_NEW_ISSUES = "Dispatcher1";
   private static final String NOTIF_NEW_ISSUES = "Dispatcher2";
   private static final String NOTIF_NEW_QUALITY_GATE_STATUS = "Dispatcher3";
-  @Rule
+  @RegisterExtension
   public final UserSessionRule userSession = UserSessionRule.standalone();
-  @Rule
+  @RegisterExtension
   public final DbTester db = DbTester.create();
   private final DbClient dbClient = db.getDbClient();
   private final DbSession dbSession = db.getSession();
@@ -71,8 +71,8 @@ public class RemoveActionIT {
   // default channel, based on class simple name
   private final NotificationChannel defaultChannel = new FakeNotificationChannel("EmailNotificationChannel");
 
-  private final NotificationUpdater notificationUpdater = new NotificationUpdater(dbClient);
   private final Dispatchers dispatchers = mock(Dispatchers.class);
+  private final NotificationUpdater notificationUpdater = new NotificationUpdater(dbClient, dispatchers);
 
   private final RemoveRequest request = new RemoveRequest().setType(NOTIF_MY_NEW_ISSUES);
 
@@ -81,7 +81,7 @@ public class RemoveActionIT {
     new NotificationChannel[] {emailChannel, twitterChannel, defaultChannel}), notificationUpdater, dispatchers, dbClient, TestComponentFinder.from(db), userSession));
 
   @Test
-  public void remove_to_email_channel_by_default() {
+  void remove_to_email_channel_by_default() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -94,7 +94,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void remove_from_a_specific_channel() {
+  void remove_from_a_specific_channel() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_NEW_QUALITY_GATE_STATUS));
@@ -107,7 +107,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void remove_a_project_notification() {
+  void remove_a_project_notification() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -122,7 +122,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void fail_when_remove_a_global_notification_when_a_project_one_exists() {
+  void fail_when_remove_a_global_notification_when_a_project_one_exists() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -137,7 +137,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void fail_when_remove_a_project_notification_when_a_global_one_exists() {
+  void fail_when_remove_a_project_notification_when_a_global_one_exists() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -153,7 +153,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void http_no_content() {
+  void http_no_content() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -167,12 +167,12 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void remove_a_notification_from_a_user_as_system_administrator() {
+  void remove_a_notification_from_a_user_as_system_administrator() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
     notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null);
-    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user.getUuid(), null);
+    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user.getUuid(), null, true);
     userSession.logIn().setSystemAdministrator();
     dbSession.commit();
 
@@ -182,7 +182,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void fail_if_login_is_provided_and_unknown() {
+  void fail_if_login_is_provided_and_unknown() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user).setSystemAdministrator();
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -194,7 +194,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void fail_if_login_provided_and_not_system_administrator() {
+  void fail_if_login_provided_and_not_system_administrator() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user).setNonSystemAdministrator();
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -207,7 +207,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void fail_when_notification_does_not_exist() {
+  void fail_when_notification_does_not_exist() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -218,7 +218,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void fail_when_unknown_channel() {
+  void fail_when_unknown_channel() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -229,7 +229,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void fail_when_unknown_global_dispatcher() {
+  void fail_when_unknown_global_dispatcher() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS));
@@ -241,7 +241,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void fail_when_unknown_project_dispatcher() {
+  void fail_when_unknown_project_dispatcher() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -255,7 +255,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void fail_when_no_type_parameter() {
+  void fail_when_no_type_parameter() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -267,7 +267,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void fail_when_project_is_unknown() {
+  void fail_when_project_is_unknown() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -279,7 +279,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void fail_when_component_is_not_a_project() {
+  void fail_when_component_is_not_a_project() {
     UserDto user = db.users().insertUser();
     userSession.logIn(user);
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
@@ -293,7 +293,7 @@ public class RemoveActionIT {
   }
 
   @Test
-  public void fail_when_not_authenticated() {
+  void fail_when_not_authenticated() {
     userSession.anonymous();
     when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
 
@@ -301,6 +301,20 @@ public class RemoveActionIT {
       .isInstanceOf(UnauthorizedException.class);
   }
 
+  @Test
+  void execute_whenDispatcherEnabledByDefault_shouldAddDisabledNotification() {
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user);
+    when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+    when(dispatchers.getEnabledByDefaultDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES));
+
+    db.notifications().assertDoesNotExist(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user.getUuid(), null);
+
+    call(request);
+
+    db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user.getUuid(), null, false);
+  }
+
   private TestResponse call(RemoveRequest remove) {
     TestRequest request = ws.newRequest();
     request.setParam(PARAM_TYPE, remove.getType());
index 9a035b404b0ac12689bd385ac8878c872235637a..794bc80388e4cd19e9df767cbb5e001c8c0a047f 100644 (file)
 package org.sonar.server.notification.ws;
 
 import java.util.List;
+import java.util.Map;
 
 public interface Dispatchers {
 
   List<String> getGlobalDispatchers();
 
   List<String> getProjectDispatchers();
+
+  List<String> getEnabledByDefaultDispatchers();
+
+  Map<String, String> getPermissionRestrictedDispatchers();
 }
index 8226f3fa3f2ab74ac68b097f8d424a6881958348..e3bfc3c84241577b8fd1d2f26b88427133e38d95 100644 (file)
 package org.sonar.server.notification.ws;
 
 import java.util.List;
+import java.util.Map;
 import org.sonar.api.Startable;
 
+import static org.sonar.server.notification.NotificationDispatcherMetadata.ENABLED_BY_DEFAULT_NOTIFICATION;
 import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
+import static org.sonar.server.notification.NotificationDispatcherMetadata.PERMISSION_RESTRICTION;
 import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
 
 public class DispatchersImpl implements Dispatchers, Startable {
@@ -31,6 +34,8 @@ public class DispatchersImpl implements Dispatchers, Startable {
 
   private List<String> projectDispatchers;
   private List<String> globalDispatchers;
+  private List<String> enabledByDefaultDispatchers;
+  private Map<String, String> permissionRestrictedDispatchers;
 
   public DispatchersImpl(NotificationCenter notificationCenter) {
     this.notificationCenter = notificationCenter;
@@ -46,6 +51,16 @@ public class DispatchersImpl implements Dispatchers, Startable {
     return projectDispatchers;
   }
 
+  @Override
+  public List<String> getEnabledByDefaultDispatchers() {
+    return enabledByDefaultDispatchers;
+  }
+
+  @Override
+  public Map<String, String> getPermissionRestrictedDispatchers() {
+    return permissionRestrictedDispatchers;
+  }
+
   @Override
   public void start() {
     this.globalDispatchers = notificationCenter.getDispatcherKeysForProperty(GLOBAL_NOTIFICATION, "true")
@@ -56,6 +71,8 @@ public class DispatchersImpl implements Dispatchers, Startable {
       .stream()
       .sorted()
       .toList();
+    this.enabledByDefaultDispatchers = notificationCenter.getDispatcherKeysForProperty(ENABLED_BY_DEFAULT_NOTIFICATION, "true");
+    this.permissionRestrictedDispatchers = notificationCenter.getValueByDispatchers(PERMISSION_RESTRICTION);
   }
 
   @Override
index d8d1fb59f0a5d36ff1eeaaec51d8a9c3e6f331c3..8868764560e41c70f3aca795df7a066b587c665b 100644 (file)
@@ -29,6 +29,8 @@ import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.UnaryOperator;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.annotation.Nullable;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
@@ -99,24 +101,50 @@ public class ListAction implements NotificationsWsAction {
     try (DbSession dbSession = dbClient.openSession(false)) {
       checkPermissions(request);
       UserDto user = getUser(dbSession, request);
-
+      Set<String> globalPermissions = getGlobalPermissions(dbSession, user);
       return Optional
         .of(ListResponse.newBuilder())
         .map(r -> r.addAllChannels(channels))
-        .map(r -> r.addAllGlobalTypes(dispatchers.getGlobalDispatchers()))
-        .map(r -> r.addAllPerProjectTypes(dispatchers.getProjectDispatchers()))
-        .map(addNotifications(dbSession, user))
+        .map(r -> r.addAllGlobalTypes(getAllowedGlobalDispatchers(globalPermissions)))
+        .map(r -> r.addAllPerProjectTypes(getAllowedProjectDispatchers(globalPermissions)))
+        .map(addNotifications(dbSession, user, globalPermissions))
         .map(ListResponse.Builder::build)
         .orElseThrow();
     }
   }
 
+  private Set<String> getGlobalPermissions(DbSession dbSession, UserDto userDto) {
+    return dbClient.authorizationDao().selectGlobalPermissions(dbSession, userDto.getUuid());
+  }
+
+  private List<String> getAllowedGlobalDispatchers(Set<String> globalPermissions) {
+    return dispatchers.getGlobalDispatchers()
+      .stream()
+      .filter(d -> hasUserPermission(globalPermissions, d))
+      .toList();
+  }
+
+  private List<String> getAllowedProjectDispatchers(Set<String> globalPermissions) {
+    return dispatchers.getProjectDispatchers()
+      .stream()
+      .filter(d -> hasUserPermission(globalPermissions, d))
+      .toList();
+  }
+
+  private boolean hasUserPermission(Set<String> globalPermissions, String dispatcher) {
+    if (!dispatchers.getPermissionRestrictedDispatchers().containsKey(dispatcher)) {
+      return true;
+    }
+    String globalPermission = dispatchers.getPermissionRestrictedDispatchers().get(dispatcher);
+    return globalPermissions.contains(globalPermission);
+  }
+
   private UserDto getUser(DbSession dbSession, Request request) {
     String login = request.param(PARAM_LOGIN) == null ? userSession.getLogin() : request.param(PARAM_LOGIN);
     return checkFound(dbClient.userDao().selectByLogin(dbSession, login), "User '%s' not found", login);
   }
 
-  private UnaryOperator<ListResponse.Builder> addNotifications(DbSession dbSession, UserDto user) {
+  private UnaryOperator<ListResponse.Builder> addNotifications(DbSession dbSession, UserDto user, Set<String> globalPermissions) {
     return response -> {
       List<PropertyDto> properties = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setUserUuid(user.getUuid()).build(),
         dbSession);
@@ -127,11 +155,19 @@ public class ListAction implements NotificationsWsAction {
 
       Notification.Builder notification = Notification.newBuilder();
 
-      properties.stream()
+      Set<PropertyDto> notificationProps = properties.stream()
         .filter(isNotification)
-        .filter(channelAndDispatcherAuthorized())
-        .filter(isComponentInDb)
-        .map(toWsNotification(notification, entitiesByUuid))
+        .filter(channelAndDispatcherAuthorized(globalPermissions))
+        .filter(isComponentInDb).collect(Collectors.toSet());
+
+      Set<Notification> activeNotifications = notificationProps.stream()
+        .filter(prop -> Boolean.parseBoolean(prop.getValue()))
+        .map(p -> toWsNotification(notification, entitiesByUuid, p.getKey(), p.getEntityUuid()))
+        .collect(Collectors.toSet());
+
+      Set<Notification> notificationsEnabledByDefault = getEnabledByDefaultNotifications(notificationProps, notification, entitiesByUuid, globalPermissions);
+
+      Stream.concat(activeNotifications.stream(), notificationsEnabledByDefault.stream())
         .sorted(comparing(Notification::getProject, nullsFirst(naturalOrder()))
           .thenComparing(Notification::getChannel)
           .thenComparing(Notification::getType))
@@ -141,17 +177,39 @@ public class ListAction implements NotificationsWsAction {
     };
   }
 
-  private Predicate<PropertyDto> channelAndDispatcherAuthorized() {
+  private Set<Notification> getEnabledByDefaultNotifications(Set<PropertyDto> notificationProps, Builder notificationBuilder, Map<String, EntityDto> entitiesByUuid,
+    Set<String> globalPermissions) {
+    Set<String> disabledNotifications = notificationProps.stream()
+      .filter(prop -> !Boolean.parseBoolean(prop.getValue()))
+      .map(PropertyDto::getKey)
+      .collect(Collectors.toSet());
+
+    return dispatchers.getEnabledByDefaultDispatchers()
+      .stream()
+      .filter(d -> hasUserPermission(globalPermissions, d))
+      .flatMap(dispatcher -> channels.stream()
+        .filter(channel -> !isNotificationDisabled(disabledNotifications, dispatcher, channel))
+        .map(channel -> toWsNotification(notificationBuilder, entitiesByUuid, "notification.%s.%s".formatted(dispatcher, channel), null)))
+      .collect(Collectors.toSet());
+  }
+
+  private static boolean isNotificationDisabled(Set<String> disabledNotification, String dispatcher, String channel) {
+    return disabledNotification.contains("notification.%s.%s".formatted(dispatcher, channel));
+  }
+
+  private Predicate<PropertyDto> channelAndDispatcherAuthorized(Set<String> globalPermissions) {
     return prop -> {
       List<String> key = PROPERTY_KEY_SPLITTER.splitToList(prop.getKey());
       return key.size() == 3
         && channels.contains(key.get(2))
-        && isDispatcherAuthorized(prop, key.get(1));
+        && isDispatcherAuthorized(prop, key.get(1), globalPermissions);
     };
   }
 
-  private boolean isDispatcherAuthorized(PropertyDto prop, String dispatcher) {
-    return (prop.getEntityUuid() != null && dispatchers.getProjectDispatchers().contains(dispatcher)) || dispatchers.getGlobalDispatchers().contains(dispatcher);
+  private boolean isDispatcherAuthorized(PropertyDto prop, String dispatcher, Set<String> globalPermissions) {
+    return ((prop.getEntityUuid() != null && dispatchers.getProjectDispatchers().contains(dispatcher))
+      || dispatchers.getGlobalDispatchers().contains(dispatcher))
+      && hasUserPermission(globalPermissions, dispatcher);
   }
 
   private Map<String, EntityDto> searchProjects(DbSession dbSession, List<PropertyDto> properties) {
@@ -167,17 +225,14 @@ public class ListAction implements NotificationsWsAction {
       .collect(Collectors.toMap(EntityDto::getUuid, Function.identity()));
   }
 
-  private static Function<PropertyDto, Notification> toWsNotification(Notification.Builder notification,
-    Map<String, EntityDto> projectsByUuid) {
-    return property -> {
-      notification.clear();
-      List<String> propertyKey = Splitter.on(".").splitToList(property.getKey());
-      notification.setType(propertyKey.get(1));
-      notification.setChannel(propertyKey.get(2));
-      ofNullable(property.getEntityUuid()).ifPresent(componentUuid -> populateProjectFields(notification, componentUuid, projectsByUuid));
-
-      return notification.build();
-    };
+  private static Notification toWsNotification(Builder notification,
+    Map<String, EntityDto> projectsByUuid, String key, @Nullable String entityUuid) {
+    notification.clear();
+    List<String> propertyKey = Splitter.on(".").splitToList(key);
+    notification.setType(propertyKey.get(1));
+    notification.setChannel(propertyKey.get(2));
+    ofNullable(entityUuid).ifPresent(componentUuid -> populateProjectFields(notification, componentUuid, projectsByUuid));
+    return notification.build();
   }
 
   private static void populateProjectFields(Builder notification, String componentUuid, Map<String, EntityDto> projectsByUuid) {
index c797bea64378b1ab820f2513f52c22ddcc6042b7..efcabdf2e70bcd75b476fd77e55666d50ae8b30e 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.server.notification.ws;
 import com.google.common.collect.ImmutableList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 import javax.annotation.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -86,4 +87,16 @@ public class NotificationCenter {
     return keys.build();
   }
 
+  public Map<String, String> getValueByDispatchers(String propertyKey) {
+    Map<String, String> valueByDispatchers = new java.util.HashMap<>();
+    for (NotificationDispatcherMetadata metadata : dispatchersMetadata) {
+      String dispatcherKey = metadata.getDispatcherKey();
+      String value = metadata.getProperty(propertyKey);
+      if (value != null) {
+        valueByDispatchers.put(dispatcherKey, value);
+      }
+    }
+    return valueByDispatchers;
+  }
+
 }
index cb8db6522c5755cfefba110b3379610be5736146..c904d862130c1a97006e54b3a6b121c531b733c3 100644 (file)
@@ -33,12 +33,15 @@ import static com.google.common.base.Preconditions.checkArgument;
 
 public class NotificationUpdater {
   private static final String PROP_NOTIFICATION_PREFIX = "notification";
-  private static final String PROP_NOTIFICATION_VALUE = "true";
+  private static final String PROP_ENABLED_NOTIFICATION_VALUE = "true";
+  private static final String PROP_DISABLED_NOTIFICATION_VALUE = "false";
 
   private final DbClient dbClient;
+  private final Dispatchers dispatchers;
 
-  public NotificationUpdater(DbClient dbClient) {
+  public NotificationUpdater(DbClient dbClient, Dispatchers dispatchers) {
     this.dbClient = dbClient;
+    this.dispatchers = dispatchers;
   }
 
   /**
@@ -52,22 +55,22 @@ public class NotificationUpdater {
     String qualifier = project == null ? null : project.getQualifier();
 
     List<PropertyDto> existingNotification = dbClient.propertiesDao().selectByQuery(
-        PropertyQuery.builder()
-          .setKey(key)
-          .setEntityUuid(projectUuid)
-          .setUserUuid(user.getUuid())
-          .build(),
-        dbSession).stream()
+      PropertyQuery.builder()
+        .setKey(key)
+        .setEntityUuid(projectUuid)
+        .setUserUuid(user.getUuid())
+        .build(),
+      dbSession).stream()
       .filter(notificationScope(project))
       .toList();
     checkArgument(existingNotification.isEmpty()
-      || !PROP_NOTIFICATION_VALUE.equals(existingNotification.get(0).getValue()), "Notification already added");
+      || !PROP_ENABLED_NOTIFICATION_VALUE.equals(existingNotification.get(0).getValue()), "Notification already added");
 
     dbClient.propertiesDao().saveProperty(dbSession, new PropertyDto()
-        .setKey(key)
-        .setUserUuid(user.getUuid())
-        .setValue(PROP_NOTIFICATION_VALUE)
-        .setEntityUuid(projectUuid),
+      .setKey(key)
+      .setUserUuid(user.getUuid())
+      .setValue(PROP_ENABLED_NOTIFICATION_VALUE)
+      .setEntityUuid(projectUuid),
       user.getLogin(), projectKey, projectName, qualifier);
   }
 
@@ -82,21 +85,31 @@ public class NotificationUpdater {
     String qualifier = project == null ? null : project.getQualifier();
 
     List<PropertyDto> existingNotification = dbClient.propertiesDao().selectByQuery(
-        PropertyQuery.builder()
-          .setKey(key)
-          .setEntityUuid(projectUuid)
-          .setUserUuid(user.getUuid())
-          .build(),
-        dbSession).stream()
+      PropertyQuery.builder()
+        .setKey(key)
+        .setEntityUuid(projectUuid)
+        .setUserUuid(user.getUuid())
+        .build(),
+      dbSession).stream()
       .filter(notificationScope(project))
       .toList();
-    checkArgument(!existingNotification.isEmpty() && PROP_NOTIFICATION_VALUE.equals(existingNotification.get(0).getValue()), "Notification doesn't exist");
 
-    dbClient.propertiesDao().delete(dbSession, new PropertyDto()
-      .setKey(key)
-      .setUserUuid(user.getUuid())
-      .setValue(PROP_NOTIFICATION_VALUE)
-      .setEntityUuid(projectUuid), user.getLogin(), projectKey, projectName, qualifier);
+    if (dispatchers.getEnabledByDefaultDispatchers().contains(dispatcher)) {
+      dbClient.propertiesDao().saveProperty(dbSession, new PropertyDto()
+        .setKey(key)
+        .setUserUuid(user.getUuid())
+        .setValue(PROP_DISABLED_NOTIFICATION_VALUE)
+        .setEntityUuid(projectUuid),
+        user.getLogin(), projectKey, projectName, qualifier);
+    } else {
+      checkArgument(!existingNotification.isEmpty() && PROP_ENABLED_NOTIFICATION_VALUE.equals(existingNotification.get(0).getValue()), "Notification doesn't exist");
+      dbClient.propertiesDao().delete(dbSession, new PropertyDto()
+        .setKey(key)
+        .setUserUuid(user.getUuid())
+        .setValue(PROP_ENABLED_NOTIFICATION_VALUE)
+        .setEntityUuid(projectUuid), user.getLogin(), projectKey, projectName, qualifier);
+    }
+
   }
 
   private static Predicate<PropertyDto> notificationScope(@Nullable EntityDto project) {
index ba2e29a32e3aa69740a3f2eb630f9b62e279fcbf..308ce734bd98795a2c9c2d2cd387f94ec0050a02 100644 (file)
@@ -19,7 +19,9 @@
  */
 package org.sonar.server.notification.ws;
 
-import org.junit.Test;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+import org.sonar.db.permission.GlobalPermission;
 import org.sonar.server.issue.notification.FPOrAcceptedNotificationHandler;
 import org.sonar.server.issue.notification.MyNewIssuesNotificationHandler;
 import org.sonar.server.issue.notification.NewIssuesNotificationHandler;
@@ -28,12 +30,14 @@ import org.sonar.server.notification.NotificationDispatcherMetadata;
 import org.sonar.server.qualitygate.notification.QGChangeNotificationHandler;
 
 import static org.assertj.core.api.Java6Assertions.assertThat;
+import static org.sonar.server.notification.NotificationDispatcherMetadata.ENABLED_BY_DEFAULT_NOTIFICATION;
 import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
+import static org.sonar.server.notification.NotificationDispatcherMetadata.PERMISSION_RESTRICTION;
 import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
 
-public class DispatchersImplTest {
+class DispatchersImplTest {
 
-  private NotificationCenter notificationCenter = new NotificationCenter(
+  private final NotificationCenter notificationCenter = new NotificationCenter(
     new NotificationDispatcherMetadata[] {
       NotificationDispatcherMetadata.create(MyNewIssuesNotificationHandler.KEY)
         .setProperty(GLOBAL_NOTIFICATION, "true")
@@ -42,17 +46,19 @@ public class DispatchersImplTest {
         .setProperty(GLOBAL_NOTIFICATION, "false"),
       NotificationDispatcherMetadata.create(QGChangeNotificationHandler.KEY)
         .setProperty(GLOBAL_NOTIFICATION, "true")
-        .setProperty(PER_PROJECT_NOTIFICATION, "true"),
+        .setProperty(PER_PROJECT_NOTIFICATION, "true")
+        .setProperty(PERMISSION_RESTRICTION, GlobalPermission.ADMINISTER_QUALITY_GATES.getKey()),
       NotificationDispatcherMetadata.create(FPOrAcceptedNotificationHandler.KEY)
         .setProperty(GLOBAL_NOTIFICATION, "false")
         .setProperty(PER_PROJECT_NOTIFICATION, "true")
+        .setProperty(ENABLED_BY_DEFAULT_NOTIFICATION, "true")
     },
     new NotificationChannel[] {});
 
-  private DispatchersImpl underTest = new DispatchersImpl(notificationCenter);
+  private final DispatchersImpl underTest = new DispatchersImpl(notificationCenter);
 
   @Test
-  public void get_sorted_global_dispatchers() {
+  void get_sorted_global_dispatchers() {
     underTest.start();
 
     assertThat(underTest.getGlobalDispatchers()).containsExactly(
@@ -60,11 +66,27 @@ public class DispatchersImplTest {
   }
 
   @Test
-  public void get_sorted_project_dispatchers() {
+  void get_sorted_project_dispatchers() {
     underTest.start();
 
     assertThat(underTest.getProjectDispatchers()).containsExactly(
       QGChangeNotificationHandler.KEY, FPOrAcceptedNotificationHandler.KEY, MyNewIssuesNotificationHandler.KEY);
   }
 
+  @Test
+  void get_enabled_by_default_dispatchers() {
+    underTest.start();
+
+    assertThat(underTest.getEnabledByDefaultDispatchers()).containsExactly(
+      FPOrAcceptedNotificationHandler.KEY);
+  }
+
+  @Test
+  void start_shouldProcessPermissionRestrictedDispatchers() {
+    underTest.start();
+
+    assertThat(underTest.getPermissionRestrictedDispatchers())
+      .containsExactlyEntriesOf(Map.of(QGChangeNotificationHandler.KEY, GlobalPermission.ADMINISTER_QUALITY_GATES.getKey()));
+  }
+
 }
index 6e815d0f4a4c8ace87ed90bbd5162a237545783f..03c1b1885da6516ebe0d8aefd3c4f082b4ac6ca2 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.notification.ws;
 
+import java.util.Map;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.server.notification.NotificationChannel;
@@ -42,8 +43,7 @@ public class NotificationCenterTest {
 
     underTest = new NotificationCenter(
       new NotificationDispatcherMetadata[] {metadata1, metadata2, metadata3},
-      new NotificationChannel[] {emailChannel, gtalkChannel}
-    );
+      new NotificationChannel[] {emailChannel, gtalkChannel});
   }
 
   @Test
@@ -74,4 +74,10 @@ public class NotificationCenterTest {
     assertThat(underTest.getDispatcherKeysForProperty("global", null)).hasSize(1);
   }
 
+  @Test
+  public void getValueByDispatchers_ShouldReturnExpectedMap() {
+    assertThat(underTest.getValueByDispatchers("global"))
+      .containsExactlyInAnyOrderEntriesOf(Map.of("Dispatcher1", "true", "Dispatcher2", "true", "Dispatcher3", "FOO"));
+  }
+
 }