From 0774e6bd3c7fc7c851dba72e18d0455a5b38539d Mon Sep 17 00:00:00 2001 From: BarbaraMAlmeida Date: Thu, 21 Mar 2024 11:28:28 -0300 Subject: [PATCH] =?UTF-8?q?Resolu=C3=A7=C3=A3o=20da=20atividade=20spring?= =?UTF-8?q?=20security?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bds04/components/JwtTokenEnhancer.java | 31 +++++ .../devsuperior/bds04/config/AppConfig.java | 38 ++++++ .../config/AuthorizationServerConfig.java | 65 ++++++++++ .../bds04/config/ResourceServerConfig.java | 60 +++++++++ .../bds04/config/WebSecurityConfig.java | 39 ++++++ .../bds04/controllers/CityController.java | 55 +++++++++ .../bds04/controllers/EventController.java | 40 ++++++ .../bds04/controllers/UserController.java | 32 +++++ .../controllers/exceptions/FieldMessage.java | 34 ++++++ .../exceptions/ResourceExceptionHandler.java | 61 ++++++++++ .../controllers/exceptions/StandardError.java | 56 +++++++++ .../exceptions/ValidationError.java | 17 +++ .../com/devsuperior/bds04/dto/CityDTO.java | 4 + .../com/devsuperior/bds04/dto/EventDTO.java | 8 ++ .../com/devsuperior/bds04/dto/RoleDTO.java | 40 ++++++ .../com/devsuperior/bds04/dto/UserDTO.java | 57 +++++++++ .../devsuperior/bds04/dto/UserInsertDTO.java | 20 +++ .../devsuperior/bds04/dto/UserUpdateDTO.java | 9 ++ .../com/devsuperior/bds04/entities/Role.java | 53 ++++++++ .../com/devsuperior/bds04/entities/User.java | 115 ++++++++++++++++++ .../bds04/repositories/CityRepository.java | 9 ++ .../bds04/repositories/EventRepository.java | 9 ++ .../bds04/repositories/RoleRepository.java | 9 ++ .../bds04/repositories/UserRepository.java | 11 ++ .../bds04/services/CityService.java | 56 +++++++++ .../bds04/services/EventService.java | 57 +++++++++ .../bds04/services/UserService.java | 66 ++++++++++ .../exceptions/DatabaseException.java | 8 ++ .../exceptions/ResourceNotFoundException.java | 6 + .../services/validation/UserInsertValid.java | 19 +++ .../validation/UserInsertValidator.java | 44 +++++++ .../services/validation/UserUpdateValid.java | 20 +++ .../validation/UserUpdateValidator.java | 53 ++++++++ .../resources/application-test.properties | 5 + src/main/resources/application.properties | 8 +- src/main/resources/data.sql | 11 ++ 36 files changed, 1224 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/devsuperior/bds04/components/JwtTokenEnhancer.java create mode 100644 src/main/java/com/devsuperior/bds04/config/AppConfig.java create mode 100644 src/main/java/com/devsuperior/bds04/config/AuthorizationServerConfig.java create mode 100644 src/main/java/com/devsuperior/bds04/config/ResourceServerConfig.java create mode 100644 src/main/java/com/devsuperior/bds04/config/WebSecurityConfig.java create mode 100644 src/main/java/com/devsuperior/bds04/controllers/CityController.java create mode 100644 src/main/java/com/devsuperior/bds04/controllers/EventController.java create mode 100644 src/main/java/com/devsuperior/bds04/controllers/UserController.java create mode 100644 src/main/java/com/devsuperior/bds04/controllers/exceptions/FieldMessage.java create mode 100644 src/main/java/com/devsuperior/bds04/controllers/exceptions/ResourceExceptionHandler.java create mode 100644 src/main/java/com/devsuperior/bds04/controllers/exceptions/StandardError.java create mode 100644 src/main/java/com/devsuperior/bds04/controllers/exceptions/ValidationError.java create mode 100644 src/main/java/com/devsuperior/bds04/dto/RoleDTO.java create mode 100644 src/main/java/com/devsuperior/bds04/dto/UserDTO.java create mode 100644 src/main/java/com/devsuperior/bds04/dto/UserInsertDTO.java create mode 100644 src/main/java/com/devsuperior/bds04/dto/UserUpdateDTO.java create mode 100644 src/main/java/com/devsuperior/bds04/entities/Role.java create mode 100644 src/main/java/com/devsuperior/bds04/entities/User.java create mode 100644 src/main/java/com/devsuperior/bds04/repositories/CityRepository.java create mode 100644 src/main/java/com/devsuperior/bds04/repositories/EventRepository.java create mode 100644 src/main/java/com/devsuperior/bds04/repositories/RoleRepository.java create mode 100644 src/main/java/com/devsuperior/bds04/repositories/UserRepository.java create mode 100644 src/main/java/com/devsuperior/bds04/services/CityService.java create mode 100644 src/main/java/com/devsuperior/bds04/services/EventService.java create mode 100644 src/main/java/com/devsuperior/bds04/services/UserService.java create mode 100644 src/main/java/com/devsuperior/bds04/services/exceptions/DatabaseException.java create mode 100644 src/main/java/com/devsuperior/bds04/services/exceptions/ResourceNotFoundException.java create mode 100644 src/main/java/com/devsuperior/bds04/services/validation/UserInsertValid.java create mode 100644 src/main/java/com/devsuperior/bds04/services/validation/UserInsertValidator.java create mode 100644 src/main/java/com/devsuperior/bds04/services/validation/UserUpdateValid.java create mode 100644 src/main/java/com/devsuperior/bds04/services/validation/UserUpdateValidator.java diff --git a/src/main/java/com/devsuperior/bds04/components/JwtTokenEnhancer.java b/src/main/java/com/devsuperior/bds04/components/JwtTokenEnhancer.java new file mode 100644 index 00000000..f24e3644 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/components/JwtTokenEnhancer.java @@ -0,0 +1,31 @@ +package com.devsuperior.bds04.components; + +import com.devsuperior.bds04.entities.User; +import com.devsuperior.bds04.repositories.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +@Component +public class JwtTokenEnhancer implements TokenEnhancer { + + @Autowired + private UserRepository userRepository; + @Override + public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) { + User user = userRepository.findByEmail(oAuth2Authentication.getName()); + Map map = new HashMap<>(); + map.put("userName", user.getUsername()); + map.put("userId", user.getId()); + + DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) oAuth2AccessToken; + token.setAdditionalInformation(map); + return oAuth2AccessToken; + } +} diff --git a/src/main/java/com/devsuperior/bds04/config/AppConfig.java b/src/main/java/com/devsuperior/bds04/config/AppConfig.java new file mode 100644 index 00000000..14217f34 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/config/AppConfig.java @@ -0,0 +1,38 @@ +package com.devsuperior.bds04.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; + +//Classes de configuração +@Configuration +public class AppConfig { + + //irá ler o valor da variavel de ambiente + @Value("${jwt.secret}") + private String jwtSecret; + + @Bean + public BCryptPasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + + //metodos para acessar e ler o token JWT + @Bean + public JwtAccessTokenConverter accessTokenConverter() { + JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter(); + //ASSINATURA DO TOKEN JWT + tokenConverter.setSigningKey(jwtSecret); + return tokenConverter; + } + + @Bean + public JwtTokenStore tokenStore() { + return new JwtTokenStore(accessTokenConverter()); + } + +} diff --git a/src/main/java/com/devsuperior/bds04/config/AuthorizationServerConfig.java b/src/main/java/com/devsuperior/bds04/config/AuthorizationServerConfig.java new file mode 100644 index 00000000..e99eff78 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/config/AuthorizationServerConfig.java @@ -0,0 +1,65 @@ +package com.devsuperior.bds04.config; + +import com.devsuperior.bds04.components.JwtTokenEnhancer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.token.TokenEnhancerChain; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; + +import java.util.Arrays; + +@Configuration +@EnableAuthorizationServer +public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { + + @Value("${security.oauth2.client.client-id}") + private String clientId; + + @Value("${security.oauth2.client.client-secret}") + private String clientSecret; + + @Value("${jwt.duration}") + private Integer jwtDuration; + + @Autowired + private BCryptPasswordEncoder passwordEncoder; + + @Autowired + private JwtAccessTokenConverter accessTokenConverter; + + @Autowired + private JwtTokenStore tokenStore; + + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { + security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()"); + } + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + clients.inMemory().withClient(clientId) + .secret(passwordEncoder.encode(clientSecret)) + .scopes("read", "write") + .authorizedGrantTypes("password") + .accessTokenValiditySeconds(jwtDuration); + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints.authenticationManager(authenticationManager) + .tokenStore(tokenStore) + .accessTokenConverter(accessTokenConverter); + } +} diff --git a/src/main/java/com/devsuperior/bds04/config/ResourceServerConfig.java b/src/main/java/com/devsuperior/bds04/config/ResourceServerConfig.java new file mode 100644 index 00000000..b9c1e04f --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/config/ResourceServerConfig.java @@ -0,0 +1,60 @@ +package com.devsuperior.bds04.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; + +import java.util.Arrays; + +@Configuration +@EnableResourceServer +public class ResourceServerConfig extends ResourceServerConfigurerAdapter { + + @Autowired + private Environment environment; + + @Autowired + private JwtTokenStore tokenStore; + + private static final String[] PUBLIC = { "/oauth/token", "/h2-console/**"}; + private static final String[] PUBLIC_GET = {"/events/**", "/cities/**" }; + private static final String[] EVENTS_POST = { "/events" }; + private static final String[] CITIES_POST = { "/cities" }; + + private static final String[] ADMIN = { "/events", "/cities" }; + public ResourceServerConfig() { + super(); + } + + @Override + public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + resources.tokenStore(tokenStore); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + //liberando o h2 + if(Arrays.asList(environment.getActiveProfiles()).contains("test")) { + http.headers().frameOptions().disable(); + } + + http.authorizeRequests() + .antMatchers(PUBLIC).permitAll() + .antMatchers(HttpMethod.GET, PUBLIC_GET).permitAll() + .antMatchers(HttpMethod.POST, EVENTS_POST).hasAnyRole("CLIENT", "ADMIN") + .antMatchers(HttpMethod.POST, CITIES_POST).hasRole("ADMIN") + .antMatchers(HttpMethod.DELETE, ADMIN).hasRole("ADMIN") + .antMatchers(HttpMethod.PATCH, ADMIN).hasRole("ADMIN") + .antMatchers(HttpMethod.PUT, ADMIN).hasRole("ADMIN") + .anyRequest().authenticated(); + } +} + +//ANA -> CLIENTE +//BOB -> ADMIN diff --git a/src/main/java/com/devsuperior/bds04/config/WebSecurityConfig.java b/src/main/java/com/devsuperior/bds04/config/WebSecurityConfig.java new file mode 100644 index 00000000..535830ac --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/config/WebSecurityConfig.java @@ -0,0 +1,39 @@ +package com.devsuperior.bds04.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +@Configuration +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private BCryptPasswordEncoder passwordEncoder; + + @Autowired + private UserDetailsService userDetailsService; + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder); + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/actuator/**"); + } + + @Override + @Bean + protected AuthenticationManager authenticationManager() throws Exception { + return super.authenticationManager(); + } +} diff --git a/src/main/java/com/devsuperior/bds04/controllers/CityController.java b/src/main/java/com/devsuperior/bds04/controllers/CityController.java new file mode 100644 index 00000000..f4c4017f --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/controllers/CityController.java @@ -0,0 +1,55 @@ +package com.devsuperior.bds04.controllers; + +import com.devsuperior.bds04.dto.CityDTO; +import com.devsuperior.bds04.services.CityService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import javax.validation.Valid; +import java.net.URI; +import java.util.List; +import java.util.Optional; + +@RestController +@RequestMapping(value = "cities") +public class CityController { + + /** + * @Todo + * CRUD para eventos e cidades + * Endpoint de login + * Configuração OAUTH + * Configuração spring security JWT + */ + + @Autowired + private CityService service; + + @GetMapping + public ResponseEntity> findAll() { + + List list = service.findAllSortedByName(); + + return ResponseEntity.ok().body(list); + } + + @GetMapping(value = "/{id}") + public ResponseEntity findById(@PathVariable Long id) { + CityDTO city = service.findById(id); + return ResponseEntity.ok().body(city); + } + + @PostMapping + public ResponseEntity create(@RequestBody @Valid CityDTO dto) { + dto = service.create(dto); + URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(dto.getId()).toUri(); + return ResponseEntity.created(uri).body(dto); + } + +} diff --git a/src/main/java/com/devsuperior/bds04/controllers/EventController.java b/src/main/java/com/devsuperior/bds04/controllers/EventController.java new file mode 100644 index 00000000..3e77d14e --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/controllers/EventController.java @@ -0,0 +1,40 @@ +package com.devsuperior.bds04.controllers; + +import com.devsuperior.bds04.dto.EventDTO; +import com.devsuperior.bds04.services.EventService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import javax.validation.Valid; +import java.net.URI; + +@RestController +@RequestMapping(value = "events") +public class EventController { + + @Autowired + private EventService service; + + @GetMapping + public ResponseEntity> findAll(Pageable pageable) { + Page list = service.findAllPaged(pageable); + return ResponseEntity.ok().body(list); + } + + @GetMapping(value = "/{id}") + public ResponseEntity findById(@PathVariable Long id) { + EventDTO city = service.findById(id); + return ResponseEntity.ok().body(city); + } + + @PostMapping + public ResponseEntity create(@RequestBody @Valid EventDTO dto) { + dto = service.create(dto); + URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(dto.getId()).toUri(); + return ResponseEntity.created(uri).body(dto); + } +} diff --git a/src/main/java/com/devsuperior/bds04/controllers/UserController.java b/src/main/java/com/devsuperior/bds04/controllers/UserController.java new file mode 100644 index 00000000..d94176dd --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/controllers/UserController.java @@ -0,0 +1,32 @@ +package com.devsuperior.bds04.controllers; + +import com.devsuperior.bds04.dto.UserDTO; +import com.devsuperior.bds04.dto.UserInsertDTO; +import com.devsuperior.bds04.services.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import javax.validation.Valid; +import java.net.URI; + +@RestController +@RequestMapping(value = "users") +public class UserController { + + @Autowired + private UserService service; + + + @PostMapping + public ResponseEntity createUser(@RequestBody @Valid UserInsertDTO dto) { + UserDTO newDto = service.insert(dto); + URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(newDto.getId()).toUri(); + return ResponseEntity.created(uri).body(newDto); + } + +} diff --git a/src/main/java/com/devsuperior/bds04/controllers/exceptions/FieldMessage.java b/src/main/java/com/devsuperior/bds04/controllers/exceptions/FieldMessage.java new file mode 100644 index 00000000..6e966e13 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/controllers/exceptions/FieldMessage.java @@ -0,0 +1,34 @@ +package com.devsuperior.bds04.controllers.exceptions; + +import java.io.Serializable; + +public class FieldMessage implements Serializable { + + private String fieldName; + private String message; + + public FieldMessage() { + + } + + public FieldMessage(String fieldName, String message) { + this.fieldName = fieldName; + this.message = message; + } + + public String getFieldName() { + return fieldName; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/com/devsuperior/bds04/controllers/exceptions/ResourceExceptionHandler.java b/src/main/java/com/devsuperior/bds04/controllers/exceptions/ResourceExceptionHandler.java new file mode 100644 index 00000000..61459492 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/controllers/exceptions/ResourceExceptionHandler.java @@ -0,0 +1,61 @@ +package com.devsuperior.bds04.controllers.exceptions; + +import com.devsuperior.bds04.services.exceptions.DatabaseException; +import com.devsuperior.bds04.services.exceptions.ResourceNotFoundException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import javax.servlet.http.HttpServletRequest; +import java.time.Instant; + +@ControllerAdvice +public class ResourceExceptionHandler { + @ExceptionHandler(ResourceNotFoundException.class) + public ResponseEntity entityNotFound(ResourceNotFoundException e, HttpServletRequest request) { + HttpStatus status = HttpStatus.NOT_FOUND; + StandardError err = new StandardError(); + err.setTimestamp(Instant.now()); + err.setStatus(status.value()); + err.setError("Resource not found"); + err.setMessage(e.getMessage()); + err.setPath(request.getRequestURI()); + + return ResponseEntity.status(status).body(err); + } + + @ExceptionHandler(DatabaseException.class) + public ResponseEntity database(DatabaseException e, HttpServletRequest request) { + HttpStatus status = HttpStatus.BAD_REQUEST; + StandardError err = new StandardError(); + err.setTimestamp(Instant.now()); + err.setStatus(status.value()); + err.setError("Database exception"); + err.setMessage(e.getMessage()); + err.setPath(request.getRequestURI()); + + return ResponseEntity.status(status).body(err); + } + + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity validation(MethodArgumentNotValidException e, HttpServletRequest request) { + HttpStatus status = HttpStatus.UNPROCESSABLE_ENTITY; + ValidationError err = new ValidationError(); + err.setTimestamp(Instant.now()); + err.setStatus(status.value()); + err.setError("Validation exception"); + err.setMessage(e.getMessage()); + err.setPath(request.getRequestURI()); + + for (FieldError f: e.getBindingResult().getFieldErrors()) { + err.addError(f.getField(), f.getDefaultMessage()); + } + + return ResponseEntity.status(status).body(err); + } + +} diff --git a/src/main/java/com/devsuperior/bds04/controllers/exceptions/StandardError.java b/src/main/java/com/devsuperior/bds04/controllers/exceptions/StandardError.java new file mode 100644 index 00000000..b79cfbfe --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/controllers/exceptions/StandardError.java @@ -0,0 +1,56 @@ +package com.devsuperior.bds04.controllers.exceptions; + +import java.io.Serializable; +import java.time.Instant; + +public class StandardError implements Serializable { + private Instant timestamp; + private Integer status; + private String error; + private String message; + private String path; + + public StandardError() { + + } + + public Instant getTimestamp() { + return timestamp; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public void setTimestamp(Instant timestamp) { + this.timestamp = timestamp; + } +} diff --git a/src/main/java/com/devsuperior/bds04/controllers/exceptions/ValidationError.java b/src/main/java/com/devsuperior/bds04/controllers/exceptions/ValidationError.java new file mode 100644 index 00000000..436dd5af --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/controllers/exceptions/ValidationError.java @@ -0,0 +1,17 @@ +package com.devsuperior.bds04.controllers.exceptions; + +import java.util.ArrayList; +import java.util.List; + +public class ValidationError extends StandardError{ + + private List errors = new ArrayList<>(); + + public List getErrors() { + return errors; + } + + public void addError(String fieldName, String message) { + errors.add(new FieldMessage(fieldName, message)); + } +} diff --git a/src/main/java/com/devsuperior/bds04/dto/CityDTO.java b/src/main/java/com/devsuperior/bds04/dto/CityDTO.java index d7cf8420..cceb63ce 100644 --- a/src/main/java/com/devsuperior/bds04/dto/CityDTO.java +++ b/src/main/java/com/devsuperior/bds04/dto/CityDTO.java @@ -4,10 +4,14 @@ import com.devsuperior.bds04.entities.City; +import javax.validation.constraints.NotBlank; + public class CityDTO implements Serializable { private static final long serialVersionUID = 1L; private Long id; + + @NotBlank(message = "Campo requerido") private String name; public CityDTO() { diff --git a/src/main/java/com/devsuperior/bds04/dto/EventDTO.java b/src/main/java/com/devsuperior/bds04/dto/EventDTO.java index 0a3024d3..62735cf2 100644 --- a/src/main/java/com/devsuperior/bds04/dto/EventDTO.java +++ b/src/main/java/com/devsuperior/bds04/dto/EventDTO.java @@ -5,13 +5,21 @@ import com.devsuperior.bds04.entities.Event; +import javax.validation.constraints.*; + public class EventDTO implements Serializable { private static final long serialVersionUID = 1L; private Long id; + + @NotBlank(message = "Campo requerido") private String name; + + @Future(message = "A data do evento não pode ser passada") private LocalDate date; private String url; + + @NotNull(message = "Campo requerido") private Long cityId; public EventDTO() { diff --git a/src/main/java/com/devsuperior/bds04/dto/RoleDTO.java b/src/main/java/com/devsuperior/bds04/dto/RoleDTO.java new file mode 100644 index 00000000..98a40b9c --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/dto/RoleDTO.java @@ -0,0 +1,40 @@ +package com.devsuperior.bds04.dto; + +import com.devsuperior.bds04.entities.Role; + +import java.io.Serializable; + +public class RoleDTO implements Serializable { + private Long id; + private String authority; + + public RoleDTO() { + + } + + public RoleDTO(Long id, String authority) { + this.id = id; + this.authority = authority; + } + + public RoleDTO(Role role) { + this.id = role.getId(); + this.authority = role.getAuthority(); + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getAuthority() { + return authority; + } + + public void setAuthority(String authority) { + this.authority = authority; + } +} diff --git a/src/main/java/com/devsuperior/bds04/dto/UserDTO.java b/src/main/java/com/devsuperior/bds04/dto/UserDTO.java new file mode 100644 index 00000000..ead80b8f --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/dto/UserDTO.java @@ -0,0 +1,57 @@ +package com.devsuperior.bds04.dto; + +import com.devsuperior.bds04.entities.User; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +public class UserDTO implements Serializable { + + private Long id; + @Email(message = "Informe um e-mail válido") + private String email; + + Set roles = new HashSet<>(); + + public UserDTO() { + + } + + public UserDTO(Long id, String firstName, String lastName, String email) { + this.id = id; + this.email = email; + } + + public UserDTO(User entity) { + this.id = entity.getId(); + this.email = entity.getEmail(); + entity.getRoles().forEach(role -> this.roles.add(new RoleDTO(role))); + } + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Set getRoles() { + return roles; + } + + public void setRoles(Set roles) { + this.roles = roles; + } + +} diff --git a/src/main/java/com/devsuperior/bds04/dto/UserInsertDTO.java b/src/main/java/com/devsuperior/bds04/dto/UserInsertDTO.java new file mode 100644 index 00000000..ac5fba38 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/dto/UserInsertDTO.java @@ -0,0 +1,20 @@ +package com.devsuperior.bds04.dto; + +import com.devsuperior.bds04.services.validation.UserInsertValid; + +@UserInsertValid +public class UserInsertDTO extends UserDTO { + + private String password; + + public UserInsertDTO() { + super(); + } + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/main/java/com/devsuperior/bds04/dto/UserUpdateDTO.java b/src/main/java/com/devsuperior/bds04/dto/UserUpdateDTO.java new file mode 100644 index 00000000..7eaae056 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/dto/UserUpdateDTO.java @@ -0,0 +1,9 @@ +package com.devsuperior.bds04.dto; + + +import com.devsuperior.bds04.services.validation.UserUpdateValid; + +@UserUpdateValid +public class UserUpdateDTO extends UserDTO { + +} diff --git a/src/main/java/com/devsuperior/bds04/entities/Role.java b/src/main/java/com/devsuperior/bds04/entities/Role.java new file mode 100644 index 00000000..82069aa5 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/entities/Role.java @@ -0,0 +1,53 @@ +package com.devsuperior.bds04.entities; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Objects; + +@Entity +@Table(name = "tb_role") +public class Role implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String authority; + + public Role() { + + } + + public Role(Long id, String authority) { + this.id = id; + this.authority = authority; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getAuthority() { + return authority; + } + + public void setAuthority(String authority) { + this.authority = authority; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Role)) return false; + Role role = (Role) o; + return Objects.equals(getId(), role.getId()) && Objects.equals(getAuthority(), role.getAuthority()); + } + + @Override + public int hashCode() { + return Objects.hash(getId()); + } +} diff --git a/src/main/java/com/devsuperior/bds04/entities/User.java b/src/main/java/com/devsuperior/bds04/entities/User.java new file mode 100644 index 00000000..5989d0a5 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/entities/User.java @@ -0,0 +1,115 @@ +package com.devsuperior.bds04.entities; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Collection; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +@Entity +@Table(name = "tb_user") +public class User implements UserDetails, Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(unique = true) + private String email; + + private String password; + + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable(name = "tb_user_role", + joinColumns = @JoinColumn(name = "user_id"), + inverseJoinColumns = @JoinColumn(name = "role_id")) + private Set roles = new HashSet<>(); + + public User() { + + } + public User(Long id, String email, String password, Set roles) { + this.id = id; + this.email = email; + this.password = password; + this.roles = roles; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + @Override + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public Set getRoles() { + return roles; + } + + @Override + public Collection getAuthorities() { + return roles.stream().map(role -> new SimpleGrantedAuthority(role.getAuthority())) + .collect(Collectors.toList()); + } + @Override + public String getUsername() { + return null; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof User)) return false; + User user = (User) o; + return Objects.equals(getId(), user.getId()) && Objects.equals(getEmail(), user.getEmail()) && Objects.equals(getPassword(), user.getPassword()) && Objects.equals(getRoles(), user.getRoles()); + } + + @Override + public int hashCode() { + return Objects.hash(getId(), getEmail(), getPassword(), getRoles()); + } +} diff --git a/src/main/java/com/devsuperior/bds04/repositories/CityRepository.java b/src/main/java/com/devsuperior/bds04/repositories/CityRepository.java new file mode 100644 index 00000000..8a0d8fbd --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/repositories/CityRepository.java @@ -0,0 +1,9 @@ +package com.devsuperior.bds04.repositories; + +import com.devsuperior.bds04.entities.City; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CityRepository extends JpaRepository { +} diff --git a/src/main/java/com/devsuperior/bds04/repositories/EventRepository.java b/src/main/java/com/devsuperior/bds04/repositories/EventRepository.java new file mode 100644 index 00000000..c8da6887 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/repositories/EventRepository.java @@ -0,0 +1,9 @@ +package com.devsuperior.bds04.repositories; + +import com.devsuperior.bds04.entities.Event; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface EventRepository extends JpaRepository { +} diff --git a/src/main/java/com/devsuperior/bds04/repositories/RoleRepository.java b/src/main/java/com/devsuperior/bds04/repositories/RoleRepository.java new file mode 100644 index 00000000..2e3924ae --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/repositories/RoleRepository.java @@ -0,0 +1,9 @@ +package com.devsuperior.bds04.repositories; + +import com.devsuperior.bds04.entities.Role; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface RoleRepository extends JpaRepository { +} diff --git a/src/main/java/com/devsuperior/bds04/repositories/UserRepository.java b/src/main/java/com/devsuperior/bds04/repositories/UserRepository.java new file mode 100644 index 00000000..2f9bdb5d --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/repositories/UserRepository.java @@ -0,0 +1,11 @@ +package com.devsuperior.bds04.repositories; + +import com.devsuperior.bds04.entities.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends JpaRepository { + + User findByEmail(String email); +} diff --git a/src/main/java/com/devsuperior/bds04/services/CityService.java b/src/main/java/com/devsuperior/bds04/services/CityService.java new file mode 100644 index 00000000..f23c2d1e --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/services/CityService.java @@ -0,0 +1,56 @@ +package com.devsuperior.bds04.services; + + +import com.devsuperior.bds04.dto.CityDTO; +import com.devsuperior.bds04.entities.City; +import com.devsuperior.bds04.repositories.CityRepository; +import com.devsuperior.bds04.services.exceptions.ResourceNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +@Service +public class CityService { + + @Autowired + private CityRepository repository; + + @Transactional(readOnly = true) + public Page findAllPaged(Pageable pageable) { + Page list = repository.findAll(pageable); + return list.map(item -> new CityDTO(item)); + } + + @Transactional(readOnly = true) + public CityDTO findById(Long id) { + Optional cityOptional = repository.findById(id); + City entity = cityOptional.orElseThrow(() -> new ResourceNotFoundException("Cidade não encontrada")); + return new CityDTO(entity); + } + + @Transactional + public CityDTO create(CityDTO dto) { + City entity = new City(); + entity.setName(dto.getName()); + entity = repository.save(entity); + + return new CityDTO(entity); + } + + @Transactional(readOnly = true) + public List findAllSortedByName() { + List cities = repository.findAll(Sort.by("name")); + + List cityDTOs = cities.stream() + .map(item -> new CityDTO(item)).collect(Collectors.toList()); + + return cityDTOs; + } +} diff --git a/src/main/java/com/devsuperior/bds04/services/EventService.java b/src/main/java/com/devsuperior/bds04/services/EventService.java new file mode 100644 index 00000000..955c69ef --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/services/EventService.java @@ -0,0 +1,57 @@ +package com.devsuperior.bds04.services; + +import com.devsuperior.bds04.dto.CityDTO; +import com.devsuperior.bds04.dto.EventDTO; +import com.devsuperior.bds04.entities.City; +import com.devsuperior.bds04.entities.Event; +import com.devsuperior.bds04.repositories.CityRepository; +import com.devsuperior.bds04.repositories.EventRepository; +import com.devsuperior.bds04.services.exceptions.ResourceNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Service +public class EventService { + @Autowired + private EventRepository repository; + + @Autowired + private CityRepository cityRepository; + + @Transactional(readOnly = true) + public Page findAllPaged(Pageable pageable) { + Page list = repository.findAll(pageable); + return list.map(item -> new EventDTO(item)); + } + + @Transactional(readOnly = true) + public EventDTO findById(Long id) { + Optional cityOptional = repository.findById(id); + Event entity = cityOptional.orElseThrow(() -> new ResourceNotFoundException("Evento não encontrado")); + return new EventDTO(entity); + } + + @Transactional + public EventDTO create(EventDTO dto) { + if (dto.getCityId() == null) { + throw new IllegalArgumentException("O ID da cidade não pode ser nulo"); + } + + Event entity = new Event(); + entity.setName(dto.getName()); + entity.setDate(dto.getDate()); + entity.setUrl(dto.getUrl()); + + City city = cityRepository.findById(dto.getCityId()) + .orElseThrow(() -> new ResourceNotFoundException("Cidade não encontrada")); + entity.setCity(city); + entity = repository.save(entity); + + return new EventDTO(entity); + } +} diff --git a/src/main/java/com/devsuperior/bds04/services/UserService.java b/src/main/java/com/devsuperior/bds04/services/UserService.java new file mode 100644 index 00000000..ce08c3bb --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/services/UserService.java @@ -0,0 +1,66 @@ +package com.devsuperior.bds04.services; + +import com.devsuperior.bds04.dto.RoleDTO; +import com.devsuperior.bds04.dto.UserDTO; +import com.devsuperior.bds04.dto.UserInsertDTO; +import com.devsuperior.bds04.entities.Role; +import com.devsuperior.bds04.entities.User; +import com.devsuperior.bds04.repositories.RoleRepository; +import com.devsuperior.bds04.repositories.UserRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class UserService implements UserDetailsService { + private static Logger logger = LoggerFactory.getLogger(UserService.class); + + @Autowired + private BCryptPasswordEncoder passwordEncoder; + + @Autowired + private UserRepository repository; + + @Autowired + private RoleRepository roleRepository; + + + @Transactional + public UserDTO insert(UserInsertDTO dto) { + User entity = new User(); + copyDtoToEntity(dto, entity); + entity.setPassword(passwordEncoder.encode(dto.getPassword())); + entity = repository.save(entity); + return new UserDTO(entity); + } + + private void copyDtoToEntity(UserDTO dto, User entity) { + entity.setEmail(dto.getEmail()); + + entity.getRoles().clear(); + for (RoleDTO roleDTO: dto.getRoles()) { + Role role = roleRepository.getOne(roleDTO.getId()); + entity.getRoles().add(role); + } + } + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + try { + User user = repository.findByEmail(username); + logger.info("Usuário foi encontrado: " + username); + return user; + } + catch (UsernameNotFoundException error) { + logger.error("O usuario não foi encontrado pelo email" + username); + throw new UsernameNotFoundException("User not found " + username); + } + } +} diff --git a/src/main/java/com/devsuperior/bds04/services/exceptions/DatabaseException.java b/src/main/java/com/devsuperior/bds04/services/exceptions/DatabaseException.java new file mode 100644 index 00000000..144de4a9 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/services/exceptions/DatabaseException.java @@ -0,0 +1,8 @@ +package com.devsuperior.bds04.services.exceptions; + +public class DatabaseException extends RuntimeException{ + private static final long serialVersionUID = 1L; + public DatabaseException(String msg) { + super(msg); + } +} diff --git a/src/main/java/com/devsuperior/bds04/services/exceptions/ResourceNotFoundException.java b/src/main/java/com/devsuperior/bds04/services/exceptions/ResourceNotFoundException.java new file mode 100644 index 00000000..b8bd810b --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/services/exceptions/ResourceNotFoundException.java @@ -0,0 +1,6 @@ +package com.devsuperior.bds04.services.exceptions; + +public class ResourceNotFoundException extends RuntimeException { + + public ResourceNotFoundException(String msg) {super(msg);} +} diff --git a/src/main/java/com/devsuperior/bds04/services/validation/UserInsertValid.java b/src/main/java/com/devsuperior/bds04/services/validation/UserInsertValid.java new file mode 100644 index 00000000..af4c0b03 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/services/validation/UserInsertValid.java @@ -0,0 +1,19 @@ +package com.devsuperior.bds04.services.validation; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +@Constraint(validatedBy = UserInsertValidator.class) +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) + +public @interface UserInsertValid { + String message() default "Validation error"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} \ No newline at end of file diff --git a/src/main/java/com/devsuperior/bds04/services/validation/UserInsertValidator.java b/src/main/java/com/devsuperior/bds04/services/validation/UserInsertValidator.java new file mode 100644 index 00000000..b3bc309e --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/services/validation/UserInsertValidator.java @@ -0,0 +1,44 @@ +package com.devsuperior.bds04.services.validation; + +import com.devsuperior.bds04.dto.UserInsertDTO; +import com.devsuperior.bds04.controllers.exceptions.FieldMessage; +import com.devsuperior.bds04.entities.User; +import com.devsuperior.bds04.repositories.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.ArrayList; +import java.util.List; + +public class UserInsertValidator implements ConstraintValidator { + + + @Autowired + private UserRepository repository; + + @Override + public void initialize(UserInsertValid ann) { + } + + @Override + public boolean isValid(UserInsertDTO dto, ConstraintValidatorContext context) { + + List list = new ArrayList<>(); + + User user = repository.findByEmail(dto.getEmail()); + + // Coloque aqui seus testes de validação, acrescentando objetos FieldMessage à lista + + if(user != null) { + list.add(new FieldMessage("email", "Este email já existe.")); + } + + for (FieldMessage e : list) { + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(e.getMessage()).addPropertyNode(e.getFieldName()) + .addConstraintViolation(); + } + return list.isEmpty(); + } +} \ No newline at end of file diff --git a/src/main/java/com/devsuperior/bds04/services/validation/UserUpdateValid.java b/src/main/java/com/devsuperior/bds04/services/validation/UserUpdateValid.java new file mode 100644 index 00000000..e4330650 --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/services/validation/UserUpdateValid.java @@ -0,0 +1,20 @@ +package com.devsuperior.bds04.services.validation; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Constraint(validatedBy = UserUpdateValidator.class) +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) + +public @interface UserUpdateValid { + String message() default "Validation error"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} \ No newline at end of file diff --git a/src/main/java/com/devsuperior/bds04/services/validation/UserUpdateValidator.java b/src/main/java/com/devsuperior/bds04/services/validation/UserUpdateValidator.java new file mode 100644 index 00000000..6c31fc8d --- /dev/null +++ b/src/main/java/com/devsuperior/bds04/services/validation/UserUpdateValidator.java @@ -0,0 +1,53 @@ +package com.devsuperior.bds04.services.validation; + +import com.devsuperior.bds04.dto.UserUpdateDTO; +import com.devsuperior.bds04.controllers.exceptions.FieldMessage; +import com.devsuperior.bds04.entities.User; +import com.devsuperior.bds04.repositories.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.servlet.HandlerMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class UserUpdateValidator implements ConstraintValidator { + + @Autowired + private HttpServletRequest request; + + @Autowired + private UserRepository repository; + + @Override + public void initialize(UserUpdateValid ann) { + } + + @Override + public boolean isValid(UserUpdateDTO dto, ConstraintValidatorContext context) { + + var uriVars = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + + long userId = Long.parseLong(uriVars.get("id")); + + List list = new ArrayList<>(); + + User user = repository.findByEmail(dto.getEmail()); + + // Coloque aqui seus testes de validação, acrescentando objetos FieldMessage à lista + + if(user != null && userId != user.getId()) { + list.add(new FieldMessage("email", "Este email já existe.")); + } + + for (FieldMessage e : list) { + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(e.getMessage()).addPropertyNode(e.getFieldName()) + .addConstraintViolation(); + } + return list.isEmpty(); + } +} \ No newline at end of file diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index c81c681e..f8728764 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -4,3 +4,8 @@ spring.datasource.password= spring.h2.console.enabled=true spring.h2.console.path=/h2-console + +# JPA, SQL +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +spring.jpa.defer-datasource-initialization=true +spring.jpa.show-sql=true diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a7dcd8af..d0b7f6c8 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1,9 @@ -spring.profiles.active=test +spring.profiles.active=${APP_PROFILE:test} spring.jpa.open-in-view=false + +security.oauth2.client.client-id=${CLIENT_ID:dscatalog} +security.oauth2.client.client-secret=${CLIENT_SECRET:dscatalog123} + +jwt.secret=${JWT_SECRET:MY-JWT-SECRET} +jwt.duration=${JWT_DURATION:86400} \ No newline at end of file diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 0b897e20..9dad5e19 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -1,3 +1,13 @@ +INSERT INTO tb_user (email, password) VALUES ('ana@gmail.com', '$2a$10$eACCYoNOHEqXve8aIWT8Nu3PkMXWBaOxJ9aORUYzfMQCbVBIhZ8tG'); +INSERT INTO tb_user (email, password) VALUES ('bob@gmail.com', '$2a$10$eACCYoNOHEqXve8aIWT8Nu3PkMXWBaOxJ9aORUYzfMQCbVBIhZ8tG'); + +INSERT INTO tb_role (authority) VALUES ('ROLE_CLIENT'); +INSERT INTO tb_role (authority) VALUES ('ROLE_ADMIN'); + +INSERT INTO tb_user_role (user_id, role_id) VALUES (1, 1); +INSERT INTO tb_user_role (user_id, role_id) VALUES (2, 2); + + INSERT INTO tb_city(name) VALUES ('São Paulo'); INSERT INTO tb_city(name) VALUES ('Brasília'); INSERT INTO tb_city(name) VALUES ('Fortaleza'); @@ -14,3 +24,4 @@ INSERT INTO tb_event(name, date, url, city_id) VALUES ('Feira do Software', '202 INSERT INTO tb_event(name, date, url, city_id) VALUES ('CCXP', '2021-04-13', 'https://ccxp.com.br', 1); INSERT INTO tb_event(name, date, url, city_id) VALUES ('Congresso Linux', '2021-05-23', 'https://congressolinux.com.br', 2); INSERT INTO tb_event(name, date, url, city_id) VALUES ('Semana Spring React', '2021-05-03', 'https://devsuperior.com.br', 3); +