Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move login-ui Service classes to Javaconfig #3208

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,38 +1,45 @@
package org.cloudfoundry.identity.uaa.account;

import com.fasterxml.jackson.core.type.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.cloudfoundry.identity.uaa.codestore.ExpiringCode;
import org.cloudfoundry.identity.uaa.codestore.ExpiringCodeStore;
import org.cloudfoundry.identity.uaa.constants.OriginKeys;
import org.cloudfoundry.identity.uaa.error.UaaException;
import org.cloudfoundry.identity.uaa.message.MessageService;
import org.cloudfoundry.identity.uaa.message.MessageType;
import org.cloudfoundry.identity.uaa.oauth.provider.ClientDetails;
import org.cloudfoundry.identity.uaa.provider.NoSuchClientException;
import org.cloudfoundry.identity.uaa.scim.ScimUser;
import org.cloudfoundry.identity.uaa.scim.ScimUserProvisioning;
import org.cloudfoundry.identity.uaa.scim.exception.ScimResourceAlreadyExistsException;
import org.cloudfoundry.identity.uaa.scim.util.ScimUtils;
import org.cloudfoundry.identity.uaa.scim.validate.PasswordValidator;
import org.cloudfoundry.identity.uaa.util.JsonUtils;
import org.cloudfoundry.identity.uaa.provider.NoSuchClientException;
import org.cloudfoundry.identity.uaa.zone.MultitenantClientServices;
import org.cloudfoundry.identity.uaa.zone.IdentityZone;
import org.cloudfoundry.identity.uaa.zone.MergedZoneBrandingInformation;
import org.cloudfoundry.identity.uaa.zone.MultitenantClientServices;
import org.cloudfoundry.identity.uaa.zone.beans.IdentityZoneManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.cloudfoundry.identity.uaa.oauth.provider.ClientDetails;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;

import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import static org.cloudfoundry.identity.uaa.codestore.ExpiringCodeType.REGISTRATION;
import static org.cloudfoundry.identity.uaa.util.UaaUrlUtils.findMatchingRedirectUri;
import static org.springframework.http.HttpStatus.BAD_REQUEST;

