mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-07-23 07:45:49 +00:00
add password modification
This commit is contained in:
parent
285e018b1a
commit
47866a9f5d
65 changed files with 1632 additions and 250 deletions
7
pom.xml
7
pom.xml
|
@ -98,6 +98,13 @@
|
||||||
<version>${spring-cloud-starter-security.version}</version>
|
<version>${spring-cloud-starter-security.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- ============================================================ MAIL -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-mail</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- ========================================================= DATABASES -->
|
<!-- ========================================================= DATABASES -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
|
|
|
@ -8,6 +8,7 @@ package org.springframework.samples.petclinic.common;
|
||||||
public final class CommonAttribute {
|
public final class CommonAttribute {
|
||||||
|
|
||||||
public static final String DESCRIPTION = "description";
|
public static final String DESCRIPTION = "description";
|
||||||
|
public static final String ID = "id";
|
||||||
|
|
||||||
public static final String NAME = "name";
|
public static final String NAME = "name";
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ public final class CommonAttribute {
|
||||||
|
|
||||||
public static final String OWNER = "owner";
|
public static final String OWNER = "owner";
|
||||||
|
|
||||||
public static final String OWNER_ID = "id";
|
public static final String OWNER_ID = "ownerId";
|
||||||
|
|
||||||
public static final String OWNER_LAST_NAME = "lastName";
|
public static final String OWNER_LAST_NAME = "lastName";
|
||||||
|
|
||||||
|
@ -39,9 +40,11 @@ public final class CommonAttribute {
|
||||||
|
|
||||||
public static final String PET_TYPE = "type";
|
public static final String PET_TYPE = "type";
|
||||||
|
|
||||||
|
public static final String TOKEN = "token";
|
||||||
|
|
||||||
public static final String USER = "user";
|
public static final String USER = "user";
|
||||||
|
|
||||||
public static final String USER_ID = "id";
|
public static final String USER_ID = "userId";
|
||||||
|
|
||||||
public static final String VETS = "vets";
|
public static final String VETS = "vets";
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,9 @@ public final class CommonEndPoint {
|
||||||
|
|
||||||
public static final String USERS_EDIT = "/users/edit";
|
public static final String USERS_EDIT = "/users/edit";
|
||||||
|
|
||||||
public static final String USERS_ID_EDIT = "/users/{ownerId}/edit";
|
public static final String USERS_ID_EDIT = "/users/{userId}/edit";
|
||||||
|
|
||||||
|
public static final String USERS_ID_EDIT_PASSWORD = "/users/{userId}/edit/password";
|
||||||
|
|
||||||
public static final String USERS_NEW = "/users/new";
|
public static final String USERS_NEW = "/users/new";
|
||||||
|
|
||||||
|
@ -35,6 +37,8 @@ public final class CommonEndPoint {
|
||||||
|
|
||||||
public static final String OAUTH2_SUCCESS = "/oauth2/success";
|
public static final String OAUTH2_SUCCESS = "/oauth2/success";
|
||||||
|
|
||||||
|
public static final String CONFIRM_ACCOUNT = "/confirm-account";
|
||||||
|
|
||||||
public static final String LOGOUT = "/logout";
|
public static final String LOGOUT = "/logout";
|
||||||
|
|
||||||
public static final String LOGOUT_SUCCESS = "/logout/success";
|
public static final String LOGOUT_SUCCESS = "/logout/success";
|
||||||
|
|
|
@ -6,6 +6,8 @@ public class CommonParameter {
|
||||||
|
|
||||||
public static final int COUNTRY_MAX = 50;
|
public static final int COUNTRY_MAX = 50;
|
||||||
|
|
||||||
|
public static final String DEFAULT_PROVIDER = "local";
|
||||||
|
|
||||||
public static final int EMAIL_MAX = 255;
|
public static final int EMAIL_MAX = 255;
|
||||||
|
|
||||||
public static final int EMAIL_MIN = 4;
|
public static final int EMAIL_MIN = 4;
|
||||||
|
@ -32,6 +34,8 @@ public class CommonParameter {
|
||||||
|
|
||||||
public static final int STREET_MAX = 50;
|
public static final int STREET_MAX = 50;
|
||||||
|
|
||||||
|
public static final int TOKEN_EXPIRATION = 60 * 24;
|
||||||
|
|
||||||
public static final int ROLE_MAX = 10;
|
public static final int ROLE_MAX = 10;
|
||||||
|
|
||||||
public static final int ZIP_MAX = 6;
|
public static final int ZIP_MAX = 6;
|
||||||
|
|
|
@ -23,7 +23,7 @@ public final class CommonView {
|
||||||
|
|
||||||
public static final String PET_CREATE_OR_UPDATE = "pets/createOrUpdatePetForm";
|
public static final String PET_CREATE_OR_UPDATE = "pets/createOrUpdatePetForm";
|
||||||
|
|
||||||
public static final String USER_REGISTRATION = "users/registration";
|
public static final String USER_REGISTRATION = "users/userRegistrationForm";
|
||||||
|
|
||||||
public static final String USER_LOGIN = "/login";
|
public static final String USER_LOGIN = "/login";
|
||||||
|
|
||||||
|
@ -31,7 +31,9 @@ public final class CommonView {
|
||||||
|
|
||||||
public static final String USER_USERS_ID_R = "redirect:/users/{userId}";
|
public static final String USER_USERS_ID_R = "redirect:/users/{userId}";
|
||||||
|
|
||||||
public static final String USER_CREATE_OR_UPDATE = "users/createOrUpdateUserForm";
|
public static final String USER_UPDATE = "users/userUpdateForm";
|
||||||
|
|
||||||
|
public static final String USER_CHANGE_PASSWORD = "users/userChangePasswordForm";
|
||||||
|
|
||||||
public static final String USER_DETAILS = "users/userDetails";
|
public static final String USER_DETAILS = "users/userDetails";
|
||||||
|
|
||||||
|
@ -41,8 +43,6 @@ public final class CommonView {
|
||||||
|
|
||||||
public static final String USER_READ_R = "redirect:/users/read/";
|
public static final String USER_READ_R = "redirect:/users/read/";
|
||||||
|
|
||||||
public static final String USER_UPDATE = "users/user-update";
|
|
||||||
|
|
||||||
public static final String USER_UPDATE_R = "redirect:/users/edit/";
|
public static final String USER_UPDATE_R = "redirect:/users/edit/";
|
||||||
|
|
||||||
public static final String USER_UPDATE_PASSWORD = "users/user-password";
|
public static final String USER_UPDATE_PASSWORD = "users/user-password";
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
package org.springframework.samples.petclinic.configuration;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.support.ResourceBundleMessageSource;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||||
|
import org.thymeleaf.ITemplateEngine;
|
||||||
|
import org.thymeleaf.spring5.SpringTemplateEngine;
|
||||||
|
import org.thymeleaf.templatemode.TemplateMode;
|
||||||
|
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
|
||||||
|
import org.thymeleaf.templateresolver.ITemplateResolver;
|
||||||
|
import org.thymeleaf.templateresolver.StringTemplateResolver;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class MailConfig {
|
||||||
|
|
||||||
|
public static final String EMAIL_TEMPLATE_ENCODING = "UTF-8";
|
||||||
|
|
||||||
|
@Value("${spring.mail.host}")
|
||||||
|
private String mailHost;
|
||||||
|
|
||||||
|
@Value("${spring.mail.port}")
|
||||||
|
private String mailPort;
|
||||||
|
|
||||||
|
@Value("${spring.mail.protocol}")
|
||||||
|
private String mailProtocol;
|
||||||
|
|
||||||
|
@Value("${spring.mail.username}")
|
||||||
|
private String mailUsername;
|
||||||
|
|
||||||
|
@Value("${spring.mail.password}")
|
||||||
|
private String mailPassword;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JavaMailSender mailSender() {
|
||||||
|
|
||||||
|
final JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
|
||||||
|
|
||||||
|
// Basic mail sender configuration, based on emailconfig.properties
|
||||||
|
mailSender.setHost(mailHost);
|
||||||
|
mailSender.setPort(Integer.parseInt(mailPort));
|
||||||
|
mailSender.setProtocol(mailProtocol);
|
||||||
|
mailSender.setUsername(mailUsername);
|
||||||
|
mailSender.setPassword(mailPassword);
|
||||||
|
|
||||||
|
return mailSender;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ResourceBundleMessageSource emailMessageSource() {
|
||||||
|
final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
|
||||||
|
messageSource.setBasename("mail/MailMessages");
|
||||||
|
return messageSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ITemplateEngine emailTemplateEngine() {
|
||||||
|
final SpringTemplateEngine emailTemplateEngine = new SpringTemplateEngine();
|
||||||
|
|
||||||
|
// Resolver for TEXT emails
|
||||||
|
emailTemplateEngine.addTemplateResolver(textTemplateResolver());
|
||||||
|
// Resolver for HTML emails (except the editable one)
|
||||||
|
emailTemplateEngine.addTemplateResolver(htmlTemplateResolver());
|
||||||
|
// Resolver for HTML editable emails (which will be treated as a String)
|
||||||
|
emailTemplateEngine.addTemplateResolver(stringTemplateResolver());
|
||||||
|
// Message source, internationalization specific to emails
|
||||||
|
emailTemplateEngine.setTemplateEngineMessageSource(emailMessageSource());
|
||||||
|
|
||||||
|
return emailTemplateEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ITemplateResolver textTemplateResolver() {
|
||||||
|
final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
|
||||||
|
templateResolver.setOrder(Integer.valueOf(1));
|
||||||
|
templateResolver.setResolvablePatterns(Collections.singleton("text/*"));
|
||||||
|
templateResolver.setPrefix("/mail/");
|
||||||
|
templateResolver.setSuffix(".txt");
|
||||||
|
templateResolver.setTemplateMode(TemplateMode.TEXT);
|
||||||
|
templateResolver.setCharacterEncoding(EMAIL_TEMPLATE_ENCODING);
|
||||||
|
templateResolver.setCacheable(false);
|
||||||
|
return templateResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ITemplateResolver htmlTemplateResolver() {
|
||||||
|
final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
|
||||||
|
templateResolver.setOrder(Integer.valueOf(2));
|
||||||
|
templateResolver.setResolvablePatterns(Collections.singleton("html/*"));
|
||||||
|
templateResolver.setPrefix("/mail/");
|
||||||
|
templateResolver.setSuffix(".html");
|
||||||
|
templateResolver.setTemplateMode(TemplateMode.HTML);
|
||||||
|
templateResolver.setCharacterEncoding(EMAIL_TEMPLATE_ENCODING);
|
||||||
|
templateResolver.setCacheable(false);
|
||||||
|
return templateResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ITemplateResolver stringTemplateResolver() {
|
||||||
|
final StringTemplateResolver templateResolver = new StringTemplateResolver();
|
||||||
|
templateResolver.setOrder(Integer.valueOf(3));
|
||||||
|
// No resolvable pattern, will simply process as a String template everything not
|
||||||
|
// previously matched
|
||||||
|
templateResolver.setTemplateMode("HTML5");
|
||||||
|
templateResolver.setCacheable(false);
|
||||||
|
return templateResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,7 +6,6 @@ import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.PropertySource;
|
import org.springframework.context.annotation.PropertySource;
|
||||||
|
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.samples.petclinic.model.common.AuthProvider;
|
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
@ -59,12 +58,13 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
|
|
||||||
http.authorizeRequests()
|
http.authorizeRequests()
|
||||||
.antMatchers("/").anonymous()
|
.antMatchers("/").permitAll()
|
||||||
.antMatchers("/login", "/logout", "/register").permitAll()
|
.antMatchers("/login", "/logout", "/register","/confirm-account").permitAll()
|
||||||
.antMatchers("/websocket/**", "/topic/**", "/app/**").permitAll()
|
.antMatchers("/websocket/**", "/topic/**", "/app/**").permitAll()
|
||||||
.antMatchers("/resources/**").permitAll()
|
.antMatchers("/resources/**").permitAll()
|
||||||
.antMatchers("/**").authenticated()
|
|
||||||
.antMatchers("/h2-console/**").permitAll()
|
.antMatchers("/h2-console/**").permitAll()
|
||||||
|
.antMatchers("/**").authenticated()
|
||||||
|
.antMatchers("/edit/**").authenticated()
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
.and()
|
.and()
|
||||||
.formLogin()
|
.formLogin()
|
||||||
|
@ -94,10 +94,12 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final List<String> clients = Arrays.asList("google", "facebook", "github");
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ClientRegistrationRepository clientRegistrationRepository() {
|
public ClientRegistrationRepository clientRegistrationRepository() {
|
||||||
|
List<String> clients = Arrays.asList("google", "facebook", "github");
|
||||||
|
|
||||||
List<ClientRegistration> registrations = clients.stream().map(c -> getRegistration(c))
|
List<ClientRegistration> registrations = clients.stream().map(c -> getRegistration(c))
|
||||||
.filter(registration -> registration != null).collect(Collectors.toList());
|
.filter(registration -> registration != null).collect(Collectors.toList());
|
||||||
|
|
||||||
|
@ -113,14 +115,14 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
String clientSecret = env.getProperty(CLIENT_PROPERTY_KEY + client + ".client-secret");
|
String clientSecret = env.getProperty(CLIENT_PROPERTY_KEY + client + ".client-secret");
|
||||||
|
|
||||||
if (client.equals(AuthProvider.google.name())) {
|
if (client.equals("google")) {
|
||||||
return CommonOAuth2Provider.GOOGLE.getBuilder(client).clientId(clientId).clientSecret(clientSecret).build();
|
return CommonOAuth2Provider.GOOGLE.getBuilder(client).clientId(clientId).clientSecret(clientSecret).build();
|
||||||
}
|
}
|
||||||
if (client.equals(AuthProvider.facebook.name())) {
|
if (client.equals("facebook")) {
|
||||||
return CommonOAuth2Provider.FACEBOOK.getBuilder(client).clientId(clientId).clientSecret(clientSecret)
|
return CommonOAuth2Provider.FACEBOOK.getBuilder(client).clientId(clientId).clientSecret(clientSecret)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
if (client.equals(AuthProvider.github.name())) {
|
if (client.equals("github")) {
|
||||||
return CommonOAuth2Provider.GITHUB.getBuilder(client).clientId(clientId).clientSecret(clientSecret).build();
|
return CommonOAuth2Provider.GITHUB.getBuilder(client).clientId(clientId).clientSecret(clientSecret).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ package org.springframework.samples.petclinic.controller;
|
||||||
import org.springframework.samples.petclinic.common.*;
|
import org.springframework.samples.petclinic.common.*;
|
||||||
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
|
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
|
||||||
import org.springframework.samples.petclinic.dto.*;
|
import org.springframework.samples.petclinic.dto.*;
|
||||||
import org.springframework.samples.petclinic.service.OwnerService;
|
import org.springframework.samples.petclinic.service.business.OwnerService;
|
||||||
import org.springframework.samples.petclinic.service.VisitService;
|
import org.springframework.samples.petclinic.service.business.VisitService;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
|
|
|
@ -19,8 +19,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.samples.petclinic.common.*;
|
import org.springframework.samples.petclinic.common.*;
|
||||||
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
|
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
|
||||||
import org.springframework.samples.petclinic.dto.*;
|
import org.springframework.samples.petclinic.dto.*;
|
||||||
|
import org.springframework.samples.petclinic.service.business.OwnerService;
|
||||||
|
import org.springframework.samples.petclinic.service.business.PetService;
|
||||||
|
import org.springframework.samples.petclinic.service.business.PetTypeService;
|
||||||
import org.springframework.samples.petclinic.validator.PetDTOValidator;
|
import org.springframework.samples.petclinic.validator.PetDTOValidator;
|
||||||
import org.springframework.samples.petclinic.service.*;
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
|
@ -3,23 +3,15 @@ package org.springframework.samples.petclinic.controller;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.data.repository.query.Param;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.samples.petclinic.common.*;
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.samples.petclinic.common.CommonAttribute;
|
|
||||||
import org.springframework.samples.petclinic.common.CommonEndPoint;
|
|
||||||
import org.springframework.samples.petclinic.common.CommonView;
|
|
||||||
import org.springframework.samples.petclinic.common.CommonWebSocket;
|
|
||||||
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
|
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
|
||||||
import org.springframework.samples.petclinic.dto.UserDTO;
|
import org.springframework.samples.petclinic.dto.common.CredentialDTO;
|
||||||
import org.springframework.samples.petclinic.service.RoleService;
|
import org.springframework.samples.petclinic.dto.common.MessageDTO;
|
||||||
import org.springframework.samples.petclinic.service.SecurityServiceImpl;
|
import org.springframework.samples.petclinic.dto.common.UserDTO;
|
||||||
import org.springframework.samples.petclinic.service.UserService;
|
import org.springframework.samples.petclinic.service.common.*;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
||||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
|
||||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
|
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
|
||||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||||
|
@ -27,18 +19,16 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
|
||||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.web.bind.WebDataBinder;
|
import org.springframework.web.bind.WebDataBinder;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,30 +38,25 @@ import java.util.Map;
|
||||||
@Controller
|
@Controller
|
||||||
public class UserController extends WebSocketSender {
|
public class UserController extends WebSocketSender {
|
||||||
|
|
||||||
private static final String ROLE_ADMIN = "ADMIN";
|
|
||||||
|
|
||||||
private static final String ROLE_STAFF = "STAFF";
|
|
||||||
|
|
||||||
private static final String ROLE_USER = "USER";
|
|
||||||
|
|
||||||
private static final String authorizationRequestBaseUri = "oauth2/authorization";
|
|
||||||
|
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
|
|
||||||
|
private final CredentialService credentialService;
|
||||||
|
|
||||||
private final RoleService roleService;
|
private final RoleService roleService;
|
||||||
|
|
||||||
private final SecurityServiceImpl securityService;
|
private final SecurityServiceImpl securityService;
|
||||||
|
|
||||||
private final BCryptPasswordEncoder bCryptPasswordEncoder;
|
private final EmailService emailService;
|
||||||
|
|
||||||
public UserController(UserService userService, RoleService roleService, SecurityServiceImpl securityService,
|
public UserController(UserService userService, CredentialService credentialService, RoleService roleService, SecurityServiceImpl securityService, EmailService emailService) {
|
||||||
BCryptPasswordEncoder bCryptPasswordEncoder) {
|
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
|
this.credentialService = credentialService;
|
||||||
this.roleService = roleService;
|
this.roleService = roleService;
|
||||||
this.securityService = securityService;
|
this.securityService = securityService;
|
||||||
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
|
this.emailService = emailService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@InitBinder("user")
|
@InitBinder("user")
|
||||||
public void setAllowedFields(WebDataBinder dataBinder) {
|
public void setAllowedFields(WebDataBinder dataBinder) {
|
||||||
dataBinder.setDisallowedFields(CommonAttribute.USER_ID);
|
dataBinder.setDisallowedFields(CommonAttribute.USER_ID);
|
||||||
|
@ -89,36 +74,48 @@ public class UserController extends WebSocketSender {
|
||||||
public String initCreationForm(Map<String, Object> model) {
|
public String initCreationForm(Map<String, Object> model) {
|
||||||
UserDTO user = new UserDTO();
|
UserDTO user = new UserDTO();
|
||||||
model.put(CommonAttribute.USER, user);
|
model.put(CommonAttribute.USER, user);
|
||||||
return CommonView.USER_CREATE_OR_UPDATE;
|
return CommonView.USER_REGISTRATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(CommonEndPoint.REGISTER)
|
@PostMapping(CommonEndPoint.REGISTER)
|
||||||
public String processCreationForm(@ModelAttribute(CommonAttribute.USER) @Valid UserDTO user, BindingResult result) {
|
public String processCreationForm(@ModelAttribute(CommonAttribute.USER) @Valid UserDTO user, BindingResult result) {
|
||||||
if (result.hasErrors()) {
|
if (result.hasErrors()) {
|
||||||
sendErrorMessage(CommonWebSocket.USER_CREATION_ERROR);
|
sendErrorMessage(CommonWebSocket.USER_CREATION_ERROR);
|
||||||
return CommonView.USER_CREATE_OR_UPDATE;
|
return CommonView.USER_REGISTRATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if(userService.existByEmail(user.getEmail())) {
|
||||||
userService.findByEmail(user.getEmail());
|
|
||||||
result.rejectValue("email", "5", "Email already exist !");
|
result.rejectValue("email", "5", "Email already exist !");
|
||||||
sendErrorMessage(CommonWebSocket.USER_CREATION_ERROR);
|
sendErrorMessage(CommonWebSocket.USER_CREATION_ERROR);
|
||||||
return CommonView.USER_CREATE_OR_UPDATE;
|
return CommonView.USER_REGISTRATION;
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set default role
|
// set default role
|
||||||
user.addRole(roleService.findByName(ROLE_USER));
|
user.addRole(roleService.findByName("ROLE_USER"));
|
||||||
|
|
||||||
// encode password because we get clear password
|
// encode password because we get clear password
|
||||||
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
|
user.encode(user.getPassword());
|
||||||
user.setMatchingPassword(user.getPassword());
|
|
||||||
|
|
||||||
user = this.userService.save(user);
|
user = this.userService.save(user);
|
||||||
sendSuccessMessage(CommonWebSocket.USER_CREATED);
|
|
||||||
return CommonView.HOME + user.getId();
|
|
||||||
|
|
||||||
|
CredentialDTO credential = new CredentialDTO(user);
|
||||||
|
credential = credentialService.save(credential);
|
||||||
|
|
||||||
|
sendSuccessMessage(CommonWebSocket.USER_CREATED);
|
||||||
|
|
||||||
|
// send confirmation mail
|
||||||
|
MessageDTO message = new MessageDTO(
|
||||||
|
user.getFirstName(), user.getLastName(),
|
||||||
|
"admin@petclinic.com",
|
||||||
|
user.getEmail(),
|
||||||
|
"New connexion",
|
||||||
|
"Your attempt to create new account. To confirm your account, please click here : ",
|
||||||
|
"http://localhost:8080/confirm-account?token=" + credential.getToken());
|
||||||
|
|
||||||
|
// emailService.sendMailAsynch(message, Locale.getDefault());
|
||||||
|
|
||||||
|
log.info(message.toString());
|
||||||
|
|
||||||
|
return CommonView.HOME + user.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(CommonEndPoint.LOGIN)
|
@GetMapping(CommonEndPoint.LOGIN)
|
||||||
|
@ -140,7 +137,7 @@ public class UserController extends WebSocketSender {
|
||||||
}
|
}
|
||||||
|
|
||||||
clientRegistrations.forEach(registration -> oauth2AuthenticationUrls.put(registration.getClientName(),
|
clientRegistrations.forEach(registration -> oauth2AuthenticationUrls.put(registration.getClientName(),
|
||||||
authorizationRequestBaseUri + "/" + registration.getRegistrationId()));
|
"oauth2/authorization/" + registration.getRegistrationId()));
|
||||||
model.put("urls", oauth2AuthenticationUrls);
|
model.put("urls", oauth2AuthenticationUrls);
|
||||||
|
|
||||||
return CommonView.USER_LOGIN;
|
return CommonView.USER_LOGIN;
|
||||||
|
@ -148,30 +145,85 @@ public class UserController extends WebSocketSender {
|
||||||
|
|
||||||
@GetMapping(CommonEndPoint.LOGIN_SUCCESS)
|
@GetMapping(CommonEndPoint.LOGIN_SUCCESS)
|
||||||
public String postLogin(Model model, Authentication authentication) {
|
public String postLogin(Model model, Authentication authentication) {
|
||||||
UserDTO user = userService.findByEmail(authentication.getName());
|
UserDTO user = (UserDTO) authentication.getPrincipal();
|
||||||
|
|
||||||
model.addAttribute(CommonAttribute.USER, user);
|
model.addAttribute(CommonAttribute.USER, user);
|
||||||
String message = String.format(CommonWebSocket.USER_LOGGED_IN, user.getFirstName(), user.getLastName());
|
String message = String.format(CommonWebSocket.USER_LOGGED_IN, user.getFirstName(), user.getLastName());
|
||||||
sendSuccessMessage(message );
|
sendSuccessMessage(message);
|
||||||
|
|
||||||
return CommonView.HOME;
|
return CommonView.HOME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(CommonEndPoint.OAUTH2_SUCCESS)
|
@GetMapping(CommonEndPoint.OAUTH2_SUCCESS)
|
||||||
public String postLogin(Model model, OAuth2AuthenticationToken authentication) {
|
public String postLogin(Model model, OAuth2AuthenticationToken authentication) {
|
||||||
|
String firstName = authentication.getPrincipal().getAttribute("given_name");
|
||||||
|
String lastName = authentication.getPrincipal().getAttribute("family_name");
|
||||||
|
|
||||||
OAuth2AuthorizedClient client = authorizedClientService .loadAuthorizedClient(authentication.getAuthorizedClientRegistrationId(), authentication.getName());
|
CredentialDTO credential = credentialService.findByAuthentication(authentication);
|
||||||
|
|
||||||
String userInfoEndpointUri = client.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri();
|
if( credential.isNew()) {
|
||||||
|
|
||||||
UserDTO user = userService.findByEmail(authentication.getName());
|
// first time authentification with this provider
|
||||||
|
credential = credentialService.saveNew(authentication);
|
||||||
|
String email = credential.getEmail();
|
||||||
|
|
||||||
if( user!=null) {
|
UserDTO user = userService.findByEmail(email);
|
||||||
model.addAttribute(CommonAttribute.USER, user);
|
|
||||||
|
|
||||||
String message = String.format(CommonWebSocket.USER_LOGGED_IN, user.getFirstName(), user.getLastName());
|
if(user == null) {
|
||||||
|
user = new UserDTO();
|
||||||
|
user.setEmail(email);
|
||||||
|
user.encode(credential.getPassword());
|
||||||
|
user.setFirstName(firstName);
|
||||||
|
user.setLastName(lastName);
|
||||||
|
user.setEnabled(true);
|
||||||
|
user.addRole(roleService.findByName("ROLE_USER"));
|
||||||
|
user = userService.save(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send confirmation mail
|
||||||
|
MessageDTO message = new MessageDTO(
|
||||||
|
firstName, lastName,
|
||||||
|
"admin@petclinic.com",
|
||||||
|
credential.getEmail(),
|
||||||
|
"New connexion from " + credential.getProvider(),
|
||||||
|
"Your attempt to connect from " + credential.getProvider() + " To confirm this connection, please click the link below : ",
|
||||||
|
"http://localhost:8080/confirm-account?token=" + credential.getToken());
|
||||||
|
|
||||||
|
log.info(message.toString());
|
||||||
|
emailService.sendMailAsynch(message, Locale.getDefault());
|
||||||
|
|
||||||
|
// disconnect
|
||||||
|
authentication.eraseCredentials();
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
|
||||||
|
} else if( credential.isVerified()) {
|
||||||
|
securityService.autoLogin(credential.getEmail(),credential.getPassword());
|
||||||
|
String message = String.format(CommonWebSocket.USER_LOGGED_IN, firstName, lastName);
|
||||||
sendSuccessMessage(message);
|
sendSuccessMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return CommonView.HOME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = CommonEndPoint.CONFIRM_ACCOUNT, method = { RequestMethod.GET, RequestMethod.POST })
|
||||||
|
public String confirmUserAccount(@RequestParam(CommonAttribute.TOKEN) String token, Model model) {
|
||||||
|
CredentialDTO credential = credentialService.findByToken(token);
|
||||||
|
|
||||||
|
if (!credential.isNew() && credential.isNotExpired()) {
|
||||||
|
credential.setVerified(true);
|
||||||
|
credential.setToken("");
|
||||||
|
credential.setExpiration(null);
|
||||||
|
credential = credentialService.save(credential);
|
||||||
|
|
||||||
|
// find corresponding user
|
||||||
|
UserDTO user = userService.findByEmail(credential.getEmail());
|
||||||
|
|
||||||
|
securityService.autoLogin(credential.getEmail(),credential.getPassword());
|
||||||
|
model.addAttribute(CommonAttribute.USER, user);
|
||||||
|
return CommonView.USER_UPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
return CommonView.HOME;
|
return CommonView.HOME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,43 +240,48 @@ public class UserController extends WebSocketSender {
|
||||||
|
|
||||||
@GetMapping(CommonEndPoint.LOGOUT_SUCCESS)
|
@GetMapping(CommonEndPoint.LOGOUT_SUCCESS)
|
||||||
public String postLogout(Model model) {
|
public String postLogout(Model model) {
|
||||||
|
|
||||||
sendSuccessMessage(CommonWebSocket.USER_LOGGED_OUT);
|
sendSuccessMessage(CommonWebSocket.USER_LOGGED_OUT);
|
||||||
return CommonView.HOME;
|
return CommonView.HOME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(CommonEndPoint.USERS_EDIT)
|
@GetMapping(CommonEndPoint.USERS_EDIT)
|
||||||
public String initUpdateOwnerForm(Model model) {
|
public String initUpdateOwnerForm(Model model) {
|
||||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
try {
|
||||||
|
UserDTO user = (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
if (!authentication.getName().equals("anonymousUser")) {
|
|
||||||
|
|
||||||
UserDTO user = userService.findByEmail(authentication.getName());
|
|
||||||
model.addAttribute(CommonAttribute.USER, user);
|
model.addAttribute(CommonAttribute.USER, user);
|
||||||
return CommonView.USER_CREATE_OR_UPDATE;
|
model.addAttribute(CommonAttribute.USER_ID, user.getId());
|
||||||
|
return CommonView.USER_UPDATE;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
// user don't have profile
|
||||||
}
|
}
|
||||||
|
|
||||||
return CommonView.HOME;
|
return CommonView.HOME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(CommonEndPoint.USERS_ID_EDIT)
|
@PostMapping(CommonEndPoint.USERS_EDIT)
|
||||||
public String processUpdateOwnerForm(@ModelAttribute(CommonAttribute.USER) @Valid UserDTO user,
|
public String processUpdateOwnerForm(@ModelAttribute(CommonAttribute.USER) @Valid UserDTO user,
|
||||||
BindingResult result, @PathVariable("userId") int userId) {
|
BindingResult result, Model model) {
|
||||||
if (result.hasErrors()) {
|
if (result.hasErrors()) {
|
||||||
sendErrorMessage(CommonWebSocket.USER_UPDATED_ERROR);
|
sendErrorMessage(CommonWebSocket.USER_UPDATED_ERROR);
|
||||||
return CommonView.USER_CREATE_OR_UPDATE;
|
return CommonView.USER_UPDATE;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
user.setId(userId);
|
|
||||||
this.userService.save(user);
|
|
||||||
|
|
||||||
|
if(!user.getPassword().equals(user.getMatchingPassword())) {
|
||||||
|
sendErrorMessage(CommonWebSocket.USER_UPDATED_ERROR);
|
||||||
|
return CommonView.USER_UPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
user = userService.save(user);
|
||||||
|
|
||||||
|
model.addAttribute(CommonAttribute.USER, user);
|
||||||
sendSuccessMessage(CommonWebSocket.USER_UPDATED);
|
sendSuccessMessage(CommonWebSocket.USER_UPDATED);
|
||||||
return CommonView.USER_USERS_ID_R;
|
return CommonView.HOME;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(CommonEndPoint.USERS_ID)
|
@GetMapping(CommonEndPoint.USERS_ID)
|
||||||
public ModelAndView showOwner(@PathVariable("userId") int userId) {
|
public ModelAndView showOwner(@PathVariable("userId") Integer userId) {
|
||||||
ModelAndView modelAndView = new ModelAndView(CommonView.USER_DETAILS);
|
ModelAndView modelAndView = new ModelAndView(CommonView.USER_DETAILS);
|
||||||
UserDTO user = this.userService.findById(userId);
|
UserDTO user = this.userService.findById(userId);
|
||||||
|
|
||||||
|
@ -232,4 +289,62 @@ public class UserController extends WebSocketSender {
|
||||||
return modelAndView;
|
return modelAndView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/user/{userId}/edit/password")
|
||||||
|
public String editPassword(@PathVariable("userId") Integer userId, Model model){
|
||||||
|
try {
|
||||||
|
UserDTO operator = (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
|
UserDTO user = userService.findById(userId);
|
||||||
|
|
||||||
|
if (user.equals(operator) || operator.getRoles().contains(roleService.findByName("ROLE_ADMIN"))) {
|
||||||
|
model.addAttribute(CommonAttribute.USER, user);
|
||||||
|
model.addAttribute(CommonAttribute.USER_ID, user.getId());
|
||||||
|
return CommonView.USER_CHANGE_PASSWORD;
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
// user don't have profile
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonView.HOME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/user/{userId}/edit/password")
|
||||||
|
public String updatePassword(@ModelAttribute(CommonAttribute.USER) @Valid UserDTO user, BindingResult bindingResult,
|
||||||
|
@PathVariable(CommonAttribute.USER_ID) Integer userId,
|
||||||
|
@Param("oldPassword") String oldPassword,
|
||||||
|
@Param("newPassword") String newPassword,
|
||||||
|
@Param("newMatchingPassword") String newMatchingPassword, Model model) {
|
||||||
|
|
||||||
|
// verify the matching with old password
|
||||||
|
if(!user.matches(oldPassword)){
|
||||||
|
bindingResult.rejectValue("password", "6", "Bad password !");
|
||||||
|
model.addAttribute(CommonAttribute.USER, user);
|
||||||
|
return CommonView.USER_CHANGE_PASSWORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify matching between two password
|
||||||
|
if(!newPassword.equals(newMatchingPassword)){
|
||||||
|
bindingResult.rejectValue("password", "7", "Bad matching password !");
|
||||||
|
model.addAttribute(CommonAttribute.USER, user);
|
||||||
|
return CommonView.USER_CHANGE_PASSWORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
UserDTO operator = (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
|
|
||||||
|
if (user.equals(operator) || operator.getRoles().contains(roleService.findByName("ROLE_ADMIN"))) {
|
||||||
|
// encode password
|
||||||
|
user.encode(newPassword);
|
||||||
|
user = userService.save(user);
|
||||||
|
|
||||||
|
model.addAttribute(CommonAttribute.USER, user);
|
||||||
|
return CommonView.USER_UPDATE_R;
|
||||||
|
}
|
||||||
|
} catch (NullPointerException exception) {
|
||||||
|
log.error(exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommonView.HOME;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import org.springframework.samples.petclinic.common.CommonView;
|
||||||
import org.springframework.samples.petclinic.common.CommonWebSocket;
|
import org.springframework.samples.petclinic.common.CommonWebSocket;
|
||||||
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
|
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
|
||||||
import org.springframework.samples.petclinic.dto.VetsDTO;
|
import org.springframework.samples.petclinic.dto.VetsDTO;
|
||||||
import org.springframework.samples.petclinic.service.VetService;
|
import org.springframework.samples.petclinic.service.business.VetService;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
|
@ -26,8 +26,8 @@ import org.springframework.samples.petclinic.common.CommonWebSocket;
|
||||||
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
|
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
|
||||||
import org.springframework.samples.petclinic.dto.PetDTO;
|
import org.springframework.samples.petclinic.dto.PetDTO;
|
||||||
import org.springframework.samples.petclinic.dto.VisitDTO;
|
import org.springframework.samples.petclinic.dto.VisitDTO;
|
||||||
import org.springframework.samples.petclinic.service.PetService;
|
import org.springframework.samples.petclinic.service.business.PetService;
|
||||||
import org.springframework.samples.petclinic.service.VisitService;
|
import org.springframework.samples.petclinic.service.business.VisitService;
|
||||||
import org.springframework.samples.petclinic.validator.VisitDTOValidator;
|
import org.springframework.samples.petclinic.validator.VisitDTOValidator;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package org.springframework.samples.petclinic.dto.common;
|
||||||
|
|
||||||
|
import org.springframework.samples.petclinic.dto.NamedDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Data Transfert Object representing a Authorization Provider.
|
||||||
|
*
|
||||||
|
* @author Paul-Emmanuel DOS SANTOS FACAO
|
||||||
|
*/
|
||||||
|
public class AuthProviderDTO extends NamedDTO {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
package org.springframework.samples.petclinic.dto.common;
|
||||||
|
|
||||||
|
import org.springframework.samples.petclinic.common.CommonError;
|
||||||
|
import org.springframework.samples.petclinic.common.CommonParameter;
|
||||||
|
import org.springframework.samples.petclinic.dto.BaseDTO;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Pattern;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Data Transfert Object representing a Credential.
|
||||||
|
*
|
||||||
|
* @author Paul-Emmanuel DOS SANTOS FACAO
|
||||||
|
*/
|
||||||
|
public class CredentialDTO extends BaseDTO {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String provider;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Size(min = CommonParameter.EMAIL_MIN, max = CommonParameter.EMAIL_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
|
+ CommonParameter.EMAIL_MIN + " AND " + CommonParameter.EMAIL_MAX + " !")
|
||||||
|
@Pattern(regexp = CommonParameter.EMAIL_REGEXP, message = CommonError.EMAIL_FORMAT)
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Boolean verified;
|
||||||
|
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
private Date expiration;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Size(min = CommonParameter.PASSWORD_MIN, max = CommonParameter.PASSWORD_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
|
+ CommonParameter.PASSWORD_MIN + " AND " + CommonParameter.PASSWORD_MAX + " !")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
public CredentialDTO(UserDTO user) {
|
||||||
|
this.verified = false;
|
||||||
|
this.setToken();
|
||||||
|
this.setExpiration();
|
||||||
|
this.setProvider(CommonParameter.DEFAULT_PROVIDER);
|
||||||
|
this.email = user.getEmail();
|
||||||
|
this.password = user.getId().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProvider() {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProvider(String provider) {
|
||||||
|
this.provider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultProvider() {
|
||||||
|
this.provider = CommonParameter.DEFAULT_PROVIDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isVerified() {
|
||||||
|
return verified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVerified(Boolean verified) {
|
||||||
|
this.verified = verified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getExpiration() {
|
||||||
|
return expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpiration(Date expiration) {
|
||||||
|
this.expiration = expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpiration() {
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(new Timestamp(cal.getTime().getTime()));
|
||||||
|
cal.add(Calendar.MINUTE, CommonParameter.TOKEN_EXPIRATION);
|
||||||
|
this.expiration = cal.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken() {
|
||||||
|
this.token = UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNotExpired() {
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(new Timestamp(cal.getTime().getTime()));
|
||||||
|
|
||||||
|
return this.expiration.after(Date.from(Instant.now()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
package org.springframework.samples.petclinic.dto.common;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import org.springframework.samples.petclinic.common.CommonError;
|
||||||
|
import org.springframework.samples.petclinic.common.CommonParameter;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Pattern;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class MessageDTO implements Serializable {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Size(min = CommonParameter.FIRSTNAME_MIN, max = CommonParameter.FIRSTNAME_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
|
+ CommonParameter.FIRSTNAME_MIN + " AND " + CommonParameter.FIRSTNAME_MAX + " !")
|
||||||
|
private String firstName;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Size(min = CommonParameter.LASTNAME_MIN, max = CommonParameter.LASTNAME_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
|
+ CommonParameter.LASTNAME_MIN + " AND " + CommonParameter.LASTNAME_MAX + " !")
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Size(min = CommonParameter.EMAIL_MIN, max = CommonParameter.EMAIL_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
|
+ CommonParameter.EMAIL_MIN + " AND " + CommonParameter.EMAIL_MAX + " !")
|
||||||
|
@Pattern(regexp = CommonParameter.EMAIL_REGEXP, message = CommonError.EMAIL_FORMAT)
|
||||||
|
private String from;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Size(min = CommonParameter.EMAIL_MIN, max = CommonParameter.EMAIL_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
|
+ CommonParameter.EMAIL_MIN + " AND " + CommonParameter.EMAIL_MAX + " !")
|
||||||
|
@Pattern(regexp = CommonParameter.EMAIL_REGEXP, message = CommonError.EMAIL_FORMAT)
|
||||||
|
private String to;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String subject;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
private String link;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public MessageDTO(@JsonProperty("firstName") String firstName, @JsonProperty("lastName") String lastName,
|
||||||
|
@JsonProperty("from") String from, @JsonProperty("to") String to, @JsonProperty("subject") String subject,
|
||||||
|
@JsonProperty("content") String content, @JsonProperty("link") String link) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
this.subject = subject;
|
||||||
|
this.content = content;
|
||||||
|
this.link = link;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFrom() {
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrom(String from) {
|
||||||
|
this.from = from;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTo() {
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTo(String to) {
|
||||||
|
this.to = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubject() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubject(String subject) {
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLink() {
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLink(String link) {
|
||||||
|
this.link = link;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "MessageDTO{" +
|
||||||
|
"first name='" + firstName + '\'' +
|
||||||
|
", last name='" + lastName + '\'' +
|
||||||
|
", from='" + from + '\'' +
|
||||||
|
", to='" + to + '\'' +
|
||||||
|
", subject='" + subject + '\'' +
|
||||||
|
", content='" + content + '\'' +
|
||||||
|
", link='" + link + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
package org.springframework.samples.petclinic.dto;
|
package org.springframework.samples.petclinic.dto.common;
|
||||||
|
|
||||||
|
import org.springframework.samples.petclinic.dto.NamedDTO;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@ -8,5 +10,4 @@ import java.io.Serializable;
|
||||||
* @author Paul-Emmanuel DOS SANTOS FACAO
|
* @author Paul-Emmanuel DOS SANTOS FACAO
|
||||||
*/
|
*/
|
||||||
public class RoleDTO extends NamedDTO implements Serializable {
|
public class RoleDTO extends NamedDTO implements Serializable {
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,37 +1,48 @@
|
||||||
package org.springframework.samples.petclinic.dto;
|
package org.springframework.samples.petclinic.dto.common;
|
||||||
|
|
||||||
import org.springframework.beans.support.MutableSortDefinition;
|
import org.springframework.beans.support.MutableSortDefinition;
|
||||||
import org.springframework.beans.support.PropertyComparator;
|
import org.springframework.beans.support.PropertyComparator;
|
||||||
import org.springframework.samples.petclinic.common.CommonError;
|
import org.springframework.samples.petclinic.common.CommonError;
|
||||||
import org.springframework.samples.petclinic.common.CommonParameter;
|
import org.springframework.samples.petclinic.common.CommonParameter;
|
||||||
|
import org.springframework.samples.petclinic.dto.PersonDTO;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
|
||||||
import javax.validation.constraints.Pattern;
|
import javax.validation.constraints.Pattern;
|
||||||
import javax.validation.constraints.Size;
|
import javax.validation.constraints.Size;
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class UserDTO extends PersonDTO implements Serializable {
|
public class UserDTO extends PersonDTO implements Serializable, UserDetails {
|
||||||
|
|
||||||
@Size(min = CommonParameter.PASSWORD_MIN, max = CommonParameter.PASSWORD_MAX, message = CommonError.FORMAT_BETWEEN
|
|
||||||
+ CommonParameter.PASSWORD_MIN + " AND " + CommonParameter.PASSWORD_MAX + " !")
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
@Size(min = CommonParameter.PASSWORD_MIN, max = CommonParameter.PASSWORD_MAX, message = CommonError.FORMAT_BETWEEN
|
|
||||||
+ CommonParameter.PASSWORD_MIN + " AND " + CommonParameter.PASSWORD_MAX + " !")
|
|
||||||
private String matchingPassword;
|
|
||||||
|
|
||||||
@Size(min = CommonParameter.EMAIL_MIN, max = CommonParameter.EMAIL_MAX, message = CommonError.FORMAT_BETWEEN
|
@Size(min = CommonParameter.EMAIL_MIN, max = CommonParameter.EMAIL_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
+ CommonParameter.EMAIL_MIN + " AND " + CommonParameter.EMAIL_MAX + " !")
|
+ CommonParameter.EMAIL_MIN + " AND " + CommonParameter.EMAIL_MAX + " !")
|
||||||
@Pattern(regexp = CommonParameter.EMAIL_REGEXP, message = CommonError.EMAIL_FORMAT)
|
@Pattern(regexp = CommonParameter.EMAIL_REGEXP, message = CommonError.EMAIL_FORMAT)
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@Size(max = CommonParameter.PHONE_MAX, message = CommonError.FORMAT_LESS + CommonParameter.PHONE_MAX)
|
@Size(min = CommonParameter.PASSWORD_MIN, max = CommonParameter.PASSWORD_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
@Pattern(regexp = CommonParameter.PHONE_REGEXP, message = CommonError.PHONE_FORMAT)
|
+ CommonParameter.PASSWORD_MIN + " AND " + CommonParameter.PASSWORD_MAX + " !")
|
||||||
private String telephone;
|
private String password;
|
||||||
|
@Size(min = CommonParameter.PASSWORD_MIN, max = CommonParameter.PASSWORD_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
|
+ CommonParameter.PASSWORD_MIN + " AND " + CommonParameter.PASSWORD_MAX + " !")
|
||||||
|
private String matchingPassword;
|
||||||
|
|
||||||
|
private boolean enabled;
|
||||||
|
private boolean accountNonExpired;
|
||||||
|
private boolean accountNonLocked;
|
||||||
|
private boolean credentialsNonExpired;
|
||||||
|
|
||||||
private Set<RoleDTO> roles;
|
private Set<RoleDTO> roles;
|
||||||
|
|
||||||
|
|
||||||
|
@Size(max = CommonParameter.PHONE_MAX, message = CommonError.FORMAT_LESS + CommonParameter.PHONE_MAX)
|
||||||
|
// @Pattern(regexp = CommonParameter.PHONE_REGEXP, message = CommonError.PHONE_FORMAT)
|
||||||
|
private String telephone;
|
||||||
|
|
||||||
@Size(max = CommonParameter.STREET_MAX, message = CommonError.FORMAT_LESS + CommonParameter.STREET_MAX + " !")
|
@Size(max = CommonParameter.STREET_MAX, message = CommonError.FORMAT_LESS + CommonParameter.STREET_MAX + " !")
|
||||||
private String street1;
|
private String street1;
|
||||||
|
|
||||||
|
@ -51,6 +62,28 @@ public class UserDTO extends PersonDTO implements Serializable {
|
||||||
@Size(max = CommonParameter.COUNTRY_MAX, message = CommonError.FORMAT_LESS + CommonParameter.COUNTRY_MAX + " !")
|
@Size(max = CommonParameter.COUNTRY_MAX, message = CommonError.FORMAT_LESS + CommonParameter.COUNTRY_MAX + " !")
|
||||||
private String country;
|
private String country;
|
||||||
|
|
||||||
|
public UserDTO() {
|
||||||
|
super();
|
||||||
|
this.enabled = false;
|
||||||
|
this.accountNonLocked = true;
|
||||||
|
this.accountNonExpired = true;
|
||||||
|
this.credentialsNonExpired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getPassword() {
|
public String getPassword() {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
@ -67,20 +100,49 @@ public class UserDTO extends PersonDTO implements Serializable {
|
||||||
this.matchingPassword = matchingPassword;
|
this.matchingPassword = matchingPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEmail() {
|
@Override
|
||||||
return email;
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEmail(String email) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.email = email;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTelephone() {
|
@Override
|
||||||
return telephone;
|
public boolean isAccountNonExpired() {
|
||||||
|
return accountNonExpired;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTelephone(String telephone) {
|
public void setAccountNonExpired(boolean accountNonExpired) {
|
||||||
this.telephone = telephone;
|
this.accountNonExpired = accountNonExpired;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonLocked() {
|
||||||
|
return accountNonLocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountNonLocked(boolean accountNonLocked) {
|
||||||
|
this.accountNonLocked = accountNonLocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCredentialsNonExpired() {
|
||||||
|
return credentialsNonExpired;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCredentialsNonExpired(boolean credentialsNonExpired) {
|
||||||
|
this.credentialsNonExpired = credentialsNonExpired;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
|
||||||
|
|
||||||
|
this.roles.forEach(role -> grantedAuthorities.add(new SimpleGrantedAuthority(role.getName())));
|
||||||
|
|
||||||
|
return grantedAuthorities;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<RoleDTO> getRolesInternal() {
|
protected Set<RoleDTO> getRolesInternal() {
|
||||||
|
@ -101,10 +163,27 @@ public class UserDTO extends PersonDTO implements Serializable {
|
||||||
return Collections.unmodifiableList(sortedRoles);
|
return Collections.unmodifiableList(sortedRoles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getNrOfRoles() {
|
||||||
|
return getRolesInternal().size();
|
||||||
|
}
|
||||||
|
|
||||||
public void addRole(RoleDTO role) {
|
public void addRole(RoleDTO role) {
|
||||||
getRolesInternal().add(role);
|
getRolesInternal().add(role);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRoles(Set<RoleDTO> roles) {
|
||||||
|
this.roles = roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTelephone() {
|
||||||
|
return telephone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTelephone(String telephone) {
|
||||||
|
this.telephone = telephone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getStreet1() {
|
public String getStreet1() {
|
||||||
return street1;
|
return street1;
|
||||||
}
|
}
|
||||||
|
@ -153,4 +232,37 @@ public class UserDTO extends PersonDTO implements Serializable {
|
||||||
this.country = country;
|
this.country = country;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "UserDTO{" +
|
||||||
|
"email='" + email + '\'' +
|
||||||
|
", password='" + password + '\'' +
|
||||||
|
", matchingPassword='" + matchingPassword + '\'' +
|
||||||
|
", user enabled=" + enabled +
|
||||||
|
", account not expired=" + accountNonExpired +
|
||||||
|
", account not locked=" + accountNonLocked +
|
||||||
|
", credentials not xxpired=" + credentialsNonExpired +
|
||||||
|
", roles=" + roles +
|
||||||
|
", telephone='" + telephone + '\'' +
|
||||||
|
", street1='" + street1 + '\'' +
|
||||||
|
", street2='" + street2 + '\'' +
|
||||||
|
", street3='" + street3 + '\'' +
|
||||||
|
", zipCode='" + zipCode + '\'' +
|
||||||
|
", city='" + city + '\'' +
|
||||||
|
", country='" + country + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encode(String rawPassword) {
|
||||||
|
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
|
||||||
|
|
||||||
|
this.password = bCryptPasswordEncoder.encode(rawPassword);
|
||||||
|
this.matchingPassword = this.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(String rawPassword) {
|
||||||
|
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
|
||||||
|
|
||||||
|
return bCryptPasswordEncoder.matches(rawPassword, this.password);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -21,8 +21,7 @@ import java.util.Locale;
|
||||||
|
|
||||||
import org.springframework.format.Formatter;
|
import org.springframework.format.Formatter;
|
||||||
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
||||||
import org.springframework.samples.petclinic.service.PetService;
|
import org.springframework.samples.petclinic.service.business.PetService;
|
||||||
import org.springframework.samples.petclinic.service.PetTypeService;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
package org.springframework.samples.petclinic.model.common;
|
package org.springframework.samples.petclinic.model.common;
|
||||||
|
|
||||||
public enum AuthProvider {
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
local, facebook, google, github
|
/**
|
||||||
|
* Class used to manage Authorization providers
|
||||||
|
*
|
||||||
|
* @author Paul-Emmanuel DOS SANTOS FACAO
|
||||||
|
*/
|
||||||
|
@Entity(name = "AuthProvider")
|
||||||
|
@Table(name = "auth_providers")
|
||||||
|
public class AuthProvider extends NamedEntity {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
package org.springframework.samples.petclinic.model.common;
|
||||||
|
|
||||||
|
import org.springframework.samples.petclinic.common.CommonError;
|
||||||
|
import org.springframework.samples.petclinic.common.CommonParameter;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Pattern;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used to manage Credentials for users
|
||||||
|
*
|
||||||
|
* @author Paul-Emmanuel DOS SANTOS FACAO
|
||||||
|
*/
|
||||||
|
@Entity(name = "Credential")
|
||||||
|
@Table(name = "credentials")
|
||||||
|
public class Credential extends BaseEntity {
|
||||||
|
private static final int TOKEN_EXPIRATION = 60 * 24;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "provider_id")
|
||||||
|
private Integer providerId;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Size(min = CommonParameter.EMAIL_MIN, max = CommonParameter.EMAIL_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
|
+ CommonParameter.EMAIL_MIN + " AND " + CommonParameter.EMAIL_MAX + " !")
|
||||||
|
@Pattern(regexp = CommonParameter.EMAIL_REGEXP, message = CommonError.EMAIL_FORMAT)
|
||||||
|
@Column(name = "email", length = CommonParameter.EMAIL_MAX)
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Size(min = CommonParameter.PASSWORD_MIN, max = CommonParameter.PASSWORD_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
|
+ CommonParameter.PASSWORD_MIN + " AND " + CommonParameter.PASSWORD_MAX + " !")
|
||||||
|
@Column(name = "password", length = CommonParameter.PASSWORD_MAX)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "verified")
|
||||||
|
private Boolean verified;
|
||||||
|
|
||||||
|
@Column(name = "token")
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
@Column(name = "expiration")
|
||||||
|
private Date expiration;
|
||||||
|
|
||||||
|
|
||||||
|
public Integer getProviderId() {
|
||||||
|
return providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProviderId(Integer providerId) {
|
||||||
|
this.providerId = providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isVerified() {
|
||||||
|
return verified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVerified(Boolean verified) {
|
||||||
|
this.verified = verified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getExpiration() {
|
||||||
|
return expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpiration(Date expirationDate) {
|
||||||
|
this.expiration = expirationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpiration() {
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(new Timestamp(cal.getTime().getTime()));
|
||||||
|
cal.add(Calendar.MINUTE, TOKEN_EXPIRATION);
|
||||||
|
this.expiration = cal.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken() {
|
||||||
|
this.token = UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,5 @@
|
||||||
package org.springframework.samples.petclinic.model.common;
|
package org.springframework.samples.petclinic.model.common;
|
||||||
|
|
||||||
import org.springframework.samples.petclinic.model.common.NamedEntity;
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@ import org.springframework.beans.support.MutableSortDefinition;
|
||||||
import org.springframework.beans.support.PropertyComparator;
|
import org.springframework.beans.support.PropertyComparator;
|
||||||
import org.springframework.samples.petclinic.common.CommonError;
|
import org.springframework.samples.petclinic.common.CommonError;
|
||||||
import org.springframework.samples.petclinic.common.CommonParameter;
|
import org.springframework.samples.petclinic.common.CommonParameter;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
@ -20,7 +23,7 @@ import java.util.*;
|
||||||
*/
|
*/
|
||||||
@Entity(name = "User")
|
@Entity(name = "User")
|
||||||
@Table(name = "users")
|
@Table(name = "users")
|
||||||
public class User extends Person implements Serializable {
|
public class User extends Person implements Serializable, UserDetails {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Size(min = CommonParameter.EMAIL_MIN, max = CommonParameter.EMAIL_MAX, message = CommonError.FORMAT_BETWEEN
|
@Size(min = CommonParameter.EMAIL_MIN, max = CommonParameter.EMAIL_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
|
@ -29,34 +32,38 @@ public class User extends Person implements Serializable {
|
||||||
@Column(name = "email", unique = true, length = CommonParameter.EMAIL_MAX)
|
@Column(name = "email", unique = true, length = CommonParameter.EMAIL_MAX)
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Column(name = "email_verified")
|
|
||||||
private Boolean emailVerified = false;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Size(min = CommonParameter.PASSWORD_MIN, max = CommonParameter.PASSWORD_MAX, message = CommonError.FORMAT_BETWEEN
|
@Size(min = CommonParameter.PASSWORD_MIN, max = CommonParameter.PASSWORD_MAX, message = CommonError.FORMAT_BETWEEN
|
||||||
+ CommonParameter.PASSWORD_MIN + " AND " + CommonParameter.PASSWORD_MAX + " !")
|
+ CommonParameter.PASSWORD_MIN + " AND " + CommonParameter.PASSWORD_MAX + " !")
|
||||||
@Column(name = "password", length = CommonParameter.PASSWORD_MAX)
|
@Column(name = "password", length = CommonParameter.PASSWORD_MAX)
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Enumerated(EnumType.STRING)
|
@Column(name = "enabled")
|
||||||
private AuthProvider provider;
|
private boolean enabled;
|
||||||
|
|
||||||
@Column(name = "provider_id")
|
@NotNull
|
||||||
private String providerId;
|
@Column(name = "account_unexpired")
|
||||||
|
private boolean accountNonExpired;
|
||||||
|
|
||||||
@Size(max = CommonParameter.PHONE_MAX, message = CommonError.FORMAT_LESS + CommonParameter.PHONE_MAX)
|
@NotNull
|
||||||
@Pattern(regexp = CommonParameter.PHONE_REGEXP, message = CommonError.PHONE_FORMAT)
|
@Column(name = "account_unlocked")
|
||||||
@Column(name = "telephone", length = CommonParameter.EMAIL_MAX)
|
private boolean accountNonLocked;
|
||||||
private String telephone;
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "credential_unexpired")
|
||||||
|
private boolean credentialsNonExpired;
|
||||||
|
|
||||||
@ManyToMany(fetch = FetchType.EAGER)
|
@ManyToMany(fetch = FetchType.EAGER)
|
||||||
@JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id"),
|
@JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id"),
|
||||||
inverseJoinColumns = @JoinColumn(name = "role_id"))
|
inverseJoinColumns = @JoinColumn(name = "role_id"))
|
||||||
private Set<Role> roles;
|
private Set<Role> roles;
|
||||||
|
|
||||||
@NotNull
|
@Size(max = CommonParameter.PHONE_MAX, message = CommonError.FORMAT_LESS + CommonParameter.PHONE_MAX)
|
||||||
|
// @Pattern(regexp = CommonParameter.PHONE_REGEXP, message = CommonError.PHONE_FORMAT)
|
||||||
|
@Column(name = "telephone", length = CommonParameter.EMAIL_MAX)
|
||||||
|
private String telephone;
|
||||||
|
|
||||||
|
|
||||||
@Size(max = CommonParameter.STREET_MAX, message = CommonError.FORMAT_LESS + CommonParameter.STREET_MAX + " !")
|
@Size(max = CommonParameter.STREET_MAX, message = CommonError.FORMAT_LESS + CommonParameter.STREET_MAX + " !")
|
||||||
@Column(name = "street1", length = CommonParameter.STREET_MAX)
|
@Column(name = "street1", length = CommonParameter.STREET_MAX)
|
||||||
private String street1;
|
private String street1;
|
||||||
|
@ -69,12 +76,10 @@ public class User extends Person implements Serializable {
|
||||||
@Column(name = "street3", length = CommonParameter.STREET_MAX)
|
@Column(name = "street3", length = CommonParameter.STREET_MAX)
|
||||||
private String street3;
|
private String street3;
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Size(max = CommonParameter.ZIP_MAX, message = CommonError.FORMAT_LESS + CommonParameter.ZIP_MAX + " !")
|
@Size(max = CommonParameter.ZIP_MAX, message = CommonError.FORMAT_LESS + CommonParameter.ZIP_MAX + " !")
|
||||||
@Column(name = "zip_code", length = CommonParameter.ZIP_MAX)
|
@Column(name = "zip_code", length = CommonParameter.ZIP_MAX)
|
||||||
private String zipCode;
|
private String zipCode;
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Size(max = CommonParameter.CITY_MAX, message = CommonError.FORMAT_LESS + CommonParameter.CITY_MAX + " !")
|
@Size(max = CommonParameter.CITY_MAX, message = CommonError.FORMAT_LESS + CommonParameter.CITY_MAX + " !")
|
||||||
@Column(name = "city", length = CommonParameter.CITY_MAX)
|
@Column(name = "city", length = CommonParameter.CITY_MAX)
|
||||||
private String city;
|
private String city;
|
||||||
|
@ -83,6 +88,11 @@ public class User extends Person implements Serializable {
|
||||||
@Column(name = "country", length = CommonParameter.COUNTRY_MAX)
|
@Column(name = "country", length = CommonParameter.COUNTRY_MAX)
|
||||||
private String country;
|
private String country;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
public String getEmail() {
|
public String getEmail() {
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
@ -91,14 +101,7 @@ public class User extends Person implements Serializable {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getEmailVerified() {
|
@Override
|
||||||
return emailVerified;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmailVerified(Boolean emailVerified) {
|
|
||||||
this.emailVerified = emailVerified;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
public String getPassword() {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
@ -107,28 +110,50 @@ public class User extends Person implements Serializable {
|
||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthProvider getProvider() {
|
@Override
|
||||||
return provider;
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProvider(AuthProvider provider) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.provider = provider;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getProviderId() {
|
@Override
|
||||||
return providerId;
|
public boolean isAccountNonExpired() {
|
||||||
|
return accountNonExpired;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProviderId(String providerId) {
|
public void setAccountNonExpired(boolean accountNonExpired) {
|
||||||
this.providerId = providerId;
|
this.accountNonExpired = accountNonExpired;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTelephone() {
|
@Override
|
||||||
return telephone;
|
public boolean isAccountNonLocked() {
|
||||||
|
return accountNonLocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTelephone(String telephone) {
|
public void setAccountNonLocked(boolean accountNonLocked) {
|
||||||
this.telephone = telephone;
|
this.accountNonLocked = accountNonLocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCredentialsNonExpired() {
|
||||||
|
return credentialsNonExpired;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCredentialsNonExpired(boolean credentialsNonExpired) {
|
||||||
|
this.credentialsNonExpired = credentialsNonExpired;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
|
||||||
|
|
||||||
|
this.roles.forEach(role -> grantedAuthorities.add(new SimpleGrantedAuthority(role.getName())));
|
||||||
|
|
||||||
|
return grantedAuthorities;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<Role> getRolesInternal() {
|
protected Set<Role> getRolesInternal() {
|
||||||
|
@ -157,6 +182,20 @@ public class User extends Person implements Serializable {
|
||||||
getRolesInternal().add(role);
|
getRolesInternal().add(role);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setRoles(Set<Role> roles) {
|
||||||
|
this.roles = roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTelephone() {
|
||||||
|
return telephone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTelephone(String telephone) {
|
||||||
|
this.telephone = telephone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getStreet1() {
|
public String getStreet1() {
|
||||||
return street1;
|
return street1;
|
||||||
}
|
}
|
||||||
|
@ -205,4 +244,5 @@ public class User extends Person implements Serializable {
|
||||||
this.country = country;
|
this.country = country;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package org.springframework.samples.petclinic.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.repository.Repository;
|
||||||
|
import org.springframework.samples.petclinic.model.common.AuthProvider;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository class for <code>AuthProvider</code> domain objects All method names are
|
||||||
|
* compliant with Spring Data naming conventions so this interface can easily be extended
|
||||||
|
* for Spring
|
||||||
|
*
|
||||||
|
* @author Paul-Emmanuel DOS SANTOS FACAO
|
||||||
|
*/
|
||||||
|
public interface AuthProviderRepository extends Repository<AuthProvider, Integer> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a {@link AuthProvider} from the data store by id.
|
||||||
|
* @param providerId the id to search for
|
||||||
|
* @return the {@link AuthProvider} if found
|
||||||
|
*/
|
||||||
|
AuthProvider findById(Integer providerId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a {@link AuthProvider} from the data store by id.
|
||||||
|
* @param providerName the name to search for
|
||||||
|
* @return the {@link AuthProvider} if found
|
||||||
|
*/
|
||||||
|
AuthProvider findByName(String providerName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all {@link AuthProvider}s from the data store
|
||||||
|
* @return a Collection of {@link AuthProvider}s (or an empty Collection if none
|
||||||
|
*/
|
||||||
|
List<AuthProvider> findAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save a {@link AuthProvider} to the data store, either inserting or updating it.
|
||||||
|
* @param authProvider the {@link AuthProvider} to save
|
||||||
|
*/
|
||||||
|
AuthProvider save(AuthProvider authProvider);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.springframework.samples.petclinic.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.Repository;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.springframework.samples.petclinic.model.common.Credential;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository class for <code>Credential</code> domain objects All method names are
|
||||||
|
* compliant with Spring Data naming conventions so this interface can easily be extended
|
||||||
|
* for Spring
|
||||||
|
*
|
||||||
|
* @author Paul-Emmanuel DOS SANTOS FACAO
|
||||||
|
*/
|
||||||
|
public interface CredentialRepository extends Repository<Credential, Integer> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a {@link Credential} from the data store by email.
|
||||||
|
* @param email the email to search for
|
||||||
|
* @param providerId the provider to search for authorization
|
||||||
|
* @return the {@link Credential} if found
|
||||||
|
*/
|
||||||
|
@Query("SELECT c FROM Credential c WHERE c.email = :email AND c.providerId = :providerId")
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
Credential findByEmailAndProvider(@Param("email") String email, @Param("providerId") Integer providerId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * Retrieve a {@link Credential} from the data store by token.
|
||||||
|
* @param token the token to search for
|
||||||
|
* @return the {@link Credential} if found
|
||||||
|
*/
|
||||||
|
@Query("SELECT DISTINCT c FROM Credential c WHERE c.token = :token")
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
Credential findByToken(@Param("token") String token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all {@link Credential}s from the data store
|
||||||
|
* @return a Collection of {@link Credential}s (or an empty Collection if none
|
||||||
|
*/
|
||||||
|
List<Credential> findAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save a {@link Credential} to the data store, either inserting or updating it.
|
||||||
|
* @param credential the {@link Credential} to save
|
||||||
|
*/
|
||||||
|
Credential save(Credential credential);
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.samples.petclinic.service;
|
package org.springframework.samples.petclinic.service.business;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.samples.petclinic.service;
|
package org.springframework.samples.petclinic.service.business;
|
||||||
|
|
||||||
import org.modelmapper.ModelMapper;
|
import org.modelmapper.ModelMapper;
|
||||||
import org.modelmapper.internal.util.Lists;
|
import org.modelmapper.internal.util.Lists;
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.samples.petclinic.service;
|
package org.springframework.samples.petclinic.service.business;
|
||||||
|
|
||||||
import org.modelmapper.ModelMapper;
|
import org.modelmapper.ModelMapper;
|
||||||
import org.springframework.samples.petclinic.dto.OwnerDTO;
|
import org.springframework.samples.petclinic.dto.OwnerDTO;
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.samples.petclinic.service;
|
package org.springframework.samples.petclinic.service.business;
|
||||||
|
|
||||||
import org.modelmapper.ModelMapper;
|
import org.modelmapper.ModelMapper;
|
||||||
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.samples.petclinic.service;
|
package org.springframework.samples.petclinic.service.business;
|
||||||
|
|
||||||
import org.modelmapper.ModelMapper;
|
import org.modelmapper.ModelMapper;
|
||||||
import org.springframework.samples.petclinic.dto.SpecialtyDTO;
|
import org.springframework.samples.petclinic.dto.SpecialtyDTO;
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.samples.petclinic.service;
|
package org.springframework.samples.petclinic.service.business;
|
||||||
|
|
||||||
import org.modelmapper.ModelMapper;
|
import org.modelmapper.ModelMapper;
|
||||||
import org.modelmapper.internal.util.Lists;
|
import org.modelmapper.internal.util.Lists;
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.samples.petclinic.service;
|
package org.springframework.samples.petclinic.service.business;
|
||||||
|
|
||||||
import org.modelmapper.ModelMapper;
|
import org.modelmapper.ModelMapper;
|
||||||
import org.springframework.samples.petclinic.dto.VisitDTO;
|
import org.springframework.samples.petclinic.dto.VisitDTO;
|
|
@ -0,0 +1,87 @@
|
||||||
|
package org.springframework.samples.petclinic.service.common;
|
||||||
|
|
||||||
|
import org.modelmapper.ModelMapper;
|
||||||
|
import org.springframework.samples.petclinic.dto.common.AuthProviderDTO;
|
||||||
|
import org.springframework.samples.petclinic.model.common.AuthProvider;
|
||||||
|
import org.springframework.samples.petclinic.repository.AuthProviderRepository;
|
||||||
|
import org.springframework.samples.petclinic.service.business.BaseService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Service between AuthProvider entity and AuthProviderDTO Data Transfert Object.
|
||||||
|
*
|
||||||
|
* @author Paul-Emmanuel DOS SANTOS FACAO
|
||||||
|
*/
|
||||||
|
@Service("AuthProviderService")
|
||||||
|
public class AuthProviderService implements BaseService<AuthProvider, AuthProviderDTO> {
|
||||||
|
|
||||||
|
private final AuthProviderRepository authProviderRepository;
|
||||||
|
|
||||||
|
private final ModelMapper modelMapper = new ModelMapper();
|
||||||
|
|
||||||
|
public AuthProviderService(AuthProviderRepository authProviderRepository) {
|
||||||
|
this.authProviderRepository = authProviderRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthProvider dtoToEntity(AuthProviderDTO dto) {
|
||||||
|
if (dto != null) {
|
||||||
|
return modelMapper.map(dto, AuthProvider.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AuthProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthProviderDTO entityToDTO(AuthProvider entity) {
|
||||||
|
if (entity != null) {
|
||||||
|
return modelMapper.map(entity, AuthProviderDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AuthProviderDTO();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthProviderDTO> entitiesToDTOS(List<AuthProvider> entities) {
|
||||||
|
List<AuthProviderDTO> dtos = new ArrayList<>();
|
||||||
|
|
||||||
|
entities.forEach(entity -> dtos.add(entityToDTO(entity)));
|
||||||
|
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthProvider> dtosToEntities(List<AuthProviderDTO> dtos) {
|
||||||
|
List<AuthProvider> entities = new ArrayList<>();
|
||||||
|
|
||||||
|
dtos.forEach(dto -> entities.add(dtoToEntity(dto)));
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthProviderDTO findById(int providerId) {
|
||||||
|
return entityToDTO(authProviderRepository.findById(providerId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AuthProviderDTO> findAll() {
|
||||||
|
return entitiesToDTOS(authProviderRepository.findAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthProviderDTO save(AuthProviderDTO dto) {
|
||||||
|
AuthProvider authProvider = dtoToEntity(dto);
|
||||||
|
authProvider = authProviderRepository.save(authProvider);
|
||||||
|
|
||||||
|
return entityToDTO(authProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthProviderDTO findByName(String providerName) {
|
||||||
|
return entityToDTO(authProviderRepository.findByName(providerName));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
package org.springframework.samples.petclinic.service.common;
|
||||||
|
|
||||||
|
import org.modelmapper.ModelMapper;
|
||||||
|
import org.springframework.samples.petclinic.common.CommonParameter;
|
||||||
|
import org.springframework.samples.petclinic.dto.common.CredentialDTO;
|
||||||
|
import org.springframework.samples.petclinic.dto.common.UserDTO;
|
||||||
|
import org.springframework.samples.petclinic.model.common.AuthProvider;
|
||||||
|
import org.springframework.samples.petclinic.model.common.Credential;
|
||||||
|
import org.springframework.samples.petclinic.repository.AuthProviderRepository;
|
||||||
|
import org.springframework.samples.petclinic.repository.CredentialRepository;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Service between User entity and UserDTO Data Transfert Object.
|
||||||
|
*
|
||||||
|
* @author Paul-Emmanuel DOS SANTOS FACAO
|
||||||
|
*/
|
||||||
|
@Service("CredentialService")
|
||||||
|
public class CredentialService {
|
||||||
|
|
||||||
|
private final CredentialRepository credentialRepository;
|
||||||
|
|
||||||
|
private final BCryptPasswordEncoder bCryptPasswordEncoder;
|
||||||
|
|
||||||
|
private final AuthProviderRepository authProviderRepository;
|
||||||
|
|
||||||
|
private final ModelMapper modelMapper = new ModelMapper();
|
||||||
|
|
||||||
|
public CredentialService(CredentialRepository credentialRepository, BCryptPasswordEncoder bCryptPasswordEncoder, AuthProviderRepository authProviderRepository) {
|
||||||
|
this.credentialRepository = credentialRepository;
|
||||||
|
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
|
||||||
|
this.authProviderRepository = authProviderRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Credential dtoToEntity(CredentialDTO dto) {
|
||||||
|
if (dto != null) {
|
||||||
|
Credential entity = modelMapper.map(dto, Credential.class);
|
||||||
|
AuthProvider authProvider = authProviderRepository.findByName(dto.getProvider());
|
||||||
|
if (authProvider == null) {
|
||||||
|
authProvider = authProviderRepository.findByName(CommonParameter.DEFAULT_PROVIDER);
|
||||||
|
}
|
||||||
|
entity.setProviderId(authProvider.getId());
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Credential();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CredentialDTO entityToDTO(Credential entity) {
|
||||||
|
if (entity != null) {
|
||||||
|
CredentialDTO dto = modelMapper.map(entity, CredentialDTO.class);
|
||||||
|
AuthProvider authProvider = authProviderRepository.findById(entity.getProviderId());
|
||||||
|
|
||||||
|
if (authProvider == null) {
|
||||||
|
dto.setProvider(CommonParameter.DEFAULT_PROVIDER);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dto.setProvider(authProvider.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CredentialDTO();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CredentialDTO findByEmailAndProvider(String email, String provider) {
|
||||||
|
AuthProvider authProvider = authProviderRepository.findByName(provider);
|
||||||
|
Credential credential = credentialRepository.findByEmailAndProvider(email, authProvider.getId());
|
||||||
|
return entityToDTO(credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CredentialDTO findByToken(String token) {
|
||||||
|
Credential credential = credentialRepository.findByToken(token);
|
||||||
|
return entityToDTO(credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CredentialDTO findByAuthentication(OAuth2AuthenticationToken authentication) {
|
||||||
|
String email = authentication.getPrincipal().getAttribute("email");
|
||||||
|
String provider = authentication.getAuthorizedClientRegistrationId();
|
||||||
|
|
||||||
|
AuthProvider authProvider = authProviderRepository.findByName(provider);
|
||||||
|
Credential credential = credentialRepository.findByEmailAndProvider(email, authProvider.getId());
|
||||||
|
return entityToDTO(credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public CredentialDTO save(CredentialDTO dto) {
|
||||||
|
Credential credential = dtoToEntity(dto);
|
||||||
|
credential = credentialRepository.save(credential);
|
||||||
|
return entityToDTO(credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CredentialDTO saveNew(UserDTO user) {
|
||||||
|
Credential credential = new Credential();
|
||||||
|
|
||||||
|
AuthProvider authProvider = authProviderRepository.findByName(CommonParameter.DEFAULT_PROVIDER);
|
||||||
|
|
||||||
|
credential.setEmail(user.getEmail());
|
||||||
|
credential.setProviderId(authProvider.getId());
|
||||||
|
credential.setPassword(user.getPassword());
|
||||||
|
credential.setVerified(false);
|
||||||
|
credential.setToken();
|
||||||
|
credential.setExpiration();
|
||||||
|
|
||||||
|
credential = credentialRepository.save(credential);
|
||||||
|
return entityToDTO(credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CredentialDTO saveNew(OAuth2AuthenticationToken authentication) {
|
||||||
|
Credential credential = new Credential();
|
||||||
|
|
||||||
|
AuthProvider authProvider = authProviderRepository.findByName(authentication.getAuthorizedClientRegistrationId());
|
||||||
|
|
||||||
|
credential.setEmail(authentication.getPrincipal().getAttribute("email"));
|
||||||
|
credential.setProviderId(authProvider.getId());
|
||||||
|
credential.setPassword(authentication.getPrincipal().getAttribute("sub"));
|
||||||
|
credential.setVerified(false);
|
||||||
|
credential.setToken();
|
||||||
|
credential.setExpiration();
|
||||||
|
|
||||||
|
credential = credentialRepository.save(credential);
|
||||||
|
return entityToDTO(credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
package org.springframework.samples.petclinic.service.common;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
|
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||||
|
import org.springframework.samples.petclinic.dto.common.MessageDTO;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.thymeleaf.ITemplateEngine;
|
||||||
|
import org.thymeleaf.context.Context;
|
||||||
|
|
||||||
|
import javax.mail.MessagingException;
|
||||||
|
import javax.mail.internet.MimeMessage;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service("EmailService")
|
||||||
|
public class EmailService {
|
||||||
|
|
||||||
|
private static final String EMAIL_TEMPLATE = "email.html";
|
||||||
|
|
||||||
|
private static final String PNG_MIME = "image/png";
|
||||||
|
|
||||||
|
@Value("${mail.background}")
|
||||||
|
private String mailBackground;
|
||||||
|
|
||||||
|
@Value("${mail.banner}")
|
||||||
|
private String mailBanner;
|
||||||
|
|
||||||
|
@Value("${mail.logo}")
|
||||||
|
private String mailLogo;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected JavaMailSender mailSender;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected ITemplateEngine templateEngine;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sendMailAsynch : for the controller MailController
|
||||||
|
* send mail asynchronously
|
||||||
|
*
|
||||||
|
* @param messageDTO : message to be send by mail
|
||||||
|
* @param locale : not used now
|
||||||
|
*/
|
||||||
|
@Async
|
||||||
|
public void sendMailAsynch(MessageDTO messageDTO, Locale locale){
|
||||||
|
sendMail(messageDTO, locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sendMail : build mail according to a Thymeleaf template and a MessageDTO object
|
||||||
|
* @param messageDTO : message to be send by mail
|
||||||
|
* @param locale : not used now
|
||||||
|
*/
|
||||||
|
public void sendMail(MessageDTO messageDTO, Locale locale) {
|
||||||
|
MimeMessage mimeMessage = mailSender.createMimeMessage();
|
||||||
|
MimeMessageHelper message;
|
||||||
|
|
||||||
|
// Prepare the evaluation context
|
||||||
|
Context ctx = new Context(locale);
|
||||||
|
ctx.setVariable("toFirstName", messageDTO.getFirstName());
|
||||||
|
ctx.setVariable("toLastName", messageDTO.getLastName());
|
||||||
|
ctx.setVariable("mailSubject", messageDTO.getSubject());
|
||||||
|
ctx.setVariable("mailContent", messageDTO.getContent());
|
||||||
|
ctx.setVariable("mailLink", messageDTO.getLink());
|
||||||
|
ctx.setVariable("mailDate", new Date());
|
||||||
|
|
||||||
|
// Create the HTML body using Thymeleaf
|
||||||
|
String output = templateEngine.process(EMAIL_TEMPLATE, ctx);
|
||||||
|
|
||||||
|
try {
|
||||||
|
message = new MimeMessageHelper(mimeMessage, true /* multipart */, "UTF-8");
|
||||||
|
|
||||||
|
message.setFrom(messageDTO.getFrom());
|
||||||
|
message.setTo(messageDTO.getTo());
|
||||||
|
message.setSubject(messageDTO.getSubject());
|
||||||
|
message.setText(output, true /* isHtml */);
|
||||||
|
|
||||||
|
message.addInline("mailBackground", new ClassPathResource(mailBackground), PNG_MIME);
|
||||||
|
message.addInline("mailBanner", new ClassPathResource(mailBanner), PNG_MIME);
|
||||||
|
message.addInline("mailLogo", new ClassPathResource(mailLogo), PNG_MIME);
|
||||||
|
}
|
||||||
|
catch (MessagingException ex) {
|
||||||
|
log.error("Error sending mail !", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send mail
|
||||||
|
this.mailSender.send(mimeMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
package org.springframework.samples.petclinic.service;
|
package org.springframework.samples.petclinic.service.common;
|
||||||
|
|
||||||
import org.modelmapper.ModelMapper;
|
import org.modelmapper.ModelMapper;
|
||||||
import org.springframework.samples.petclinic.dto.RoleDTO;
|
import org.springframework.samples.petclinic.dto.common.RoleDTO;
|
||||||
import org.springframework.samples.petclinic.model.common.Role;
|
import org.springframework.samples.petclinic.model.common.Role;
|
||||||
import org.springframework.samples.petclinic.repository.RoleRepository;
|
import org.springframework.samples.petclinic.repository.RoleRepository;
|
||||||
|
import org.springframework.samples.petclinic.service.business.BaseService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.samples.petclinic.service;
|
package org.springframework.samples.petclinic.service.common;
|
||||||
|
|
||||||
public interface SecurityService {
|
public interface SecurityService {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.samples.petclinic.service;
|
package org.springframework.samples.petclinic.service.common;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
@ -1,20 +1,14 @@
|
||||||
package org.springframework.samples.petclinic.service;
|
package org.springframework.samples.petclinic.service.common;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.samples.petclinic.dto.RoleDTO;
|
import org.springframework.samples.petclinic.dto.common.UserDTO;
|
||||||
import org.springframework.samples.petclinic.dto.UserDTO;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service("UserDetailsService")
|
@Service("UserDetailsService")
|
||||||
public class UserDetailsServiceImpl implements UserDetailsService {
|
public class UserDetailsServiceImpl implements UserDetailsService {
|
||||||
|
@ -36,15 +30,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
|
||||||
if (userDTO == null)
|
if (userDTO == null)
|
||||||
throw new UsernameNotFoundException("User not found with email :" + email);
|
throw new UsernameNotFoundException("User not found with email :" + email);
|
||||||
|
|
||||||
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
|
return userDTO;
|
||||||
|
|
||||||
for (RoleDTO role : userDTO.getRoles()) {
|
|
||||||
grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new org.springframework.security.core.userdetails.User(userDTO.getEmail(), userDTO.getMatchingPassword(),
|
|
||||||
grantedAuthorities);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,11 +1,12 @@
|
||||||
package org.springframework.samples.petclinic.service;
|
package org.springframework.samples.petclinic.service.common;
|
||||||
|
|
||||||
import org.modelmapper.ModelMapper;
|
import org.modelmapper.ModelMapper;
|
||||||
import org.springframework.samples.petclinic.dto.RoleDTO;
|
import org.springframework.samples.petclinic.dto.common.RoleDTO;
|
||||||
import org.springframework.samples.petclinic.dto.UserDTO;
|
import org.springframework.samples.petclinic.dto.common.UserDTO;
|
||||||
import org.springframework.samples.petclinic.model.common.Role;
|
import org.springframework.samples.petclinic.model.common.Role;
|
||||||
import org.springframework.samples.petclinic.model.common.User;
|
import org.springframework.samples.petclinic.model.common.User;
|
||||||
import org.springframework.samples.petclinic.repository.UserRepository;
|
import org.springframework.samples.petclinic.repository.UserRepository;
|
||||||
|
import org.springframework.samples.petclinic.service.business.BaseService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -37,13 +38,14 @@ public class UserService implements BaseService<User, UserDTO> {
|
||||||
User user = modelMapper.map(dto, User.class);
|
User user = modelMapper.map(dto, User.class);
|
||||||
user.setPassword(dto.getPassword());
|
user.setPassword(dto.getPassword());
|
||||||
|
|
||||||
|
/*
|
||||||
if (dto.getRoles() != null) {
|
if (dto.getRoles() != null) {
|
||||||
for (RoleDTO roleDTO : dto.getRoles()) {
|
for (RoleDTO roleDTO : dto.getRoles()) {
|
||||||
Role role = modelMapper.map(roleDTO, Role.class);
|
Role role = modelMapper.map(roleDTO, Role.class);
|
||||||
user.addRole(role);
|
user.addRole(role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,14 +58,14 @@ public class UserService implements BaseService<User, UserDTO> {
|
||||||
UserDTO userDto = modelMapper.map(entity, UserDTO.class);
|
UserDTO userDto = modelMapper.map(entity, UserDTO.class);
|
||||||
userDto.setPassword(entity.getPassword());
|
userDto.setPassword(entity.getPassword());
|
||||||
userDto.setMatchingPassword(entity.getPassword());
|
userDto.setMatchingPassword(entity.getPassword());
|
||||||
|
/*
|
||||||
if (entity.getRoles() != null) {
|
if (entity.getRoles() != null) {
|
||||||
for (Role role : entity.getRoles()) {
|
for (Role role : entity.getRoles()) {
|
||||||
RoleDTO roleDTO = modelMapper.map(role, RoleDTO.class);
|
RoleDTO roleDTO = modelMapper.map(role, RoleDTO.class);
|
||||||
userDto.addRole(roleDTO);
|
userDto.addRole(roleDTO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return userDto;
|
return userDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,4 +116,8 @@ public class UserService implements BaseService<User, UserDTO> {
|
||||||
return entityToDTO(user);
|
return entityToDTO(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean existByEmail(String email) {
|
||||||
|
return userRepository.existsByEmail(email);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -30,8 +30,6 @@ spring.resources.cache.cachecontrol.max-age=12h
|
||||||
#logging.level.org.hibernate: DEBUG
|
#logging.level.org.hibernate: DEBUG
|
||||||
#logging.level.org.springframework.context.annotation=TRACE
|
#logging.level.org.springframework.context.annotation=TRACE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
spring.datasource.hikari.connectionTimeout=20000
|
spring.datasource.hikari.connectionTimeout=20000
|
||||||
spring.datasource.hikari.maximumPoolSize=5
|
spring.datasource.hikari.maximumPoolSize=5
|
||||||
spring.datasource.initialize=true
|
spring.datasource.initialize=true
|
||||||
|
@ -42,6 +40,7 @@ spring.datasource.password=
|
||||||
spring.h2.console.enabled=true
|
spring.h2.console.enabled=true
|
||||||
spring.h2.console.path=/h2-console
|
spring.h2.console.path=/h2-console
|
||||||
|
|
||||||
|
######################################################################### OAUTH2
|
||||||
spring.security.oauth2.client.registration.google.client-id=${OAUTH2_GOOGLE_CLIENT_ID}
|
spring.security.oauth2.client.registration.google.client-id=${OAUTH2_GOOGLE_CLIENT_ID}
|
||||||
spring.security.oauth2.client.registration.google.client-secret=${OAUTH2_GOOGLE_CLIENT_SECRET}
|
spring.security.oauth2.client.registration.google.client-secret=${OAUTH2_GOOGLE_CLIENT_SECRET}
|
||||||
|
|
||||||
|
@ -52,6 +51,17 @@ spring.security.oauth2.client.registration.github.client-secret=${OAUTH2_GITHUB_
|
||||||
#spring.security.oauth2.client.registration.facebook.client-id=<your client id>
|
#spring.security.oauth2.client.registration.facebook.client-id=<your client id>
|
||||||
#spring.security.oauth2.client.registration.facebook.client-secret=<your client secret>
|
#spring.security.oauth2.client.registration.facebook.client-secret=<your client secret>
|
||||||
|
|
||||||
|
|
||||||
#spring.security.oauth2.client.registration.twitter.client-id=<your client id>
|
#spring.security.oauth2.client.registration.twitter.client-id=<your client id>
|
||||||
#spring.security.oauth2.client.registration.twitter.client-secret=<your client secret>
|
#spring.security.oauth2.client.registration.twitter.client-secret=<your client secret>
|
||||||
|
|
||||||
|
#################################################################### SPRING MAIL
|
||||||
|
spring.mail.host=smtp.mailtrap.io
|
||||||
|
spring.mail.port=2525
|
||||||
|
spring.mail.protocol=smtp
|
||||||
|
spring.mail.username=${SPRING_MAIL_USERNAME}
|
||||||
|
spring.mail.password=${SPRING_MAIL_PASSWORD}
|
||||||
|
mail.background=static/resources/images/mail-background.png
|
||||||
|
mail.banner=static/resources/images/mail-banner.png
|
||||||
|
mail.logo=static/resources/images/mail-logo.png
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,16 +52,30 @@ INSERT INTO visits VALUES (2, 8, '2013-01-02', 'rabies shot');
|
||||||
INSERT INTO visits VALUES (3, 8, '2013-01-03', 'neutered');
|
INSERT INTO visits VALUES (3, 8, '2013-01-03', 'neutered');
|
||||||
INSERT INTO visits VALUES (4, 7, '2013-01-04', 'spayed');
|
INSERT INTO visits VALUES (4, 7, '2013-01-04', 'spayed');
|
||||||
|
|
||||||
INSERT INTO roles VALUES (1,'ADMIN');
|
INSERT INTO roles (id, name) VALUES
|
||||||
INSERT INTO roles VALUES (2,'STAFF');
|
(1,'ROLE_ADMIN'),
|
||||||
INSERT INTO roles VALUES (3,'USER');
|
(2,'ROLE_STAFF'),
|
||||||
|
(3,'ROLE_USER');
|
||||||
|
|
||||||
INSERT INTO users VALUES (1, 'George', 'Franklin', 'georges.franklin@petclinic.com', true,'$2a$10$8KypNYtPopFo8Sk5jbKJ4.lCKeBhdApsrkmFfhwjB8nCls8qpzjZG', 'local', null, '6085551023', '110 W. Liberty St.','','',12354,'Madison','USA');
|
INSERT INTO users (id, first_name, last_name, email, password, enabled, telephone, street1, zip_code, city, country) VALUES
|
||||||
INSERT INTO users VALUES (2, 'Betty', 'Davis', 'betty.davis@petclinic.com', true, '$2a$10$InKx/fhX3CmLi8zKpHYx/.ETHUlZwvT1xn.Za/pp2JR0iEtYV9a9O', 'local', null, '6085551749','638 Cardinal Ave.', '', '', 6546, 'Sun Prairie', 'USA');
|
(1, 'George', 'Franklin', 'georges.franklin@petclinic.com', '$2a$10$8KypNYtPopFo8Sk5jbKJ4.lCKeBhdApsrkmFfhwjB8nCls8qpzjZG', true, '6085551023', '110 W. Liberty St.',12354,'Madison','USA'),
|
||||||
INSERT INTO users VALUES (3, 'Eduardo', 'Rodriquez', 'eduardo.rodriguez@petclinic.com', true, '$2a$10$P55nbvVibHpoyWzenHngjOf.oEmcj74mI/VJaUZwGX9v8klctzsNW', 'local', null, '6085558763','2693 Commerce St.', '', '', 65454, 'McFarland', 'USA');
|
(2, 'Betty', 'Davis', 'betty.davis@petclinic.com', '$2a$10$InKx/fhX3CmLi8zKpHYx/.ETHUlZwvT1xn.Za/pp2JR0iEtYV9a9O', true, '6085551749','638 Cardinal Ave.', 6546, 'Sun Prairie', 'USA'),
|
||||||
|
(3, 'Eduardo', 'Rodriquez', 'eduardo.rodriguez@petclinic.com', '$2a$10$P55nbvVibHpoyWzenHngjOf.oEmcj74mI/VJaUZwGX9v8klctzsNW', true, '6085558763','2693 Commerce St.', 65454, 'McFarland', 'USA'),
|
||||||
|
(4, 'Paul-Emmanuel','DOS SANTOS FACAO','pedsf.fullstack@gmail.com','$2a$10$AzoUxi1IQFJMzLHcCGmDjuDHAQqAcAiRLz6UMeItdTL3mMWxMZEPC', true, '6085558763','2693 Commerce St.', 65454, 'McFarland', 'USA');
|
||||||
|
|
||||||
|
INSERT INTO users_roles (user_id, role_id) VALUES
|
||||||
|
(1,1),(1,2),(1,3),
|
||||||
|
(2,3),(3,3);
|
||||||
|
|
||||||
|
INSERT INTO auth_providers (id, name) VALUES
|
||||||
|
(1,'local'),
|
||||||
|
(2,'google'),
|
||||||
|
(3,'github'),
|
||||||
|
(4,'twitter');
|
||||||
|
|
||||||
|
INSERT INTO credentials (provider_id, email, password, verified) VALUES
|
||||||
|
(1, 'georges.franklin@petclinic.com', '$2a$10$8KypNYtPopFo8Sk5jbKJ4.lCKeBhdApsrkmFfhwjB8nCls8qpzjZG', true),
|
||||||
|
(1, 'betty.davis@petclinic.com', '$2a$10$InKx/fhX3CmLi8zKpHYx/.ETHUlZwvT1xn.Za/pp2JR0iEtYV9a9O', true),
|
||||||
|
(1, 'eduardo.rodriguez@petclinic.com', '$2a$10$P55nbvVibHpoyWzenHngjOf.oEmcj74mI/VJaUZwGX9v8klctzsNW', true),
|
||||||
|
(2, 'pedsf.fullstack@gmail.com','117496521794255275093', true);
|
||||||
|
|
||||||
INSERT INTO users_roles VALUES (1,1);
|
|
||||||
INSERT INTO users_roles VALUES (1,2);
|
|
||||||
INSERT INTO users_roles VALUES (1,3);
|
|
||||||
INSERT INTO users_roles VALUES (2,3);
|
|
||||||
INSERT INTO users_roles VALUES (3,3);
|
|
||||||
|
|
|
@ -7,7 +7,10 @@ DROP TABLE types IF EXISTS;
|
||||||
DROP TABLE owners IF EXISTS;
|
DROP TABLE owners IF EXISTS;
|
||||||
DROP TABLE roles IF EXISTS;
|
DROP TABLE roles IF EXISTS;
|
||||||
DROP TABLE users IF EXISTS;
|
DROP TABLE users IF EXISTS;
|
||||||
|
DROP TABLE users_email IF EXISTS;
|
||||||
|
DROP TABLE users_roles IF EXISTS;
|
||||||
|
DROP TABLE auth_providers IF EXISTS;
|
||||||
|
DROP TABLE credentials IF EXISTS;
|
||||||
|
|
||||||
CREATE TABLE vets (
|
CREATE TABLE vets (
|
||||||
id INTEGER IDENTITY PRIMARY KEY,
|
id INTEGER IDENTITY PRIMARY KEY,
|
||||||
|
@ -72,21 +75,22 @@ CREATE TABLE roles (
|
||||||
CREATE INDEX roles_name ON roles (name);
|
CREATE INDEX roles_name ON roles (name);
|
||||||
|
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
id INTEGER IDENTITY PRIMARY KEY,
|
id INTEGER IDENTITY PRIMARY KEY,
|
||||||
first_name VARCHAR(30) NOT NULL,
|
first_name VARCHAR(30) NOT NULL,
|
||||||
last_name VARCHAR_IGNORECASE(30) NOT NULL,
|
last_name VARCHAR_IGNORECASE(30) NOT NULL,
|
||||||
email VARCHAR(50) NOT NULL,
|
email VARCHAR(50) NOT NULL,
|
||||||
email_verified BOOLEAN NOT NULL,
|
password VARCHAR(255) NOT NULL,
|
||||||
password VARCHAR(255) NOT NULL,
|
enabled BOOLEAN NOT NULL,
|
||||||
provider VARCHAR(20),
|
account_unexpired BOOLEAN NOT NULL DEFAULT true,
|
||||||
provider_id VARCHAR(20),
|
account_unlocked BOOLEAN NOT NULL DEFAULT true,
|
||||||
telephone VARCHAR(20),
|
credential_unexpired BOOLEAN NOT NULL DEFAULT true,
|
||||||
street1 VARCHAR(50),
|
telephone VARCHAR(20),
|
||||||
street2 VARCHAR(50),
|
street1 VARCHAR(50),
|
||||||
street3 VARCHAR(50),
|
street2 VARCHAR(50),
|
||||||
zip_code VARCHAR(6),
|
street3 VARCHAR(50),
|
||||||
city VARCHAR(80),
|
zip_code VARCHAR(6),
|
||||||
country VARCHAR(50)
|
city VARCHAR(80),
|
||||||
|
country VARCHAR(50)
|
||||||
);
|
);
|
||||||
CREATE INDEX users_email ON users (email);
|
CREATE INDEX users_email ON users (email);
|
||||||
|
|
||||||
|
@ -97,3 +101,21 @@ CREATE TABLE public.users_roles (
|
||||||
ALTER TABLE users_roles ADD CONSTRAINT fk_users_roles_user_id FOREIGN KEY (user_id) REFERENCES users (id);
|
ALTER TABLE users_roles ADD CONSTRAINT fk_users_roles_user_id FOREIGN KEY (user_id) REFERENCES users (id);
|
||||||
ALTER TABLE users_roles ADD CONSTRAINT fk_users_roles_role_id FOREIGN KEY (role_id) REFERENCES roles (id);
|
ALTER TABLE users_roles ADD CONSTRAINT fk_users_roles_role_id FOREIGN KEY (role_id) REFERENCES roles (id);
|
||||||
CREATE INDEX users_roles_user_id ON users_roles (user_id);
|
CREATE INDEX users_roles_user_id ON users_roles (user_id);
|
||||||
|
|
||||||
|
CREATE TABLE auth_providers (
|
||||||
|
id INTEGER IDENTITY PRIMARY KEY,
|
||||||
|
name VARCHAR(20) NOT NULL
|
||||||
|
);
|
||||||
|
CREATE INDEX auth_providers_name ON auth_providers (name);
|
||||||
|
|
||||||
|
CREATE TABLE credentials (
|
||||||
|
id INTEGER IDENTITY PRIMARY KEY,
|
||||||
|
provider_id INTEGER NOT NULL,
|
||||||
|
email VARCHAR(50) NOT NULL,
|
||||||
|
password VARCHAR(255) NOT NULL,
|
||||||
|
verified BOOLEAN NOT NULL,
|
||||||
|
token VARCHAR(255) DEFAULT NULL,
|
||||||
|
expiration DATE DEFAULT NULL
|
||||||
|
);
|
||||||
|
ALTER TABLE credentials ADD CONSTRAINT fk_credentials_provider_id FOREIGN KEY (provider_id) REFERENCES auth_providers (id);
|
||||||
|
CREATE INDEX credentials_email ON credentials (email);
|
||||||
|
|
BIN
src/main/resources/static/resources/images/mail-background.png
Normal file
BIN
src/main/resources/static/resources/images/mail-background.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
BIN
src/main/resources/static/resources/images/mail-banner.png
Normal file
BIN
src/main/resources/static/resources/images/mail-banner.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
BIN
src/main/resources/static/resources/images/mail-logo.png
Normal file
BIN
src/main/resources/static/resources/images/mail-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
49
src/main/resources/templates/email.html
Normal file
49
src/main/resources/templates/email.html
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="https://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title data-th-remove="all">Template for HTML email (editable)</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="background-color: #ccc; background-image: url(images/background.png)"
|
||||||
|
data-th-style="|background-color: #ccc; background-image: url(cid:mailBackground)|">
|
||||||
|
<div style="padding: 40px;">
|
||||||
|
<div style="margin-left: auto; margin-right: auto; min-width: 320px; border: solid 1px #555; border-radius: 6px;">
|
||||||
|
<div style="background-color: #555; padding: 4px 4px 0px 4px; text-align: left;">
|
||||||
|
<div style="background-image: url(images/logo-background.png);"
|
||||||
|
data-th-style="|background-image: url(cid:mailBanner)|">
|
||||||
|
<img style="border: solid 1px #555; border-radius: 6px;"
|
||||||
|
src="images/shop-logo.png" data-th-src="|cid:mailLogo|" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="padding: 15px 15px 30px 15px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size:1em; background-color: #fff; color:#333;">
|
||||||
|
<h1>
|
||||||
|
<span data-th-text="${mailSubject}">Subject</span></p>
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
<span>Hello </span>
|
||||||
|
<b data-th-text="${toFirstName}">FirstName</b>
|
||||||
|
<b data-th-text="${toLastName}">toLastName</b>!
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p th:utext="${#strings.replace(#strings.escapeXml(mailContent),' ','<br>')}">mail content</p>
|
||||||
|
<a th:href="@{${mailLink}}">Approve the connection</a>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<span data-th-text="${#dates.format(mailDate)}">date</span>
|
||||||
|
</p>
|
||||||
|
<p>Regards </p>
|
||||||
|
</div>
|
||||||
|
<div style="background-color: #555; padding: 4px 4px 0px 4px; text-align: right;">
|
||||||
|
<div style="background-image: url(images/logo-background.png);"
|
||||||
|
data-th-style="|background-image: url(cid:mailBackground)|">
|
||||||
|
<img style="border: solid 1px #555; border-radius: 6px;"
|
||||||
|
src="images/shop-logo.png" data-th-src="|cid:mailBanner|" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||||
<link rel="stylesheet" th:href="@{/resources/css/petclinic.css}" />
|
<link rel="stylesheet" th:href="@{/resources/css/petclinic.css}" />
|
||||||
<!--link rel="stylesheet" th:href="@{/resources/css/style.css}" /-->
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -21,8 +21,9 @@
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
<button
|
<button
|
||||||
th:with="text=${owner['new']} ? 'Add Owner' : 'Update Owner'"
|
th:with="text=${owner['new']} ? 'Add Owner' : 'Update Owner'"
|
||||||
class="btn btn-default" type="submit" th:text="${text}">Add
|
class="btn btn-default" type="submit" th:text="${text}">Add Owner
|
||||||
Owner</button>
|
</button>
|
||||||
|
<a class="btn btn-default" href="/">Cancel</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
<html xmlns:th="https://www.thymeleaf.org"
|
||||||
|
th:replace="~{fragments/layout :: layout (~{::body},'users')}">
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h2>Change password</h2>
|
||||||
|
<form th:object="${user}" class="form-horizontal" id="add-user-form" method="post">
|
||||||
|
<input type="hidden" th:field="${user.id}" />
|
||||||
|
<input type="hidden" th:field="${user.firstName}" />
|
||||||
|
<input type="hidden" th:field="${user.lastName}" />
|
||||||
|
<input type="hidden" th:field="${user.password}" />
|
||||||
|
<input type="hidden" th:field="${user.matchingPassword}" />
|
||||||
|
<input type="hidden" th:field="${user.enabled}" />
|
||||||
|
<input type="hidden" th:field="${user.accountNonExpired}" />
|
||||||
|
<input type="hidden" th:field="${user.accountNonLocked}" />
|
||||||
|
<input type="hidden" th:field="${user.credentialsNonExpired}" />;
|
||||||
|
<input type="hidden" th:field="${user.roles}" />
|
||||||
|
<input type="hidden" th:field="${user.telephone}" />
|
||||||
|
<input type="hidden" th:field="${user.street1}" />
|
||||||
|
<input type="hidden" th:field="${user.street2}" />
|
||||||
|
<input type="hidden" th:field="${user.street3}" />
|
||||||
|
<input type="hidden" th:field="${user.zipCode}" />
|
||||||
|
<input type="hidden" th:field="${user.city}" />
|
||||||
|
<input type="hidden" th:field="${user.country}" />
|
||||||
|
|
||||||
|
<div class="form-group has-feedback">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="email">Email address</label>
|
||||||
|
<input type="email" th:field="${user.email}" class="form-control input-lg" id="email" readonly>
|
||||||
|
<small id="emailHelp" class="form-text text-muted">We'll never share your emailConfiguration with anyone else.</small>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="oldPassword">Present password</label>
|
||||||
|
<input type="password" name="oldPassword" class="form-control input-lg" id="oldPassword" th:placeholder="password" value="">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="newPassword">New password</label>
|
||||||
|
<input type="password" name="newPassword" class="form-control input-lg" id="newPassword" th:placeholder="password" value="">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="newMatchingPassword">Password</label>
|
||||||
|
<input type="password" name="newMatchingPassword" class="form-control input-lg" id="newMatchingPassword" th:placeholder="password" value="">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<button class="btn btn-default" type="submit">Change password</button>
|
||||||
|
<a class="btn btn-default" th:href="@{/}">Cancel</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -3,9 +3,16 @@
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<h2>User</h2>
|
<h2>User registration</h2>
|
||||||
<form th:object="${user}" class="form-horizontal" id="add-user-form" method="post">
|
<form th:object="${user}" class="form-horizontal" id="add-user-form" method="post">
|
||||||
|
<input type="hidden" th:field="${user.enabled}" />
|
||||||
|
<input type="hidden" th:field="${user.accountNonExpired}" />
|
||||||
|
<input type="hidden" th:field="${user.accountNonLocked}" />
|
||||||
|
<input type="hidden" th:field="${user.credentialsNonExpired}" />
|
||||||
|
|
||||||
<div class="form-group has-feedback">
|
<div class="form-group has-feedback">
|
||||||
|
<input
|
||||||
|
th:replace="~{fragments/inputField :: input ('Email', 'email', 'email')}" />
|
||||||
<input
|
<input
|
||||||
th:replace="~{fragments/inputField :: input ('First Name', 'firstName', 'text')}" />
|
th:replace="~{fragments/inputField :: input ('First Name', 'firstName', 'text')}" />
|
||||||
<input
|
<input
|
||||||
|
@ -14,8 +21,6 @@
|
||||||
th:replace="~{fragments/inputField :: input ('Password', 'password', 'password')}" />
|
th:replace="~{fragments/inputField :: input ('Password', 'password', 'password')}" />
|
||||||
<input
|
<input
|
||||||
th:replace="~{fragments/inputField :: input ('Repeat password', 'matchingPassword', 'password')}" />
|
th:replace="~{fragments/inputField :: input ('Repeat password', 'matchingPassword', 'password')}" />
|
||||||
<input
|
|
||||||
th:replace="~{fragments/inputField :: input ('Email', 'email', 'email')}" />
|
|
||||||
<input
|
<input
|
||||||
th:replace="~{fragments/inputField :: input ('Phone', 'telephone', 'text')}" />
|
th:replace="~{fragments/inputField :: input ('Phone', 'telephone', 'text')}" />
|
||||||
<input
|
<input
|
||||||
|
@ -33,10 +38,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
<button
|
<button class="btn btn-default" type="submit">Register</button>
|
||||||
th:with="text=${user['new']} ? 'Register' : 'Update User'"
|
<a class="btn btn-default" th:href="@{/}">Cancel</a>
|
||||||
class="btn btn-default" type="submit" th:text="${text}">Add User</button>
|
|
||||||
<a class="btn btn-default" href="/">Cancel</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
49
src/main/resources/templates/users/userUpdateForm.html
Normal file
49
src/main/resources/templates/users/userUpdateForm.html
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<html xmlns:th="https://www.thymeleaf.org"
|
||||||
|
th:replace="~{fragments/layout :: layout (~{::body},'users')}">
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h2>User update</h2>
|
||||||
|
<form th:object="${user}" class="form-horizontal" id="add-user-form" method="post">
|
||||||
|
<input type="hidden" th:field="${user.id}" />
|
||||||
|
<input type="hidden" th:field="${user.password}" />
|
||||||
|
<input type="hidden" th:field="${user.matchingPassword}" />
|
||||||
|
<input type="hidden" th:field="${user.enabled}" />
|
||||||
|
<input type="hidden" th:field="${user.accountNonExpired}" />
|
||||||
|
<input type="hidden" th:field="${user.accountNonLocked}" />
|
||||||
|
<input type="hidden" th:field="${user.credentialsNonExpired}" />
|
||||||
|
<input type="hidden" th:field="${user.roles}" />
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group has-feedback">
|
||||||
|
<input
|
||||||
|
th:replace="~{fragments/inputField :: input ('Email', 'email', 'email')}" disabled />
|
||||||
|
<input
|
||||||
|
th:replace="~{fragments/inputField :: input ('First Name', 'firstName', 'text')}" />
|
||||||
|
<input
|
||||||
|
th:replace="~{fragments/inputField :: input ('Last Name', 'lastName', 'text')}" />
|
||||||
|
<input
|
||||||
|
th:replace="~{fragments/inputField :: input ('Phone', 'telephone', 'text')}" />
|
||||||
|
<input
|
||||||
|
th:replace="~{fragments/inputField :: input ('Address', 'street1', 'text')}" />
|
||||||
|
<input
|
||||||
|
th:replace="~{fragments/inputField :: input ('Address', 'street2', 'text')}" />
|
||||||
|
<input
|
||||||
|
th:replace="~{fragments/inputField :: input ('Address', 'street3', 'text')}" />
|
||||||
|
<input
|
||||||
|
th:replace="~{fragments/inputField :: input ('City', 'city', 'text')}" />
|
||||||
|
<input
|
||||||
|
th:replace="~{fragments/inputField :: input ('Zip code', 'zipCode', 'text')}" />
|
||||||
|
<input
|
||||||
|
th:replace="~{fragments/inputField :: input ('Country', 'country', 'text')}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<button class="btn btn-default" type="submit">Update</button>
|
||||||
|
<a class="btn btn-default" th:href="@{'/user/' + ${user.id} + '/edit/password'}">Change password</a>
|
||||||
|
<a class="btn btn-default" th:href="@{/}">Cancel</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,6 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<html xmlns:th="https://www.thymeleaf.org"
|
||||||
|
th:replace="~{fragments/layout :: layout (~{::body},'home')}">
|
||||||
<html xmlns:th="https://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'home')}">
|
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
@ -13,4 +12,4 @@
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -12,7 +12,7 @@ import org.springframework.samples.petclinic.dto.OwnerDTO;
|
||||||
import org.springframework.samples.petclinic.dto.PetDTO;
|
import org.springframework.samples.petclinic.dto.PetDTO;
|
||||||
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
||||||
import org.springframework.samples.petclinic.dto.VisitDTO;
|
import org.springframework.samples.petclinic.dto.VisitDTO;
|
||||||
import org.springframework.samples.petclinic.service.OwnerService;
|
import org.springframework.samples.petclinic.service.business.OwnerService;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
||||||
|
|
|
@ -40,8 +40,8 @@ import org.springframework.samples.petclinic.dto.OwnerDTO;
|
||||||
import org.springframework.samples.petclinic.dto.PetDTO;
|
import org.springframework.samples.petclinic.dto.PetDTO;
|
||||||
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
||||||
import org.springframework.samples.petclinic.dto.VisitDTO;
|
import org.springframework.samples.petclinic.dto.VisitDTO;
|
||||||
import org.springframework.samples.petclinic.service.OwnerService;
|
import org.springframework.samples.petclinic.service.business.OwnerService;
|
||||||
import org.springframework.samples.petclinic.service.VisitService;
|
import org.springframework.samples.petclinic.service.business.VisitService;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.empty;
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
|
|
@ -11,8 +11,8 @@ import org.springframework.samples.petclinic.common.CommonView;
|
||||||
import org.springframework.samples.petclinic.dto.OwnerDTO;
|
import org.springframework.samples.petclinic.dto.OwnerDTO;
|
||||||
import org.springframework.samples.petclinic.dto.PetDTO;
|
import org.springframework.samples.petclinic.dto.PetDTO;
|
||||||
import org.springframework.samples.petclinic.repository.PetRepository;
|
import org.springframework.samples.petclinic.repository.PetRepository;
|
||||||
import org.springframework.samples.petclinic.service.OwnerService;
|
import org.springframework.samples.petclinic.service.business.OwnerService;
|
||||||
import org.springframework.samples.petclinic.service.PetService;
|
import org.springframework.samples.petclinic.service.business.PetService;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
|
|
||||||
|
|
|
@ -42,9 +42,9 @@ import org.springframework.samples.petclinic.dto.OwnerDTO;
|
||||||
import org.springframework.samples.petclinic.dto.PetDTO;
|
import org.springframework.samples.petclinic.dto.PetDTO;
|
||||||
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
||||||
import org.springframework.samples.petclinic.formatter.PetTypeFormatter;
|
import org.springframework.samples.petclinic.formatter.PetTypeFormatter;
|
||||||
import org.springframework.samples.petclinic.service.OwnerService;
|
import org.springframework.samples.petclinic.service.business.OwnerService;
|
||||||
import org.springframework.samples.petclinic.service.PetService;
|
import org.springframework.samples.petclinic.service.business.PetService;
|
||||||
import org.springframework.samples.petclinic.service.PetTypeService;
|
import org.springframework.samples.petclinic.service.business.PetTypeService;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,7 +15,7 @@ import org.springframework.samples.petclinic.common.CommonEndPoint;
|
||||||
import org.springframework.samples.petclinic.common.CommonView;
|
import org.springframework.samples.petclinic.common.CommonView;
|
||||||
import org.springframework.samples.petclinic.dto.VetsDTO;
|
import org.springframework.samples.petclinic.dto.VetsDTO;
|
||||||
import org.springframework.samples.petclinic.repository.VetRepository;
|
import org.springframework.samples.petclinic.repository.VetRepository;
|
||||||
import org.springframework.samples.petclinic.service.VetService;
|
import org.springframework.samples.petclinic.service.business.VetService;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ package org.springframework.samples.petclinic.controller;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
@ -40,10 +39,9 @@ import org.springframework.samples.petclinic.common.CommonView;
|
||||||
import org.springframework.samples.petclinic.dto.SpecialtyDTO;
|
import org.springframework.samples.petclinic.dto.SpecialtyDTO;
|
||||||
import org.springframework.samples.petclinic.dto.VetDTO;
|
import org.springframework.samples.petclinic.dto.VetDTO;
|
||||||
import org.springframework.samples.petclinic.dto.VetsDTO;
|
import org.springframework.samples.petclinic.dto.VetsDTO;
|
||||||
import org.springframework.samples.petclinic.service.VetService;
|
import org.springframework.samples.petclinic.service.business.VetService;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
import org.springframework.test.web.servlet.ResultActions;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -12,7 +12,7 @@ import org.springframework.samples.petclinic.dto.PetDTO;
|
||||||
import org.springframework.samples.petclinic.dto.VisitDTO;
|
import org.springframework.samples.petclinic.dto.VisitDTO;
|
||||||
import org.springframework.samples.petclinic.model.business.Visit;
|
import org.springframework.samples.petclinic.model.business.Visit;
|
||||||
import org.springframework.samples.petclinic.repository.VisitRepository;
|
import org.springframework.samples.petclinic.repository.VisitRepository;
|
||||||
import org.springframework.samples.petclinic.service.PetService;
|
import org.springframework.samples.petclinic.service.business.PetService;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,8 @@ import org.springframework.samples.petclinic.dto.PetDTO;
|
||||||
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
||||||
import org.springframework.samples.petclinic.dto.VisitDTO;
|
import org.springframework.samples.petclinic.dto.VisitDTO;
|
||||||
import org.springframework.samples.petclinic.model.business.Visit;
|
import org.springframework.samples.petclinic.model.business.Visit;
|
||||||
import org.springframework.samples.petclinic.service.PetService;
|
import org.springframework.samples.petclinic.service.business.PetService;
|
||||||
import org.springframework.samples.petclinic.service.VisitService;
|
import org.springframework.samples.petclinic.service.business.VisitService;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
||||||
import org.springframework.samples.petclinic.formatter.PetTypeFormatter;
|
import org.springframework.samples.petclinic.formatter.PetTypeFormatter;
|
||||||
import org.springframework.samples.petclinic.model.business.PetType;
|
import org.springframework.samples.petclinic.model.business.PetType;
|
||||||
import org.springframework.samples.petclinic.service.PetService;
|
import org.springframework.samples.petclinic.service.business.PetService;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
|
@ -31,7 +31,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
import org.springframework.samples.petclinic.dto.PetTypeDTO;
|
||||||
import org.springframework.samples.petclinic.formatter.PetTypeFormatter;
|
import org.springframework.samples.petclinic.formatter.PetTypeFormatter;
|
||||||
import org.springframework.samples.petclinic.model.business.PetType;
|
import org.springframework.samples.petclinic.model.business.PetType;
|
||||||
import org.springframework.samples.petclinic.service.PetService;
|
import org.springframework.samples.petclinic.service.business.PetService;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
|
|
|
@ -19,6 +19,9 @@ import org.springframework.samples.petclinic.repository.OwnerRepository;
|
||||||
import org.springframework.samples.petclinic.repository.PetRepository;
|
import org.springframework.samples.petclinic.repository.PetRepository;
|
||||||
import org.springframework.samples.petclinic.repository.PetTypeRepository;
|
import org.springframework.samples.petclinic.repository.PetTypeRepository;
|
||||||
import org.springframework.samples.petclinic.repository.VisitRepository;
|
import org.springframework.samples.petclinic.repository.VisitRepository;
|
||||||
|
import org.springframework.samples.petclinic.service.business.OwnerService;
|
||||||
|
import org.springframework.samples.petclinic.service.business.PetService;
|
||||||
|
import org.springframework.samples.petclinic.service.business.PetTypeService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
|
@ -17,6 +17,9 @@ import org.springframework.samples.petclinic.model.business.PetType;
|
||||||
import org.springframework.samples.petclinic.repository.PetRepository;
|
import org.springframework.samples.petclinic.repository.PetRepository;
|
||||||
import org.springframework.samples.petclinic.repository.PetTypeRepository;
|
import org.springframework.samples.petclinic.repository.PetTypeRepository;
|
||||||
import org.springframework.samples.petclinic.repository.VisitRepository;
|
import org.springframework.samples.petclinic.repository.VisitRepository;
|
||||||
|
import org.springframework.samples.petclinic.service.business.OwnerService;
|
||||||
|
import org.springframework.samples.petclinic.service.business.PetService;
|
||||||
|
import org.springframework.samples.petclinic.service.business.PetTypeService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.springframework.samples.petclinic.dto.VetDTO;
|
||||||
import org.springframework.samples.petclinic.model.business.Vet;
|
import org.springframework.samples.petclinic.model.business.Vet;
|
||||||
import org.springframework.samples.petclinic.repository.SpecialtyRepository;
|
import org.springframework.samples.petclinic.repository.SpecialtyRepository;
|
||||||
import org.springframework.samples.petclinic.repository.VetRepository;
|
import org.springframework.samples.petclinic.repository.VetRepository;
|
||||||
|
import org.springframework.samples.petclinic.service.business.VetService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
Loading…
Reference in a new issue