]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-22516 Retrieve SMTP configuration from internal_properties
authorAntoine Vigneau <antoine.vigneau@sonarsource.com>
Tue, 30 Jul 2024 12:32:11 +0000 (14:32 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 16 Aug 2024 20:02:58 +0000 (20:02 +0000)
server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
server/sonar-server-common/src/main/java/org/sonar/server/email/EmailSmtpConfiguration.java [new file with mode: 0644]
server/sonar-server-common/src/main/java/org/sonar/server/notification/email/EmailNotificationChannel.java
server/sonar-server-common/src/test/java/org/sonar/server/notification/email/EmailNotificationChannelTest.java
server/sonar-webserver-core/src/main/java/org/sonar/server/notification/NotificationModule.java
server/sonar-webserver-core/src/test/java/org/sonar/server/notification/NotificationModuleTest.java
sonar-plugin-api/src/main/java/org/sonar/api/config/EmailSettings.java [new file with mode: 0644]

index ff49a13410167a0b99ce4e55ce5f73262e2a1657..4d9d5b47a8a1dd5e1b23e22fca6f7b9f6fe2c555 100644 (file)
@@ -88,6 +88,7 @@ import org.sonar.process.Props;
 import org.sonar.process.logging.LogbackHelper;
 import org.sonar.server.component.index.EntityDefinitionIndexer;
 import org.sonar.server.config.ConfigurationProvider;
+import org.sonar.server.email.EmailSmtpConfiguration;
 import org.sonar.server.es.EsModule;
 import org.sonar.server.es.IndexersImpl;
 import org.sonar.server.extension.CoreExtensionBootstraper;
@@ -407,6 +408,7 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
       // Notifications
       QGChangeEmailTemplate.class,
       EmailSettings.class,
+      EmailSmtpConfiguration.class,
       NotificationService.class,
       DefaultNotificationManager.class,
       EmailNotificationChannel.class,
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/email/EmailSmtpConfiguration.java b/server/sonar-server-common/src/main/java/org/sonar/server/email/EmailSmtpConfiguration.java
new file mode 100644 (file)
index 0000000..b7873fa
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 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.email;
+
+import org.sonar.api.ce.ComputeEngineSide;
+import org.sonar.api.server.ServerSide;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+
+@ServerSide
+@ComputeEngineSide
+public class EmailSmtpConfiguration {
+  // Common configuration
+  public static final String EMAIL_CONFIG_SMTP_HOST = "email.smtp_host.secured";
+  public static final String EMAIL_CONFIG_SMTP_HOST_DEFAULT = "";
+  public static final String EMAIL_CONFIG_SMTP_PORT = "email.smtp_port.secured";
+  public static final String EMAIL_CONFIG_SMTP_PORT_DEFAULT = "25";
+  public static final String EMAIL_CONFIG_SMTP_SECURE_CONNECTION = "email.smtp_secure_connection.secured";
+  public static final String EMAIL_CONFIG_SMTP_SECURE_CONNECTION_DEFAULT = "";
+  public static final String EMAIL_CONFIG_SMTP_AUTH_METHOD= "email.smtp.auth.method";
+  public static final String EMAIL_CONFIG_SMTP_AUTH_METHOD_DEFAULT = "BASIC";
+  // Email content
+  public static final String EMAIL_CONFIG_FROM = "email.from";
+  public static final String EMAIL_CONFIG_FROM_DEFAULT = "noreply@nowhere";
+  public static final String EMAIL_CONFIG_FROM_NAME = "email.fromName";
+  public static final String EMAIL_CONFIG_FROM_NAME_DEFAULT = "SonarQube";
+  public static final String EMAIL_CONFIG_PREFIX = "email.prefix";
+  public static final String EMAIL_CONFIG_PREFIX_DEFAULT = "[SONARQUBE]";
+  // Basic Auth
+  public static final String EMAIL_CONFIG_SMTP_USERNAME = "email.smtp_username.secured";
+  public static final String EMAIL_CONFIG_SMTP_USERNAME_DEFAULT = "";
+  public static final String EMAIL_CONFIG_SMTP_PASSWORD = "email.smtp_password.secured";
+  public static final String EMAIL_CONFIG_SMTP_PASSWORD_DEFAULT = "";
+  // Modern auth
+  public static final String EMAIL_CONFIG_SMTP_OAUTH_HOST = "email.smtp.oauth.host";
+  public static final String EMAIL_CONFIG_SMTP_OAUTH_HOST_DEFAULT = "https://login.microsoftonline.com";
+  public static final String EMAIL_CONFIG_SMTP_OAUTH_TENANT = "email.smtp.oauth.tenant";
+  public static final String EMAIL_CONFIG_SMTP_OAUTH_CLIENTID = "email.smtp.oauth.clientId";
+  public static final String EMAIL_CONFIG_SMTP_OAUTH_CLIENTSECRET = "email.smtp.oauth.clientSecret";
+  public static final String EMAIL_CONFIG_SMTP_OAUTH_SCOPE = "email.smtp.oauth.scope";
+  public static final String EMAIL_CONFIG_SMTP_OAUTH_SCOPE_DEFAULT = "client_credentials";
+
+  private final DbClient dbClient;
+
+  public EmailSmtpConfiguration(DbClient dbClient) {
+    this.dbClient = dbClient;
+  }
+
+  public String getSmtpHost() {
+    return get(EMAIL_CONFIG_SMTP_HOST, EMAIL_CONFIG_SMTP_HOST_DEFAULT);
+  }
+
+  public int getSmtpPort() {
+    return Integer.parseInt(get(EMAIL_CONFIG_SMTP_PORT, EMAIL_CONFIG_SMTP_PORT_DEFAULT));
+  }
+
+  public String getSecureConnection() {
+    return get(EMAIL_CONFIG_SMTP_SECURE_CONNECTION, EMAIL_CONFIG_SMTP_SECURE_CONNECTION_DEFAULT);
+  }
+
+  public String getAuthMethod() {
+    return get(EMAIL_CONFIG_SMTP_AUTH_METHOD, EMAIL_CONFIG_SMTP_AUTH_METHOD_DEFAULT);
+  }
+
+  public String getFrom() {
+    return get(EMAIL_CONFIG_FROM, EMAIL_CONFIG_FROM_DEFAULT);
+  }
+
+  public String getFromName() {
+    return get(EMAIL_CONFIG_FROM_NAME, EMAIL_CONFIG_FROM_NAME_DEFAULT);
+  }
+
+  public String getPrefix() {
+    return get(EMAIL_CONFIG_PREFIX, EMAIL_CONFIG_PREFIX_DEFAULT);
+  }
+
+  public String getSmtpUsername() {
+    return get(EMAIL_CONFIG_SMTP_USERNAME, EMAIL_CONFIG_SMTP_USERNAME_DEFAULT);
+  }
+
+  public String getSmtpPassword() {
+    return get(EMAIL_CONFIG_SMTP_PASSWORD, EMAIL_CONFIG_SMTP_PASSWORD_DEFAULT);
+  }
+
+  public String getOAuthHost() {
+    return get(EMAIL_CONFIG_SMTP_OAUTH_HOST, EMAIL_CONFIG_SMTP_OAUTH_HOST_DEFAULT);
+  }
+
+  public String getOAuthTenant() {
+    return get(EMAIL_CONFIG_SMTP_OAUTH_TENANT, "");
+  }
+
+  public String getOAuthClientId() {
+    return get(EMAIL_CONFIG_SMTP_OAUTH_CLIENTID, "");
+  }
+
+  public String getOAuthClientSecret() {
+    return get(EMAIL_CONFIG_SMTP_OAUTH_CLIENTSECRET, "");
+  }
+
+  public String getOAuthScope() {
+    return get(EMAIL_CONFIG_SMTP_OAUTH_SCOPE, EMAIL_CONFIG_SMTP_OAUTH_SCOPE_DEFAULT);
+  }
+
+  private String get(String key, String defaultValue) {
+    try (DbSession dbSession = dbClient.openSession(false)) {
+      return dbClient.internalPropertiesDao().selectByKey(dbSession, key).orElse(defaultValue);
+    }
+  }
+
+}
index f91a2fef12a880cf3005e265c6f14c6744f8df6b..4c9fcc001098da0a8cfcdfecb1dbc8ebca7a15af 100644 (file)
@@ -33,13 +33,14 @@ import org.apache.commons.mail.HtmlEmail;
 import org.apache.commons.mail.SimpleEmail;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.sonar.api.config.EmailSettings;
 import org.sonar.api.notifications.Notification;
+import org.sonar.api.platform.Server;
 import org.sonar.api.user.User;
 import org.sonar.api.utils.SonarException;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.user.UserDto;
+import org.sonar.server.email.EmailSmtpConfiguration;
 import org.sonar.server.issue.notification.EmailMessage;
 import org.sonar.server.issue.notification.EmailTemplate;
 import org.sonar.server.notification.NotificationChannel;
@@ -97,12 +98,14 @@ public class EmailNotificationChannel extends NotificationChannel {
   private static final String SMTP_HOST_NOT_CONFIGURED_DEBUG_MSG = "SMTP host was not configured - email will not be sent";
   private static final String MAIL_SENT_FROM = "%sMail sent from: %s";
 
-  private final EmailSettings configuration;
+  private final EmailSmtpConfiguration configuration;
+  private final Server server;
   private final EmailTemplate[] templates;
   private final DbClient dbClient;
 
-  public EmailNotificationChannel(EmailSettings configuration, EmailTemplate[] templates, DbClient dbClient) {
+  public EmailNotificationChannel(EmailSmtpConfiguration configuration, Server server, EmailTemplate[] templates, DbClient dbClient) {
     this.configuration = configuration;
+    this.server = server;
     this.templates = templates;
     this.dbClient = dbClient;
   }
@@ -260,7 +263,7 @@ public class EmailNotificationChannel extends NotificationChannel {
   @CheckForNull
   private String resolveHost() {
     try {
-      return new URL(configuration.getServerBaseURL()).getHost();
+      return new URL(server.getPublicRootUrl()).getHost();
     } catch (MalformedURLException e) {
       // ignore
       return null;
@@ -282,7 +285,7 @@ public class EmailNotificationChannel extends NotificationChannel {
       }
       // Set headers for proper filtering
       email.addHeader(LIST_ID_HEADER, "SonarQube <sonar." + host + ">");
-      email.addHeader(LIST_ARCHIVE_HEADER, configuration.getServerBaseURL());
+      email.addHeader(LIST_ARCHIVE_HEADER, server.getPublicRootUrl());
     }
   }
 
@@ -336,7 +339,7 @@ public class EmailNotificationChannel extends NotificationChannel {
   }
 
   private String getServerBaseUrlFooter() {
-    return String.format(MAIL_SENT_FROM, "\n\n", configuration.getServerBaseURL());
+    return String.format(MAIL_SENT_FROM, "\n\n", server.getPublicRootUrl());
   }
 
 }
index 567b829639897d7ae8190c1622d392778f257860..e4aad4cf909e8183cc8e9743bb268319a7197b74 100644 (file)
@@ -39,10 +39,11 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.slf4j.event.Level;
-import org.sonar.api.config.EmailSettings;
 import org.sonar.api.notifications.Notification;
+import org.sonar.api.platform.Server;
 import org.sonar.api.testfixtures.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.server.email.EmailSmtpConfiguration;
 import org.sonar.server.issue.notification.EmailMessage;
 import org.sonar.server.issue.notification.EmailTemplate;
 import org.sonar.server.notification.email.EmailNotificationChannel.EmailDeliveryRequest;
@@ -69,7 +70,8 @@ public class EmailNotificationChannelTest {
   public LogTester logTester = new LogTester();
 
   private Wiser smtpServer;
-  private EmailSettings configuration;
+  private EmailSmtpConfiguration configuration;
+  private Server server;
   private EmailNotificationChannel underTest;
 
   @Before
@@ -78,8 +80,10 @@ public class EmailNotificationChannelTest {
     smtpServer = new Wiser(0);
     smtpServer.start();
 
-    configuration = mock(EmailSettings.class);
-    underTest = new EmailNotificationChannel(configuration, null, null);
+    configuration = mock(EmailSmtpConfiguration.class);
+    server = mock(Server.class);
+
+    underTest = new EmailNotificationChannel(configuration, server, null, null);
   }
 
   @After
@@ -251,8 +255,8 @@ public class EmailNotificationChannelTest {
 
   @Test
   public void deliverAll_has_no_effect_if_set_is_empty() {
-    EmailSettings emailSettings = mock(EmailSettings.class);
-    EmailNotificationChannel underTest = new EmailNotificationChannel(emailSettings, null, null);
+    EmailSmtpConfiguration emailSettings = mock(EmailSmtpConfiguration.class);
+    EmailNotificationChannel underTest = new EmailNotificationChannel(emailSettings, server, null, null);
 
     int count = underTest.deliverAll(Collections.emptySet());
 
@@ -263,12 +267,12 @@ public class EmailNotificationChannelTest {
 
   @Test
   public void deliverAll_has_no_effect_if_smtp_host_is_null() {
-    EmailSettings emailSettings = mock(EmailSettings.class);
+    EmailSmtpConfiguration emailSettings = mock(EmailSmtpConfiguration.class);
     when(emailSettings.getSmtpHost()).thenReturn(null);
     Set<EmailDeliveryRequest> requests = IntStream.range(0, 1 + new Random().nextInt(10))
       .mapToObj(i -> new EmailDeliveryRequest("foo" + i + "@moo", mock(Notification.class)))
       .collect(toSet());
-    EmailNotificationChannel underTest = new EmailNotificationChannel(emailSettings, null, null);
+    EmailNotificationChannel underTest = new EmailNotificationChannel(emailSettings, server, null, null);
 
     int count = underTest.deliverAll(requests);
 
@@ -281,12 +285,12 @@ public class EmailNotificationChannelTest {
   @Test
   @UseDataProvider("emptyStrings")
   public void deliverAll_ignores_requests_which_recipient_is_empty(String emptyString) {
-    EmailSettings emailSettings = mock(EmailSettings.class);
+    EmailSmtpConfiguration emailSettings = mock(EmailSmtpConfiguration.class);
     when(emailSettings.getSmtpHost()).thenReturn(null);
     Set<EmailDeliveryRequest> requests = IntStream.range(0, 1 + new Random().nextInt(10))
       .mapToObj(i -> new EmailDeliveryRequest(emptyString, mock(Notification.class)))
       .collect(toSet());
-    EmailNotificationChannel underTest = new EmailNotificationChannel(emailSettings, null, null);
+    EmailNotificationChannel underTest = new EmailNotificationChannel(emailSettings, server, null, null);
 
     int count = underTest.deliverAll(requests);
 
@@ -312,7 +316,7 @@ public class EmailNotificationChannelTest {
     Set<EmailDeliveryRequest> requests = Stream.of(notification1, notification2, notification3)
       .map(t -> new EmailDeliveryRequest(recipientEmail, t))
       .collect(toSet());
-    EmailNotificationChannel underTest = new EmailNotificationChannel(configuration, new EmailTemplate[] {template1, template3}, null);
+    EmailNotificationChannel underTest = new EmailNotificationChannel(configuration, server, new EmailTemplate[] {template1, template3}, null);
 
     int count = underTest.deliverAll(requests);
 
@@ -352,7 +356,7 @@ public class EmailNotificationChannelTest {
     when(template11.format(notification1)).thenReturn(emailMessage11);
     when(template12.format(notification1)).thenReturn(emailMessage12);
     EmailDeliveryRequest request = new EmailDeliveryRequest(recipientEmail, notification1);
-    EmailNotificationChannel underTest = new EmailNotificationChannel(configuration, new EmailTemplate[] {template11, template12}, null);
+    EmailNotificationChannel underTest = new EmailNotificationChannel(configuration, server, new EmailTemplate[] {template11, template12}, null);
 
     int count = underTest.deliverAll(Collections.singleton(request));
 
@@ -377,7 +381,7 @@ public class EmailNotificationChannelTest {
     when(configuration.getFrom()).thenReturn("server@nowhere");
     when(configuration.getFromName()).thenReturn("SonarQube from NoWhere");
     when(configuration.getPrefix()).thenReturn(SUBJECT_PREFIX);
-    when(configuration.getServerBaseURL()).thenReturn("http://nemo.sonarsource.org");
+    when(server.getPublicRootUrl()).thenReturn("http://nemo.sonarsource.org");
   }
 
 }
index f18ed2d391580ad3b874ff349d07e70ceabc72a8..9fcd6a9291830547ea04b8a64aa4168d860d378c 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.server.notification;
 
 import org.sonar.api.config.EmailSettings;
 import org.sonar.core.platform.Module;
+import org.sonar.server.email.EmailSmtpConfiguration;
 import org.sonar.server.notification.email.EmailNotificationChannel;
 
 public class NotificationModule extends Module {
@@ -28,6 +29,7 @@ public class NotificationModule extends Module {
   protected void configureModule() {
     add(
       EmailSettings.class,
+      EmailSmtpConfiguration.class,
       NotificationService.class,
       DefaultNotificationManager.class,
       NotificationDaemon.class,
index fa040dc7bd5979904704d070c4450a66533a4355..94fadfc4d61b18f96948fa55fea6a6b64e23e38e 100644 (file)
@@ -29,6 +29,6 @@ public class NotificationModuleTest {
   public void verify_count_of_added_components() {
     ListContainer container = new ListContainer();
     new NotificationModule().configure(container);
-    assertThat(container.getAddedObjects()).hasSize(5);
+    assertThat(container.getAddedObjects()).hasSize(6);
   }
 }
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/EmailSettings.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/EmailSettings.java
new file mode 100644 (file)
index 0000000..63b5f43
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.plugins.email;
+
+import org.apache.commons.configuration.Configuration;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.ServerExtension;
+
+/**
+ * Ruby uses constants from this class.
+ * 
+ * @since 2.10
+ */
+public class EmailConfiguration implements ServerExtension {
+
+  public static final String SMTP_HOST = "email.smtp_host";
+  public static final String SMTP_HOST_DEFAULT = "";
+  public static final String SMTP_PORT = "email.smtp_port";
+  public static final String SMTP_PORT_DEFAULT = "25";
+  public static final String SMTP_USE_TLS = "email.smtp_use_tls";
+  public static final boolean SMTP_USE_TLS_DEFAULT = false;
+  public static final String SMTP_USERNAME = "email.smtp_username";
+  public static final String SMTP_USERNAME_DEFAULT = "";
+  public static final String SMTP_PASSWORD = "email.smtp_password";
+  public static final String SMTP_PASSWORD_DEFAULT = "";
+  public static final String FROM = "email.from";
+  public static final String FROM_DEFAULT = "noreply@nowhere";
+  public static final String PREFIX = "email.prefix";
+  public static final String PREFIX_DEFAULT = "[SONAR]";
+
+  private Configuration configuration;
+
+  public EmailConfiguration(Configuration configuration) {
+    this.configuration = configuration;
+  }
+
+  public String getSmtpHost() {
+    return configuration.getString(SMTP_HOST, SMTP_HOST_DEFAULT);
+  }
+
+  public String getSmtpPort() {
+    return configuration.getString(SMTP_PORT, SMTP_PORT_DEFAULT);
+  }
+
+  public boolean isUseTLS() {
+    return configuration.getBoolean(SMTP_USE_TLS, SMTP_USE_TLS_DEFAULT);
+  }
+
+  public String getSmtpUsername() {
+    return configuration.getString(SMTP_USERNAME, SMTP_USERNAME_DEFAULT);
+  }
+
+  public String getSmtpPassword() {
+    return configuration.getString(SMTP_PASSWORD, SMTP_PASSWORD_DEFAULT);
+  }
+
+  public String getFrom() {
+    return configuration.getString(FROM, FROM_DEFAULT);
+  }
+
+  public String getPrefix() {
+    return configuration.getString(PREFIX, PREFIX_DEFAULT);
+  }
+
+  public String getServerBaseURL() {
+    return configuration.getString(CoreProperties.SERVER_BASE_URL, CoreProperties.SERVER_BASE_URL_DEFAULT_VALUE);
+  }
+
+}