diff options
author | Antoine Vigneau <antoine.vigneau@sonarsource.com> | 2024-11-27 15:42:48 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2024-11-29 20:03:09 +0000 |
commit | 488c8a3cce3fe721370970b04ff3cefde0f6d0b2 (patch) | |
tree | 17b0f405a9793704382719f033afb6f33aa12173 /server/sonar-server-common | |
parent | 170f39121421b369abf7fda95fb1b47f57e1362a (diff) | |
download | sonarqube-488c8a3cce3fe721370970b04ff3cefde0f6d0b2.tar.gz sonarqube-488c8a3cce3fe721370970b04ff3cefde0f6d0b2.zip |
SONAR-23719 Make sure all components are using the new Email Configuration
Diffstat (limited to 'server/sonar-server-common')
19 files changed, 320 insertions, 303 deletions
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/email/EmailSender.java b/server/sonar-server-common/src/main/java/org/sonar/server/email/EmailSender.java index 8d1e95103f3..047590493b0 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/email/EmailSender.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/email/EmailSender.java @@ -21,26 +21,32 @@ package org.sonar.server.email; import java.net.MalformedURLException; import java.time.Duration; +import java.util.Properties; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.mail.Email; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.HtmlEmail; import org.apache.commons.mail.MultiPartEmail; -import org.sonar.api.config.EmailSettings; +import org.sonar.api.platform.Server; +import org.sonar.server.oauth.OAuthMicrosoftRestClient; import static java.nio.charset.StandardCharsets.UTF_8; import static java.time.temporal.ChronoUnit.SECONDS; -import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase; -import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank; +import static org.sonar.server.email.EmailSmtpConfiguration.EMAIL_CONFIG_SMTP_AUTH_METHOD_OAUTH; public abstract class EmailSender<T extends BasicEmail> { private static final Duration SOCKET_TIMEOUT = Duration.of(30, SECONDS); - protected final EmailSettings emailSettings; + protected final EmailSmtpConfiguration emailSmtpConfiguration; + protected final Server server; + private final OAuthMicrosoftRestClient oAuthMicrosoftRestClient; - protected EmailSender(EmailSettings emailSettings) { - this.emailSettings = emailSettings; + protected EmailSender(EmailSmtpConfiguration emailSmtpConfiguration, Server server, OAuthMicrosoftRestClient oAuthMicrosoftRestClient) { + this.emailSmtpConfiguration = emailSmtpConfiguration; + this.server = server; + this.oAuthMicrosoftRestClient = oAuthMicrosoftRestClient; } public void send(T report) { @@ -68,44 +74,60 @@ public abstract class EmailSender<T extends BasicEmail> { } public boolean areEmailSettingsSet() { - return isNotBlank(emailSettings.getSmtpHost()); + return isNotBlank(emailSmtpConfiguration.getSmtpHost()); } protected abstract void addReportContent(HtmlEmail email, T report) throws EmailException, MalformedURLException; private void setEmailSettings(MultiPartEmail email) throws EmailException { configureSecureConnection(email); - email.setHostName(emailSettings.getSmtpHost()); + email.setHostName(emailSmtpConfiguration.getSmtpHost()); email.setSocketConnectionTimeout(SOCKET_TIMEOUT); email.setSocketTimeout(SOCKET_TIMEOUT); email.setCharset(UTF_8.name()); - email.setFrom(emailSettings.getFrom(), emailSettings.getFromName()); + email.setFrom(emailSmtpConfiguration.getFrom(), emailSmtpConfiguration.getFromName()); - if (isNotBlank(emailSettings.getSmtpUsername() + emailSettings.getSmtpPassword())) { - email.setAuthentication(emailSettings.getSmtpUsername(), emailSettings.getSmtpPassword()); + if (EMAIL_CONFIG_SMTP_AUTH_METHOD_OAUTH.equals(emailSmtpConfiguration.getAuthMethod())) { + setOauthAuthentication(email); + } else if (StringUtils.isNotBlank(emailSmtpConfiguration.getSmtpUsername()) || StringUtils.isNotBlank(emailSmtpConfiguration.getSmtpPassword())) { + setBasicAuthentication(email); + } + } + + private void setOauthAuthentication(Email email) throws EmailException { + String token = oAuthMicrosoftRestClient.getAccessTokenFromClientCredentialsGrantFlow(emailSmtpConfiguration.getOAuthHost(), emailSmtpConfiguration.getOAuthClientId(), + emailSmtpConfiguration.getOAuthClientSecret(), emailSmtpConfiguration.getOAuthTenant(), emailSmtpConfiguration.getOAuthScope()); + email.setAuthentication(emailSmtpConfiguration.getSmtpUsername(), token); + Properties props = email.getMailSession().getProperties(); + props.put("mail.smtp.auth.mechanisms", "XOAUTH2"); + props.put("mail.smtp.auth.login.disable", "true"); + props.put("mail.smtp.auth.plain.disable", "true"); + } + + private void setBasicAuthentication(Email email) { + if (StringUtils.isNotBlank(emailSmtpConfiguration.getSmtpUsername()) || StringUtils.isNotBlank(emailSmtpConfiguration.getSmtpPassword())) { + email.setAuthentication(emailSmtpConfiguration.getSmtpUsername(), emailSmtpConfiguration.getSmtpPassword()); } } private void configureSecureConnection(MultiPartEmail email) { - String secureConnection = emailSettings.getSecureConnection(); - int smtpPort = emailSettings.getSmtpPort(); - if (equalsIgnoreCase(secureConnection, "ssl")) { + if (StringUtils.equalsIgnoreCase(emailSmtpConfiguration.getSecureConnection(), "SSLTLS")) { email.setSSLOnConnect(true); email.setSSLCheckServerIdentity(true); - email.setSslSmtpPort(String.valueOf(smtpPort)); + email.setSslSmtpPort(String.valueOf(emailSmtpConfiguration.getSmtpPort())); // this port is not used except in EmailException message, that's why it's set with the same value than SSL port. // It prevents from getting bad message. - email.setSmtpPort(smtpPort); - } else if (equalsIgnoreCase(secureConnection, "starttls")) { + email.setSmtpPort(emailSmtpConfiguration.getSmtpPort()); + } else if (StringUtils.equalsIgnoreCase(emailSmtpConfiguration.getSecureConnection(), "STARTTLS")) { email.setStartTLSEnabled(true); email.setStartTLSRequired(true); email.setSSLCheckServerIdentity(true); - email.setSmtpPort(smtpPort); - } else if (isBlank(secureConnection)) { - email.setSmtpPort(smtpPort); + email.setSmtpPort(emailSmtpConfiguration.getSmtpPort()); + } else if (StringUtils.equalsIgnoreCase(emailSmtpConfiguration.getSecureConnection(), "NONE")) { + email.setSmtpPort(emailSmtpConfiguration.getSmtpPort()); } else { - throw new IllegalStateException("Unknown type of SMTP secure connection: " + secureConnection); + throw new IllegalStateException("Unknown type of SMTP secure connection: " + emailSmtpConfiguration.getSecureConnection()); } } 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 index 883b5ce0e49..1001da4fee1 100644 --- 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 @@ -44,6 +44,7 @@ public class EmailSmtpConfiguration { // Auth selection public static final String EMAIL_CONFIG_SMTP_AUTH_METHOD = "email.smtp.auth.method"; public static final String EMAIL_CONFIG_SMTP_AUTH_METHOD_DEFAULT = "BASIC"; + public static final String EMAIL_CONFIG_SMTP_AUTH_METHOD_OAUTH = "OAUTH"; // Basic Auth public static final String EMAIL_CONFIG_SMTP_USERNAME = "email.smtp_username.secured"; public static final String EMAIL_CONFIG_SMTP_USERNAME_DEFAULT = ""; diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/AbstractNewIssuesEmailTemplate.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/AbstractNewIssuesEmailTemplate.java index ef679e187ed..ad8cf300c6b 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/AbstractNewIssuesEmailTemplate.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/AbstractNewIssuesEmailTemplate.java @@ -24,8 +24,8 @@ import java.net.URLEncoder; import java.util.Date; import javax.annotation.CheckForNull; import javax.annotation.Nullable; -import org.sonar.api.config.EmailSettings; import org.sonar.api.notifications.Notification; +import org.sonar.api.platform.Server; import org.sonar.api.utils.DateUtils; import org.sonar.server.issue.notification.NewIssuesStatistics.Metric; @@ -51,10 +51,10 @@ public abstract class AbstractNewIssuesEmailTemplate implements EmailTemplate { static final String FIELD_BRANCH = "branch"; static final String FIELD_PULL_REQUEST = "pullRequest"; - protected final EmailSettings settings; + protected final Server server; - protected AbstractNewIssuesEmailTemplate(EmailSettings settings) { - this.settings = settings; + protected AbstractNewIssuesEmailTemplate(Server server) { + this.server = server; } public static String encode(String toEncode) { @@ -175,8 +175,7 @@ public abstract class AbstractNewIssuesEmailTemplate implements EmailTemplate { String dateString = notification.getFieldValue(FIELD_PROJECT_DATE); if (projectKey != null && dateString != null) { Date date = DateUtils.parseDateTime(dateString); - String url = String.format("%s/project/issues?id=%s", - settings.getServerBaseURL(), encode(projectKey)); + String url = String.format("%s/project/issues?id=%s", server.getPublicRootUrl(), encode(projectKey)); String branchName = notification.getFieldValue(FIELD_BRANCH); if (branchName != null) { url += "&branch=" + encode(branchName); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/ChangesOnMyIssuesEmailTemplate.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/ChangesOnMyIssuesEmailTemplate.java index 250f17973c4..98b2fa204da 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/ChangesOnMyIssuesEmailTemplate.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/ChangesOnMyIssuesEmailTemplate.java @@ -23,8 +23,8 @@ import com.google.common.collect.ListMultimap; import com.google.common.collect.SetMultimap; import java.util.List; import javax.annotation.CheckForNull; -import org.sonar.api.config.EmailSettings; import org.sonar.api.notifications.Notification; +import org.sonar.api.platform.Server; import org.sonar.core.i18n.I18n; import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.AnalysisChange; import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.ChangedIssue; @@ -47,8 +47,8 @@ import static org.sonar.server.issue.notification.RuleGroup.resolveGroup; public class ChangesOnMyIssuesEmailTemplate extends IssueChangesEmailTemplate { private static final String NOTIFICATION_NAME_I18N_KEY = "notification.dispatcher.ChangesOnMyIssue"; - public ChangesOnMyIssuesEmailTemplate(I18n i18n, EmailSettings settings) { - super(i18n, settings); + public ChangesOnMyIssuesEmailTemplate(I18n i18n, Server server) { + super(i18n, server); } @Override diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/FpOrAcceptedEmailTemplate.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/FpOrAcceptedEmailTemplate.java index d1169ac6540..e95758f0da6 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/FpOrAcceptedEmailTemplate.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/FpOrAcceptedEmailTemplate.java @@ -20,8 +20,8 @@ package org.sonar.server.issue.notification; import javax.annotation.CheckForNull; -import org.sonar.api.config.EmailSettings; import org.sonar.api.notifications.Notification; +import org.sonar.api.platform.Server; import org.sonar.core.i18n.I18n; import org.sonar.server.issue.notification.FPOrAcceptedNotification.FpPrAccepted; import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.User; @@ -37,8 +37,8 @@ public class FpOrAcceptedEmailTemplate extends IssueChangesEmailTemplate { private static final String NOTIFICATION_NAME_I18N_KEY = "notification.dispatcher.NewFalsePositiveIssue"; - public FpOrAcceptedEmailTemplate(I18n i18n, EmailSettings settings) { - super(i18n, settings); + public FpOrAcceptedEmailTemplate(I18n i18n, Server server) { + super(i18n, server); } @Override diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/IssueChangesEmailTemplate.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/IssueChangesEmailTemplate.java index 8debc1f4c1e..2f44fb408ae 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/IssueChangesEmailTemplate.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/IssueChangesEmailTemplate.java @@ -36,7 +36,7 @@ import java.util.SortedSet; import java.util.function.BiConsumer; import java.util.function.Consumer; import javax.annotation.Nullable; -import org.sonar.api.config.EmailSettings; +import org.sonar.api.platform.Server; import org.sonar.api.rules.RuleType; import org.sonar.core.i18n.I18n; import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.ChangedIssue; @@ -74,11 +74,11 @@ public abstract class IssueChangesEmailTemplate implements EmailTemplate { private static final String URL_ENCODED_COMMA = urlEncode(","); private final I18n i18n; - private final EmailSettings settings; + private final Server server; - protected IssueChangesEmailTemplate(I18n i18n, EmailSettings settings) { + protected IssueChangesEmailTemplate(I18n i18n, Server server) { this.i18n = i18n; - this.settings = settings; + this.server = server; } /** @@ -195,7 +195,7 @@ public abstract class IssueChangesEmailTemplate implements EmailTemplate { BiConsumer<StringBuilder, Collection<ChangedIssue>> projectIssuePageHref(String projectParams) { return (s, issues) -> { - s.append(settings.getServerBaseURL()).append("/project/issues?").append(projectParams) + s.append(server.getPublicRootUrl()).append("/project/issues?").append(projectParams) .append("&issues="); Iterator<ChangedIssue> issueIterator = issues.iterator(); @@ -214,7 +214,7 @@ public abstract class IssueChangesEmailTemplate implements EmailTemplate { BiConsumer<StringBuilder, Collection<ChangedIssue>> securityHotspotPageHref(String projectParams) { return (s, issues) -> { - s.append(settings.getServerBaseURL()).append("/security_hotspots?").append(projectParams) + s.append(server.getPublicRootUrl()).append("/security_hotspots?").append(projectParams) .append("&hotspots="); Iterator<ChangedIssue> issueIterator = issues.iterator(); @@ -246,7 +246,7 @@ public abstract class IssueChangesEmailTemplate implements EmailTemplate { .append('"').append(i18n.message(Locale.ENGLISH, notificationI18nKey, notificationI18nKey)).append('"') .append(" notifications from SonarQube."); s.append(" Click "); - link(s, s1 -> s1.append(settings.getServerBaseURL()).append("/account/notifications"), s1 -> s1.append("here")); + link(s, s1 -> s1.append(server.getPublicRootUrl()).append("/account/notifications"), s1 -> s1.append("here")); s.append(" to edit your email preferences."); s.append("</small>"); }); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplate.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplate.java index 1669aff81cc..b4fdf58fb6e 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplate.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplate.java @@ -20,8 +20,8 @@ package org.sonar.server.issue.notification; import java.util.Date; -import org.sonar.api.config.EmailSettings; import org.sonar.api.notifications.Notification; +import org.sonar.api.platform.Server; import org.sonar.api.utils.DateUtils; import org.sonar.server.issue.notification.NewIssuesStatistics.Metric; @@ -30,8 +30,8 @@ import org.sonar.server.issue.notification.NewIssuesStatistics.Metric; */ public class MyNewIssuesEmailTemplate extends AbstractNewIssuesEmailTemplate { - public MyNewIssuesEmailTemplate(EmailSettings settings) { - super(settings); + public MyNewIssuesEmailTemplate(Server server) { + super(server); } @Override @@ -61,7 +61,7 @@ public class MyNewIssuesEmailTemplate extends AbstractNewIssuesEmailTemplate { if (projectKey != null && dateString != null && assignee != null) { Date date = DateUtils.parseDateTime(dateString); String url = String.format("%s/project/issues?id=%s&assignees=%s", - settings.getServerBaseURL(), + server.getPublicRootUrl(), encode(projectKey), encode(assignee)); String branchName = notification.getFieldValue(FIELD_BRANCH); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/NewIssuesEmailTemplate.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/NewIssuesEmailTemplate.java index 5296f91ee41..76dd5409521 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/NewIssuesEmailTemplate.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/notification/NewIssuesEmailTemplate.java @@ -19,16 +19,16 @@ */ package org.sonar.server.issue.notification; -import org.sonar.api.config.EmailSettings; import org.sonar.api.notifications.Notification; +import org.sonar.api.platform.Server; /** * Creates email message for notification "new-issues". */ public class NewIssuesEmailTemplate extends AbstractNewIssuesEmailTemplate { - public NewIssuesEmailTemplate(EmailSettings settings) { - super(settings); + public NewIssuesEmailTemplate(Server server) { + super(server); } @Override diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/notification/email/EmailNotificationChannel.java b/server/sonar-server-common/src/main/java/org/sonar/server/notification/email/EmailNotificationChannel.java index f4005480631..0fc971bd8f0 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/notification/email/EmailNotificationChannel.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/notification/email/EmailNotificationChannel.java @@ -42,13 +42,14 @@ 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.oauth.OAuthMicrosoftRestClient; import org.sonar.server.issue.notification.EmailMessage; import org.sonar.server.issue.notification.EmailTemplate; import org.sonar.server.notification.NotificationChannel; +import org.sonar.server.oauth.OAuthMicrosoftRestClient; import static java.time.temporal.ChronoUnit.SECONDS; import static java.util.Objects.requireNonNull; +import static org.sonar.server.email.EmailSmtpConfiguration.EMAIL_CONFIG_SMTP_AUTH_METHOD_OAUTH; /** * References: @@ -99,18 +100,20 @@ public class EmailNotificationChannel extends NotificationChannel { private static final String SUBJECT_DEFAULT = "Notification"; 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 static final String OAUTH_AUTH_METHOD = "OAUTH"; private final EmailSmtpConfiguration configuration; private final Server server; private final EmailTemplate[] templates; private final DbClient dbClient; + private final OAuthMicrosoftRestClient oAuthMicrosoftRestClient; - public EmailNotificationChannel(EmailSmtpConfiguration configuration, Server server, EmailTemplate[] templates, DbClient dbClient) { + public EmailNotificationChannel(EmailSmtpConfiguration configuration, Server server, EmailTemplate[] templates, DbClient dbClient, + OAuthMicrosoftRestClient oAuthMicrosoftRestClient) { this.configuration = configuration; this.server = server; this.templates = templates; this.dbClient = dbClient; + this.oAuthMicrosoftRestClient = oAuthMicrosoftRestClient; } public boolean isActivated() { @@ -297,7 +300,7 @@ public class EmailNotificationChannel extends NotificationChannel { configureSecureConnection(email); email.setSocketConnectionTimeout(SOCKET_TIMEOUT); email.setSocketTimeout(SOCKET_TIMEOUT); - if (OAUTH_AUTH_METHOD.equals(configuration.getAuthMethod())) { + if (EMAIL_CONFIG_SMTP_AUTH_METHOD_OAUTH.equals(configuration.getAuthMethod())) { setOauthAuthentication(email); } else if (StringUtils.isNotBlank(configuration.getSmtpUsername()) || StringUtils.isNotBlank(configuration.getSmtpPassword())) { setBasicAuthentication(email); @@ -305,7 +308,7 @@ public class EmailNotificationChannel extends NotificationChannel { } private void setOauthAuthentication(Email email) throws EmailException { - String token = OAuthMicrosoftRestClient.getAccessTokenFromClientCredentialsGrantFlow(configuration.getOAuthHost(), configuration.getOAuthClientId(), + String token = oAuthMicrosoftRestClient.getAccessTokenFromClientCredentialsGrantFlow(configuration.getOAuthHost(), configuration.getOAuthClientId(), configuration.getOAuthClientSecret(), configuration.getOAuthTenant(), configuration.getOAuthScope()); email.setAuthentication(configuration.getSmtpUsername(), token); Properties props = email.getMailSession().getProperties(); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/oauth/OAuthMicrosoftRestClient.java b/server/sonar-server-common/src/main/java/org/sonar/server/oauth/OAuthMicrosoftRestClient.java index 3a7ada75440..24311990824 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/oauth/OAuthMicrosoftRestClient.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/oauth/OAuthMicrosoftRestClient.java @@ -26,11 +26,7 @@ import java.util.concurrent.ExecutionException; public class OAuthMicrosoftRestClient { - private OAuthMicrosoftRestClient() { - // Only static method - } - - public static String getAccessTokenFromClientCredentialsGrantFlow(String host, String clientId, String clientSecret, String tenant, String scope) { + public String getAccessTokenFromClientCredentialsGrantFlow(String host, String clientId, String clientSecret, String tenant, String scope) { final OAuth20Service service = new ServiceBuilder(clientId) .apiSecret(clientSecret) .defaultScope(scope) diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplate.java b/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplate.java index f7abea14a29..9a7d1706b6a 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplate.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplate.java @@ -23,9 +23,9 @@ import java.util.Optional; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.commons.lang3.StringUtils; -import org.sonar.api.config.EmailSettings; import org.sonar.api.measures.Metric; import org.sonar.api.notifications.Notification; +import org.sonar.api.platform.Server; import org.sonar.server.issue.notification.EmailMessage; import org.sonar.server.issue.notification.EmailTemplate; import org.sonar.server.measure.Rating; @@ -37,10 +37,10 @@ import org.sonar.server.measure.Rating; */ public class QGChangeEmailTemplate implements EmailTemplate { - private final EmailSettings configuration; + private final Server server; - public QGChangeEmailTemplate(EmailSettings configuration) { - this.configuration = configuration; + public QGChangeEmailTemplate( Server server) { + this.server = server; } @Override @@ -123,7 +123,7 @@ public class QGChangeEmailTemplate implements EmailTemplate { } } - messageBody.append("\n").append("More details at: ").append(configuration.getServerBaseURL()).append("/dashboard?id=").append(projectKey); + messageBody.append("\n").append("More details at: ").append(server.getPublicRootUrl()).append("/dashboard?id=").append(projectKey); if (branchName != null) { messageBody.append("&branch=").append(branchName); } diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/email/EmailSenderTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/email/EmailSenderTest.java index 299bbb4b293..e8c549d2667 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/email/EmailSenderTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/email/EmailSenderTest.java @@ -19,13 +19,13 @@ */ package org.sonar.server.email; -import java.net.MalformedURLException; +import java.util.Properties; import java.util.Set; -import org.apache.commons.mail.EmailException; import org.apache.commons.mail.HtmlEmail; import org.apache.commons.mail.MultiPartEmail; import org.junit.Test; -import org.sonar.api.config.EmailSettings; +import org.sonar.api.platform.Server; +import org.sonar.server.oauth.OAuthMicrosoftRestClient; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.doReturn; @@ -33,11 +33,15 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.sonar.server.email.EmailSmtpConfiguration.EMAIL_CONFIG_SMTP_AUTH_METHOD_OAUTH; +import static org.sonar.server.email.EmailSmtpConfiguration.EMAIL_CONFIG_SMTP_OAUTH_SCOPE_DEFAULT; public class EmailSenderTest { - private EmailSettings emailSettings = mock(EmailSettings.class); - private EmailSender<BasicEmail> sender = new EmailSender<>(emailSettings) { - @Override protected void addReportContent(HtmlEmail email, BasicEmail report) throws EmailException, MalformedURLException { + private final EmailSmtpConfiguration emailSmtpConfiguration = mock(); + private final Server server = mock(); + private final OAuthMicrosoftRestClient oAuthMicrosoftRestClient = mock(); + private final EmailSender<BasicEmail> sender = new EmailSender<>(emailSmtpConfiguration, server, oAuthMicrosoftRestClient) { + @Override protected void addReportContent(HtmlEmail email, BasicEmail report) { email.setSubject("Email Subject"); } }; @@ -45,13 +49,14 @@ public class EmailSenderTest { @Test public void test_email_fields() throws Exception { BasicEmail basicEmail = new BasicEmail(Set.of("noreply@nowhere")); - when(emailSettings.getSmtpHost()).thenReturn("smtphost"); - when(emailSettings.getSmtpPort()).thenReturn(25); - when(emailSettings.getFrom()).thenReturn("noreply@nowhere"); - when(emailSettings.getFromName()).thenReturn("My SonarQube"); - when(emailSettings.getPrefix()).thenReturn("[SONAR]"); - when(emailSettings.getSmtpUsername()).thenReturn(""); - when(emailSettings.getSmtpPassword()).thenReturn(""); + when(emailSmtpConfiguration.getSmtpHost()).thenReturn("smtphost"); + when(emailSmtpConfiguration.getSmtpPort()).thenReturn(25); + when(emailSmtpConfiguration.getSecureConnection()).thenReturn("NONE"); + when(emailSmtpConfiguration.getFrom()).thenReturn("noreply@nowhere"); + when(emailSmtpConfiguration.getFromName()).thenReturn("My SonarQube"); + when(emailSmtpConfiguration.getPrefix()).thenReturn("[SONAR]"); + when(emailSmtpConfiguration.getSmtpUsername()).thenReturn(""); + when(emailSmtpConfiguration.getSmtpPassword()).thenReturn(""); MultiPartEmail email = sender.createEmail(basicEmail); @@ -71,9 +76,10 @@ public class EmailSenderTest { @Test public void support_empty_body() throws Exception { BasicEmail basicEmail = new BasicEmail(Set.of("noreply@nowhere")); - when(emailSettings.getSmtpHost()).thenReturn("smtphost"); - when(emailSettings.getSmtpPort()).thenReturn(465); - when(emailSettings.getFrom()).thenReturn("noreply@nowhere"); + when(emailSmtpConfiguration.getSmtpHost()).thenReturn("smtphost"); + when(emailSmtpConfiguration.getSmtpPort()).thenReturn(465); + when(emailSmtpConfiguration.getSecureConnection()).thenReturn("NONE"); + when(emailSmtpConfiguration.getFrom()).thenReturn("noreply@nowhere"); MultiPartEmail email = sender.createEmail(basicEmail); @@ -83,12 +89,12 @@ public class EmailSenderTest { @Test public void support_ssl() throws Exception { BasicEmail basicEmail = new BasicEmail(Set.of("noreply@nowhere")); - when(emailSettings.getSecureConnection()).thenReturn("SSL"); - when(emailSettings.getSmtpHost()).thenReturn("smtphost"); - when(emailSettings.getSmtpPort()).thenReturn(466); - when(emailSettings.getFrom()).thenReturn("noreply@nowhere"); - when(emailSettings.getSmtpUsername()).thenReturn("login"); - when(emailSettings.getSmtpPassword()).thenReturn("pwd"); + when(emailSmtpConfiguration.getSecureConnection()).thenReturn("SSLTLS"); + when(emailSmtpConfiguration.getSmtpHost()).thenReturn("smtphost"); + when(emailSmtpConfiguration.getSmtpPort()).thenReturn(466); + when(emailSmtpConfiguration.getFrom()).thenReturn("noreply@nowhere"); + when(emailSmtpConfiguration.getSmtpUsername()).thenReturn("login"); + when(emailSmtpConfiguration.getSmtpPassword()).thenReturn("pwd"); MultiPartEmail email = sender.createEmail(basicEmail); @@ -103,12 +109,12 @@ public class EmailSenderTest { @Test public void support_starttls() throws Exception { BasicEmail basicEmail = new BasicEmail(Set.of("noreply@nowhere")); - when(emailSettings.getSecureConnection()).thenReturn("STARTTLS"); - when(emailSettings.getSmtpHost()).thenReturn("smtphost"); - when(emailSettings.getSmtpPort()).thenReturn(587); - when(emailSettings.getFrom()).thenReturn("noreply@nowhere"); - when(emailSettings.getSmtpUsername()).thenReturn("login"); - when(emailSettings.getSmtpPassword()).thenReturn("pwd"); + when(emailSmtpConfiguration.getSecureConnection()).thenReturn("STARTTLS"); + when(emailSmtpConfiguration.getSmtpHost()).thenReturn("smtphost"); + when(emailSmtpConfiguration.getSmtpPort()).thenReturn(587); + when(emailSmtpConfiguration.getFrom()).thenReturn("noreply@nowhere"); + when(emailSmtpConfiguration.getSmtpUsername()).thenReturn("login"); + when(emailSmtpConfiguration.getSmtpPassword()).thenReturn("pwd"); MultiPartEmail email = sender.createEmail(basicEmail); @@ -120,6 +126,38 @@ public class EmailSenderTest { } @Test + public void support_oauth() throws Exception { + BasicEmail basicEmail = new BasicEmail(Set.of("noreply@nowhere")); + when(emailSmtpConfiguration.getSecureConnection()).thenReturn("STARTTLS"); + when(emailSmtpConfiguration.getSmtpHost()).thenReturn("smtphost"); + when(emailSmtpConfiguration.getSmtpPort()).thenReturn(587); + when(emailSmtpConfiguration.getFrom()).thenReturn("noreply@nowhere"); + when(emailSmtpConfiguration.getAuthMethod()).thenReturn(EMAIL_CONFIG_SMTP_AUTH_METHOD_OAUTH); + when(emailSmtpConfiguration.getSmtpUsername()).thenReturn("login"); + when(emailSmtpConfiguration.getSmtpPassword()).thenReturn("pwd"); + when(emailSmtpConfiguration.getOAuthHost()).thenReturn("oauthHost"); + when(emailSmtpConfiguration.getOAuthClientId()).thenReturn("oauthClientId"); + when(emailSmtpConfiguration.getOAuthClientSecret()).thenReturn("oauthClientSecret"); + when(emailSmtpConfiguration.getOAuthTenant()).thenReturn("oauthTenant"); + when(emailSmtpConfiguration.getOAuthScope()).thenReturn(EMAIL_CONFIG_SMTP_OAUTH_SCOPE_DEFAULT); + when(oAuthMicrosoftRestClient.getAccessTokenFromClientCredentialsGrantFlow("oauthHost", "oauthClientId", "oauthClientSecret", "oauthTenant", + EMAIL_CONFIG_SMTP_OAUTH_SCOPE_DEFAULT)).thenReturn("token"); + + MultiPartEmail email = sender.createEmail(basicEmail); + + assertThat(email.isSSLOnConnect()).isFalse(); + assertThat(email.isStartTLSEnabled()).isTrue(); + assertThat(email.isStartTLSRequired()).isTrue(); + assertThat(email.getHostName()).isEqualTo("smtphost"); + assertThat(email.getSmtpPort()).isEqualTo("587"); + Properties emailProperties = email.getMailSession().getProperties(); + assertThat(emailProperties) + .containsEntry("mail.smtp.auth.mechanisms", "XOAUTH2") + .containsEntry("mail.smtp.auth.login.disable", "true") + .containsEntry("mail.smtp.auth.plain.disable", "true"); + } + + @Test public void send_email() throws Exception { HtmlEmail email = mock(HtmlEmail.class); BasicEmail basicEmail = new BasicEmail(Set.of("noreply@nowhere")); diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/ChangesOnMyIssuesEmailTemplateTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/ChangesOnMyIssuesEmailTemplateTest.java index 009ed3c2d2d..e8150810402 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/ChangesOnMyIssuesEmailTemplateTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/ChangesOnMyIssuesEmailTemplateTest.java @@ -35,8 +35,8 @@ import java.util.stream.Stream; import org.elasticsearch.common.util.set.Sets; import org.junit.Test; import org.junit.runner.RunWith; -import org.sonar.api.config.EmailSettings; import org.sonar.api.notifications.Notification; +import org.sonar.api.platform.Server; import org.sonar.api.rules.RuleType; import org.sonar.core.i18n.I18n; import org.sonar.server.issue.notification.IssuesChangesNotificationBuilder.AnalysisChange; @@ -82,9 +82,9 @@ public class ChangesOnMyIssuesEmailTemplateTest { private static final String[] SECURITY_HOTSPOTS_STATUSES = {STATUS_TO_REVIEW, STATUS_REVIEWED}; - private I18n i18n = mock(I18n.class); - private EmailSettings emailSettings = mock(EmailSettings.class); - private ChangesOnMyIssuesEmailTemplate underTest = new ChangesOnMyIssuesEmailTemplate(i18n, emailSettings); + private final I18n i18n = mock(I18n.class); + private final Server server = mock(); + private final ChangesOnMyIssuesEmailTemplate underTest = new ChangesOnMyIssuesEmailTemplate(i18n, server); @Test public void format_returns_null_on_Notification() { @@ -311,7 +311,7 @@ public class ChangesOnMyIssuesEmailTemplateTest { String host = secure().nextAlphabetic(15); when(i18n.message(Locale.ENGLISH, "notification.dispatcher.ChangesOnMyIssue", "notification.dispatcher.ChangesOnMyIssue")) .thenReturn(wordingNotification); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); Project project = newProject("foo"); Rule rule = newRule("bar", ruleType); Set<ChangedIssue> changedIssues = IntStream.range(0, 2 + new Random().nextInt(4)) @@ -397,7 +397,7 @@ public class ChangesOnMyIssuesEmailTemplateTest { String host = secure().nextAlphabetic(15); ChangedIssue changedIssue = newChangedIssue("key", randomValidStatus(), project, ruleName, randomRuleTypeHotspotExcluded()); AnalysisChange analysisChange = newAnalysisChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(analysisChange, ImmutableSet.of(changedIssue))); @@ -418,9 +418,9 @@ public class ChangesOnMyIssuesEmailTemplateTest { Rule rule = newRule(ruleName, randomRuleTypeHotspotExcluded()); List<ChangedIssue> changedIssues = IntStream.range(0, 2 + new Random().nextInt(5)) .mapToObj(i -> newChangedIssue("issue_" + i, randomValidStatus(), project, rule)) - .collect(toList()); + .toList(); UserChange userChange = newUserChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(userChange, ImmutableSet.copyOf(changedIssues))); @@ -449,7 +449,7 @@ public class ChangesOnMyIssuesEmailTemplateTest { String host = secure().nextAlphabetic(15); ChangedIssue changedIssue = newChangedIssue("key", randomValidStatus(), project, ruleName, randomRuleTypeHotspotExcluded()); UserChange userChange = newUserChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(userChange, ImmutableSet.of(changedIssue))); @@ -471,7 +471,7 @@ public class ChangesOnMyIssuesEmailTemplateTest { String key = "key"; ChangedIssue changedIssue = newChangedIssue(key, randomValidStatus(), project, ruleName, randomRuleTypeHotspotExcluded()); AnalysisChange analysisChange = newAnalysisChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(analysisChange, ImmutableSet.of(changedIssue))); @@ -494,7 +494,7 @@ public class ChangesOnMyIssuesEmailTemplateTest { String key = "key"; ChangedIssue changedIssue = newChangedIssue(key, randomValidStatus(), project, ruleName, randomRuleTypeHotspotExcluded()); UserChange userChange = newUserChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(userChange, ImmutableSet.of(changedIssue))); @@ -517,9 +517,9 @@ public class ChangesOnMyIssuesEmailTemplateTest { String issueStatus = randomValidStatus(); List<ChangedIssue> changedIssues = IntStream.range(0, 2 + new Random().nextInt(5)) .mapToObj(i -> newChangedIssue("issue_" + i, issueStatus, project, rule)) - .collect(toList()); + .toList(); AnalysisChange analysisChange = newAnalysisChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(analysisChange, ImmutableSet.copyOf(changedIssues))); @@ -543,9 +543,9 @@ public class ChangesOnMyIssuesEmailTemplateTest { Rule rule = newRule(ruleName, randomRuleTypeHotspotExcluded()); List<ChangedIssue> changedIssues = IntStream.range(0, 2 + new Random().nextInt(5)) .mapToObj(i -> newChangedIssue("issue_" + i, randomValidStatus(), project, rule)) - .collect(toList()); + .toList(); UserChange userChange = newUserChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(userChange, ImmutableSet.copyOf(changedIssues))); @@ -571,9 +571,9 @@ public class ChangesOnMyIssuesEmailTemplateTest { String status = randomValidStatus(); List<ChangedIssue> changedIssues = IntStream.range(0, 2 + new Random().nextInt(5)) .mapToObj(i -> newChangedIssue("issue_" + i, status, project, rule)) - .collect(toList()); + .toList(); AnalysisChange analysisChange = newAnalysisChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(analysisChange, ImmutableSet.copyOf(changedIssues))); @@ -598,9 +598,9 @@ public class ChangesOnMyIssuesEmailTemplateTest { Rule rule = newRandomNotAHotspotRule(ruleName); List<ChangedIssue> changedIssues = IntStream.range(0, 2 + new Random().nextInt(5)) .mapToObj(i -> newChangedIssue("issue_" + i, randomValidStatus(), project, rule)) - .collect(toList()); + .toList(); UserChange userChange = newUserChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(userChange, ImmutableSet.copyOf(changedIssues))); @@ -630,7 +630,7 @@ public class ChangesOnMyIssuesEmailTemplateTest { .collect(toList()); Collections.shuffle(changedIssues); UserChange userChange = newUserChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(userChange, ImmutableSet.copyOf(changedIssues))); @@ -667,7 +667,7 @@ public class ChangesOnMyIssuesEmailTemplateTest { .collect(toList()); Collections.shuffle(changedIssues); AnalysisChange analysisChange = newAnalysisChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(analysisChange, ImmutableSet.copyOf(changedIssues))); @@ -702,7 +702,7 @@ public class ChangesOnMyIssuesEmailTemplateTest { .collect(toList()); Collections.shuffle(changedIssues); UserChange userChange = newUserChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(userChange, ImmutableSet.copyOf(changedIssues))); @@ -745,7 +745,7 @@ public class ChangesOnMyIssuesEmailTemplateTest { Collections.shuffle(changedIssues); AnalysisChange analysisChange = newAnalysisChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(analysisChange, ImmutableSet.copyOf(changedIssues))); @@ -808,7 +808,7 @@ public class ChangesOnMyIssuesEmailTemplateTest { .collect(toList()); Collections.shuffle(changedIssues); UserChange userChange = newUserChange(); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new ChangesOnMyIssuesNotification(userChange, ImmutableSet.copyOf(changedIssues))); diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/FpPrAcceptedEmailTemplateTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/FpPrAcceptedEmailTemplateTest.java index 967e5955cd8..68b26b62290 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/FpPrAcceptedEmailTemplateTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/FpPrAcceptedEmailTemplateTest.java @@ -32,8 +32,8 @@ import java.util.stream.IntStream; import java.util.stream.Stream; import org.junit.Test; import org.junit.runner.RunWith; -import org.sonar.api.config.EmailSettings; import org.sonar.api.notifications.Notification; +import org.sonar.api.platform.Server; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.RuleType; import org.sonar.core.i18n.I18n; @@ -63,8 +63,8 @@ import static org.sonar.server.issue.notification.IssuesChangesNotificationBuild @RunWith(DataProviderRunner.class) public class FpPrAcceptedEmailTemplateTest { private final I18n i18n = mock(I18n.class); - private final EmailSettings emailSettings = mock(EmailSettings.class); - private final FpOrAcceptedEmailTemplate underTest = new FpOrAcceptedEmailTemplate(i18n, emailSettings); + private final Server server = mock(); + private final FpOrAcceptedEmailTemplate underTest = new FpOrAcceptedEmailTemplate(i18n, server); private static final long DATE_LONG = Instant.now().toEpochMilli(); @@ -144,7 +144,7 @@ public class FpPrAcceptedEmailTemplateTest { String host = secure().nextAlphabetic(15); when(i18n.message(Locale.ENGLISH, "notification.dispatcher.NewFalsePositiveIssue", "notification.dispatcher.NewFalsePositiveIssue")) .thenReturn(wordingNotification); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new FPOrAcceptedNotification(change, Collections.emptySet(), fpPrAccepted)); @@ -169,7 +169,7 @@ public class FpPrAcceptedEmailTemplateTest { String ruleName = secure().nextAlphabetic(8); String host = secure().nextAlphabetic(15); ChangedIssue changedIssue = newChangedIssue("key", project, ruleName, randomRuleTypeHotspotExcluded()); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new FPOrAcceptedNotification(change, ImmutableSet.of(changedIssue), fpPrAccepted)); @@ -189,7 +189,7 @@ public class FpPrAcceptedEmailTemplateTest { String ruleName = secure().nextAlphabetic(8); String host = secure().nextAlphabetic(15); ChangedIssue changedIssue = newChangedIssue("key", project, ruleName, SECURITY_HOTSPOT); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new FPOrAcceptedNotification(change, ImmutableSet.of(changedIssue), fpPrAccepted)); @@ -211,7 +211,7 @@ public class FpPrAcceptedEmailTemplateTest { String host = secure().nextAlphabetic(15); String key = "key"; ChangedIssue changedIssue = newChangedIssue(key, project, ruleName, randomRuleTypeHotspotExcluded()); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new FPOrAcceptedNotification(change, ImmutableSet.of(changedIssue), fpPrAccepted)); @@ -234,7 +234,7 @@ public class FpPrAcceptedEmailTemplateTest { String host = secure().nextAlphabetic(15); String key = "key"; ChangedIssue changedIssue = newChangedIssue(key, project, ruleName, SECURITY_HOTSPOT); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new FPOrAcceptedNotification(change, ImmutableSet.of(changedIssue), fpPrAccepted)); @@ -257,8 +257,8 @@ public class FpPrAcceptedEmailTemplateTest { Rule rule = newRandomNotAHotspotRule(ruleName); List<ChangedIssue> changedIssues = IntStream.range(0, 2 + new Random().nextInt(5)) .mapToObj(i -> newChangedIssue("issue_" + i, project, rule)) - .collect(toList()); - when(emailSettings.getServerBaseURL()).thenReturn(host); + .toList(); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new FPOrAcceptedNotification(change, ImmutableSet.copyOf(changedIssues), fpPrAccepted)); @@ -283,8 +283,8 @@ public class FpPrAcceptedEmailTemplateTest { Rule rule = newSecurityHotspotRule(ruleName); List<ChangedIssue> changedIssues = IntStream.range(0, 2 + new Random().nextInt(5)) .mapToObj(i -> newChangedIssue("issue_" + i, project, rule)) - .collect(toList()); - when(emailSettings.getServerBaseURL()).thenReturn(host); + .toList(); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new FPOrAcceptedNotification(change, ImmutableSet.copyOf(changedIssues), fpPrAccepted)); @@ -310,8 +310,8 @@ public class FpPrAcceptedEmailTemplateTest { Rule rule = newRandomNotAHotspotRule(ruleName); List<ChangedIssue> changedIssues = IntStream.range(0, 2 + new Random().nextInt(5)) .mapToObj(i -> newChangedIssue("issue_" + i, project, rule)) - .collect(toList()); - when(emailSettings.getServerBaseURL()).thenReturn(host); + .toList(); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new FPOrAcceptedNotification(change, ImmutableSet.copyOf(changedIssues), fpPrAccepted)); @@ -337,8 +337,8 @@ public class FpPrAcceptedEmailTemplateTest { Rule rule = newSecurityHotspotRule(ruleName); List<ChangedIssue> changedIssues = IntStream.range(0, 2 + new Random().nextInt(5)) .mapToObj(i -> newChangedIssue("issue_" + i, project, rule)) - .collect(toList()); - when(emailSettings.getServerBaseURL()).thenReturn(host); + .toList(); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new FPOrAcceptedNotification(change, ImmutableSet.copyOf(changedIssues), fpPrAccepted)); @@ -368,7 +368,7 @@ public class FpPrAcceptedEmailTemplateTest { .map(project -> newChangedIssue("issue_" + project.getUuid(), project, newRandomNotAHotspotRule(secure().nextAlphabetic(2)))) .collect(toList()); Collections.shuffle(changedIssues); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new FPOrAcceptedNotification(change, ImmutableSet.copyOf(changedIssues), fpPrAccepted)); @@ -403,7 +403,7 @@ public class FpPrAcceptedEmailTemplateTest { .map(rule -> newChangedIssue("issue_" + rule.getName(), project, rule)) .collect(toList()); Collections.shuffle(changedIssues); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new FPOrAcceptedNotification(change, ImmutableSet.copyOf(changedIssues), fpPrAccepted)); @@ -436,7 +436,7 @@ public class FpPrAcceptedEmailTemplateTest { .flatMap(t -> t) .collect(toList()); Collections.shuffle(changedIssues); - when(emailSettings.getServerBaseURL()).thenReturn(host); + when(server.getPublicRootUrl()).thenReturn(host); EmailMessage emailMessage = underTest.format(new FPOrAcceptedNotification(change, ImmutableSet.copyOf(changedIssues), fpPrAccepted)); diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest.java index e91c59de41d..39bb7cc07f9 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/MyNewIssuesEmailTemplateTest.java @@ -19,13 +19,8 @@ */ package org.sonar.server.issue.notification; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import org.apache.commons.io.IOUtils; import org.junit.Before; import org.junit.Test; -import org.sonar.api.config.EmailSettings; -import org.sonar.api.config.internal.MapSettings; import org.sonar.api.notifications.Notification; import org.sonar.api.platform.Server; @@ -39,10 +34,8 @@ import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.TAG public class MyNewIssuesEmailTemplateTest { - private MapSettings settings = new MapSettings(); - - private Server server = mock(Server.class); - private MyNewIssuesEmailTemplate underTest = new MyNewIssuesEmailTemplate(new EmailSettings(settings.asConfig(), server)); + private final Server server = mock(Server.class); + private final MyNewIssuesEmailTemplate underTest = new MyNewIssuesEmailTemplate(server); @Before public void setUp() { @@ -65,7 +58,6 @@ public class MyNewIssuesEmailTemplateTest { EmailMessage message = underTest.format(notification); - // TODO datetime to be completed when test is isolated from JVM timezone assertThat(message.getMessage()).startsWith(""" Project: Struts @@ -121,7 +113,6 @@ public class MyNewIssuesEmailTemplateTest { EmailMessage message = underTest.format(notification); - // TODO datetime to be completed when test is isolated from JVM timezone assertThat(message.getMessage()).startsWith(""" Project: Struts Version: 52.0 @@ -139,7 +130,6 @@ public class MyNewIssuesEmailTemplateTest { EmailMessage message = underTest.format(notification); - // TODO datetime to be completed when test is isolated from JVM timezone assertThat(message.getMessage()).startsWith(""" Project: Struts Branch: feature1 @@ -169,7 +159,6 @@ public class MyNewIssuesEmailTemplateTest { EmailMessage message = underTest.format(notification); - // TODO datetime to be completed when test is isolated from JVM timezone assertThat(message.getMessage()).startsWith(""" Project: Struts Branch: feature1 @@ -222,15 +211,4 @@ public class MyNewIssuesEmailTemplateTest { .setFieldValue(RULE + ".2.count", "5"); } - private void assertStartsWithFile(String message, String resourcePath) throws IOException { - String fileContent = IOUtils.toString(getClass().getResource(resourcePath), StandardCharsets.UTF_8); - assertThat(sanitizeString(message)).startsWith(sanitizeString(fileContent)); - } - - /** - * sanitize EOL and tabs if git clone is badly configured - */ - private static String sanitizeString(String s) { - return s.replaceAll("\\r\\n|\\r|\\s+", ""); - } } diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java index 413b9bcfbf7..3fa7f1d44ec 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/notification/NewIssuesEmailTemplateTest.java @@ -19,13 +19,8 @@ */ package org.sonar.server.issue.notification; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import org.apache.commons.io.IOUtils; import org.junit.Before; import org.junit.Test; -import org.sonar.api.config.EmailSettings; -import org.sonar.api.config.internal.MapSettings; import org.sonar.api.notifications.Notification; import org.sonar.api.platform.Server; @@ -40,10 +35,8 @@ import static org.sonar.server.issue.notification.NewIssuesStatistics.Metric.TAG public class NewIssuesEmailTemplateTest { - private MapSettings settings = new MapSettings(); - - private Server server = mock(Server.class); - private NewIssuesEmailTemplate template = new NewIssuesEmailTemplate(new EmailSettings(settings.asConfig(), server)); + private final Server server = mock(Server.class); + private final NewIssuesEmailTemplate template = new NewIssuesEmailTemplate(server); @Before public void setUp() { @@ -96,7 +89,6 @@ public class NewIssuesEmailTemplateTest { EmailMessage message = template.format(notification); - // TODO datetime to be completed when test is isolated from JVM timezone assertThat(message.getMessage()).startsWith(""" Project: Struts Version: 42.1.1 @@ -128,7 +120,6 @@ public class NewIssuesEmailTemplateTest { EmailMessage message = template.format(notification); - // TODO datetime to be completed when test is isolated from JVM timezone assertThat(message.getMessage()).startsWith(""" Project: Struts @@ -156,7 +147,6 @@ public class NewIssuesEmailTemplateTest { EmailMessage message = template.format(notification); - // TODO datetime to be completed when test is isolated from JVM timezone assertThat(message.getMessage()).startsWith(""" Project: Struts Branch: feature1 @@ -174,7 +164,6 @@ public class NewIssuesEmailTemplateTest { EmailMessage message = template.format(notification); - // TODO datetime to be completed when test is isolated from JVM timezone assertThat(message.getMessage()).startsWith(""" Project: Struts Branch: feature1 @@ -236,15 +225,4 @@ public class NewIssuesEmailTemplateTest { .setFieldValue(RULE + ".2.count", "5"); } - private void assertStartsWithFile(String message, String resourcePath) throws IOException { - String fileContent = IOUtils.toString(getClass().getResource(resourcePath), StandardCharsets.UTF_8); - assertThat(sanitizeString(message)).startsWith(sanitizeString(fileContent)); - } - - /** - * sanitize EOL and tabs if git clone is badly configured - */ - private static String sanitizeString(String s) { - return s.replaceAll("\\r\\n|\\r|\\s+", ""); - } } diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/notification/email/EmailNotificationChannelTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/notification/email/EmailNotificationChannelTest.java index 750fdff9f10..64ad508a0fd 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/notification/email/EmailNotificationChannelTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/notification/email/EmailNotificationChannelTest.java @@ -47,6 +47,7 @@ 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; +import org.sonar.server.oauth.OAuthMicrosoftRestClient; import org.subethamail.wiser.Wiser; import org.subethamail.wiser.WiserMessage; @@ -83,7 +84,7 @@ public class EmailNotificationChannelTest { configuration = mock(EmailSmtpConfiguration.class); server = mock(Server.class); - underTest = new EmailNotificationChannel(configuration, server, null, null); + underTest = new EmailNotificationChannel(configuration, server, null, null, mock(OAuthMicrosoftRestClient.class)); } @After @@ -256,7 +257,7 @@ public class EmailNotificationChannelTest { @Test public void deliverAll_has_no_effect_if_set_is_empty() { EmailSmtpConfiguration emailSettings = mock(EmailSmtpConfiguration.class); - EmailNotificationChannel emailNotificationChannel = new EmailNotificationChannel(emailSettings, server, null, null); + EmailNotificationChannel emailNotificationChannel = new EmailNotificationChannel(emailSettings, server, null, null, mock(OAuthMicrosoftRestClient.class)); int count = emailNotificationChannel.deliverAll(Collections.emptySet()); @@ -272,7 +273,7 @@ public class EmailNotificationChannelTest { Set<EmailDeliveryRequest> requests = IntStream.range(0, 1 + new Random().nextInt(10)) .mapToObj(i -> new EmailDeliveryRequest("foo" + i + "@moo", mock(Notification.class))) .collect(toSet()); - EmailNotificationChannel emailNotificationChannel = new EmailNotificationChannel(emailSettings, server, null, null); + EmailNotificationChannel emailNotificationChannel = new EmailNotificationChannel(emailSettings, server, null, null, mock(OAuthMicrosoftRestClient.class)); int count = emailNotificationChannel.deliverAll(requests); @@ -290,7 +291,7 @@ public class EmailNotificationChannelTest { Set<EmailDeliveryRequest> requests = IntStream.range(0, 1 + new Random().nextInt(10)) .mapToObj(i -> new EmailDeliveryRequest(emptyString, mock(Notification.class))) .collect(toSet()); - EmailNotificationChannel emailNotificationChannel = new EmailNotificationChannel(emailSettings, server, null, null); + EmailNotificationChannel emailNotificationChannel = new EmailNotificationChannel(emailSettings, server, null, null, mock(OAuthMicrosoftRestClient.class)); int count = emailNotificationChannel.deliverAll(requests); @@ -316,7 +317,8 @@ public class EmailNotificationChannelTest { Set<EmailDeliveryRequest> requests = Stream.of(notification1, notification2, notification3) .map(t -> new EmailDeliveryRequest(recipientEmail, t)) .collect(toSet()); - EmailNotificationChannel emailNotificationChannel = new EmailNotificationChannel(configuration, server, new EmailTemplate[] {template1, template3}, null); + EmailNotificationChannel emailNotificationChannel = + new EmailNotificationChannel(configuration, server, new EmailTemplate[] {template1, template3}, null, mock(OAuthMicrosoftRestClient.class)); int count = emailNotificationChannel.deliverAll(requests); @@ -356,7 +358,8 @@ public class EmailNotificationChannelTest { when(template11.format(notification1)).thenReturn(emailMessage11); when(template12.format(notification1)).thenReturn(emailMessage12); EmailDeliveryRequest request = new EmailDeliveryRequest(recipientEmail, notification1); - EmailNotificationChannel emailNotificationChannel = new EmailNotificationChannel(configuration, server, new EmailTemplate[] {template11, template12}, null); + EmailNotificationChannel emailNotificationChannel = + new EmailNotificationChannel(configuration, server, new EmailTemplate[] {template11, template12}, null, mock(OAuthMicrosoftRestClient.class)); int count = emailNotificationChannel.deliverAll(Collections.singleton(request)); diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/oauth/OAuthMicrosoftRestClientTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/oauth/OAuthMicrosoftRestClientTest.java index 39e796d41a8..b80fd60b923 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/oauth/OAuthMicrosoftRestClientTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/oauth/OAuthMicrosoftRestClientTest.java @@ -25,9 +25,11 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; class OAuthMicrosoftRestClientTest { + private final OAuthMicrosoftRestClient underTest = new OAuthMicrosoftRestClient(); + @Test void getAccessTokenFromClientCredentialsGrantFlow_throwsException() { - assertThatThrownBy(() -> OAuthMicrosoftRestClient.getAccessTokenFromClientCredentialsGrantFlow("https://localhost", "clientId", "clientSecret", "tenant", "scope")) + assertThatThrownBy(() -> underTest.getAccessTokenFromClientCredentialsGrantFlow("https://localhost", "clientId", "clientSecret", "tenant", "scope")) .isInstanceOf(IllegalStateException.class) .hasMessageStartingWith("Unable to get a token: "); } diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplateTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplateTest.java index 0194d39635d..6fa0780aa40 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplateTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/notification/QGChangeEmailTemplateTest.java @@ -25,52 +25,49 @@ import com.tngtech.java.junit.dataprovider.UseDataProvider; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.sonar.api.config.EmailSettings; import org.sonar.api.notifications.Notification; +import org.sonar.api.platform.Server; import org.sonar.server.issue.notification.EmailMessage; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @RunWith(DataProviderRunner.class) public class QGChangeEmailTemplateTest { - private QGChangeEmailTemplate template; + private final Server server = mock(); + private final QGChangeEmailTemplate underTest = new QGChangeEmailTemplate(server); @Before public void setUp() { - EmailSettings configuration = mock(EmailSettings.class); - when(configuration.getServerBaseURL()).thenReturn("http://nemo.sonarsource.org"); - template = new QGChangeEmailTemplate(configuration); + when(server.getPublicRootUrl()).thenReturn("http://nemo.sonarsource.org"); } @Test public void shouldNotFormatIfNotCorrectNotification() { Notification notification = new Notification("other-notif"); - EmailMessage message = template.format(notification); - assertThat(message, nullValue()); + EmailMessage message = underTest.format(notification); + assertThat(message).isNull(); } @Test public void shouldFormatAlertWithSeveralMessages() { Notification notification = createNotification("Failed", "violations > 4, coverage < 75%", "ERROR", "false"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("alerts/45")); - assertThat(message.getSubject(), is("Quality gate status changed on \"Foo\"")); - assertThat(message.getMessage(), is("" + - "Project: Foo\n" + - "Version: V1-SNAP\n" + - "Quality gate status: Failed\n" + - "\n" + - "Quality gate thresholds:\n" + - " - violations > 4\n" + - " - coverage < 75%\n" + - "\n" + - "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); + EmailMessage message = underTest.format(notification); + assertThat(message.getMessageId()).isEqualTo("alerts/45"); + assertThat(message.getSubject()).isEqualTo("Quality gate status changed on \"Foo\""); + assertThat(message.getMessage()).isEqualTo(""" + Project: Foo + Version: V1-SNAP + Quality gate status: Failed + + Quality gate thresholds: + - violations > 4 + - coverage < 75% + + More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"""); } @Test @@ -78,56 +75,56 @@ public class QGChangeEmailTemplateTest { Notification notification = createNotification("Failed", "violations > 4, coverage < 75%", "ERROR", "false") .setFieldValue("branch", "feature"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("alerts/45")); - assertThat(message.getSubject(), is("Quality gate status changed on \"Foo (feature)\"")); - assertThat(message.getMessage(), is("" + - "Project: Foo\n" + - "Branch: feature\n" + - "Version: V1-SNAP\n" + - "Quality gate status: Failed\n" + - "\n" + - "Quality gate thresholds:\n" + - " - violations > 4\n" + - " - coverage < 75%\n" + - "\n" + - "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature")); + EmailMessage message = underTest.format(notification); + assertThat(message.getMessageId()).isEqualTo("alerts/45"); + assertThat(message.getSubject()).isEqualTo("Quality gate status changed on \"Foo (feature)\""); + assertThat(message.getMessage()).isEqualTo(""" + Project: Foo + Branch: feature + Version: V1-SNAP + Quality gate status: Failed + + Quality gate thresholds: + - violations > 4 + - coverage < 75% + + More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature"""); } @Test public void shouldFormatNewAlertWithSeveralMessages() { Notification notification = createNotification("Failed", "violations > 4, coverage < 75%", "ERROR", "true"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("alerts/45")); - assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo\"")); - assertThat(message.getMessage(), is("" + - "Project: Foo\n" + - "Version: V1-SNAP\n" + - "Quality gate status: Failed\n" + - "\n" + - "New quality gate thresholds:\n" + - " - violations > 4\n" + - " - coverage < 75%\n" + - "\n" + - "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); + EmailMessage message = underTest.format(notification); + assertThat(message.getMessageId()).isEqualTo("alerts/45"); + assertThat(message.getSubject()).isEqualTo("New quality gate threshold reached on \"Foo\""); + assertThat(message.getMessage()).isEqualTo(""" + Project: Foo + Version: V1-SNAP + Quality gate status: Failed + + New quality gate thresholds: + - violations > 4 + - coverage < 75% + + More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"""); } @Test public void shouldFormatNewAlertWithOneMessage() { Notification notification = createNotification("Failed", "violations > 4", "ERROR", "true"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("alerts/45")); - assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo\"")); - assertThat(message.getMessage(), is("" + - "Project: Foo\n" + - "Version: V1-SNAP\n" + - "Quality gate status: Failed\n" + - "\n" + - "New quality gate threshold: violations > 4\n" + - "\n" + - "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); + EmailMessage message = underTest.format(notification); + assertThat(message.getMessageId()).isEqualTo("alerts/45"); + assertThat(message.getSubject()).isEqualTo("New quality gate threshold reached on \"Foo\""); + assertThat(message.getMessage()).isEqualTo(""" + Project: Foo + Version: V1-SNAP + Quality gate status: Failed + + New quality gate threshold: violations > 4 + + More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"""); } @Test @@ -135,32 +132,32 @@ public class QGChangeEmailTemplateTest { Notification notification = createNotification("Failed", "violations > 4", "ERROR", "true") .setFieldValue("projectVersion", null); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("alerts/45")); - assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo\"")); - assertThat(message.getMessage(), is("" + - "Project: Foo\n" + - "Quality gate status: Failed\n" + - "\n" + - "New quality gate threshold: violations > 4\n" + - "\n" + - "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); + EmailMessage message = underTest.format(notification); + assertThat(message.getMessageId()).isEqualTo("alerts/45"); + assertThat(message.getSubject()).isEqualTo("New quality gate threshold reached on \"Foo\""); + assertThat(message.getMessage()).isEqualTo(""" + Project: Foo + Quality gate status: Failed + + New quality gate threshold: violations > 4 + + More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"""); } @Test public void shouldFormatBackToGreenMessage() { Notification notification = createNotification("Passed", "", "OK", "false"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("alerts/45")); - assertThat(message.getSubject(), is("\"Foo\" is back to green")); - assertThat(message.getMessage(), is("" + - "Project: Foo\n" + - "Version: V1-SNAP\n" + - "Quality gate status: Passed\n" + - "\n" + - "\n" + - "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); + EmailMessage message = underTest.format(notification); + assertThat(message.getMessageId()).isEqualTo("alerts/45"); + assertThat(message.getSubject()).isEqualTo("\"Foo\" is back to green"); + assertThat(message.getMessage()).isEqualTo(""" + Project: Foo + Version: V1-SNAP + Quality gate status: Passed + + + More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo"""); } @Test @@ -168,18 +165,18 @@ public class QGChangeEmailTemplateTest { Notification notification = createNotification("Failed", "violations > 4", "ERROR", "true") .setFieldValue("branch", "feature"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("alerts/45")); - assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo (feature)\"")); - assertThat(message.getMessage(), is("" + - "Project: Foo\n" + - "Branch: feature\n" + - "Version: V1-SNAP\n" + - "Quality gate status: Failed\n" + - "\n" + - "New quality gate threshold: violations > 4\n" + - "\n" + - "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature")); + EmailMessage message = underTest.format(notification); + assertThat(message.getMessageId()).isEqualTo("alerts/45"); + assertThat(message.getSubject()).isEqualTo("New quality gate threshold reached on \"Foo (feature)\""); + assertThat(message.getMessage()).isEqualTo(""" + Project: Foo + Branch: feature + Version: V1-SNAP + Quality gate status: Failed + + New quality gate threshold: violations > 4 + + More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature"""); } @Test @@ -187,17 +184,17 @@ public class QGChangeEmailTemplateTest { Notification notification = createNotification("Passed", "", "OK", "false") .setFieldValue("branch", "feature"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("alerts/45")); - assertThat(message.getSubject(), is("\"Foo (feature)\" is back to green")); - assertThat(message.getMessage(), is("" + - "Project: Foo\n" + - "Branch: feature\n" + - "Version: V1-SNAP\n" + - "Quality gate status: Passed\n" + - "\n" + - "\n" + - "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature")); + EmailMessage message = underTest.format(notification); + assertThat(message.getMessageId()).isEqualTo("alerts/45"); + assertThat(message.getSubject()).isEqualTo("\"Foo (feature)\" is back to green"); + assertThat(message.getMessage()).isEqualTo(""" + Project: Foo + Branch: feature + Version: V1-SNAP + Quality gate status: Passed + + + More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo&branch=feature"""); } @DataProvider @@ -230,17 +227,17 @@ public class QGChangeEmailTemplateTest { public void shouldFormatNewAlertWithThresholdProperlyFormatted(String alertText, String expectedFormattedAlertText) { Notification notification = createNotification("Failed", alertText, "ERROR", "true"); - EmailMessage message = template.format(notification); - assertThat(message.getMessageId(), is("alerts/45")); - assertThat(message.getSubject(), is("New quality gate threshold reached on \"Foo\"")); - assertThat(message.getMessage(), is("" + - "Project: Foo\n" + - "Version: V1-SNAP\n" + - "Quality gate status: Failed\n" + - "\n" + - "New quality gate threshold: " + expectedFormattedAlertText + "\n" + - "\n" + - "More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo")); + EmailMessage message = underTest.format(notification); + assertThat(message.getMessageId()).isEqualTo("alerts/45"); + assertThat(message.getSubject()).isEqualTo("New quality gate threshold reached on \"Foo\""); + assertThat(message.getMessage()).isEqualTo(""" + Project: Foo + Version: V1-SNAP + Quality gate status: Failed + + New quality gate threshold: %s + + More details at: http://nemo.sonarsource.org/dashboard?id=org.sonar.foo:foo""".formatted(expectedFormattedAlertText)); } |