diff --git a/client/src/main/java/org/apache/cloudstack/ServerDaemon.java b/client/src/main/java/org/apache/cloudstack/ServerDaemon.java index 196695e1fc6b..30020cf89298 100644 --- a/client/src/main/java/org/apache/cloudstack/ServerDaemon.java +++ b/client/src/main/java/org/apache/cloudstack/ServerDaemon.java @@ -74,11 +74,6 @@ public class ServerDaemon implements Daemon { private static final String BIND_INTERFACE = "bind.interface"; private static final String CONTEXT_PATH = "context.path"; private static final String SESSION_TIMEOUT = "session.timeout"; - private static final String HTTP_ENABLE = "http.enable"; - private static final String HTTP_PORT = "http.port"; - private static final String HTTPS_ENABLE = "https.enable"; - private static final String HTTPS_PORT = "https.port"; - private static final String KEYSTORE_FILE = "https.keystore"; private static final String KEYSTORE_PASSWORD = "https.keystore.password"; private static final String WEBAPP_DIR = "webapp.dir"; private static final String ACCESS_LOG = "access.log"; @@ -140,11 +135,11 @@ public void init(final DaemonContext context) { } setBindInterface(properties.getProperty(BIND_INTERFACE, null)); setContextPath(properties.getProperty(CONTEXT_PATH, "/client")); - setHttpEnable(Boolean.valueOf(properties.getProperty(HTTP_ENABLE, "true"))); - setHttpPort(Integer.valueOf(properties.getProperty(HTTP_PORT, "8080"))); - setHttpsEnable(Boolean.valueOf(properties.getProperty(HTTPS_ENABLE, "false"))); - setHttpsPort(Integer.valueOf(properties.getProperty(HTTPS_PORT, "8443"))); - setKeystoreFile(properties.getProperty(KEYSTORE_FILE)); + setHttpEnable(Boolean.valueOf(properties.getProperty(ServerProperties.HTTP_ENABLE, "true"))); + setHttpPort(Integer.valueOf(properties.getProperty(ServerProperties.HTTP_PORT, "8080"))); + setHttpsEnable(Boolean.valueOf(properties.getProperty(ServerProperties.HTTPS_ENABLE, "false"))); + setHttpsPort(Integer.valueOf(properties.getProperty(ServerProperties.HTTPS_PORT, "8443"))); + setKeystoreFile(properties.getProperty(ServerProperties.KEYSTORE_FILE)); setKeystorePassword(properties.getProperty(KEYSTORE_PASSWORD)); setWebAppLocation(properties.getProperty(WEBAPP_DIR)); setAccessLogFile(properties.getProperty(ACCESS_LOG, "access.log")); diff --git a/server/src/main/java/org/apache/cloudstack/user/UserPasswordResetManager.java b/server/src/main/java/org/apache/cloudstack/user/UserPasswordResetManager.java index 377e57b31e93..ca14f6a1654e 100644 --- a/server/src/main/java/org/apache/cloudstack/user/UserPasswordResetManager.java +++ b/server/src/main/java/org/apache/cloudstack/user/UserPasswordResetManager.java @@ -78,7 +78,9 @@ public interface UserPasswordResetManager { ConfigKey UserPasswordResetDomainURL = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, String.class, "user.password.reset.mail.domain.url", null, - "Domain URL for reset password links sent to the user via email", true, + "Domain URL (along with scheme - http:// or https:// and port as applicable) for reset password links sent to the user via email. " + + "If this is not set, CloudStack would determine the domain url based on the first management server from 'host' setting " + + "and http scheme based on the https.enabled flag from server.properties file in the management server.", true, ConfigKey.Scope.Global); void setResetTokenAndSend(UserAccount userAccount); diff --git a/server/src/main/java/org/apache/cloudstack/user/UserPasswordResetManagerImpl.java b/server/src/main/java/org/apache/cloudstack/user/UserPasswordResetManagerImpl.java index 618ad5c86572..c62bca8eca4b 100644 --- a/server/src/main/java/org/apache/cloudstack/user/UserPasswordResetManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/user/UserPasswordResetManagerImpl.java @@ -23,6 +23,7 @@ import com.cloud.user.dao.UserDao; import com.cloud.utils.StringUtils; import com.cloud.utils.component.ManagerBase; +import com.cloud.utils.server.ServerProperties; import com.github.mustachejava.DefaultMustacheFactory; import com.github.mustachejava.Mustache; import com.github.mustachejava.MustacheFactory; @@ -48,6 +49,7 @@ import java.util.Set; import java.util.UUID; +import static org.apache.cloudstack.config.ApiServiceConfiguration.ManagementServerAddresses; import static org.apache.cloudstack.resourcedetail.UserDetailVO.PasswordResetToken; import static org.apache.cloudstack.resourcedetail.UserDetailVO.PasswordResetTokenExpiryDate; @@ -68,7 +70,7 @@ public class UserPasswordResetManagerImpl extends ManagerBase implements UserPas new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, String.class, "user.password.reset.mail.template", "Hello {{username}}!\n" + "You have requested to reset your password. Please click the following link to reset your password:\n" + - "{{{domainUrl}}}{{{resetLink}}}\n" + + "{{{resetLink}}}\n" + "If you did not request a password reset, please ignore this email.\n" + "\n" + "Regards,\n" + @@ -179,10 +181,26 @@ public void setResetTokenAndSend(UserAccount userAccount) { final String email = userAccount.getEmail(); final String username = userAccount.getUsername(); final String subject = "Password Reset Request"; - final String domainUrl = UserPasswordResetDomainURL.value(); + String domainUrl = UserPasswordResetDomainURL.value(); + if (StringUtils.isBlank(domainUrl)) { + String mgmtServerAddr = ManagementServerAddresses.value().split(",")[0]; + if (ServerProperties.isHttpsEnabled()) { + domainUrl = "https://" + mgmtServerAddr + ":" + ServerProperties.getHttpsPort(); + } else { + domainUrl = "http://" + mgmtServerAddr + ":" + ServerProperties.getHttpPort(); + } + } else if (!domainUrl.startsWith("http://") && !domainUrl.startsWith("https://")) { + if (ServerProperties.isHttpsEnabled()) { + domainUrl = "https://" + domainUrl; + } else { + domainUrl = "http://" + domainUrl; + } + } + + domainUrl = domainUrl.replaceAll("/+$", ""); - String resetLink = String.format("/client/#/user/resetPassword?username=%s&token=%s", - username, resetToken); + String resetLink = String.format("%s/client/#/user/resetPassword?username=%s&token=%s", + domainUrl, username, resetToken); String content = getMessageBody(userAccount, resetToken, resetLink); SMTPMailProperties mailProperties = new SMTPMailProperties(); diff --git a/utils/src/main/java/com/cloud/utils/server/ServerProperties.java b/utils/src/main/java/com/cloud/utils/server/ServerProperties.java index 36d8614e68f1..9e81fff90f01 100644 --- a/utils/src/main/java/com/cloud/utils/server/ServerProperties.java +++ b/utils/src/main/java/com/cloud/utils/server/ServerProperties.java @@ -17,10 +17,12 @@ package com.cloud.utils.server; import com.cloud.utils.crypt.EncryptionSecretKeyChecker; +import com.cloud.utils.StringUtils; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.Properties; @@ -28,9 +30,20 @@ public class ServerProperties { protected Logger logger = LogManager.getLogger(getClass()); + public static final String HTTP_ENABLE = "http.enable"; + public static final String HTTP_PORT = "http.port"; + public static final String HTTPS_ENABLE = "https.enable"; + public static final String HTTPS_PORT = "https.port"; + public static final String KEYSTORE_FILE = "https.keystore"; + public static final String PASSWORD_ENCRYPTION_TYPE = "password.encryption.type"; + private static Properties properties = new Properties(); private static boolean loaded = false; - public static final String passwordEncryptionType = "password.encryption.type"; + + private static int httpPort = 8080; + + private static boolean httpsEnable = false; + private static int httpsPort = 8443; public synchronized static Properties getServerProperties(InputStream inputStream) { if (!loaded) { @@ -39,7 +52,7 @@ public synchronized static Properties getServerProperties(InputStream inputStrea serverProps.load(inputStream); EncryptionSecretKeyChecker checker = new EncryptionSecretKeyChecker(); - checker.check(serverProps, passwordEncryptionType); + checker.check(serverProps, PASSWORD_ENCRYPTION_TYPE); if (EncryptionSecretKeyChecker.useEncryption()) { EncryptionSecretKeyChecker.decryptAnyProperties(serverProps); @@ -50,10 +63,29 @@ public synchronized static Properties getServerProperties(InputStream inputStrea IOUtils.closeQuietly(inputStream); } + httpPort = Integer.parseInt(serverProps.getProperty(ServerProperties.HTTP_PORT, "8080")); + + boolean httpsEnabled = Boolean.parseBoolean(serverProps.getProperty(ServerProperties.HTTPS_ENABLE, "false")); + String keystoreFile = serverProps.getProperty(KEYSTORE_FILE); + httpsEnable = httpsEnabled && StringUtils.isNotEmpty(keystoreFile) && new File(keystoreFile).exists(); + httpsPort = Integer.parseInt(serverProps.getProperty(ServerProperties.HTTPS_PORT, "8443")); + properties = serverProps; loaded = true; } return properties; } + + public static int getHttpPort() { + return httpPort; + } + + public static boolean isHttpsEnabled() { + return httpsEnable; + } + + public static int getHttpsPort() { + return httpsPort; + } }