diff --git a/README.md b/README.md
index c8b9ded..31d2f06 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,10 @@ Configurar JWT: [application.properties](https://github.com/Marc0Franc0/School-M
(Se utiliza para firmar los tokens)
- jwt.time.expiration = 86400000 (equivalente a un día)
+Configurar usuario admin:
+- user.admin.username = nombre_de_usuario_admin
+- user.admin.password = contraseña_de_usuario_admin
+
Ejecutar localmente
```shell
diff --git a/pom.xml b/pom.xml
index 4ecf269..b468a0f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
com.app
User-Api-Jwt
- 1.1.1
+ 1.2.0
User-Api-Jwt
Proyecto de muestra sobre cómo implementar la seguridad con
JWT basada en Spring boot 3 y Spring security 6
@@ -47,7 +47,6 @@
org.springframework.boot
spring-boot-starter-web
-
com.mysql
mysql-connector-j
@@ -68,6 +67,11 @@
spring-security-test
test
+
+ jakarta.validation
+ jakarta.validation-api
+ 3.0.2
+
diff --git a/src/main/java/com/app/UserApiJwtApplication.java b/src/main/java/com/app/UserApiJwtApplication.java
index f038aa7..e58dd8c 100644
--- a/src/main/java/com/app/UserApiJwtApplication.java
+++ b/src/main/java/com/app/UserApiJwtApplication.java
@@ -1,6 +1,7 @@
package com.app;
import com.app.model.ERole;
+import com.app.dto.PersonalData;
import com.app.model.RoleEntity;
import com.app.model.UserEntity;
import com.app.repository.UserRepository;
@@ -40,6 +41,8 @@ CommandLineRunner init() {
.roles(Set.of(RoleEntity.builder()
.name(ERole.valueOf(ERole.ADMIN.name()))
.build()))
+ .personalData(new PersonalData
+ ("","",0,""))
.build();
userRepository.save(userEntity);
diff --git a/src/main/java/com/app/controller/AdminController.java b/src/main/java/com/app/controller/AdminController.java
index 6234c0e..2bbbf2f 100644
--- a/src/main/java/com/app/controller/AdminController.java
+++ b/src/main/java/com/app/controller/AdminController.java
@@ -2,6 +2,7 @@
import com.app.dto.RegisterDTO;
import com.app.service.UserEntityService;
+import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@@ -17,7 +18,7 @@ public class AdminController {
//Endpoint para poder registrarse y tener acceso como admin
@PostMapping("/auth/register")
- public ResponseEntity> register(@RequestBody RegisterDTO registerDTO) {
+ public ResponseEntity> register(@Valid @RequestBody RegisterDTO registerDTO) {
RegisterDTO user = registerDTO;
user.getRoles().clear();
user.setRoles(Set.of("ADMIN","USER"));
diff --git a/src/main/java/com/app/controller/Controller.java b/src/main/java/com/app/controller/Controller.java
index 8cda2cc..2753e59 100644
--- a/src/main/java/com/app/controller/Controller.java
+++ b/src/main/java/com/app/controller/Controller.java
@@ -2,6 +2,7 @@
import com.app.dto.RegisterDTO;
import com.app.service.UserEntityService;
+import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@@ -16,7 +17,7 @@ public class Controller {
UserEntityService userEntityService;
//Endpoint para poder registrarse y tener acceso
@PostMapping("/auth/register")
- public ResponseEntity> register(@RequestBody RegisterDTO registerDTO){
+ public ResponseEntity> register(@Valid @RequestBody RegisterDTO registerDTO){
RegisterDTO user = registerDTO;
user.getRoles().clear();
user.setRoles(Set.of("USER"));
diff --git a/src/main/java/com/app/dto/PersonalData.java b/src/main/java/com/app/dto/PersonalData.java
new file mode 100644
index 0000000..cf37847
--- /dev/null
+++ b/src/main/java/com/app/dto/PersonalData.java
@@ -0,0 +1,11 @@
+package com.app.dto;
+
+import jakarta.persistence.Embeddable;
+
+@Embeddable
+public record PersonalData(String firstName,
+ String lastName,
+ int age,
+ String email) {
+
+}
diff --git a/src/main/java/com/app/dto/RegisterDTO.java b/src/main/java/com/app/dto/RegisterDTO.java
index 2f93ccb..9e21ff8 100644
--- a/src/main/java/com/app/dto/RegisterDTO.java
+++ b/src/main/java/com/app/dto/RegisterDTO.java
@@ -1,5 +1,8 @@
package com.app.dto;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@@ -10,7 +13,19 @@
@Getter
@Setter
public class RegisterDTO {
+ @NotBlank(message = "username no debe estar vacío")
private String username;
+ @NotBlank(message = "password no debe estar vacío")
private String password;
private Setroles;
+ @NotBlank(message = "firstName no debe estar vacío")
+ private String firstName;
+ @NotBlank(message = "lastName no debe estar vacío")
+ private String lastName;
+ @NotNull(message = "age no debe estar vacío")
+ private Integer age;
+ @NotBlank(message = "email no debe estar vacío")
+ @Email(message = "email debe tener un formato correcto")
+ private String email;
+
}
diff --git a/src/main/java/com/app/exception/SQLException.java b/src/main/java/com/app/exception/SQLException.java
new file mode 100644
index 0000000..713e45e
--- /dev/null
+++ b/src/main/java/com/app/exception/SQLException.java
@@ -0,0 +1,23 @@
+package com.app.exception;
+
+import com.zaxxer.hikari.pool.HikariPool;
+import org.hibernate.HibernateException;
+import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.InternalAuthenticationServiceException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import java.net.ConnectException;
+import java.sql.SQLIntegrityConstraintViolationException;
+@RestControllerAdvice
+public class SQLException {
+ //Validaciones al registrarse (username duplicado en la base de datos)
+ @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
+ public ResponseEntity captureSQLIntegrityConstraintViolationException
+ (SQLIntegrityConstraintViolationException e){
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Message: ".concat(e.getMessage()));
+ }
+
+}
diff --git a/src/main/java/com/app/exception/ValidationException.java b/src/main/java/com/app/exception/ValidationException.java
new file mode 100644
index 0000000..79455b4
--- /dev/null
+++ b/src/main/java/com/app/exception/ValidationException.java
@@ -0,0 +1,36 @@
+package com.app.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.validation.FieldError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import java.util.List;
+import java.util.stream.Collectors;
+
+//Clase para la captura de excepciones que puedan ocurrir
+@RestControllerAdvice
+public class ValidationException {
+ //Validaciones al registrarse-> entrada de datos vacios o nulos
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public ResponseEntity captureMethodArgumentNotValidException
+ (MethodArgumentNotValidException e){
+ List errors = e
+ .getBindingResult()
+ .getFieldErrors()
+ .stream().map(FieldError::getDefaultMessage)
+ .collect(Collectors.toList());
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Message: ".concat(errors.toString()));
+ }
+
+ //Formato JSON recibido
+ @ExceptionHandler( HttpMessageNotReadableException.class)
+ public ResponseEntity captureHttpMessageNotReadableException
+ (HttpMessageNotReadableException e){
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST)
+ .body("Message: ".concat(e.getMessage()));
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/app/model/Person.java b/src/main/java/com/app/model/Person.java
deleted file mode 100644
index 9e13c38..0000000
--- a/src/main/java/com/app/model/Person.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.app.model;
-
-import lombok.Data;
-
-@Data
-public abstract class Person {
- private String firstName;
- private String lastName;
- private int age;
- private String email;
-}
diff --git a/src/main/java/com/app/model/UserEntity.java b/src/main/java/com/app/model/UserEntity.java
index f1a70f0..711ed87 100644
--- a/src/main/java/com/app/model/UserEntity.java
+++ b/src/main/java/com/app/model/UserEntity.java
@@ -1,6 +1,6 @@
package com.app.model;
-import jakarta.annotation.Nullable;
+import com.app.dto.PersonalData;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -8,7 +8,6 @@
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
-import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Set;
@@ -23,8 +22,11 @@ public class UserEntity implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
+ @Column(unique = true)
private String username;
private String password;
+ @Embedded
+ private PersonalData personalData;
@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
@JoinTable(name = "users_roles",
joinColumns = @JoinColumn(name = "user_id"),
diff --git a/src/main/java/com/app/service/UserEntityServiceImpl.java b/src/main/java/com/app/service/UserEntityServiceImpl.java
index 1536c6c..c2d3a99 100644
--- a/src/main/java/com/app/service/UserEntityServiceImpl.java
+++ b/src/main/java/com/app/service/UserEntityServiceImpl.java
@@ -1,10 +1,12 @@
package com.app.service;
+import com.app.dto.PersonalData;
import com.app.dto.RegisterDTO;
import com.app.model.ERole;
import com.app.model.RoleEntity;
import com.app.model.UserEntity;
import com.app.repository.UserRepository;
+import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -36,6 +38,12 @@ public UserEntity registerUser(RegisterDTO registerDTO){
.password(passwordEncoder.encode(registerDTO.getPassword()))
//roles del usuario
.roles(roles)
+ .personalData( new PersonalData(
+ registerDTO.getFirstName(),
+ registerDTO.getLastName(),
+ registerDTO.getAge(),
+ registerDTO.getEmail()
+ ))
.build();
return userRepository.save(userEntity);