@Service
public class EmailAccountCreationService implements AccountCreationService {

private final Logger logger = LoggerFactory.getLogger(getClass());
Expand All @@ -48,7 +55,7 @@ public class EmailAccountCreationService implements AccountCreationService {
private final IdentityZoneManager identityZoneManager;

public EmailAccountCreationService(
SpringTemplateEngine templateEngine,
@Qualifier("mailTemplateEngine") SpringTemplateEngine templateEngine,
MessageService messageService,
ExpiringCodeStore codeStore,
ScimUserProvisioning scimUserProvisioning,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,32 @@
import org.cloudfoundry.identity.uaa.error.UaaException;
import org.cloudfoundry.identity.uaa.message.MessageService;
import org.cloudfoundry.identity.uaa.message.MessageType;
import org.cloudfoundry.identity.uaa.oauth.provider.ClientDetails;
import org.cloudfoundry.identity.uaa.provider.NoSuchClientException;
import org.cloudfoundry.identity.uaa.scim.ScimUser;
import org.cloudfoundry.identity.uaa.scim.ScimUserProvisioning;
import org.cloudfoundry.identity.uaa.util.JsonUtils;
import org.cloudfoundry.identity.uaa.util.UaaUrlUtils;
import org.cloudfoundry.identity.uaa.provider.NoSuchClientException;
import org.cloudfoundry.identity.uaa.zone.MergedZoneBrandingInformation;
import org.cloudfoundry.identity.uaa.zone.MultitenantClientServices;
import org.cloudfoundry.identity.uaa.zone.beans.IdentityZoneManager;
import org.cloudfoundry.identity.uaa.oauth.provider.ClientDetails;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import java.sql.Timestamp;
import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.cloudfoundry.identity.uaa.codestore.ExpiringCodeType.EMAIL;
import static org.cloudfoundry.identity.uaa.util.UaaUrlUtils.findMatchingRedirectUri;

@Service
public class EmailChangeEmailService implements ChangeEmailService {

static final String CHANGE_EMAIL_REDIRECT_URL = "change_email_redirect_url";
Expand All @@ -38,7 +45,8 @@ public class EmailChangeEmailService implements ChangeEmailService {
private final MultitenantClientServices clientDetailsService;
private final IdentityZoneManager identityZoneManager;

EmailChangeEmailService(final TemplateEngine templateEngine,
EmailChangeEmailService(
@Qualifier("mailTemplateEngine") final TemplateEngine templateEngine,
final MessageService messageService,
final ScimUserProvisioning scimUserProvisioning,
final ExpiringCodeStore codeStore,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

import static org.cloudfoundry.identity.uaa.constants.OriginKeys.UAA;
import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY;

@Service
public class UaaChangePasswordService implements ChangePasswordService, ApplicationEventPublisherAware {

private final ScimUserProvisioning scimUserProvisioning;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.springframework.core.io.support.ResourcePropertySource;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.cloudfoundry.identity.uaa.oauth.provider.ClientDetails;

import java.sql.Timestamp;
Expand All @@ -39,6 +40,7 @@
import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY;
import static org.springframework.util.StringUtils.isEmpty;

@Service("resetPasswordService")
public class UaaResetPasswordService implements ResetPasswordService, ApplicationEventPublisherAware {

public static final int PASSWORD_RESET_LIFETIME = 30 * 60 * 1000;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,138 @@
package org.cloudfoundry.identity.uaa.impl.config;

import org.cloudfoundry.identity.uaa.message.EmailService;
import org.cloudfoundry.identity.uaa.message.LocalUaaRestTemplate;
import org.cloudfoundry.identity.uaa.message.MessageService;
import org.cloudfoundry.identity.uaa.message.MessageType;
import org.cloudfoundry.identity.uaa.message.NotificationsService;
import org.cloudfoundry.identity.uaa.message.util.FakeJavaMailSender;
import org.cloudfoundry.identity.uaa.zone.beans.IdentityZoneManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
* Configuration for sending e-mails or HTTP-based notifications, e.g. on account creation.
* <p>
* If a {@code notifications.url} property is defined, it uses HTTP-based notifications.
* Otherwise, if {@code smtp.*} properties are defined, it will send e-mails. If none of
* these properties are configured, it uses a {@link FakeJavaMailSender} mailer.
* <p>
* All beans are marked lazy except {@link NotificationConfiguration#notificationMessageService},
* as they are all "fallback" options and do not need to be created when {@code notifications.url}
* is defined.
*/
@Lazy
@Configuration
@EnableConfigurationProperties(SmtpProperties.class)
public class LoginServerConfig {

/**
* Fallback bean for when there is no "notifications.url".
* TODO: dgarnier annotate with @Fallback in Boot 3.4
*
* @return -
*/
@Bean
public MessageService messageService(EmailService emailService, NotificationsService notificationsService, Environment environment) {
if (environment.getProperty("notifications.url") != null && !"".equals(environment.getProperty("notifications.url"))) {
return notificationsService;
} else {
return emailService;
public MessageService emailMessageService(
// dgarnier: use DEFAULT_UAA_URL
@Value("${login.url:http://localhost:8080/uaa}") String loginUrl,
JavaMailSender mailSender,
SmtpProperties smtpProperties,
IdentityZoneManager identityZoneManager) {
return new EmailService(
mailSender,
loginUrl,
smtpProperties.fromAddress(),
identityZoneManager
);
}

/**
* Fallback for SMTP mail sender, when no real mail sender is used. This is mostly used in tests.
* TODO: dgarnier annotate with @Fallback in Boot 3.4
*
* @return -
*/
@Bean
JavaMailSender fakeJavaMailSender() {
return new FakeJavaMailSender();
}

@Bean
@Primary
@ConditionalOnProperty(value = "smtp.host", matchIfMissing = false)
JavaMailSender smtpMailSender(SmtpProperties smtpProperties) {
var mailSender = new JavaMailSenderImpl();
mailSender.setHost(smtpProperties.host());
mailSender.setPort(smtpProperties.port());
mailSender.setPassword(smtpProperties.password());
mailSender.setUsername(smtpProperties.user());

var javaMailProperties = new Properties();
javaMailProperties.put("mail.smtp.auth", smtpProperties.auth());
javaMailProperties.put("mail.smtp.starttls.enable", smtpProperties.starttls());
javaMailProperties.put("mail.smtp.ssl.protocols", smtpProperties.sslprotocols());
mailSender.setJavaMailProperties(javaMailProperties);
return mailSender;
}

@Configuration
@ConditionalOnProperty(value = "notifications.url", matchIfMissing = false)
@EnableConfigurationProperties(NotificationsProperties.class)
static class NotificationConfiguration {

/**
* HTTP-based {@link MessageService}. Takes precedence over any email-basedO
* configuration.
*
* @param notificationsTemplate -
* @param notificationsProperties -
* @return -
*/
@Bean
@Primary
public MessageService notificationMessageService(
LocalUaaRestTemplate notificationsTemplate,
NotificationsProperties notificationsProperties
) {
return new NotificationsService(
notificationsTemplate,
notificationsProperties.url(),
notifications(),
notificationsProperties.sendInDefaultZone()
);
}

private static Map<MessageType, HashMap<String, Object>> notifications() {
return Map.of(
MessageType.CREATE_ACCOUNT_CONFIRMATION, notification("Send activation code", "f7a85fdc-d920-41f0-b3a4-55db08e408ce"),
MessageType.PASSWORD_RESET, notification("Reset Password", "141200f6-93bd-4761-a721-941ab511ba2c"),
MessageType.CHANGE_EMAIL, notification("Change Email", "712de257-a7fa-44cb-b1ac-8a6588d1be23"),
MessageType.INVITATION, notification("Invitation", "e6722687-3f0f-4e7a-9925-839a04712cea")
);
}

private static HashMap<String, Object> notification(String description, String id) {
return new HashMap<>(
Map.of(
"description", description,
"id", id,
"critical", true
)
);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.cloudfoundry.identity.uaa.impl.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;

@ConfigurationProperties(prefix = "notifications")
record NotificationsProperties(
String url,
@DefaultValue("true") boolean sendInDefaultZone
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.cloudfoundry.identity.uaa.impl.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;

@ConfigurationProperties(prefix = "smtp")
public record SmtpProperties(
@DefaultValue("localhost") String host,
@DefaultValue("25") int port,
@DefaultValue("") String user,
@DefaultValue("") String password,
@DefaultValue("false") boolean auth,
@DefaultValue("false") boolean starttls,
@DefaultValue("TLSv1.2") String sslprotocols,
@DefaultValue("") String fromAddress
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class ForcePasswordChangeController {

public ForcePasswordChangeController(
final ResourcePropertySource resourcePropertySource,
final @Qualifier("resetPasswordService") ResetPasswordService resetPasswordService) {
ResetPasswordService resetPasswordService) {
this.resourcePropertySource = resourcePropertySource;
this.resetPasswordService = resetPasswordService;
}
Expand Down
Loading
Loading