This commit is contained in:
Erik Böck 2026-07-04 15:35:15 +01:00 committed by GitHub
commit 07a5cdd556
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 59 additions and 18 deletions

View File

@ -66,6 +66,7 @@ public class CallContext {
private final Map<String, String> apiResourcesUuids = new HashMap<>();
private Project project;
private String apiName;
private String requestRemoteAddress;
static EntityManager s_entityMgr;
@ -401,6 +402,14 @@ public class CallContext {
return context;
}
public String getRequestRemoteAddress() {
return requestRemoteAddress;
}
public void setRequestRemoteAddress(String remoteAddress) {
this.requestRemoteAddress = remoteAddress;
}
public void putContextParameters(Map<Object, Object> details){
if (details == null) return;
for(Map.Entry<Object,Object>entry : details.entrySet()){

View File

@ -216,6 +216,7 @@ public class ApiServlet extends HttpServlet {
HttpUtils.RESPONSE_TYPE_XML, ApiServer.JSONcontentType.value());
return;
}
CallContext.current().setRequestRemoteAddress(req.getServerName());
final StringBuilder auditTrailSb = new StringBuilder(128);
auditTrailSb.append(" ").append(remoteAddress.getHostAddress());

View File

@ -29,13 +29,16 @@ import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.gui.theme.dao.GuiThemeDetailsDao;
import org.apache.cloudstack.resourcedetail.UserDetailVO;
import org.apache.cloudstack.resourcedetail.dao.UserDetailsDao;
import org.apache.cloudstack.utils.mailing.MailAddress;
import org.apache.cloudstack.utils.mailing.SMTPMailProperties;
import org.apache.cloudstack.utils.mailing.SMTPMailSender;
import org.apache.http.conn.util.InetAddressUtils;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
@ -45,6 +48,7 @@ import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@ -65,6 +69,9 @@ public class UserPasswordResetManagerImpl extends ManagerBase implements UserPas
@Inject
private UserDao userDao;
@Inject
private GuiThemeDetailsDao guiThemeDetailsDao;
private SMTPMailSender mailSender;
public static ConfigKey<String> PasswordResetMailTemplate =
@ -182,26 +189,12 @@ public class UserPasswordResetManagerImpl extends ManagerBase implements UserPas
final String email = userAccount.getEmail();
final String username = userAccount.getUsername();
final String subject = "Password Reset Request";
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 requestDomain = CallContext.current().getRequestRemoteAddress();
String resetLinkDomain = getResetLinkDomain(requestDomain);
String formattedResetLinkDomain = formatResetLinkDomain(resetLinkDomain);
String resetLink = String.format("%s/client/#/user/resetPassword?username=%s&token=%s",
domainUrl, username, resetToken);
formattedResetLinkDomain, username, resetToken);
String content = getMessageBody(userAccount, resetToken, resetLink);
SMTPMailProperties mailProperties = new SMTPMailProperties();
@ -222,6 +215,44 @@ public class UserPasswordResetManagerImpl extends ManagerBase implements UserPas
userAccount, userAccount.getAccountId(), userAccount.getDomainId(), email, resetTokenExpiryTime);
}
private String getResetLinkDomain(String requestDomain) {
if (StringUtils.isNotBlank(requestDomain)) {
logger.debug("Searching for GUI theme with common name that matches the request's domain: [{}]", requestDomain);
List<Long> commonNameDetails = guiThemeDetailsDao.listGuiThemeIdsByCommonName(requestDomain);
if (!commonNameDetails.isEmpty()) {
logger.debug("GUI theme with ID {} was found; using request's domain for password reset link.", commonNameDetails.get(0));
return requestDomain;
} else {
logger.debug("No GUI theme was found with a common name that matches the request's domain.");
}
}
String configurationDomain = UserPasswordResetDomainURL.value();
if (StringUtils.isNotBlank(configurationDomain)) {
logger.debug("Defaulting reset link's domain to the [{}] configuration value: [{}].", UserPasswordResetDomainURL.key(), UserPasswordResetDomainURL.value());
return configurationDomain;
}
logger.debug("Using the first IP address in the [{}] configuration for the reset password email domain because the [{}] configuration is not defined.", ManagementServerAddresses.key(), UserPasswordResetDomainURL.key());
return ManagementServerAddresses.value().split(",")[0];
}
private String formatResetLinkDomain(String resetLinkDomain) {
String protocol = ServerProperties.isHttpsEnabled() ? "https" : "http";
if (InetAddressUtils.isIPv4Address(resetLinkDomain)) {
int port = protocol.equals("https") ? ServerProperties.getHttpsPort() : ServerProperties.getHttpPort();
resetLinkDomain = resetLinkDomain + ":" + port;
}
if (!resetLinkDomain.startsWith("http")) {
resetLinkDomain = protocol + "://" + resetLinkDomain;
}
return resetLinkDomain.replaceAll("/+$", "");
}
@Override
public boolean validateAndResetPassword(UserAccount user, String token, String password) {
UserDetailVO resetTokenDetail = userDetailsDao.findDetail(user.getId(), PasswordResetToken);