Spaces:
Configuration error
Configuration error
Fix folder structure of frontend
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- pom.xml +7 -2
- src/main/java/com/attendenceSystem/constant/Routes.java +13 -0
- src/main/java/com/attendenceSystem/exception/GlobalExceptionHandler.java +41 -0
- src/main/java/com/attendenceSystem/exception/custom/BadRequestException.java +7 -0
- src/main/java/com/attendenceSystem/exception/custom/ResourceNotFoundException.java +7 -0
- src/main/java/com/attendenceSystem/module/log/dto/request/AuditLogRequest.java +14 -0
- src/main/java/com/attendenceSystem/module/log/dto/response/AuditLogResponse.java +18 -0
- src/main/java/com/attendenceSystem/module/log/entity/AuditLog.java +58 -0
- src/main/java/com/attendenceSystem/module/log/entity/converter/LogActionConverter.java +21 -0
- src/main/java/com/attendenceSystem/module/log/entity/converter/LogEntityTypeConverter.java +21 -0
- src/main/java/com/attendenceSystem/module/log/entity/enums/LogAction.java +31 -0
- src/main/java/com/attendenceSystem/module/log/entity/enums/LogEntityType.java +20 -0
- src/main/java/com/attendenceSystem/module/log/mapper/request/AuditLogRequestMapping.java +5 -0
- src/main/java/com/attendenceSystem/module/log/mapper/response/AuditLogResponseMapper.java +20 -0
- src/main/java/com/attendenceSystem/module/log/repository/AuditLogRepository.java +13 -0
- src/main/java/com/attendenceSystem/module/log/service/AuditLogService.java +13 -0
- src/main/java/com/attendenceSystem/module/log/service/impl/AuditLogServiceImpl.java +40 -0
- src/main/java/com/attendenceSystem/module/user/controller/AuthController.java +25 -0
- src/main/java/com/attendenceSystem/module/user/dto/request/LoginRequest.java +13 -0
- src/main/java/com/attendenceSystem/module/user/dto/request/RegisterRequest.java +37 -0
- src/main/java/com/attendenceSystem/module/user/dto/response/UserResponse.java +14 -0
- src/main/java/com/attendenceSystem/{user → module/user}/entity/User.java +24 -14
- src/main/java/com/attendenceSystem/module/user/entity/converter/RoleConverter.java +20 -0
- src/main/java/com/attendenceSystem/{user → module/user}/entity/enums/Role.java +1 -1
- src/main/java/com/attendenceSystem/module/user/mapper/request/RegisterRequestMapper.java +19 -0
- src/main/java/com/attendenceSystem/{user → module/user}/mapper/response/UserResponseMapper.java +7 -17
- src/main/java/com/attendenceSystem/module/user/repository/UserRepository.java +24 -0
- src/main/java/com/attendenceSystem/module/user/service/AuthService.java +12 -0
- src/main/java/com/attendenceSystem/module/user/service/UserService.java +12 -0
- src/main/java/com/attendenceSystem/module/user/service/impl/AuthServiceImpl.java +72 -0
- src/main/java/com/attendenceSystem/module/user/service/impl/UserServiceImpl.java +43 -0
- src/main/java/com/attendenceSystem/security/ActiveUserFilter.java +67 -0
- src/main/java/com/attendenceSystem/security/ForceChangePasswordInterceptor.java +41 -0
- src/main/java/com/attendenceSystem/security/SecurityConfig.java +60 -0
- src/main/java/com/attendenceSystem/user/dto/request/LoginRequest.java +0 -20
- src/main/java/com/attendenceSystem/user/dto/request/RegisterRequest.java +0 -38
- src/main/java/com/attendenceSystem/user/dto/response/UserResponse.java +0 -17
- src/main/java/com/attendenceSystem/user/entity/converter/RoleConverter.java +0 -15
- src/main/java/com/attendenceSystem/user/mapper/request/LoginRequestMapper.java +0 -5
- src/main/java/com/attendenceSystem/user/mapper/request/RegisterRequestMapper.java +0 -5
- src/main/java/com/attendenceSystem/user/repository/UserRepository.java +0 -11
- src/main/java/com/attendenceSystem/user/service/UserService.java +0 -15
- src/main/java/com/attendenceSystem/user/service/impl/UserServiceImpl.java +0 -65
- src/main/java/com/attendenceSystem/validator/PasswordMatchValidator.java +5 -5
- src/main/resources/application.properties +19 -8
- src/main/resources/templates/cms/{auths → auth}/login.html +0 -0
- src/main/resources/templates/cms/{auths → auth}/register.html +0 -0
- src/main/resources/templates/cms/{auths → auth}/verify-otp.html +0 -0
- src/main/resources/templates/cms/{documents → document}/document-create.html +0 -0
- src/main/resources/templates/cms/{documents → document}/document-detail.html +0 -0
pom.xml
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
-
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
| 3 |
-
|
|
|
|
| 4 |
<modelVersion>4.0.0</modelVersion>
|
| 5 |
<parent>
|
| 6 |
<groupId>org.springframework.boot</groupId>
|
|
@@ -34,6 +35,10 @@
|
|
| 34 |
<groupId>org.springframework.boot</groupId>
|
| 35 |
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
| 36 |
</dependency> -->
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
<dependency>
|
| 38 |
<groupId>org.springframework.boot</groupId>
|
| 39 |
<artifactId>spring-boot-starter-validation</artifactId>
|
|
|
|
| 1 |
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
+
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
| 3 |
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
| 4 |
+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
| 5 |
<modelVersion>4.0.0</modelVersion>
|
| 6 |
<parent>
|
| 7 |
<groupId>org.springframework.boot</groupId>
|
|
|
|
| 35 |
<groupId>org.springframework.boot</groupId>
|
| 36 |
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
| 37 |
</dependency> -->
|
| 38 |
+
<dependency>
|
| 39 |
+
<groupId>org.mariadb.jdbc</groupId>
|
| 40 |
+
<artifactId>mariadb-java-client</artifactId>
|
| 41 |
+
</dependency>
|
| 42 |
<dependency>
|
| 43 |
<groupId>org.springframework.boot</groupId>
|
| 44 |
<artifactId>spring-boot-starter-validation</artifactId>
|
src/main/java/com/attendenceSystem/constant/Routes.java
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.constant;
|
| 2 |
+
|
| 3 |
+
import lombok.AccessLevel;
|
| 4 |
+
import lombok.NoArgsConstructor;
|
| 5 |
+
|
| 6 |
+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
| 7 |
+
public final class Routes {
|
| 8 |
+
public static final class Auth {
|
| 9 |
+
public static final String ROOT = "/auth";
|
| 10 |
+
public static final String LOGIN = "/login";
|
| 11 |
+
public static final String REGISTER = "/register";
|
| 12 |
+
}
|
| 13 |
+
}
|
src/main/java/com/attendenceSystem/exception/GlobalExceptionHandler.java
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// package com.attendenceSystem.exception;
|
| 2 |
+
|
| 3 |
+
// import org.springframework.http.HttpStatus;
|
| 4 |
+
// import org.springframework.security.access.AccessDeniedException;
|
| 5 |
+
// import org.springframework.web.bind.annotation.ControllerAdvice;
|
| 6 |
+
// import org.springframework.web.bind.annotation.ExceptionHandler;
|
| 7 |
+
// import org.springframework.web.bind.annotation.ResponseStatus;
|
| 8 |
+
|
| 9 |
+
// import com.attendenceSystem.exception.custom.BadRequestException;
|
| 10 |
+
// import com.attendenceSystem.exception.custom.ResourceNotFoundException;
|
| 11 |
+
|
| 12 |
+
// @ControllerAdvice
|
| 13 |
+
// public class GlobalExceptionHandler {
|
| 14 |
+
// @ExceptionHandler(ResourceNotFoundException.class)
|
| 15 |
+
// @ResponseStatus(HttpStatus.NOT_FOUND)
|
| 16 |
+
// public String notFound() {
|
| 17 |
+
// return "error/404";
|
| 18 |
+
// }
|
| 19 |
+
|
| 20 |
+
// @ExceptionHandler(AccessDeniedException.class)
|
| 21 |
+
// @ResponseStatus(HttpStatus.FORBIDDEN)
|
| 22 |
+
// public String forbidden() {
|
| 23 |
+
// return "error/403";
|
| 24 |
+
// }
|
| 25 |
+
|
| 26 |
+
// @ExceptionHandler(BadRequestException.class)
|
| 27 |
+
// @ResponseStatus(HttpStatus.BAD_REQUEST)
|
| 28 |
+
// public String badRequest() {
|
| 29 |
+
// return "error/400";
|
| 30 |
+
// }
|
| 31 |
+
|
| 32 |
+
// @ExceptionHandler(Exception.class)
|
| 33 |
+
// @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
| 34 |
+
// public String internalServerError(Exception ex) {
|
| 35 |
+
|
| 36 |
+
// ex.printStackTrace();
|
| 37 |
+
|
| 38 |
+
// return "error/500";
|
| 39 |
+
// }
|
| 40 |
+
|
| 41 |
+
// }
|
src/main/java/com/attendenceSystem/exception/custom/BadRequestException.java
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.exception.custom;
|
| 2 |
+
|
| 3 |
+
public class BadRequestException extends RuntimeException{
|
| 4 |
+
public BadRequestException(String message){
|
| 5 |
+
super(message);
|
| 6 |
+
}
|
| 7 |
+
}
|
src/main/java/com/attendenceSystem/exception/custom/ResourceNotFoundException.java
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.exception.custom;
|
| 2 |
+
|
| 3 |
+
public class ResourceNotFoundException extends RuntimeException{
|
| 4 |
+
public ResourceNotFoundException(String message){
|
| 5 |
+
super(message);
|
| 6 |
+
}
|
| 7 |
+
}
|
src/main/java/com/attendenceSystem/module/log/dto/request/AuditLogRequest.java
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.log.dto.request;
|
| 2 |
+
|
| 3 |
+
import com.attendenceSystem.module.log.entity.enums.LogAction;
|
| 4 |
+
import com.attendenceSystem.module.log.entity.enums.LogEntityType;
|
| 5 |
+
import com.attendenceSystem.module.user.entity.User;
|
| 6 |
+
|
| 7 |
+
public record AuditLogRequest(
|
| 8 |
+
User user,
|
| 9 |
+
LogEntityType logEntityType,
|
| 10 |
+
Long entityId,
|
| 11 |
+
LogAction action,
|
| 12 |
+
String description) {
|
| 13 |
+
|
| 14 |
+
}
|
src/main/java/com/attendenceSystem/module/log/dto/response/AuditLogResponse.java
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.log.dto.response;
|
| 2 |
+
|
| 3 |
+
import com.attendenceSystem.module.log.entity.enums.LogAction;
|
| 4 |
+
import com.attendenceSystem.module.log.entity.enums.LogEntityType;
|
| 5 |
+
|
| 6 |
+
import lombok.Builder;
|
| 7 |
+
|
| 8 |
+
@Builder
|
| 9 |
+
public record AuditLogResponse(
|
| 10 |
+
Long id,
|
| 11 |
+
Long userId,
|
| 12 |
+
String username,
|
| 13 |
+
LogEntityType entityType,
|
| 14 |
+
Long entityId,
|
| 15 |
+
LogAction action,
|
| 16 |
+
String description,
|
| 17 |
+
String createdAt) {
|
| 18 |
+
}
|
src/main/java/com/attendenceSystem/module/log/entity/AuditLog.java
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.log.entity;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
|
| 5 |
+
import org.hibernate.annotations.CreationTimestamp;
|
| 6 |
+
|
| 7 |
+
import com.attendenceSystem.module.log.entity.enums.LogAction;
|
| 8 |
+
import com.attendenceSystem.module.log.entity.enums.LogEntityType;
|
| 9 |
+
import com.attendenceSystem.module.user.entity.User;
|
| 10 |
+
|
| 11 |
+
import jakarta.persistence.Column;
|
| 12 |
+
import jakarta.persistence.Entity;
|
| 13 |
+
import jakarta.persistence.FetchType;
|
| 14 |
+
import jakarta.persistence.GeneratedValue;
|
| 15 |
+
import jakarta.persistence.GenerationType;
|
| 16 |
+
import jakarta.persistence.Id;
|
| 17 |
+
import jakarta.persistence.JoinColumn;
|
| 18 |
+
import jakarta.persistence.ManyToOne;
|
| 19 |
+
import jakarta.persistence.Table;
|
| 20 |
+
import lombok.AllArgsConstructor;
|
| 21 |
+
import lombok.Builder;
|
| 22 |
+
import lombok.Getter;
|
| 23 |
+
import lombok.NoArgsConstructor;
|
| 24 |
+
import lombok.Setter;
|
| 25 |
+
|
| 26 |
+
@Entity
|
| 27 |
+
@Table(name = "audit_logs")
|
| 28 |
+
@Getter
|
| 29 |
+
@Setter
|
| 30 |
+
@NoArgsConstructor
|
| 31 |
+
@AllArgsConstructor
|
| 32 |
+
@Builder
|
| 33 |
+
public class AuditLog {
|
| 34 |
+
|
| 35 |
+
@Id
|
| 36 |
+
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
| 37 |
+
private Long id;
|
| 38 |
+
|
| 39 |
+
@Column(name = "entity_id")
|
| 40 |
+
private Long entityId;
|
| 41 |
+
|
| 42 |
+
@Column(name = "entity_type", nullable = false)
|
| 43 |
+
private LogEntityType entityType;
|
| 44 |
+
|
| 45 |
+
@Column(name = "action", nullable = false)
|
| 46 |
+
private LogAction action;
|
| 47 |
+
|
| 48 |
+
@Column(name = "description", columnDefinition = "LONGTEXT")
|
| 49 |
+
private String description;
|
| 50 |
+
|
| 51 |
+
@CreationTimestamp
|
| 52 |
+
@Column(name = "created_at", updatable = false)
|
| 53 |
+
private Instant createdAt;
|
| 54 |
+
|
| 55 |
+
@ManyToOne(fetch = FetchType.LAZY)
|
| 56 |
+
@JoinColumn(name = "user_id", updatable = false)
|
| 57 |
+
private User user;
|
| 58 |
+
}
|
src/main/java/com/attendenceSystem/module/log/entity/converter/LogActionConverter.java
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.log.entity.converter;
|
| 2 |
+
|
| 3 |
+
import com.attendenceSystem.module.log.entity.enums.LogAction;
|
| 4 |
+
|
| 5 |
+
import jakarta.persistence.AttributeConverter;
|
| 6 |
+
import jakarta.persistence.Converter;
|
| 7 |
+
|
| 8 |
+
@Converter(autoApply = true)
|
| 9 |
+
public class LogActionConverter implements AttributeConverter<LogAction, Long> {
|
| 10 |
+
|
| 11 |
+
@Override
|
| 12 |
+
public Long convertToDatabaseColumn(LogAction attribute) {
|
| 13 |
+
return attribute == null ? null : attribute.getCode();
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
@Override
|
| 17 |
+
public LogAction convertToEntityAttribute(Long dbData) {
|
| 18 |
+
return dbData == null ? null : LogAction.fromValue(dbData);
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
}
|
src/main/java/com/attendenceSystem/module/log/entity/converter/LogEntityTypeConverter.java
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.log.entity.converter;
|
| 2 |
+
|
| 3 |
+
import com.attendenceSystem.module.log.entity.enums.LogEntityType;
|
| 4 |
+
|
| 5 |
+
import jakarta.persistence.AttributeConverter;
|
| 6 |
+
import jakarta.persistence.Converter;
|
| 7 |
+
|
| 8 |
+
@Converter(autoApply = true)
|
| 9 |
+
public class LogEntityTypeConverter implements AttributeConverter<LogEntityType, Long>{
|
| 10 |
+
|
| 11 |
+
@Override
|
| 12 |
+
public Long convertToDatabaseColumn(LogEntityType attribute) {
|
| 13 |
+
return attribute == null ? null : attribute.getCode();
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
@Override
|
| 17 |
+
public LogEntityType convertToEntityAttribute(Long dbData) {
|
| 18 |
+
return dbData == null ? null : LogEntityType.fromValue(dbData);
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
}
|
src/main/java/com/attendenceSystem/module/log/entity/enums/LogAction.java
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.log.entity.enums;
|
| 2 |
+
|
| 3 |
+
import lombok.Getter;
|
| 4 |
+
import lombok.RequiredArgsConstructor;
|
| 5 |
+
|
| 6 |
+
@Getter
|
| 7 |
+
@RequiredArgsConstructor
|
| 8 |
+
public enum LogAction {
|
| 9 |
+
CREATE(1),
|
| 10 |
+
UPDATE(2),
|
| 11 |
+
DELETE(3),
|
| 12 |
+
RESTORE(4),
|
| 13 |
+
APPROVE(5),
|
| 14 |
+
LOCK(6),
|
| 15 |
+
UNLOCK(7),
|
| 16 |
+
CHANGE_PASSWORD(8),
|
| 17 |
+
LOGIN(9),
|
| 18 |
+
LOGOUT(10),
|
| 19 |
+
PROCESS(11);
|
| 20 |
+
|
| 21 |
+
private final long code;
|
| 22 |
+
|
| 23 |
+
public static LogAction fromValue(long code) {
|
| 24 |
+
for (LogAction action : LogAction.values()) {
|
| 25 |
+
if (action.code == code) {
|
| 26 |
+
return action;
|
| 27 |
+
}
|
| 28 |
+
}
|
| 29 |
+
throw new IllegalArgumentException("Không tìm thấy loại hành động: " + code);
|
| 30 |
+
}
|
| 31 |
+
}
|
src/main/java/com/attendenceSystem/module/log/entity/enums/LogEntityType.java
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.log.entity.enums;
|
| 2 |
+
|
| 3 |
+
import lombok.Getter;
|
| 4 |
+
import lombok.RequiredArgsConstructor;
|
| 5 |
+
|
| 6 |
+
@Getter
|
| 7 |
+
@RequiredArgsConstructor
|
| 8 |
+
public enum LogEntityType {
|
| 9 |
+
USER(1);
|
| 10 |
+
|
| 11 |
+
private final long code;
|
| 12 |
+
public static LogEntityType fromValue(long code) {
|
| 13 |
+
for (LogEntityType action : LogEntityType.values()) {
|
| 14 |
+
if (action.code == code) {
|
| 15 |
+
return action;
|
| 16 |
+
}
|
| 17 |
+
}
|
| 18 |
+
throw new IllegalArgumentException("Không tìm thấy loại Entity: " + code);
|
| 19 |
+
}
|
| 20 |
+
}
|
src/main/java/com/attendenceSystem/module/log/mapper/request/AuditLogRequestMapping.java
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.log.mapper.request;
|
| 2 |
+
|
| 3 |
+
public class AuditLogRequestMapping {
|
| 4 |
+
|
| 5 |
+
}
|
src/main/java/com/attendenceSystem/module/log/mapper/response/AuditLogResponseMapper.java
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.log.mapper.response;
|
| 2 |
+
|
| 3 |
+
import com.attendenceSystem.module.log.dto.response.AuditLogResponse;
|
| 4 |
+
import com.attendenceSystem.module.log.entity.AuditLog;
|
| 5 |
+
import com.attendenceSystem.util.TimeUtil;
|
| 6 |
+
|
| 7 |
+
public class AuditLogResponseMapper {
|
| 8 |
+
public static AuditLogResponse fromEntity(AuditLog auditLog) {
|
| 9 |
+
return AuditLogResponse.builder()
|
| 10 |
+
.id(auditLog.getId())
|
| 11 |
+
.userId(auditLog.getUser().getId())
|
| 12 |
+
.username(auditLog.getUser().getUsername())
|
| 13 |
+
.entityType(auditLog.getEntityType())
|
| 14 |
+
.entityId(auditLog.getEntityId())
|
| 15 |
+
.action(auditLog.getAction())
|
| 16 |
+
.description(auditLog.getDescription())
|
| 17 |
+
.createdAt(TimeUtil.formatInstant(auditLog.getCreatedAt(), null))
|
| 18 |
+
.build();
|
| 19 |
+
}
|
| 20 |
+
}
|
src/main/java/com/attendenceSystem/module/log/repository/AuditLogRepository.java
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.log.repository;
|
| 2 |
+
|
| 3 |
+
import org.springframework.data.domain.Page;
|
| 4 |
+
import org.springframework.data.domain.Pageable;
|
| 5 |
+
import org.springframework.data.jpa.repository.JpaRepository;
|
| 6 |
+
import org.springframework.stereotype.Repository;
|
| 7 |
+
|
| 8 |
+
import com.attendenceSystem.module.log.entity.AuditLog;
|
| 9 |
+
|
| 10 |
+
@Repository
|
| 11 |
+
public interface AuditLogRepository extends JpaRepository<AuditLog, Long> {
|
| 12 |
+
Page<AuditLog> findAllByOrderByCreatedAtDesc(Pageable pageable);
|
| 13 |
+
}
|
src/main/java/com/attendenceSystem/module/log/service/AuditLogService.java
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.log.service;
|
| 2 |
+
|
| 3 |
+
import org.springframework.data.domain.Page;
|
| 4 |
+
import org.springframework.data.domain.Pageable;
|
| 5 |
+
|
| 6 |
+
import com.attendenceSystem.module.log.dto.request.AuditLogRequest;
|
| 7 |
+
import com.attendenceSystem.module.log.dto.response.AuditLogResponse;
|
| 8 |
+
|
| 9 |
+
public interface AuditLogService {
|
| 10 |
+
void log(AuditLogRequest request);
|
| 11 |
+
|
| 12 |
+
Page<AuditLogResponse> getLogs(Pageable pageable);
|
| 13 |
+
}
|
src/main/java/com/attendenceSystem/module/log/service/impl/AuditLogServiceImpl.java
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.log.service.impl;
|
| 2 |
+
|
| 3 |
+
import org.springframework.data.domain.Page;
|
| 4 |
+
import org.springframework.data.domain.Pageable;
|
| 5 |
+
import org.springframework.transaction.annotation.Transactional;
|
| 6 |
+
|
| 7 |
+
import com.attendenceSystem.module.log.dto.request.AuditLogRequest;
|
| 8 |
+
import com.attendenceSystem.module.log.dto.response.AuditLogResponse;
|
| 9 |
+
import com.attendenceSystem.module.log.entity.AuditLog;
|
| 10 |
+
import com.attendenceSystem.module.log.mapper.response.AuditLogResponseMapper;
|
| 11 |
+
import com.attendenceSystem.module.log.repository.AuditLogRepository;
|
| 12 |
+
import com.attendenceSystem.module.log.service.AuditLogService;
|
| 13 |
+
|
| 14 |
+
import lombok.RequiredArgsConstructor;
|
| 15 |
+
|
| 16 |
+
@RequiredArgsConstructor
|
| 17 |
+
public class AuditLogServiceImpl implements AuditLogService {
|
| 18 |
+
private final AuditLogRepository auditLogRepository;
|
| 19 |
+
|
| 20 |
+
@Transactional
|
| 21 |
+
@Override
|
| 22 |
+
public void log(AuditLogRequest request) {
|
| 23 |
+
AuditLog auditLog = AuditLog.builder()
|
| 24 |
+
.user(request.user())
|
| 25 |
+
.entityType(request.logEntityType())
|
| 26 |
+
.entityId(request.entityId())
|
| 27 |
+
.action(request.action())
|
| 28 |
+
.description(request.description())
|
| 29 |
+
.build();
|
| 30 |
+
auditLogRepository.save(auditLog);
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
@Override
|
| 34 |
+
public Page<AuditLogResponse> getLogs(Pageable pageable) {
|
| 35 |
+
return auditLogRepository
|
| 36 |
+
.findAll(pageable)
|
| 37 |
+
.map(AuditLogResponseMapper::fromEntity);
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
}
|
src/main/java/com/attendenceSystem/module/user/controller/AuthController.java
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.controller;
|
| 2 |
+
|
| 3 |
+
import org.springframework.stereotype.Controller;
|
| 4 |
+
import org.springframework.web.bind.annotation.RequestMapping;
|
| 5 |
+
|
| 6 |
+
import com.attendenceSystem.constant.Routes;
|
| 7 |
+
import com.attendenceSystem.module.user.service.AuthService;
|
| 8 |
+
|
| 9 |
+
import lombok.RequiredArgsConstructor;
|
| 10 |
+
import org.springframework.web.bind.annotation.GetMapping;
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
@Controller
|
| 15 |
+
@RequestMapping(Routes.Auth.ROOT)
|
| 16 |
+
@RequiredArgsConstructor
|
| 17 |
+
public class AuthController {
|
| 18 |
+
private final AuthService authService;
|
| 19 |
+
|
| 20 |
+
@GetMapping(Routes.Auth.REGISTER)
|
| 21 |
+
public String toRegisterPage() {
|
| 22 |
+
return "auth/register";
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
}
|
src/main/java/com/attendenceSystem/module/user/dto/request/LoginRequest.java
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.dto.request;
|
| 2 |
+
|
| 3 |
+
import jakarta.validation.constraints.NotBlank;
|
| 4 |
+
import jakarta.validation.constraints.Size;
|
| 5 |
+
|
| 6 |
+
public record LoginRequest(
|
| 7 |
+
@NotBlank(message = "Tên đăng nhập hoặc email không được để trống")
|
| 8 |
+
String login,
|
| 9 |
+
|
| 10 |
+
@NotBlank(message = "Mật khẩu không được để trống")
|
| 11 |
+
@Size(min = 8, message = "Mật khẩu phải chứa ít nhất 8 kí tự")
|
| 12 |
+
String password) {
|
| 13 |
+
}
|
src/main/java/com/attendenceSystem/module/user/dto/request/RegisterRequest.java
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.dto.request;
|
| 2 |
+
|
| 3 |
+
import com.attendenceSystem.annotation.PasswordMatch;
|
| 4 |
+
import com.fasterxml.jackson.annotation.JsonProperty;
|
| 5 |
+
|
| 6 |
+
import jakarta.validation.constraints.Email;
|
| 7 |
+
import jakarta.validation.constraints.NotBlank;
|
| 8 |
+
import jakarta.validation.constraints.Pattern;
|
| 9 |
+
import jakarta.validation.constraints.Size;
|
| 10 |
+
|
| 11 |
+
@PasswordMatch
|
| 12 |
+
public record RegisterRequest(
|
| 13 |
+
|
| 14 |
+
@NotBlank(message = "Tên đăng nhập không được để trống")
|
| 15 |
+
@Size(min = 3, max = 30, message = "Tên đăng nhập phải có độ dài từ 3 đến 30 ký tự")
|
| 16 |
+
@Pattern(regexp = "^[a-zA-Z0-9]+$", message = "Tên đăng nhập không được chứa ký tự đặc biệt")
|
| 17 |
+
String username,
|
| 18 |
+
|
| 19 |
+
@NotBlank(message = "Email không được để trống")
|
| 20 |
+
@Size(max = 255, message = "Email không được vượt quá 255 ký tự")
|
| 21 |
+
@Email(message = "Email không đúng định dạng")
|
| 22 |
+
String email,
|
| 23 |
+
|
| 24 |
+
@NotBlank(message = "Mật khẩu không được để trống")
|
| 25 |
+
@Size(min = 8, message = "Mật khẩu phải chứa ít nhất 8 kí tự")
|
| 26 |
+
String password,
|
| 27 |
+
|
| 28 |
+
@NotBlank(message = "Mật khẩu xác nhận không được để trống")
|
| 29 |
+
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
|
| 30 |
+
String rePassword,
|
| 31 |
+
|
| 32 |
+
@NotBlank(message = "Họ tên không được để trống")
|
| 33 |
+
@Size(max = 255, message = "Họ tên không được vượt quá 255 ký tự")
|
| 34 |
+
String fullName
|
| 35 |
+
|
| 36 |
+
) {
|
| 37 |
+
}
|
src/main/java/com/attendenceSystem/module/user/dto/response/UserResponse.java
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.dto.response;
|
| 2 |
+
|
| 3 |
+
import lombok.Builder;
|
| 4 |
+
|
| 5 |
+
@Builder
|
| 6 |
+
public record UserResponse(
|
| 7 |
+
Long id,
|
| 8 |
+
String username,
|
| 9 |
+
String email,
|
| 10 |
+
String fullName,
|
| 11 |
+
Boolean isActive,
|
| 12 |
+
String role) {
|
| 13 |
+
|
| 14 |
+
}
|
src/main/java/com/attendenceSystem/{user → module/user}/entity/User.java
RENAMED
|
@@ -1,7 +1,12 @@
|
|
| 1 |
-
package com.attendenceSystem.user.entity;
|
| 2 |
|
| 3 |
import java.time.Instant;
|
| 4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
import jakarta.persistence.Column;
|
| 6 |
import jakarta.persistence.Entity;
|
| 7 |
import jakarta.persistence.GeneratedValue;
|
|
@@ -26,22 +31,27 @@ public class User {
|
|
| 26 |
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
| 27 |
@Column(name = "id")
|
| 28 |
private Long id;
|
| 29 |
-
@Column(name = "
|
|
|
|
|
|
|
| 30 |
private String email;
|
| 31 |
-
@Column(name = "password")
|
| 32 |
private String password;
|
| 33 |
-
@Column(name = "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
private String fullName;
|
| 35 |
-
@
|
| 36 |
-
|
| 37 |
-
@Column(name = "role")
|
| 38 |
-
private String role;
|
| 39 |
-
@Column(name = "status")
|
| 40 |
-
private String status;
|
| 41 |
-
@Column(name = "created_at")
|
| 42 |
private Instant createdAt;
|
| 43 |
-
@
|
|
|
|
| 44 |
private Instant updatedAt;
|
| 45 |
-
|
| 46 |
-
|
|
|
|
|
|
|
| 47 |
}
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.entity;
|
| 2 |
|
| 3 |
import java.time.Instant;
|
| 4 |
|
| 5 |
+
import org.hibernate.annotations.CreationTimestamp;
|
| 6 |
+
import org.hibernate.annotations.UpdateTimestamp;
|
| 7 |
+
|
| 8 |
+
import com.attendenceSystem.module.user.entity.enums.Role;
|
| 9 |
+
|
| 10 |
import jakarta.persistence.Column;
|
| 11 |
import jakarta.persistence.Entity;
|
| 12 |
import jakarta.persistence.GeneratedValue;
|
|
|
|
| 31 |
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
| 32 |
@Column(name = "id")
|
| 33 |
private Long id;
|
| 34 |
+
@Column(name = "username", unique = true, nullable = false, length = 30)
|
| 35 |
+
private String username;
|
| 36 |
+
@Column(name = "email", unique = true, nullable = false, length = 255)
|
| 37 |
private String email;
|
| 38 |
+
@Column(name = "password", nullable = false, length = 255)
|
| 39 |
private String password;
|
| 40 |
+
@Column(name = "role", nullable = false)
|
| 41 |
+
private Role role;
|
| 42 |
+
@Column(name = "is_active", nullable = false)
|
| 43 |
+
@Builder.Default
|
| 44 |
+
private boolean isActive = true;
|
| 45 |
+
@Column(name = "full_name", nullable = false, length = 255)
|
| 46 |
private String fullName;
|
| 47 |
+
@CreationTimestamp
|
| 48 |
+
@Column(name = "created_at", nullable = false, updatable = false)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
private Instant createdAt;
|
| 50 |
+
@UpdateTimestamp
|
| 51 |
+
@Column(name = "updated_at", nullable = false)
|
| 52 |
private Instant updatedAt;
|
| 53 |
+
|
| 54 |
+
@Column(name = "must_change_password", nullable = false)
|
| 55 |
+
@Builder.Default
|
| 56 |
+
private boolean mustChangePassword = false;
|
| 57 |
}
|
src/main/java/com/attendenceSystem/module/user/entity/converter/RoleConverter.java
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.entity.converter;
|
| 2 |
+
|
| 3 |
+
import com.attendenceSystem.module.user.entity.enums.Role;
|
| 4 |
+
|
| 5 |
+
import jakarta.persistence.AttributeConverter;
|
| 6 |
+
import jakarta.persistence.Converter;
|
| 7 |
+
|
| 8 |
+
@Converter(autoApply = true)
|
| 9 |
+
public class RoleConverter implements AttributeConverter<Role, Integer> {
|
| 10 |
+
|
| 11 |
+
@Override
|
| 12 |
+
public Integer convertToDatabaseColumn(Role role) {
|
| 13 |
+
return role == null ? null : role.getValue();
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
@Override
|
| 17 |
+
public Role convertToEntityAttribute(Integer dbData) {
|
| 18 |
+
return dbData == null ? null : Role.fromValue(dbData);
|
| 19 |
+
}
|
| 20 |
+
}
|
src/main/java/com/attendenceSystem/{user → module/user}/entity/enums/Role.java
RENAMED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
package com.attendenceSystem.user.entity.enums;
|
| 2 |
|
| 3 |
import lombok.Getter;
|
| 4 |
import lombok.RequiredArgsConstructor;
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.entity.enums;
|
| 2 |
|
| 3 |
import lombok.Getter;
|
| 4 |
import lombok.RequiredArgsConstructor;
|
src/main/java/com/attendenceSystem/module/user/mapper/request/RegisterRequestMapper.java
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.mapper.request;
|
| 2 |
+
|
| 3 |
+
import com.attendenceSystem.module.user.dto.request.RegisterRequest;
|
| 4 |
+
import com.attendenceSystem.module.user.entity.User;
|
| 5 |
+
|
| 6 |
+
import lombok.AccessLevel;
|
| 7 |
+
import lombok.NoArgsConstructor;
|
| 8 |
+
|
| 9 |
+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
| 10 |
+
public final class RegisterRequestMapper {
|
| 11 |
+
public static User toEntity(RegisterRequest request, String hashPassword) {
|
| 12 |
+
return User.builder()
|
| 13 |
+
.username(request.username())
|
| 14 |
+
.email(request.email())
|
| 15 |
+
.password(hashPassword)
|
| 16 |
+
.fullName(request.fullName())
|
| 17 |
+
.build();
|
| 18 |
+
}
|
| 19 |
+
}
|
src/main/java/com/attendenceSystem/{user → module/user}/mapper/response/UserResponseMapper.java
RENAMED
|
@@ -1,12 +1,11 @@
|
|
| 1 |
-
package com.attendenceSystem.user.mapper.response;
|
| 2 |
|
| 3 |
import java.time.ZoneId;
|
| 4 |
|
| 5 |
import org.springframework.stereotype.Component;
|
| 6 |
|
| 7 |
-
import com.attendenceSystem.user.dto.response.UserResponse;
|
| 8 |
-
import com.attendenceSystem.user.entity.User;
|
| 9 |
-
import com.attendenceSystem.util.TimeUtil;
|
| 10 |
|
| 11 |
import lombok.RequiredArgsConstructor;
|
| 12 |
|
|
@@ -16,23 +15,14 @@ public class UserResponseMapper {
|
|
| 16 |
|
| 17 |
private final ZoneId applicationZoneId;
|
| 18 |
|
| 19 |
-
public UserResponse
|
| 20 |
-
|
| 21 |
return UserResponse.builder()
|
| 22 |
.id(user.getId())
|
|
|
|
| 23 |
.email(user.getEmail())
|
| 24 |
.fullName(user.getFullName())
|
| 25 |
-
.
|
| 26 |
-
.
|
| 27 |
-
.createdAt(
|
| 28 |
-
TimeUtil.formatInstant(
|
| 29 |
-
user.getCreatedAt(),
|
| 30 |
-
applicationZoneId))
|
| 31 |
-
.updatedAt(
|
| 32 |
-
TimeUtil.formatInstant(
|
| 33 |
-
user.getUpdatedAt(),
|
| 34 |
-
applicationZoneId))
|
| 35 |
-
.deleted(user.getDeleted())
|
| 36 |
.build();
|
| 37 |
}
|
| 38 |
}
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.mapper.response;
|
| 2 |
|
| 3 |
import java.time.ZoneId;
|
| 4 |
|
| 5 |
import org.springframework.stereotype.Component;
|
| 6 |
|
| 7 |
+
import com.attendenceSystem.module.user.dto.response.UserResponse;
|
| 8 |
+
import com.attendenceSystem.module.user.entity.User;
|
|
|
|
| 9 |
|
| 10 |
import lombok.RequiredArgsConstructor;
|
| 11 |
|
|
|
|
| 15 |
|
| 16 |
private final ZoneId applicationZoneId;
|
| 17 |
|
| 18 |
+
public UserResponse fromEntity(User user) {
|
|
|
|
| 19 |
return UserResponse.builder()
|
| 20 |
.id(user.getId())
|
| 21 |
+
.username(user.getUsername())
|
| 22 |
.email(user.getEmail())
|
| 23 |
.fullName(user.getFullName())
|
| 24 |
+
.isActive(user.isActive())
|
| 25 |
+
.role(user.getRole().name())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
.build();
|
| 27 |
}
|
| 28 |
}
|
src/main/java/com/attendenceSystem/module/user/repository/UserRepository.java
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.repository;
|
| 2 |
+
|
| 3 |
+
import java.util.Optional;
|
| 4 |
+
|
| 5 |
+
import org.springframework.data.domain.Page;
|
| 6 |
+
import org.springframework.data.domain.Pageable;
|
| 7 |
+
import org.springframework.data.jpa.repository.JpaRepository;
|
| 8 |
+
import org.springframework.stereotype.Repository;
|
| 9 |
+
|
| 10 |
+
import com.attendenceSystem.module.user.entity.User;
|
| 11 |
+
|
| 12 |
+
@Repository
|
| 13 |
+
public interface UserRepository extends JpaRepository<User, Long> {
|
| 14 |
+
Optional<User> findUserByUsername(String username);
|
| 15 |
+
Optional<User> findUserByEmail(String email);
|
| 16 |
+
boolean existsByUsername(String username);
|
| 17 |
+
boolean existsByEmail(String email);
|
| 18 |
+
Optional<User> findUserByUsernameOrEmail(String username, String email);
|
| 19 |
+
boolean existsByUsernameOrEmail(String username, String email);
|
| 20 |
+
Page<User> findAllByOrderByIdAsc(Pageable pageable);
|
| 21 |
+
long countByIsActiveTrue();
|
| 22 |
+
long countByIsActiveFalse();
|
| 23 |
+
Optional<User> findByUsername(String username);
|
| 24 |
+
}
|
src/main/java/com/attendenceSystem/module/user/service/AuthService.java
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.service;
|
| 2 |
+
|
| 3 |
+
import com.attendenceSystem.module.user.dto.request.LoginRequest;
|
| 4 |
+
import com.attendenceSystem.module.user.dto.request.RegisterRequest;
|
| 5 |
+
import com.attendenceSystem.module.user.dto.response.UserResponse;
|
| 6 |
+
|
| 7 |
+
public interface AuthService {
|
| 8 |
+
UserResponse login(LoginRequest request);
|
| 9 |
+
|
| 10 |
+
void register(RegisterRequest request);
|
| 11 |
+
|
| 12 |
+
}
|
src/main/java/com/attendenceSystem/module/user/service/UserService.java
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.service;
|
| 2 |
+
|
| 3 |
+
import org.springframework.data.domain.Page;
|
| 4 |
+
import org.springframework.data.domain.Pageable;
|
| 5 |
+
|
| 6 |
+
import com.attendenceSystem.module.user.dto.response.UserResponse;
|
| 7 |
+
|
| 8 |
+
public interface UserService {
|
| 9 |
+
Page<UserResponse> getAccounts(Pageable pageable);
|
| 10 |
+
UserResponse getById(Long id);
|
| 11 |
+
void deleteUser(Long id);
|
| 12 |
+
}
|
src/main/java/com/attendenceSystem/module/user/service/impl/AuthServiceImpl.java
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.service.impl;
|
| 2 |
+
|
| 3 |
+
import com.attendenceSystem.module.user.mapper.request.RegisterRequestMapper;
|
| 4 |
+
import com.attendenceSystem.module.user.mapper.response.UserResponseMapper;
|
| 5 |
+
import java.util.Optional;
|
| 6 |
+
|
| 7 |
+
import org.springframework.security.authentication.AuthenticationManager;
|
| 8 |
+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
| 9 |
+
import org.springframework.security.core.Authentication;
|
| 10 |
+
import org.springframework.security.core.context.SecurityContext;
|
| 11 |
+
import org.springframework.security.core.context.SecurityContextHolder;
|
| 12 |
+
import org.springframework.security.crypto.password.PasswordEncoder;
|
| 13 |
+
import org.springframework.stereotype.Service;
|
| 14 |
+
import org.springframework.transaction.annotation.Transactional;
|
| 15 |
+
|
| 16 |
+
import com.attendenceSystem.module.user.dto.request.LoginRequest;
|
| 17 |
+
import com.attendenceSystem.module.user.dto.request.RegisterRequest;
|
| 18 |
+
import com.attendenceSystem.module.user.dto.response.UserResponse;
|
| 19 |
+
import com.attendenceSystem.module.user.entity.User;
|
| 20 |
+
import com.attendenceSystem.module.user.repository.UserRepository;
|
| 21 |
+
import com.attendenceSystem.module.user.service.AuthService;
|
| 22 |
+
|
| 23 |
+
import lombok.RequiredArgsConstructor;
|
| 24 |
+
|
| 25 |
+
@Service
|
| 26 |
+
@RequiredArgsConstructor
|
| 27 |
+
public class AuthServiceImpl implements AuthService {
|
| 28 |
+
private final UserResponseMapper userResponseMapper;
|
| 29 |
+
private final UserRepository userRepository;
|
| 30 |
+
private final AuthenticationManager authenticationManager;
|
| 31 |
+
private final PasswordEncoder passwordEncoder;
|
| 32 |
+
|
| 33 |
+
@Transactional
|
| 34 |
+
@Override
|
| 35 |
+
public void register(RegisterRequest request) {
|
| 36 |
+
if (existsByKeyword(request.username())) {
|
| 37 |
+
throw new IllegalArgumentException("Tên đăng nhập đã tồn tại!");
|
| 38 |
+
}
|
| 39 |
+
if (existsByKeyword(request.email())) {
|
| 40 |
+
throw new IllegalArgumentException("Email này đã được đăng ký!");
|
| 41 |
+
}
|
| 42 |
+
String hashPassword = passwordEncoder.encode(request.password());
|
| 43 |
+
User savedUser = RegisterRequestMapper.toEntity(request, hashPassword);
|
| 44 |
+
userRepository.save(savedUser);
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
@Override
|
| 48 |
+
public UserResponse login(LoginRequest request) {
|
| 49 |
+
|
| 50 |
+
Authentication authentication = authenticationManager.authenticate(
|
| 51 |
+
new UsernamePasswordAuthenticationToken(
|
| 52 |
+
request.login(),
|
| 53 |
+
request.password()));
|
| 54 |
+
|
| 55 |
+
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
| 56 |
+
context.setAuthentication(authentication);
|
| 57 |
+
SecurityContextHolder.setContext(context);
|
| 58 |
+
|
| 59 |
+
User user = findUser(authentication.getName())
|
| 60 |
+
.orElseThrow(() -> new IllegalArgumentException(
|
| 61 |
+
"Tên đăng nhập hoặc mật khẩu không đúng."));
|
| 62 |
+
return userResponseMapper.fromEntity(user);
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
private Optional<User> findUser(String keyword) {
|
| 66 |
+
return userRepository.findUserByUsernameOrEmail(keyword, keyword);
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
private boolean existsByKeyword(String keyword) {
|
| 70 |
+
return userRepository.existsByUsernameOrEmail(keyword, keyword);
|
| 71 |
+
}
|
| 72 |
+
}
|
src/main/java/com/attendenceSystem/module/user/service/impl/UserServiceImpl.java
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.module.user.service.impl;
|
| 2 |
+
|
| 3 |
+
import org.springframework.data.domain.Page;
|
| 4 |
+
import org.springframework.data.domain.Pageable;
|
| 5 |
+
import org.springframework.stereotype.Service;
|
| 6 |
+
import org.springframework.transaction.annotation.Transactional;
|
| 7 |
+
|
| 8 |
+
import com.attendenceSystem.module.user.dto.response.UserResponse;
|
| 9 |
+
import com.attendenceSystem.module.user.entity.User;
|
| 10 |
+
import com.attendenceSystem.module.user.mapper.response.UserResponseMapper;
|
| 11 |
+
import com.attendenceSystem.module.user.repository.UserRepository;
|
| 12 |
+
import com.attendenceSystem.module.user.service.UserService;
|
| 13 |
+
|
| 14 |
+
import lombok.RequiredArgsConstructor;
|
| 15 |
+
|
| 16 |
+
@Service
|
| 17 |
+
@RequiredArgsConstructor
|
| 18 |
+
public class UserServiceImpl implements UserService {
|
| 19 |
+
private final UserRepository userRepository;
|
| 20 |
+
private final UserResponseMapper userResponseMapper;
|
| 21 |
+
|
| 22 |
+
@Override
|
| 23 |
+
public UserResponse getById(Long id) {
|
| 24 |
+
return userResponseMapper.fromEntity(findById(id));
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
@Transactional
|
| 28 |
+
@Override
|
| 29 |
+
public void deleteUser(Long id) {
|
| 30 |
+
userRepository.delete(findById(id));
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
private User findById(Long id) {
|
| 34 |
+
return userRepository.findById(id)
|
| 35 |
+
.orElseThrow(() -> new IllegalArgumentException("Không tìm thấy người dùng với id: " + id));
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
@Override
|
| 39 |
+
public Page<UserResponse> getAccounts(Pageable pageable) {
|
| 40 |
+
// TODO Auto-generated method stub
|
| 41 |
+
throw new UnsupportedOperationException("Unimplemented method 'getAccounts'");
|
| 42 |
+
}
|
| 43 |
+
}
|
src/main/java/com/attendenceSystem/security/ActiveUserFilter.java
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// package com.attendenceSystem.security;
|
| 2 |
+
|
| 3 |
+
// import java.io.IOException;
|
| 4 |
+
|
| 5 |
+
// import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
| 6 |
+
// import org.springframework.security.core.Authentication;
|
| 7 |
+
// import org.springframework.security.core.context.SecurityContextHolder;
|
| 8 |
+
// import org.springframework.stereotype.Component;
|
| 9 |
+
// import org.springframework.web.filter.OncePerRequestFilter;
|
| 10 |
+
|
| 11 |
+
// import com.attendenceSystem.constant.Routes;
|
| 12 |
+
// import com.attendenceSystem.entity.User;
|
| 13 |
+
// import com.attendenceSystem.repository.UserRepository;
|
| 14 |
+
|
| 15 |
+
// import jakarta.servlet.FilterChain;
|
| 16 |
+
// import jakarta.servlet.ServletException;
|
| 17 |
+
// import jakarta.servlet.http.HttpServletRequest;
|
| 18 |
+
// import jakarta.servlet.http.HttpServletResponse;
|
| 19 |
+
// import jakarta.servlet.http.HttpSession;
|
| 20 |
+
// import lombok.RequiredArgsConstructor;
|
| 21 |
+
|
| 22 |
+
// @Component
|
| 23 |
+
// @RequiredArgsConstructor
|
| 24 |
+
// public class ActiveUserFilter extends OncePerRequestFilter {
|
| 25 |
+
|
| 26 |
+
// private final UserRepository userRepository;
|
| 27 |
+
|
| 28 |
+
// @Override
|
| 29 |
+
// protected void doFilterInternal(
|
| 30 |
+
// HttpServletRequest request,
|
| 31 |
+
// HttpServletResponse response,
|
| 32 |
+
// FilterChain filterChain)
|
| 33 |
+
// throws ServletException, IOException {
|
| 34 |
+
|
| 35 |
+
// Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
| 36 |
+
|
| 37 |
+
// if (authentication != null
|
| 38 |
+
// && authentication.isAuthenticated()
|
| 39 |
+
// && !(authentication instanceof AnonymousAuthenticationToken)) {
|
| 40 |
+
|
| 41 |
+
// String username = authentication.getName();
|
| 42 |
+
|
| 43 |
+
// User user = userRepository.findByUsername(username).orElse(null);
|
| 44 |
+
|
| 45 |
+
// if (user == null || !user.isActive()) {
|
| 46 |
+
// SecurityContextHolder.clearContext();
|
| 47 |
+
// HttpSession session = request.getSession(false);
|
| 48 |
+
// if (session != null) {
|
| 49 |
+
// session.invalidate();
|
| 50 |
+
// }
|
| 51 |
+
// response.sendRedirect(Routes.USER + "/login");
|
| 52 |
+
// return;
|
| 53 |
+
// }
|
| 54 |
+
// }
|
| 55 |
+
|
| 56 |
+
// filterChain.doFilter(request, response);
|
| 57 |
+
// }
|
| 58 |
+
|
| 59 |
+
// @Override
|
| 60 |
+
// protected boolean shouldNotFilter(HttpServletRequest request) {
|
| 61 |
+
// String uri = request.getRequestURI();
|
| 62 |
+
|
| 63 |
+
// return uri.startsWith("/css/")
|
| 64 |
+
// || uri.startsWith("/js/")
|
| 65 |
+
// || uri.startsWith("/images/");
|
| 66 |
+
// }
|
| 67 |
+
// }
|
src/main/java/com/attendenceSystem/security/ForceChangePasswordInterceptor.java
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// package com.attendenceSystem.security;
|
| 2 |
+
|
| 3 |
+
// import org.springframework.stereotype.Component;
|
| 4 |
+
// import org.springframework.web.servlet.HandlerInterceptor;
|
| 5 |
+
|
| 6 |
+
// import com.attendenceSystem.constant.Routes;
|
| 7 |
+
// import com.attendenceSystem.entity.User;
|
| 8 |
+
// import com.attendenceSystem.repository.UserRepository;
|
| 9 |
+
// import com.attendenceSystem.util.SecurityUtil;
|
| 10 |
+
|
| 11 |
+
// import jakarta.servlet.http.HttpServletRequest;
|
| 12 |
+
// import jakarta.servlet.http.HttpServletResponse;
|
| 13 |
+
// import lombok.RequiredArgsConstructor;
|
| 14 |
+
|
| 15 |
+
// @Component
|
| 16 |
+
// @RequiredArgsConstructor
|
| 17 |
+
// public class ForceChangePasswordInterceptor implements HandlerInterceptor {
|
| 18 |
+
// private final UserRepository userRepository;
|
| 19 |
+
|
| 20 |
+
// @Override
|
| 21 |
+
// public boolean preHandle(
|
| 22 |
+
// HttpServletRequest request,
|
| 23 |
+
// HttpServletResponse response,
|
| 24 |
+
// Object handler)
|
| 25 |
+
// throws Exception {
|
| 26 |
+
// String username = SecurityUtil.getCurrentUserName();
|
| 27 |
+
// if (username == null) {
|
| 28 |
+
// return true;
|
| 29 |
+
// }
|
| 30 |
+
// User user = userRepository.findUserByUsername(username).orElse(null);
|
| 31 |
+
// if (user == null) {
|
| 32 |
+
// return true;
|
| 33 |
+
// }
|
| 34 |
+
// String uri = request.getRequestURI();
|
| 35 |
+
// if (user.isMustChangePassword() && !uri.startsWith(Routes.USER + "/change-password")) {
|
| 36 |
+
// response.sendRedirect(Routes.USER + "/change-password");
|
| 37 |
+
// return false;
|
| 38 |
+
// }
|
| 39 |
+
// return true;
|
| 40 |
+
// }
|
| 41 |
+
// }
|
src/main/java/com/attendenceSystem/security/SecurityConfig.java
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.attendenceSystem.security;
|
| 2 |
+
|
| 3 |
+
import org.springframework.context.annotation.Bean;
|
| 4 |
+
import org.springframework.context.annotation.Configuration;
|
| 5 |
+
import org.springframework.security.authentication.AuthenticationManager;
|
| 6 |
+
import org.springframework.security.authentication.ProviderManager;
|
| 7 |
+
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
| 8 |
+
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
| 9 |
+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
| 10 |
+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
| 11 |
+
import org.springframework.security.core.userdetails.UserDetailsService;
|
| 12 |
+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
| 13 |
+
import org.springframework.security.crypto.password.PasswordEncoder;
|
| 14 |
+
import org.springframework.security.web.SecurityFilterChain;
|
| 15 |
+
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
| 16 |
+
|
| 17 |
+
// import com.attendenceSystem.constant.Routes;
|
| 18 |
+
// import com.attendenceSystem.entity.enums.Role;
|
| 19 |
+
|
| 20 |
+
import lombok.RequiredArgsConstructor;
|
| 21 |
+
|
| 22 |
+
@Configuration
|
| 23 |
+
@EnableWebSecurity
|
| 24 |
+
@RequiredArgsConstructor
|
| 25 |
+
public class SecurityConfig {
|
| 26 |
+
// private final ActiveUserFilter activeUserFilter;
|
| 27 |
+
private final AuthenticationConfiguration authenticationConfiguration;
|
| 28 |
+
|
| 29 |
+
@Bean
|
| 30 |
+
public PasswordEncoder passwordEncoder() {
|
| 31 |
+
return new BCryptPasswordEncoder();
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
@Bean
|
| 35 |
+
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
| 36 |
+
http
|
| 37 |
+
.authorizeHttpRequests(auth -> auth
|
| 38 |
+
.anyRequest().permitAll())
|
| 39 |
+
.csrf(csrf -> csrf.disable());
|
| 40 |
+
return http.build();
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
@Bean
|
| 44 |
+
public AuthenticationManager authenticationManager() throws Exception {
|
| 45 |
+
return authenticationConfiguration.getAuthenticationManager();
|
| 46 |
+
}
|
| 47 |
+
// Chỉ dùng để test admin
|
| 48 |
+
// @Bean
|
| 49 |
+
// public UserDetailsService userDetailsService(
|
| 50 |
+
// PasswordEncoder passwordEncoder) {
|
| 51 |
+
|
| 52 |
+
// UserDetails admin = User.builder()
|
| 53 |
+
// .username("admin")
|
| 54 |
+
// .password(passwordEncoder.encode("123456"))
|
| 55 |
+
// .roles(Role.ADMIN.name())
|
| 56 |
+
// .build();
|
| 57 |
+
|
| 58 |
+
// return new InMemoryUserDetailsManager(admin);
|
| 59 |
+
// }
|
| 60 |
+
}
|
src/main/java/com/attendenceSystem/user/dto/request/LoginRequest.java
DELETED
|
@@ -1,20 +0,0 @@
|
|
| 1 |
-
package com.attendenceSystem.user.dto.request;
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
import jakarta.validation.constraints.Email;
|
| 5 |
-
import jakarta.validation.constraints.NotBlank;
|
| 6 |
-
import jakarta.validation.constraints.Size;
|
| 7 |
-
import lombok.Data;
|
| 8 |
-
|
| 9 |
-
@Data
|
| 10 |
-
public class LoginRequest {
|
| 11 |
-
@NotBlank(message = "Email không được để trống")
|
| 12 |
-
@Size(max = 255, message = "Email không được vượt quá 255 ký tự")
|
| 13 |
-
@Email(message = "Email không đúng định dạng")
|
| 14 |
-
private String email;
|
| 15 |
-
@NotBlank(message = "Mật khẩu không được để trống")
|
| 16 |
-
@Size(min = 8, message = "Mật khẩu phải chứa ít nhất 8 kí tự")
|
| 17 |
-
private String password;
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/main/java/com/attendenceSystem/user/dto/request/RegisterRequest.java
DELETED
|
@@ -1,38 +0,0 @@
|
|
| 1 |
-
package com.attendenceSystem.user.dto.request;
|
| 2 |
-
|
| 3 |
-
import com.attendenceSystem.annotation.PasswordMatch;
|
| 4 |
-
import com.attendenceSystem.user.entity.User;
|
| 5 |
-
import com.fasterxml.jackson.annotation.JsonProperty;
|
| 6 |
-
|
| 7 |
-
import jakarta.validation.constraints.Email;
|
| 8 |
-
import jakarta.validation.constraints.NotBlank;
|
| 9 |
-
import jakarta.validation.constraints.Size;
|
| 10 |
-
import lombok.Data;
|
| 11 |
-
import lombok.NonNull;
|
| 12 |
-
|
| 13 |
-
@Data
|
| 14 |
-
@PasswordMatch
|
| 15 |
-
public class RegisterRequest {
|
| 16 |
-
@NotBlank(message = "Email không được để trống")
|
| 17 |
-
@Size(max = 255, message = "Email không được vượt quá 255 ký tự")
|
| 18 |
-
@Email(message = "Email không đúng định dạng")
|
| 19 |
-
private String email;
|
| 20 |
-
@NotBlank(message = "Mật khẩu không được để trống")
|
| 21 |
-
@Size(min = 8, message = "Mật khẩu phải chứa ít nhất 8 kí tự")
|
| 22 |
-
private String password;
|
| 23 |
-
@NotBlank(message = "Mật khẩu xác nhận không được để trống")
|
| 24 |
-
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
|
| 25 |
-
private String rePassword;
|
| 26 |
-
@NotBlank(message = "Họ tên không được để trống")
|
| 27 |
-
@Size(max = 255, message = "Họ tên không được vượt quá 255 ký tự")
|
| 28 |
-
private String fullName;
|
| 29 |
-
|
| 30 |
-
@NonNull
|
| 31 |
-
public User toEntity(String hashPassword) {
|
| 32 |
-
return User.builder()
|
| 33 |
-
.email(this.email)
|
| 34 |
-
.password(hashPassword)
|
| 35 |
-
.fullName(this.fullName)
|
| 36 |
-
.build();
|
| 37 |
-
}
|
| 38 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/main/java/com/attendenceSystem/user/dto/response/UserResponse.java
DELETED
|
@@ -1,17 +0,0 @@
|
|
| 1 |
-
package com.attendenceSystem.user.dto.response;
|
| 2 |
-
|
| 3 |
-
import lombok.Builder;
|
| 4 |
-
import lombok.Data;
|
| 5 |
-
|
| 6 |
-
@Data
|
| 7 |
-
@Builder
|
| 8 |
-
public class UserResponse {
|
| 9 |
-
private Long id;
|
| 10 |
-
private String email;
|
| 11 |
-
private String fullName;
|
| 12 |
-
private String avatar;
|
| 13 |
-
private String status;
|
| 14 |
-
private String createdAt;
|
| 15 |
-
private String updatedAt;
|
| 16 |
-
private Boolean deleted;
|
| 17 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/main/java/com/attendenceSystem/user/entity/converter/RoleConverter.java
DELETED
|
@@ -1,15 +0,0 @@
|
|
| 1 |
-
// package com.attendenceSystem.user.entity.converter;
|
| 2 |
-
|
| 3 |
-
// @Converter(autoApply = true)
|
| 4 |
-
// public class RoleConverter implements AttributeConverter<Role, Integer> {
|
| 5 |
-
|
| 6 |
-
// @Override
|
| 7 |
-
// public Integer convertToDatabaseColumn(Role role) {
|
| 8 |
-
// return role == null ? null : role.getValue();
|
| 9 |
-
// }
|
| 10 |
-
|
| 11 |
-
// @Override
|
| 12 |
-
// public Role convertToEntityAttribute(Integer dbData) {
|
| 13 |
-
// return dbData == null ? null : Role.fromValue(dbData);
|
| 14 |
-
// }
|
| 15 |
-
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/main/java/com/attendenceSystem/user/mapper/request/LoginRequestMapper.java
DELETED
|
@@ -1,5 +0,0 @@
|
|
| 1 |
-
package com.attendenceSystem.user.mapper.request;
|
| 2 |
-
|
| 3 |
-
public class LoginRequestMapper {
|
| 4 |
-
|
| 5 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/main/java/com/attendenceSystem/user/mapper/request/RegisterRequestMapper.java
DELETED
|
@@ -1,5 +0,0 @@
|
|
| 1 |
-
package com.attendenceSystem.user.mapper.request;
|
| 2 |
-
|
| 3 |
-
public class RegisterRequestMapper {
|
| 4 |
-
|
| 5 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/main/java/com/attendenceSystem/user/repository/UserRepository.java
DELETED
|
@@ -1,11 +0,0 @@
|
|
| 1 |
-
package com.attendenceSystem.user.repository;
|
| 2 |
-
|
| 3 |
-
import org.springframework.data.jpa.repository.JpaRepository;
|
| 4 |
-
import org.springframework.stereotype.Repository;
|
| 5 |
-
|
| 6 |
-
import com.attendenceSystem.user.entity.User;
|
| 7 |
-
|
| 8 |
-
@Repository
|
| 9 |
-
public interface UserRepository extends JpaRepository<User, Long> {
|
| 10 |
-
|
| 11 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/main/java/com/attendenceSystem/user/service/UserService.java
DELETED
|
@@ -1,15 +0,0 @@
|
|
| 1 |
-
package com.attendenceSystem.user.service;
|
| 2 |
-
|
| 3 |
-
import com.attendenceSystem.user.dto.request.LoginRequest;
|
| 4 |
-
import com.attendenceSystem.user.dto.request.RegisterRequest;
|
| 5 |
-
import com.attendenceSystem.user.dto.response.UserResponse;
|
| 6 |
-
|
| 7 |
-
public interface UserService {
|
| 8 |
-
UserResponse login(LoginRequest request);
|
| 9 |
-
|
| 10 |
-
void register(RegisterRequest request);
|
| 11 |
-
|
| 12 |
-
void deleteUser(Long id);
|
| 13 |
-
|
| 14 |
-
UserResponse findAccountById(Long id);
|
| 15 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/main/java/com/attendenceSystem/user/service/impl/UserServiceImpl.java
DELETED
|
@@ -1,65 +0,0 @@
|
|
| 1 |
-
package com.attendenceSystem.user.service.impl;
|
| 2 |
-
|
| 3 |
-
import java.time.Instant;
|
| 4 |
-
import java.time.ZoneId;
|
| 5 |
-
|
| 6 |
-
import com.attendenceSystem.user.dto.request.LoginRequest;
|
| 7 |
-
import com.attendenceSystem.user.dto.request.RegisterRequest;
|
| 8 |
-
import com.attendenceSystem.user.dto.response.UserResponse;
|
| 9 |
-
import com.attendenceSystem.user.entity.User;
|
| 10 |
-
import com.attendenceSystem.user.repository.UserRepository;
|
| 11 |
-
import com.attendenceSystem.user.service.UserService;
|
| 12 |
-
import com.attendenceSystem.util.TimeUtil;
|
| 13 |
-
|
| 14 |
-
import lombok.RequiredArgsConstructor;
|
| 15 |
-
|
| 16 |
-
@RequiredArgsConstructor
|
| 17 |
-
public class UserServiceImpl implements UserService {
|
| 18 |
-
private final UserRepository userRepository;
|
| 19 |
-
private final ZoneId applicationZoneId;
|
| 20 |
-
// private final PasswordEncoder passwordEncoder;
|
| 21 |
-
|
| 22 |
-
@Override
|
| 23 |
-
public UserResponse login(LoginRequest request) {
|
| 24 |
-
// Tìm tài khoản thông qua email từ request, không có báo lỗi.
|
| 25 |
-
|
| 26 |
-
// Kiểm tra mật khẩu từ request có chính xác không. Sai báo lỗi
|
| 27 |
-
|
| 28 |
-
// Trả UserResponse
|
| 29 |
-
return null;
|
| 30 |
-
}
|
| 31 |
-
|
| 32 |
-
// @Transactional
|
| 33 |
-
@Override
|
| 34 |
-
public void register(RegisterRequest request) {
|
| 35 |
-
// Kiểm tra email
|
| 36 |
-
|
| 37 |
-
// encode password
|
| 38 |
-
|
| 39 |
-
// Lưu User
|
| 40 |
-
}
|
| 41 |
-
|
| 42 |
-
@Override
|
| 43 |
-
public void deleteUser(Long id) {
|
| 44 |
-
// TODO Auto-generated method stub
|
| 45 |
-
throw new UnsupportedOperationException("Unimplemented method 'deleteUser'");
|
| 46 |
-
}
|
| 47 |
-
|
| 48 |
-
@Override
|
| 49 |
-
public UserResponse findAccountById(Long id) {
|
| 50 |
-
// Kiểm tra id == null
|
| 51 |
-
|
| 52 |
-
// Tìm kiếm user thông qua id
|
| 53 |
-
|
| 54 |
-
// Trả về UserResponse.
|
| 55 |
-
return null;
|
| 56 |
-
}
|
| 57 |
-
|
| 58 |
-
private String getCurrentTime() {
|
| 59 |
-
|
| 60 |
-
return TimeUtil.formatInstant(
|
| 61 |
-
Instant.now(),
|
| 62 |
-
applicationZoneId);
|
| 63 |
-
}
|
| 64 |
-
|
| 65 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/main/java/com/attendenceSystem/validator/PasswordMatchValidator.java
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
package com.attendenceSystem.validator;
|
| 2 |
|
| 3 |
import com.attendenceSystem.annotation.PasswordMatch;
|
| 4 |
-
import com.attendenceSystem.user.dto.request.RegisterRequest;
|
| 5 |
|
| 6 |
import jakarta.validation.ConstraintValidator;
|
| 7 |
import jakarta.validation.ConstraintValidatorContext;
|
|
@@ -13,13 +13,13 @@ public class PasswordMatchValidator
|
|
| 13 |
public boolean isValid(RegisterRequest request,
|
| 14 |
ConstraintValidatorContext context) {
|
| 15 |
|
| 16 |
-
if (request.
|
| 17 |
-
|| request.
|
| 18 |
return true;
|
| 19 |
}
|
| 20 |
|
| 21 |
-
boolean valid = request.
|
| 22 |
-
.equals(request.
|
| 23 |
|
| 24 |
if (!valid) {
|
| 25 |
context.disableDefaultConstraintViolation();
|
|
|
|
| 1 |
package com.attendenceSystem.validator;
|
| 2 |
|
| 3 |
import com.attendenceSystem.annotation.PasswordMatch;
|
| 4 |
+
import com.attendenceSystem.module.user.dto.request.RegisterRequest;
|
| 5 |
|
| 6 |
import jakarta.validation.ConstraintValidator;
|
| 7 |
import jakarta.validation.ConstraintValidatorContext;
|
|
|
|
| 13 |
public boolean isValid(RegisterRequest request,
|
| 14 |
ConstraintValidatorContext context) {
|
| 15 |
|
| 16 |
+
if (request.password() == null
|
| 17 |
+
|| request.rePassword() == null) {
|
| 18 |
return true;
|
| 19 |
}
|
| 20 |
|
| 21 |
+
boolean valid = request.password()
|
| 22 |
+
.equals(request.rePassword());
|
| 23 |
|
| 24 |
if (!valid) {
|
| 25 |
context.disableDefaultConstraintViolation();
|
src/main/resources/application.properties
CHANGED
|
@@ -23,14 +23,14 @@ spring.devtools.livereload.enabled=true
|
|
| 23 |
server.servlet.jsp.init-parameters.development=true
|
| 24 |
|
| 25 |
# DataSource Configuration for SQL Server
|
| 26 |
-
|
| 27 |
-
# spring.datasource.username=root
|
| 28 |
-
# spring.datasource.password=QQQewqwqa401!
|
| 29 |
-
# spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
|
| 30 |
-
|
| 31 |
-
spring.datasource.url=jdbc:mysql://localhost:3306/game_promo_web
|
| 32 |
spring.datasource.username=root
|
| 33 |
-
spring.datasource.password=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
|
| 36 |
# SMPT EMAIL
|
|
@@ -40,7 +40,18 @@ spring.datasource.password=annguyenthanh2k5
|
|
| 40 |
# spring.mail.password=lzzxdgzmirxdwqdv
|
| 41 |
|
| 42 |
# JPA configuration
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
|
|
|
|
|
|
| 44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
|
| 46 |
-
|
|
|
|
| 23 |
server.servlet.jsp.init-parameters.development=true
|
| 24 |
|
| 25 |
# DataSource Configuration for SQL Server
|
| 26 |
+
spring.datasource.url=jdbc:mariadb://localhost:3306/ATTENDANCE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
spring.datasource.username=root
|
| 28 |
+
spring.datasource.password=QQQewqwqa401!
|
| 29 |
+
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
|
| 30 |
+
|
| 31 |
+
# spring.datasource.url=jdbc:mysql://localhost:3306/game_promo_web
|
| 32 |
+
# spring.datasource.username=root
|
| 33 |
+
# spring.datasource.password=annguyenthanh2k5
|
| 34 |
|
| 35 |
|
| 36 |
# SMPT EMAIL
|
|
|
|
| 40 |
# spring.mail.password=lzzxdgzmirxdwqdv
|
| 41 |
|
| 42 |
# JPA configuration
|
| 43 |
+
spring.jpa.hibernate.ddl-auto=update
|
| 44 |
+
spring.jpa.show-sql=true
|
| 45 |
+
|
| 46 |
+
|
| 47 |
|
| 48 |
+
# spring.mail.properties.mail.smtp.auth=true
|
| 49 |
+
# spring.mail.properties.mail.smtp.starttls.enable=true
|
| 50 |
|
| 51 |
+
# Catch exception
|
| 52 |
+
# server.error.include-message=never
|
| 53 |
+
# server.error.include-binding-errors=never
|
| 54 |
+
# server.error.include-stacktrace=never
|
| 55 |
+
# server.error.include-exception=false
|
| 56 |
|
| 57 |
+
app.timezone=Asia/Ho_Chi_Minh
|
src/main/resources/templates/cms/{auths → auth}/login.html
RENAMED
|
File without changes
|
src/main/resources/templates/cms/{auths → auth}/register.html
RENAMED
|
File without changes
|
src/main/resources/templates/cms/{auths → auth}/verify-otp.html
RENAMED
|
File without changes
|
src/main/resources/templates/cms/{documents → document}/document-create.html
RENAMED
|
File without changes
|
src/main/resources/templates/cms/{documents → document}/document-detail.html
RENAMED
|
File without changes
|