diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index e15d93b..d476aa7 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -8,6 +8,7 @@
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..9c5b81b
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules/vega-hrm-auth/VegaHRM.Backend.vega-hrm-auth.main.iml b/.idea/modules/vega-hrm-auth/VegaHRM.Backend.vega-hrm-auth.main.iml
new file mode 100644
index 0000000..b987421
--- /dev/null
+++ b/.idea/modules/vega-hrm-auth/VegaHRM.Backend.vega-hrm-auth.main.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules/vega-hrm-core/VegaHRM.Backend.vega-hrm-core.main.iml b/.idea/modules/vega-hrm-core/VegaHRM.Backend.vega-hrm-core.main.iml
new file mode 100644
index 0000000..4321feb
--- /dev/null
+++ b/.idea/modules/vega-hrm-core/VegaHRM.Backend.vega-hrm-core.main.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config/shared.properties b/config/shared.properties
index 7f1a820..8d60eb9 100644
--- a/config/shared.properties
+++ b/config/shared.properties
@@ -26,10 +26,13 @@ spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql=TRACE
-#spring.data.redis.sentinel.master=redismaster
-#spring.data.redis.sentinel.nodes=10.22.18.138:26379,10.22.18.139:26379,10.22.18.140:26379
-#spring.data.redis.sentinel.password=dLF5ZnOeOHM6/pzTHezV+WNXU+F7ZBGu85f8bwzk
-#spring.data.redis.sentinel.database=17
-cors.allowed-origins=http://localhost:4201,http://localhost:4202,http://localhost:4200,http://localhost:4203
+
+# redis
+redis.host=103.166.141.147
+redis.port=6379
+redis.password=VegaHrm@2025
+redis.database=0
+
+cors.allowed-origins=*
#vcb-lounge.redis.time-to-live=600
#spring.cache.type=simple
\ No newline at end of file
diff --git a/vega-hrm-auth/build.gradle b/vega-hrm-auth/build.gradle
index 2d9fff3..20d1ffd 100644
--- a/vega-hrm-auth/build.gradle
+++ b/vega-hrm-auth/build.gradle
@@ -1,5 +1,7 @@
plugins {
id 'java'
+ id 'org.springframework.boot' version '3.4.0'
+ id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.vega.hrm'
@@ -10,10 +12,30 @@ repositories {
}
dependencies {
- testImplementation platform('org.junit:junit-bom:5.10.0')
- testImplementation 'org.junit.jupiter:junit-jupiter'
+
+}
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.4.0'
+ implementation 'org.springframework.boot:spring-boot-starter-web:3.4.0'
+ implementation 'org.projectlombok:lombok:1.18.38'
+ implementation('org.springframework.boot:spring-boot-starter:3.4.0') {
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+ }
+ implementation 'org.springframework.boot:spring-boot-starter-log4j2:3.4.0'
+ implementation 'org.springframework.boot:spring-boot-starter-validation:3.4.0'
+ implementation 'de.mkammerer:argon2-jvm:2.1'
+ annotationProcessor 'org.projectlombok:lombok:1.18.38'
+ implementation project(":vega-hrm-core")
+ implementation 'jakarta.annotation:jakarta.annotation-api:2.1.1'
+
}
-test {
- useJUnitPlatform()
-}
\ No newline at end of file
+configurations {
+ all {
+ // Loại bỏ Logback
+ exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
+
+ // Loại bỏ logging mặc định
+ exclude group: 'ch.qos.logback', module: 'logback-classic'
+ }
+}
diff --git a/vega-hrm-auth/src/main/java/com/vega/hrm/AuthHelper.java b/vega-hrm-auth/src/main/java/com/vega/hrm/AuthHelper.java
new file mode 100644
index 0000000..4f92392
--- /dev/null
+++ b/vega-hrm-auth/src/main/java/com/vega/hrm/AuthHelper.java
@@ -0,0 +1,82 @@
+package com.vega.hrm;
+
+import com.vega.hrm.dto.BoFunctionDto;
+import com.vega.hrm.core.entities.BoFunction;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+import java.util.Comparator;
+import java.util.List;
+
+
+public class AuthHelper {
+ private AuthHelper() {
+ throw new IllegalStateException("Utility class");
+ }
+ private static final String UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ private static final String LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
+ private static final String DIGITS = "0123456789";
+ private static final String SPECIAL_CHARS = "!@#$%^&*()-_+=<>?/"; // tùy chọn
+ private static final String ALL_CHARS = UPPERCASE + LOWERCASE + DIGITS + SPECIAL_CHARS;
+
+ private static final SecureRandom random = new SecureRandom();
+
+ public static String hashPassword(String userName, String password) {
+ try {
+ var input = userName + password + "&3%@6v";
+ var digest = MessageDigest.getInstance("SHA-256");
+ var hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
+ var hexString = new StringBuilder();
+ for (var b : hash) {
+ var hex = Integer.toHexString(0xff & b);
+ if (hex.length() == 1) {
+ hexString.append('0');
+ }
+ hexString.append(hex);
+ }
+ return hexString.toString();
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+
+ public static List getChildrenFunction(BoFunction function, List allFunctions) {
+ return allFunctions.stream()
+ .filter(x -> x.getParentId().equals(function.getId()))
+ .sorted(Comparator.comparingLong(BoFunction::getFunctionOrder))
+ .map(x -> new BoFunctionDto(x, getChildrenFunction(x, allFunctions)))
+ .toList();
+ }
+
+
+ public static String generateValidPassword(int length) {
+ if (length < 8 || length > 20) {
+ throw new IllegalArgumentException("Độ dài password phải từ 8 tới 20 ký tự.");
+ }
+
+ StringBuilder password = new StringBuilder(length);
+ password.append(pickRandomChar(UPPERCASE));
+ password.append(pickRandomChar(DIGITS));
+ password.append(pickRandomChar(SPECIAL_CHARS));
+
+ for (int i = 3; i < length; i++) {
+ password.append(pickRandomChar(ALL_CHARS));
+ }
+ return shuffleString(password.toString());
+ }
+
+ private static char pickRandomChar(String charSet) {
+ return charSet.charAt(random.nextInt(charSet.length()));
+ }
+
+ private static String shuffleString(String input) {
+ char[] chars = input.toCharArray();
+ for (int i = chars.length - 1; i > 0; i--) {
+ int index = random.nextInt(i + 1);
+ char temp = chars[index];
+ chars[index] = chars[i];
+ chars[i] = temp;
+ }
+ return new String(chars);
+ }
+}
diff --git a/vega-hrm-auth/src/main/java/com/vega/hrm/Main.java b/vega-hrm-auth/src/main/java/com/vega/hrm/Main.java
deleted file mode 100644
index 361c303..0000000
--- a/vega-hrm-auth/src/main/java/com/vega/hrm/Main.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.vega.hrm;
-
-//TIP To Run code, press or
-// click the icon in the gutter.
-public class Main {
-
- public static void main(String[] args) {
- //TIP Press with your caret at the highlighted text
- // to see how IntelliJ IDEA suggests fixing it.
- System.out.printf("Hello and welcome!");
-
- for (int i = 1; i <= 5; i++) {
- //TIP Press to start debugging your code. We have set one breakpoint
- // for you, but you can always add more by pressing .
- System.out.println("i = " + i);
- }
- }
-}
\ No newline at end of file
diff --git a/vega-hrm-auth/src/main/java/com/vega/hrm/VegaHrmAuthApplication.java b/vega-hrm-auth/src/main/java/com/vega/hrm/VegaHrmAuthApplication.java
new file mode 100644
index 0000000..0dffce7
--- /dev/null
+++ b/vega-hrm-auth/src/main/java/com/vega/hrm/VegaHrmAuthApplication.java
@@ -0,0 +1,15 @@
+package com.vega.hrm;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@SpringBootApplication(scanBasePackages = "com.vega.hrm")
+@EnableTransactionManagement
+public class VegaHrmAuthApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(VegaHrmAuthApplication.class, args);
+ }
+}
\ No newline at end of file
diff --git a/vega-hrm-auth/src/main/java/com/vega/hrm/controller/UserController.java b/vega-hrm-auth/src/main/java/com/vega/hrm/controller/UserController.java
new file mode 100644
index 0000000..b8259d9
--- /dev/null
+++ b/vega-hrm-auth/src/main/java/com/vega/hrm/controller/UserController.java
@@ -0,0 +1,29 @@
+package com.vega.hrm.controller;
+
+import com.vega.hrm.core.models.responses.BaseResponse;
+import com.vega.hrm.request.user.CreateUserRequest;
+import com.vega.hrm.request.user.LoginRequest;
+import com.vega.hrm.service.UserService;
+import lombok.RequiredArgsConstructor;
+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;
+
+@RestController
+@RequestMapping("/auth/user")
+@RequiredArgsConstructor
+public class UserController {
+ private final UserService userService;
+
+ @PostMapping("/login")
+ public ResponseEntity> login(@RequestBody LoginRequest request) {
+ return ResponseEntity.ok(userService.login(request));
+ }
+
+ @PostMapping("/insert")
+ public ResponseEntity> insert(@RequestBody CreateUserRequest request) {
+ return ResponseEntity.ok(userService.insert(request));
+ }
+}
diff --git a/vega-hrm-auth/src/main/java/com/vega/hrm/dto/BoFunctionDto.java b/vega-hrm-auth/src/main/java/com/vega/hrm/dto/BoFunctionDto.java
new file mode 100644
index 0000000..8d7c193
--- /dev/null
+++ b/vega-hrm-auth/src/main/java/com/vega/hrm/dto/BoFunctionDto.java
@@ -0,0 +1,30 @@
+package com.vega.hrm.dto;
+
+import com.vega.hrm.core.entities.BoFunction;
+import java.util.List;
+import java.util.UUID;
+import lombok.Getter;
+
+
+@Getter
+public class BoFunctionDto {
+ private final UUID id;
+ private final String funcName;
+ private final Long funcOrder;
+ private final Long funcDisplay;
+ private final Long funcLevel;
+ private final UUID parentId;
+ private final String funcUrl;
+ private final List children;
+
+ public BoFunctionDto(BoFunction boFunction, List children) {
+ this.id = boFunction.getId();
+ this.funcName = boFunction.getFunctionName();
+ this.funcOrder = boFunction.getFunctionOrder();
+ this.funcDisplay = Long.valueOf(String.valueOf(boFunction.getFunctionDisplay()));
+ this.funcLevel = boFunction.getFunctionLevel();
+ this.parentId = boFunction.getParentId();
+ this.funcUrl = boFunction.getFunctionUrl();
+ this.children = children;
+ }
+}
diff --git a/vega-hrm-auth/src/main/java/com/vega/hrm/request/user/CreateUserRequest.java b/vega-hrm-auth/src/main/java/com/vega/hrm/request/user/CreateUserRequest.java
new file mode 100644
index 0000000..a80c6a9
--- /dev/null
+++ b/vega-hrm-auth/src/main/java/com/vega/hrm/request/user/CreateUserRequest.java
@@ -0,0 +1,14 @@
+package com.vega.hrm.request.user;
+
+import java.util.UUID;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class CreateUserRequest {
+ private String userName;
+ private String password;
+ private String fullName;
+ private String roleId;
+}
\ No newline at end of file
diff --git a/vega-hrm-auth/src/main/java/com/vega/hrm/request/user/LoginRequest.java b/vega-hrm-auth/src/main/java/com/vega/hrm/request/user/LoginRequest.java
new file mode 100644
index 0000000..b3ad0e5
--- /dev/null
+++ b/vega-hrm-auth/src/main/java/com/vega/hrm/request/user/LoginRequest.java
@@ -0,0 +1,9 @@
+package com.vega.hrm.request.user;
+
+import lombok.Getter;
+
+@Getter
+public class LoginRequest {
+ private String userName;
+ private String password;
+}
diff --git a/vega-hrm-auth/src/main/java/com/vega/hrm/response/LoginResponse.java b/vega-hrm-auth/src/main/java/com/vega/hrm/response/LoginResponse.java
new file mode 100644
index 0000000..a6f4f36
--- /dev/null
+++ b/vega-hrm-auth/src/main/java/com/vega/hrm/response/LoginResponse.java
@@ -0,0 +1,17 @@
+package com.vega.hrm.response;
+
+import com.vega.hrm.core.entities.BoUser;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+@Data
+@Builder
+@AllArgsConstructor
+public class LoginResponse {
+ private BoUser user;
+ private String token;
+}
diff --git a/vega-hrm-auth/src/main/java/com/vega/hrm/service/UserService.java b/vega-hrm-auth/src/main/java/com/vega/hrm/service/UserService.java
new file mode 100644
index 0000000..b34d468
--- /dev/null
+++ b/vega-hrm-auth/src/main/java/com/vega/hrm/service/UserService.java
@@ -0,0 +1,86 @@
+package com.vega.hrm.service;
+
+import com.vega.hrm.AuthHelper;
+import com.vega.hrm.core.constants.CommonConst;
+import com.vega.hrm.core.entities.BoUser;
+import com.vega.hrm.core.helpers.JwtHelper;
+import com.vega.hrm.core.models.responses.BaseResponse;
+import com.vega.hrm.core.repositories.CoreUserRepository;
+import com.vega.hrm.core.service.RedisService;
+import com.vega.hrm.request.user.CreateUserRequest;
+import com.vega.hrm.request.user.LoginRequest;
+import com.vega.hrm.response.LoginResponse;
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.UUID;
+import lombok.RequiredArgsConstructor;
+import org.apache.logging.log4j.util.Strings;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@RequiredArgsConstructor
+public class UserService {
+ private final CoreUserRepository userRepository;
+ private final RedisService redisService;
+
+ public BaseResponse