first
This commit is contained in:
parent
19225eca0d
commit
86a4e6fc76
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -24,3 +24,9 @@
|
||||||
hs_err_pid*
|
hs_err_pid*
|
||||||
replay_pid*
|
replay_pid*
|
||||||
|
|
||||||
|
|
||||||
|
# Ignore Gradle project-specific cache directory
|
||||||
|
.gradle
|
||||||
|
|
||||||
|
# Ignore Gradle build output directory
|
||||||
|
build
|
||||||
|
|
|
||||||
54
config/log4j2.properties
Normal file
54
config/log4j2.properties
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
property.log.dir=logs/${spring:spring.application.name}
|
||||||
|
property.log.dir.info=${log.dir}/info
|
||||||
|
property.log.dir.error=${log.dir}/error
|
||||||
|
property.log.pattern=%d{yyyy-MM-dd HH:mm:ss} - [%t] - %p - %m%n
|
||||||
|
|
||||||
|
# Console Logger
|
||||||
|
appender.Console.type=Console
|
||||||
|
appender.Console.name=Console
|
||||||
|
appender.Console.target=SYSTEM_OUT
|
||||||
|
appender.Console.layout.type=PatternLayout
|
||||||
|
appender.Console.layout.pattern=${log.pattern}
|
||||||
|
|
||||||
|
# Info Log File - Rolling by Day
|
||||||
|
appender.InfoFile.type=RollingFile
|
||||||
|
appender.InfoFile.name=InfoFile
|
||||||
|
appender.InfoFile.fileName=${log.dir.info}/app-info.log
|
||||||
|
appender.InfoFile.filePattern=${log.dir.info}/app-info-%d{yyyy-MM-dd}.log.gz
|
||||||
|
appender.InfoFile.layout.type=PatternLayout
|
||||||
|
appender.InfoFile.layout.pattern=${log.pattern}
|
||||||
|
|
||||||
|
appender.InfoFile.filter.0.type=ThresholdFilter
|
||||||
|
appender.InfoFile.filter.0.level=INFO
|
||||||
|
appender.InfoFile.filter.0.onMatch=ACCEPT
|
||||||
|
appender.InfoFile.filter.0.onMismatch=NEUTRAL
|
||||||
|
|
||||||
|
appender.InfoFile.filter.1.type=ThresholdFilter
|
||||||
|
appender.InfoFile.filter.1.level=WARN
|
||||||
|
appender.InfoFile.filter.1.onMatch=ACCEPT
|
||||||
|
appender.InfoFile.filter.1.onMismatch=DENY
|
||||||
|
|
||||||
|
appender.InfoFile.policies.type=Policies
|
||||||
|
appender.InfoFile.policies.timeBased.type=TimeBasedTriggeringPolicy
|
||||||
|
appender.InfoFile.policies.timeBased.interval=1
|
||||||
|
appender.InfoFile.policies.timeBased.modulate=true
|
||||||
|
|
||||||
|
# Error Log File - Rolling by Day
|
||||||
|
appender.ErrorFile.type=RollingFile
|
||||||
|
appender.ErrorFile.name=ErrorFile
|
||||||
|
appender.ErrorFile.fileName=${log.dir.error}/app-error.log
|
||||||
|
appender.ErrorFile.filePattern=${log.dir.error}/app-error-%d{yyyy-MM-dd}.log.gz
|
||||||
|
appender.ErrorFile.layout.type=PatternLayout
|
||||||
|
appender.ErrorFile.layout.pattern=${log.pattern}
|
||||||
|
appender.ErrorFile.filter.threshold.type=ThresholdFilter
|
||||||
|
appender.ErrorFile.filter.threshold.level=ERROR
|
||||||
|
appender.ErrorFile.policies.type=Policies
|
||||||
|
appender.ErrorFile.policies.timeBased.type=TimeBasedTriggeringPolicy
|
||||||
|
appender.ErrorFile.policies.timeBased.interval=1
|
||||||
|
appender.ErrorFile.policies.timeBased.modulate=true
|
||||||
|
|
||||||
|
# Root Logger
|
||||||
|
rootLogger.level=INFO
|
||||||
|
rootLogger.appenderRef.Console.ref=Console
|
||||||
|
rootLogger.appenderRef.InfoFile.ref=InfoFile
|
||||||
|
rootLogger.appenderRef.ErrorFile.ref=ErrorFile
|
||||||
35
config/shared.properties
Normal file
35
config/shared.properties
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
spring.jpa.open-in-view=false
|
||||||
|
|
||||||
|
app.datasource.vega.url=jdbc:postgresql://103.166.141.147:5440/db_vega_hrm
|
||||||
|
app.datasource.vega.username=vega_hrm
|
||||||
|
app.datasource.vega.password=VegaHrm@2025
|
||||||
|
|
||||||
|
app.datasource.vega.hikari.idle-timeout=10000
|
||||||
|
app.datasource.vega.hikari.maximum-pool-size=10
|
||||||
|
app.datasource.vega.hikari.minimum-idle=5
|
||||||
|
app.datasource.vega.hikari.pool-name=VEGA_POOL
|
||||||
|
app.datasource.vega.hibernate.default_schema=vega_hrm
|
||||||
|
# Hibernate PostgreSQL dialect
|
||||||
|
app.datasource.vega.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
|
||||||
|
|
||||||
|
app.datasource.vega.hibernate.format_sql=true
|
||||||
|
app.datasource.vega.hikari.show-sql=true
|
||||||
|
|
||||||
|
app.datasource.vega.hikari.max-lifetime=1800000
|
||||||
|
app.datasource.vega.hikari.connection-timeout=30000
|
||||||
|
app.datasource.vega.hikari.validation-timeout=5000
|
||||||
|
vega.hrm.postgre.enabled=true
|
||||||
|
#app.datasource.core.vcb.url=jdbc:oracle:thin:@//10.22.19.197:1521/DVNHTEST
|
||||||
|
#app.datasource.core.vcb.username=VCB_AIRPORT_LOUNGE
|
||||||
|
#app.datasource.core.vcb.password=TGwE247q0Hh7aZAAw6YDT1IP8f+z+SQINE4Gi8GgE48=
|
||||||
|
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
|
||||||
|
#vcb-lounge.redis.time-to-live=600
|
||||||
|
#spring.cache.type=simple
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
package com.vega.hrm.configs;
|
||||||
|
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
|
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||||
|
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||||
|
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||||
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Slf4j
|
||||||
|
@Order(2)
|
||||||
|
@EnableJpaRepositories(
|
||||||
|
basePackages = "${vega.jpa.repository.basePackage}",
|
||||||
|
entityManagerFactoryRef = "vegaHrmEntityManager",
|
||||||
|
transactionManagerRef = "vegaHrmTransactionManager"
|
||||||
|
)
|
||||||
|
@ConditionalOnProperty(name = "vega.hrm.postgre.enabled", havingValue = "true")
|
||||||
|
@EnableTransactionManagement
|
||||||
|
public class VegaDatabaseConfig {
|
||||||
|
|
||||||
|
@Value("${vega.jpa.entity.basePackage:com.core.entity}")
|
||||||
|
private String entityBasePackage;
|
||||||
|
|
||||||
|
@Value("${app.datasource.vega.hikari.maximum-pool-size:10}")
|
||||||
|
private Integer hikariMaximumPoolSize;
|
||||||
|
|
||||||
|
@Value("${app.datasource.vega.hikari.minimum-idle:5}")
|
||||||
|
private Integer hikariMinimumIdle;
|
||||||
|
|
||||||
|
@Value("${app.datasource.vega.hikari.connection-timeout:30000}")
|
||||||
|
private Long hikariConnectionTimeout;
|
||||||
|
|
||||||
|
@Value("${app.datasource.vega.hikari.idle-timeout:10000}")
|
||||||
|
private Long hikariIdleTimeout;
|
||||||
|
|
||||||
|
@Value("${app.datasource.vega.hikari.max-lifetime:1800000}")
|
||||||
|
private Long hikariMaxLifeTime;
|
||||||
|
|
||||||
|
@Value("${app.datasource.vega.hikari.pool-name:VCB_LOUNGE_POOL}")
|
||||||
|
private String hikariPoolName;
|
||||||
|
|
||||||
|
@Value("${app.datasource.vega.hikari.validation-timeout:5000}")
|
||||||
|
private Long validationTimeout;
|
||||||
|
|
||||||
|
@Value("${app.datasource.vega.hibernate.default_schema:}")
|
||||||
|
private String hibernateDefaultSchema;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConfigurationProperties(prefix = "app.datasource.vega")
|
||||||
|
public DataSourceProperties vegaHrmDataSourceProperties() {
|
||||||
|
return new DataSourceProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(name = "vegaDataSource")
|
||||||
|
public DataSource vegaDataSource() {
|
||||||
|
var dataSourceProperties = vegaHrmDataSourceProperties();
|
||||||
|
return configureHikariDataSource(dataSourceProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataSource configureHikariDataSource(DataSourceProperties properties) {
|
||||||
|
var dataSource = properties
|
||||||
|
.initializeDataSourceBuilder()
|
||||||
|
.type(HikariDataSource.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Hikari settings
|
||||||
|
if (hikariMaximumPoolSize != null) {
|
||||||
|
dataSource.setMaximumPoolSize(hikariMaximumPoolSize);
|
||||||
|
}
|
||||||
|
if (hikariMinimumIdle != null) {
|
||||||
|
dataSource.setMinimumIdle(hikariMinimumIdle);
|
||||||
|
}
|
||||||
|
if (hikariConnectionTimeout != null) {
|
||||||
|
dataSource.setConnectionTimeout(hikariConnectionTimeout);
|
||||||
|
}
|
||||||
|
if (hikariMaxLifeTime != null) {
|
||||||
|
dataSource.setMaxLifetime(hikariMaxLifeTime);
|
||||||
|
}
|
||||||
|
if (hikariIdleTimeout != null) {
|
||||||
|
dataSource.setIdleTimeout(hikariIdleTimeout);
|
||||||
|
}
|
||||||
|
if (hikariPoolName != null) {
|
||||||
|
dataSource.setPoolName(hikariPoolName);
|
||||||
|
}
|
||||||
|
if (validationTimeout != null) {
|
||||||
|
dataSource.setValidationTimeout(validationTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostgreSQL driver
|
||||||
|
dataSource.setDriverClassName("org.postgresql.Driver");
|
||||||
|
|
||||||
|
log.info(
|
||||||
|
"HikariCP Pool Config: MaxPoolSize={}, MinIdle={}, IdleTimeout={}, MaxLifetime={}, ConnectionTimeout={}",
|
||||||
|
hikariMaximumPoolSize, hikariMinimumIdle, hikariIdleTimeout, hikariMaxLifeTime,
|
||||||
|
hikariConnectionTimeout);
|
||||||
|
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public LocalContainerEntityManagerFactoryBean vegaHrmEntityManager(
|
||||||
|
@Qualifier("vegaDataSource") DataSource dataSource) {
|
||||||
|
|
||||||
|
var em = new LocalContainerEntityManagerFactoryBean();
|
||||||
|
em.setDataSource(dataSource);
|
||||||
|
em.setPackagesToScan(entityBasePackage);
|
||||||
|
em.setPersistenceUnitName("db1");
|
||||||
|
|
||||||
|
var vendorAdapter = new HibernateJpaVendorAdapter();
|
||||||
|
em.setJpaVendorAdapter(vendorAdapter);
|
||||||
|
Map<String, Object> jpaProps = new HashMap<>();
|
||||||
|
jpaProps.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
|
||||||
|
jpaProps.put("hibernate.format_sql", true);
|
||||||
|
jpaProps.put("hibernate.show_sql", false);
|
||||||
|
|
||||||
|
if (hibernateDefaultSchema != null && !hibernateDefaultSchema.isBlank()) {
|
||||||
|
jpaProps.put("hibernate.default_schema", hibernateDefaultSchema.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
em.setJpaPropertyMap(jpaProps);
|
||||||
|
|
||||||
|
loggingDatabaseSource(em);
|
||||||
|
return em;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loggingDatabaseSource(LocalContainerEntityManagerFactoryBean em) {
|
||||||
|
log.info("vcbDatabaseSourceConfig entityBasePackage : {}", entityBasePackage);
|
||||||
|
|
||||||
|
try (Connection connection = Objects.requireNonNull(em.getDataSource()).getConnection()) {
|
||||||
|
log.info("Database URL: {}", connection.getMetaData().getURL());
|
||||||
|
log.info("Database Product: {} {}", connection.getMetaData().getDatabaseProductName(),
|
||||||
|
connection.getMetaData().getDatabaseProductVersion());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error retrieving database URL", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PlatformTransactionManager vegaHrmTransactionManager(
|
||||||
|
@Qualifier("vegaDataSource") DataSource dataSource) {
|
||||||
|
|
||||||
|
var transactionManager = new JpaTransactionManager();
|
||||||
|
transactionManager.setEntityManagerFactory(vegaHrmEntityManager(dataSource).getObject());
|
||||||
|
return transactionManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.vega.hrm.constants;
|
||||||
|
|
||||||
|
public class KeySecurityConst {
|
||||||
|
public static String KEY_SECURITY_DATABASE = "lDCfYiZ5rxH1G1ElIth9ppqED6MgaLKZ";
|
||||||
|
public static final String JWT_KEY = "e2)q2Nzc%MQz_i(EeUZMla^sW8LpSNRV";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.vega.hrm.constants;
|
||||||
|
|
||||||
|
public class ResponseCodeConst {
|
||||||
|
public static final String SUCCESS = "00";
|
||||||
|
public static final String INVALID = "01";
|
||||||
|
public static final String NOT_FOUND = "02";
|
||||||
|
public static final String INTERNAL_SYSTEM_ERROR = "99";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.vega.hrm.constants;
|
||||||
|
|
||||||
|
public class ResponseMessageConst {
|
||||||
|
public static final String INTERNAL_SYSTEM_ERROR = "Lỗi hệ thống";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.vega.hrm.constants;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class UserHistoryConstant {
|
||||||
|
public static final String ACTION_TYPE_CREATE = "CREATE";
|
||||||
|
public static final String ACTION_TYPE_SEARCH = "SEARCH";
|
||||||
|
public static final String ACTION_TYPE_VIEW = "VIEW";
|
||||||
|
public static final String ACTION_TYPE_UPDATE = "UPDATE";
|
||||||
|
public static final String ACTION_TYPE_DELETE = "DELETE";
|
||||||
|
public static final String ACTION_TYPE_LOGIN = "LOGIN";
|
||||||
|
public static final String ACTION_TYPE_LOGOUT = "LOGOUT";
|
||||||
|
public static final String ACTION_TYPE_CHANGE_STATUS = "CHANGE_STATUS";
|
||||||
|
public static final String ACTION_TYPE_CHANGE_STATUS_MOBILE = "CHANGE_STATUS_MOBILE";
|
||||||
|
public static final String ACTION_TYPE_APPROVE = "APPROVE";
|
||||||
|
public static final String ACTION_TYPE_EXPORT = "EXPORT";
|
||||||
|
public static final String ACTION_TYPE_DOWNLOAD = "DOWNLOAD";
|
||||||
|
public static final String ACTION_TYPE_RESET_PASSWORD = "RESET_PASSWORD";
|
||||||
|
public static final String ACTION_DESC_TEMPLATE = "IP: %s - %s bởi %s";
|
||||||
|
public static final HashMap<String, String> ACTION_TYPE_NAMES = new HashMap<>() {
|
||||||
|
{
|
||||||
|
put(ACTION_TYPE_CREATE, "Thêm mới");
|
||||||
|
put(ACTION_TYPE_SEARCH, "Truy vấn");
|
||||||
|
put(ACTION_TYPE_VIEW, "Xem chi tiết");
|
||||||
|
put(ACTION_TYPE_UPDATE, "Cập nhật");
|
||||||
|
put(ACTION_TYPE_DELETE, "Xóa");
|
||||||
|
put(ACTION_TYPE_LOGIN, "Đăng nhập");
|
||||||
|
put(ACTION_TYPE_LOGOUT, "Đăng xuất");
|
||||||
|
put(ACTION_TYPE_CHANGE_STATUS, "Đổi trạng thái");
|
||||||
|
put(ACTION_TYPE_CHANGE_STATUS_MOBILE, "Đổi trạng thái SĐT");
|
||||||
|
put(ACTION_TYPE_APPROVE, "Phê duyệt");
|
||||||
|
put(ACTION_TYPE_EXPORT, "Kết xuất");
|
||||||
|
put(ACTION_TYPE_DOWNLOAD, "Tải file");
|
||||||
|
put(ACTION_TYPE_RESET_PASSWORD,"Reset password");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.vega.hrm.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.ColumnDefault;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Entity
|
||||||
|
@Table(name = "bo_function")
|
||||||
|
public class BoFunction {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@ColumnDefault("gen_random_uuid()")
|
||||||
|
@Column(name = "function_id", nullable = false)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@Size(max = 200)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "function_name", nullable = false, length = 200)
|
||||||
|
private String functionName;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "function_level", nullable = false)
|
||||||
|
private Long functionLevel;
|
||||||
|
|
||||||
|
@Size(max = 100)
|
||||||
|
@Column(name = "function_url", length = 100)
|
||||||
|
private String functionUrl;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "function_order", nullable = false)
|
||||||
|
private Long functionOrder;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "parent_id", nullable = false)
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
@Size(max = 20)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "created_by", nullable = false, length = 20)
|
||||||
|
private String createdBy;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@ColumnDefault("now()")
|
||||||
|
@Column(name = "create_time", nullable = false)
|
||||||
|
private Instant createTime;
|
||||||
|
|
||||||
|
@Size(max = 20)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "function_display", nullable = false, length = 20)
|
||||||
|
private String functionDisplay;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.vega.hrm.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.JoinColumn;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.ColumnDefault;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Entity
|
||||||
|
@Table(name = "bo_new_func_auth")
|
||||||
|
public class BoNewFuncAuth {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@ColumnDefault("gen_random_uuid()")
|
||||||
|
@Column(name = "id", nullable = false)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "func_id")
|
||||||
|
private BoFunction func;
|
||||||
|
|
||||||
|
@Size(max = 255)
|
||||||
|
@Column(name = "api_endpoint")
|
||||||
|
private String apiEndpoint;
|
||||||
|
|
||||||
|
}
|
||||||
49
vega-hrm-core/src/main/java/com/vega/hrm/entity/BoRole.java
Normal file
49
vega-hrm-core/src/main/java/com/vega/hrm/entity/BoRole.java
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.vega.hrm.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.ColumnDefault;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Entity
|
||||||
|
@Table(name = "bo_role")
|
||||||
|
public class BoRole {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@ColumnDefault("gen_random_uuid()")
|
||||||
|
@Column(name = "role_id", nullable = false)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@Size(max = 200)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "role_name", nullable = false, length = 200)
|
||||||
|
private String roleName;
|
||||||
|
|
||||||
|
@Size(max = 100)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "created_by", nullable = false, length = 100)
|
||||||
|
private String createdBy;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "create_time", nullable = false)
|
||||||
|
private Instant createTime;
|
||||||
|
|
||||||
|
@Size(max = 1000)
|
||||||
|
@Column(name = "description", length = 1000)
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Size(max = 1)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "status", nullable = false, length = 1)
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.vega.hrm.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.JoinColumn;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.ColumnDefault;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Entity
|
||||||
|
@Table(name = "bo_role_func")
|
||||||
|
public class BoRoleFunc {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@ColumnDefault("gen_random_uuid()")
|
||||||
|
@Column(name = "id", nullable = false)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||||
|
@JoinColumn(name = "function_id", nullable = false)
|
||||||
|
private BoFunction function;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||||
|
@JoinColumn(name = "role_id", nullable = false)
|
||||||
|
private BoRole role;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "create_time", nullable = false)
|
||||||
|
private Instant createTime;
|
||||||
|
|
||||||
|
@Size(max = 30)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "create_user", nullable = false, length = 30)
|
||||||
|
private String createUser;
|
||||||
|
|
||||||
|
}
|
||||||
89
vega-hrm-core/src/main/java/com/vega/hrm/entity/BoUser.java
Normal file
89
vega-hrm-core/src/main/java/com/vega/hrm/entity/BoUser.java
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
package com.vega.hrm.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.ColumnDefault;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Entity
|
||||||
|
@Table(name = "bo_user")
|
||||||
|
public class BoUser {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@ColumnDefault("gen_random_uuid()")
|
||||||
|
@Column(name = "user_id", nullable = false)
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@Size(max = 200)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "user_name", nullable = false, length = 200)
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
@Size(max = 200)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "full_name", nullable = false, length = 200)
|
||||||
|
private String fullName;
|
||||||
|
|
||||||
|
@Size(max = 50)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "status", nullable = false, length = 50)
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Size(max = 200)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "password", nullable = false, length = 200)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Column(name = "pwd_expire_date")
|
||||||
|
private Instant pwdExpireDate;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "created_date", nullable = false)
|
||||||
|
private Instant createdDate;
|
||||||
|
|
||||||
|
@Size(max = 200)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "created_user", nullable = false, length = 200)
|
||||||
|
private String createdUser;
|
||||||
|
|
||||||
|
@Column(name = "role_id")
|
||||||
|
private Long roleId;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@ColumnDefault("0")
|
||||||
|
@Column(name = "is_password_changed", nullable = false)
|
||||||
|
private Long isPasswordChanged;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@ColumnDefault("0")
|
||||||
|
@Column(name = "number_of_failed_logins", nullable = false)
|
||||||
|
private Long numberOfFailedLogins;
|
||||||
|
|
||||||
|
@Column(name = "last_login_time")
|
||||||
|
private Instant lastLoginTime;
|
||||||
|
|
||||||
|
@Column(name = "updated_date")
|
||||||
|
private Instant updatedDate;
|
||||||
|
|
||||||
|
@Size(max = 20)
|
||||||
|
@Column(name = "updated_user", length = 20)
|
||||||
|
private String updatedUser;
|
||||||
|
|
||||||
|
@Size(max = 100)
|
||||||
|
@Column(name = "uuid", length = 100)
|
||||||
|
private String uuid;
|
||||||
|
|
||||||
|
@Size(max = 255)
|
||||||
|
@Column(name = "email")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.vega.hrm.exceptions;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import com.vega.hrm.constants.ResponseCodeConst;
|
||||||
|
import com.vega.hrm.constants.ResponseMessageConst;
|
||||||
|
import com.vega.hrm.models.responses.BaseResponse;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
|
||||||
|
@ControllerAdvice
|
||||||
|
@Slf4j
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
|
public ResponseEntity<?> handleValidationExceptions(MethodArgumentNotValidException ex) {
|
||||||
|
var messageValid = new StringBuilder();
|
||||||
|
|
||||||
|
Map<String, String> errors = new HashMap<>();
|
||||||
|
ex.getBindingResult()
|
||||||
|
.getFieldErrors()
|
||||||
|
.forEach(
|
||||||
|
error -> {
|
||||||
|
messageValid.append(error.getField()).append(":").append(error.getDefaultMessage()).append(";");
|
||||||
|
errors.put(error.getField(), error.getDefaultMessage());
|
||||||
|
});
|
||||||
|
|
||||||
|
return ResponseEntity.ok(
|
||||||
|
BaseResponse.<Map<String, String>>builder()
|
||||||
|
.code(ResponseCodeConst.INVALID)
|
||||||
|
.message(messageValid.substring(0, messageValid.length() - 1))
|
||||||
|
.data(errors)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler({Exception.class})
|
||||||
|
public ResponseEntity<?> handleExceptions(Exception ex) {
|
||||||
|
log.error(ex.getMessage(), ex);
|
||||||
|
|
||||||
|
return new ResponseEntity<>(
|
||||||
|
BaseResponse.<Map<String, String>>builder()
|
||||||
|
.code(ResponseCodeConst.INTERNAL_SYSTEM_ERROR)
|
||||||
|
.message(ResponseMessageConst.INTERNAL_SYSTEM_ERROR)
|
||||||
|
.build(),
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.vega.hrm.filters;
|
||||||
|
|
||||||
|
|
||||||
|
import io.jsonwebtoken.ExpiredJwtException;
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.logging.log4j.ThreadContext;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Order(2)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AuthorizationFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||||
|
FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.vega.hrm.filters;
|
||||||
|
|
||||||
|
|
||||||
|
import com.vega.hrm.helpers.LogHelper;
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.logging.log4j.ThreadContext;
|
||||||
|
import org.apache.logging.log4j.util.Strings;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
@Order(1)
|
||||||
|
public class CorsFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
@Value("${cors.allowed-origins:*}")
|
||||||
|
private String[] allowedOrigins;
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(
|
||||||
|
@NonNull HttpServletRequest request,
|
||||||
|
@NonNull HttpServletResponse response,
|
||||||
|
@NonNull FilterChain filterChain
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
var startTime = Instant.now();
|
||||||
|
var origin = request.getHeader("Origin");
|
||||||
|
if (Strings.isNotBlank(origin) && Arrays.stream(allowedOrigins).toList()
|
||||||
|
.contains(origin)) {
|
||||||
|
response.setHeader("Access-Control-Allow-Origin", origin);
|
||||||
|
}
|
||||||
|
response.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
|
||||||
|
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
||||||
|
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, b");
|
||||||
|
response.setHeader("Access-Control-Allow-Credentials", "true");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
if (request.getMethod().equalsIgnoreCase("OPTIONS")) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_OK);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var clientIp = request.getHeader("X-Forwarded-For");
|
||||||
|
if (Strings.isBlank(clientIp)) {
|
||||||
|
clientIp = request.getRemoteAddr();
|
||||||
|
} else {
|
||||||
|
clientIp = clientIp.split(",")[0];
|
||||||
|
}
|
||||||
|
ThreadContext.put("ip", clientIp);
|
||||||
|
ThreadContext.put("uri", request.getRequestURI());
|
||||||
|
var traceId = UUID.randomUUID().toString();
|
||||||
|
ThreadContext.put("traceId", traceId);
|
||||||
|
LogHelper.info("Request start");
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
var duration = Instant.now().toEpochMilli() - startTime.toEpochMilli();
|
||||||
|
LogHelper.info("Request end - Duration: " + duration + "ms");
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
package com.vega.hrm.helpers;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.modelmapper.ModelMapper;
|
||||||
|
import org.springframework.web.context.request.RequestAttributes;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
public class CommonHelper {
|
||||||
|
|
||||||
|
private static ModelMapper modelMapper = new ModelMapper();
|
||||||
|
public static <S, T> List<T> mapList(List<S> source, Class<T> targetClass) {
|
||||||
|
return source
|
||||||
|
.stream()
|
||||||
|
.map(element -> modelMapper.map(element, targetClass))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Long convertStringToLong(String str) {
|
||||||
|
if (str == null || str.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Long.parseLong(str.trim());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getClientIp(HttpServletRequest request) {
|
||||||
|
if (request == null) {
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
String ip = request.getHeader("X-Forwarded-For"); // Header used by proxies/load balancers
|
||||||
|
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("Proxy-Client-IP");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getRemoteAddr(); // Direct IP
|
||||||
|
}
|
||||||
|
if (ip != null && ip.contains(",")) {
|
||||||
|
ip = ip.split(",")[0].trim();
|
||||||
|
}
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getClientIp() {
|
||||||
|
HttpServletRequest request = getCurrentHttpRequest();
|
||||||
|
if (request == null) {
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
return getClientIp(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpServletRequest getCurrentHttpRequest() {
|
||||||
|
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||||
|
if (requestAttributes == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ((ServletRequestAttributes) requestAttributes).getRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> String convertObjectToCommaSeparated(T object){
|
||||||
|
if (object == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object instanceof List<?> list) {
|
||||||
|
return list.stream()
|
||||||
|
.map(CommonHelper::convertObjectToCommaSeparated)
|
||||||
|
.collect(Collectors.joining("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
Field[] fields = object.getClass().getDeclaredFields();
|
||||||
|
for (Field field : fields) {
|
||||||
|
field.setAccessible(true); // Cho phép truy cập vào các trường private
|
||||||
|
try {
|
||||||
|
Object value = field.get(object);
|
||||||
|
result.append(value).append(",");
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
LogHelper.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!result.isEmpty()) {
|
||||||
|
result.deleteCharAt(result.length() - 1);
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String convertObjectToString(Object object) {
|
||||||
|
try{
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
return mapper.writeValueAsString(object);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
LogHelper.error(e.getMessage());
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.vega.hrm.helpers;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class CryptoHelper {
|
||||||
|
|
||||||
|
public static String hashSHA256(String input) {
|
||||||
|
try {
|
||||||
|
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||||
|
byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return bytesToHex(hash);
|
||||||
|
} catch (NoSuchAlgorithmException ex) {
|
||||||
|
|
||||||
|
log.error(ex.getMessage());
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String bytesToHex(byte[] hash) {
|
||||||
|
StringBuilder hexString = new StringBuilder(2 * hash.length);
|
||||||
|
for (int i = 0; i < hash.length; i++) {
|
||||||
|
String hex = Integer.toHexString(0xff & hash[i]);
|
||||||
|
if (hex.length() == 1) {
|
||||||
|
hexString.append('0');
|
||||||
|
}
|
||||||
|
hexString.append(hex);
|
||||||
|
}
|
||||||
|
return hexString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
111
vega-hrm-core/src/main/java/com/vega/hrm/helpers/DateHelper.java
Normal file
111
vega-hrm-core/src/main/java/com/vega/hrm/helpers/DateHelper.java
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
package com.vega.hrm.helpers;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Date;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class DateHelper {
|
||||||
|
|
||||||
|
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy");
|
||||||
|
|
||||||
|
public static Date convertStringToDate(String dateString) {
|
||||||
|
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
|
||||||
|
formatter.setLenient(false);
|
||||||
|
try {
|
||||||
|
return formatter.parse(dateString);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
log.error("convertStringToDate Lỗi format dd/MM/yyyy");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Instant convertStringToInstant(String dateString, String pattern) {
|
||||||
|
try {
|
||||||
|
if (dateString == null || dateString.isEmpty()) {
|
||||||
|
pattern = "dd/MM/yyyy";
|
||||||
|
}
|
||||||
|
if (dateString == null || dateString.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||||
|
LocalDateTime localDateTime;
|
||||||
|
if (pattern.equals("dd/MM/yyyy")) {
|
||||||
|
LocalDate localDate = LocalDate.parse(dateString, formatter);
|
||||||
|
LocalTime now = LocalTime.now();
|
||||||
|
|
||||||
|
localDateTime = LocalDateTime.of(localDate, now);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
localDateTime = LocalDateTime.parse(dateString, formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return localDateTime.toInstant(ZoneOffset.UTC);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String convertDateToString(Date date, String format) {
|
||||||
|
if (date == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
SimpleDateFormat formatter = new SimpleDateFormat(format);
|
||||||
|
return formatter.format(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String convertLocalDateToString(LocalDateTime date, String format) {
|
||||||
|
if (date == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
|
||||||
|
return date.format(formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date getStartOfDay(String dateStr) {
|
||||||
|
LocalDate localDate = LocalDate.parse(dateStr, FORMATTER);
|
||||||
|
LocalDateTime startOfDay = localDate.atStartOfDay().plusSeconds(1); // 00:00:01
|
||||||
|
return Date.from(startOfDay.atZone(ZoneId.of("UTC")).toInstant());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date convertDateZone(String dateStr,String pattern) {
|
||||||
|
DateTimeFormatter format = DateTimeFormatter.ofPattern(pattern);
|
||||||
|
LocalDate localDate = LocalDate.parse(dateStr, format);
|
||||||
|
LocalDateTime startOfDay = localDate.atStartOfDay().plusSeconds(1); // 00:00:01
|
||||||
|
return Date.from(startOfDay.atZone(ZoneId.of("UTC")).toInstant());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalDateTime getStartOfDayLocalDate(String dateStr) {
|
||||||
|
LocalDate localDate = LocalDate.parse(dateStr, FORMATTER);
|
||||||
|
LocalDateTime startOfDay = localDate.atStartOfDay().plusSeconds(1); // 00:00:01
|
||||||
|
return startOfDay.atZone(ZoneId.of("UTC")).toLocalDateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalDateTime convertDateZoneLocalDate(String dateStr,String pattern) {
|
||||||
|
DateTimeFormatter format = DateTimeFormatter.ofPattern(pattern);
|
||||||
|
LocalDate localDate = LocalDate.parse(dateStr, format);
|
||||||
|
LocalDateTime startOfDay = localDate.atStartOfDay().plusSeconds(1); // 00:00:01
|
||||||
|
return LocalDateTime.from(startOfDay.atZone(ZoneId.of("UTC")).toInstant());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalDateTime getEndOfDayLocalDate(String dateStr) {
|
||||||
|
LocalDate localDate = LocalDate.parse(dateStr, FORMATTER);
|
||||||
|
LocalDateTime endOfDay = localDate.atTime(23, 59, 59); // 00:00:01
|
||||||
|
return endOfDay.atZone(ZoneId.of("UTC")).toLocalDateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Date getEndOfDay(String dateStr) {
|
||||||
|
LocalDate localDate = LocalDate.parse(dateStr, FORMATTER);
|
||||||
|
LocalDateTime endOfDay = localDate.atTime(23, 59, 59); // 23:59:59
|
||||||
|
return Date.from(endOfDay.atZone(ZoneId.of("UTC")).toInstant());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.vega.hrm.helpers;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
public class JsonConvertHelper {
|
||||||
|
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
public static String toJsonString(Object object) {
|
||||||
|
try {
|
||||||
|
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||||
|
javaTimeModule.addSerializer(LocalDateTime.class,
|
||||||
|
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss")));
|
||||||
|
objectMapper.registerModule(javaTimeModule);
|
||||||
|
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||||
|
objectMapper.findAndRegisterModules();
|
||||||
|
return objectMapper.writeValueAsString(object);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static <T> T convertStringToObject(String text,Class<T> clazz) {
|
||||||
|
try {
|
||||||
|
return objectMapper.readValue(text,clazz);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
package com.vega.hrm.helpers;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.ExpiredJwtException;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.MalformedJwtException;
|
||||||
|
import io.jsonwebtoken.UnsupportedJwtException;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.Key;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class JwtHelper {
|
||||||
|
|
||||||
|
private static final String SECRET_KEY = "b05f17acb2d09f123a472406051512ca08b";
|
||||||
|
private static final long EXPIRATION_TIME_MS = 600_000; // 10 phut
|
||||||
|
private static final Key SIGNING_KEY = generateSigningKey();
|
||||||
|
|
||||||
|
public static String generateToken(String username, Long userId, Long roleId) {
|
||||||
|
return Jwts.builder()
|
||||||
|
.claims(Map.of(
|
||||||
|
"userId", userId,
|
||||||
|
"roleId", roleId,
|
||||||
|
"userName", username
|
||||||
|
))
|
||||||
|
.subject(username)
|
||||||
|
.issuedAt(new Date())
|
||||||
|
.expiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME_MS))
|
||||||
|
.signWith(SIGNING_KEY)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Key generateSigningKey() {
|
||||||
|
return Keys.hmacShaKeyFor(SECRET_KEY.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Long getUserId(String token) {
|
||||||
|
Claims claims = extractUsername(token);
|
||||||
|
return Long.parseLong(claims.get("userId").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Long getRoleId(String token) {
|
||||||
|
Claims claims = extractUsername(token);
|
||||||
|
return Long.parseLong(claims.get("roleId").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDataByKey(String token, String key) {
|
||||||
|
Claims claims = extractUsername(token);
|
||||||
|
return claims.get(key).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Claims extractUsername(String token) {
|
||||||
|
return Jwts.parser()
|
||||||
|
.verifyWith(new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "HmacSHA256"))
|
||||||
|
.build()
|
||||||
|
.parseSignedClaims(token)
|
||||||
|
.getPayload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean validateToken(String authToken) {
|
||||||
|
try {
|
||||||
|
extractUsername(authToken);
|
||||||
|
return true;
|
||||||
|
} catch (MalformedJwtException ex) {
|
||||||
|
log.error("Invalid JWT token");
|
||||||
|
} catch (ExpiredJwtException ex) {
|
||||||
|
log.error("Expired JWT token");
|
||||||
|
} catch (UnsupportedJwtException ex) {
|
||||||
|
log.error("Unsupported JWT token");
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
log.error("JWT claims string is empty.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.vega.hrm.helpers;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.logging.log4j.ThreadContext;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class LogHelper {
|
||||||
|
|
||||||
|
public static void info(String message) {
|
||||||
|
log.info("{}", getLogContent(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void error(String message) {
|
||||||
|
log.error("{}", getLogContent(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void error(Exception e) {
|
||||||
|
var traceBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
for (var stackTraceElement : e.getStackTrace()) {
|
||||||
|
traceBuilder.append(String.format(
|
||||||
|
"\n at %s.%s (%s:%s)",
|
||||||
|
stackTraceElement.getClassName(),
|
||||||
|
stackTraceElement.getMethodName(),
|
||||||
|
stackTraceElement.getFileName(),
|
||||||
|
stackTraceElement.getLineNumber()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
log.error("{}", getLogContent(String.format("%s: %s%s", e.getClass().getName(), e.getMessage(), traceBuilder)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getLogContent(String message) {
|
||||||
|
return String.format(
|
||||||
|
"[ip - %s] [path - %s] [req - %s] [user - %s] - %s",
|
||||||
|
ThreadContext.get("ip"),
|
||||||
|
ThreadContext.get("uri"),
|
||||||
|
ThreadContext.get("traceId"),
|
||||||
|
ThreadContext.get("userName"),
|
||||||
|
message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.vega.hrm.helpers;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import org.apache.logging.log4j.ThreadContext;
|
||||||
|
|
||||||
|
public class LogHisTemplateHelper {
|
||||||
|
|
||||||
|
public static <T> String logContent(String actionType, String feature, T dataOld, T dataNew) {
|
||||||
|
return String.format(
|
||||||
|
"[ip - %s] [Thao tác - %s - %s] [user - %s] - %s<br/>---------->>><br/>%s",
|
||||||
|
ThreadContext.get("ip"),
|
||||||
|
feature,
|
||||||
|
actionUserDir.get(actionType),
|
||||||
|
ThreadContext.get("userName"), CommonHelper.convertObjectToCommaSeparated(dataOld),
|
||||||
|
CommonHelper.convertObjectToCommaSeparated(dataNew)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HashMap<String, String> actionUserDir =
|
||||||
|
new HashMap<>() {
|
||||||
|
{
|
||||||
|
put("0", "Query");
|
||||||
|
put("1", "AddNew");
|
||||||
|
put("2", "Update");
|
||||||
|
put("3", "Delete");
|
||||||
|
put("4", "ChangeStatus");
|
||||||
|
put("5", "Others");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.vega.hrm.helpers;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
public class StringHelper {
|
||||||
|
|
||||||
|
public static String PW_CHARS = "abcdefghjkmnpqrstuvwxyz";
|
||||||
|
public static String PW_NUMBERS = "123456789";
|
||||||
|
public static String PW_SPECIAL_CHARS = "!#$%&()*+,-./:;<=>?@[]^_{}~";
|
||||||
|
|
||||||
|
private static final SecureRandom RANDOM = new SecureRandom();
|
||||||
|
|
||||||
|
public static String randomStr(String str, int length) {
|
||||||
|
if (str == null || str.isBlank()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
length = Math.min(length, str.length());
|
||||||
|
StringBuilder stringBuilder = new StringBuilder(length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
int index = RANDOM.nextInt(str.length());
|
||||||
|
|
||||||
|
stringBuilder.append(str.charAt(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.vega.hrm.models;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import vn.vnpay.dvnh.backoffice.core.common.utility.DateTimeUtils;
|
||||||
|
@Getter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class RedisEccKeyPair {
|
||||||
|
private String privateKey;
|
||||||
|
private String expiration;
|
||||||
|
|
||||||
|
public RedisEccKeyPair(String privateKey, Instant expiration) {
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
this.expiration = DateTimeUtils.format(expiration);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.vega.hrm.models.requests;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class BaseDecryptedRequest {
|
||||||
|
|
||||||
|
private String request;
|
||||||
|
private String key;
|
||||||
|
private String p;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.vega.hrm.models.requests;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class BaseRequest {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.vega.hrm.models.requests;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ChangeStatusRequest<T> extends BaseRequest {
|
||||||
|
private T id;
|
||||||
|
private String status;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.vega.hrm.models.requests;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class CreateUserHistoryRequest {
|
||||||
|
private String funcName;
|
||||||
|
private String actionType;
|
||||||
|
private String action;
|
||||||
|
private String oldValue;
|
||||||
|
private String newValue;
|
||||||
|
private String editTable;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.vega.hrm.models.requests;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class GetByIdRequest<T> extends BaseRequest {
|
||||||
|
private T id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.vega.hrm.models.requests;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
|
import jakarta.validation.constraints.Positive;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class PagingRequest<T> {
|
||||||
|
@Min(1)
|
||||||
|
private int pageIndex;
|
||||||
|
|
||||||
|
@Positive
|
||||||
|
private int pageSize;
|
||||||
|
|
||||||
|
private T filter;
|
||||||
|
|
||||||
|
public Pageable toPageable(){
|
||||||
|
return PageRequest.of(this.pageIndex - 1, this.pageSize, Sort.unsorted());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pageable toPageable(Sort sort){
|
||||||
|
return PageRequest.of(this.pageIndex - 1, this.pageSize, sort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.vega.hrm.models.responses;
|
||||||
|
|
||||||
|
public record BaseEncryptedResponse(String key, String response) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.vega.hrm.models.responses;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import com.vega.hrm.constants.ResponseCodeConst;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import org.apache.logging.log4j.ThreadContext;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class BaseResponse<T> {
|
||||||
|
@Builder.Default
|
||||||
|
private String traceId = ThreadContext.get("traceId");
|
||||||
|
|
||||||
|
@Builder.Default
|
||||||
|
private String code = ResponseCodeConst.SUCCESS;
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
private T data;
|
||||||
|
|
||||||
|
public static <T> BaseResponse<T> Success(String msg) {
|
||||||
|
return BaseResponse.<T>builder()
|
||||||
|
.code(ResponseCodeConst.SUCCESS)
|
||||||
|
.message(msg)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> BaseResponse<T> Invalid(String msg) {
|
||||||
|
return BaseResponse.<T>builder()
|
||||||
|
.code(ResponseCodeConst.INVALID)
|
||||||
|
.message(msg)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> BaseResponse<T> NotFound(String msg) {
|
||||||
|
return BaseResponse.<T>builder()
|
||||||
|
.code(ResponseCodeConst.NOT_FOUND)
|
||||||
|
.message(msg)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> BaseResponse<T> InternalSystemError() {
|
||||||
|
return BaseResponse.<T>builder()
|
||||||
|
.code(ResponseCodeConst.INTERNAL_SYSTEM_ERROR)
|
||||||
|
.message("Internal System Error")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.vega.hrm.models.responses;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class PagedList<T> {
|
||||||
|
private int pageCount;
|
||||||
|
private long totalItemCount;
|
||||||
|
private List<T> items;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.vega.hrm.models.responses;
|
||||||
|
|
||||||
|
|
||||||
|
import com.vega.hrm.constants.ResponseCodeConst;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import org.apache.logging.log4j.ThreadContext;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class PagedListResponse<T> {
|
||||||
|
|
||||||
|
@Builder.Default
|
||||||
|
private String traceId = ThreadContext.get("traceId");
|
||||||
|
|
||||||
|
@Builder.Default
|
||||||
|
private String code = ResponseCodeConst.SUCCESS;
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
private PagedList<T> data;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.vega.hrm.wrapper;
|
||||||
|
|
||||||
|
import jakarta.servlet.ReadListener;
|
||||||
|
import jakarta.servlet.ServletInputStream;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class CustomRequestWrapper extends HttpServletRequestWrapper {
|
||||||
|
|
||||||
|
private final byte[] body;
|
||||||
|
|
||||||
|
public CustomRequestWrapper(HttpServletRequest request, String bodyString) {
|
||||||
|
super(request);
|
||||||
|
this.body = bodyString.getBytes(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServletInputStream getInputStream() {
|
||||||
|
return new ServletInputStream() {
|
||||||
|
private final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() {
|
||||||
|
return byteArrayInputStream.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFinished() {
|
||||||
|
return byteArrayInputStream.available() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReadListener(ReadListener readListener) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferedReader getReader() {
|
||||||
|
return new BufferedReader(new InputStreamReader(getInputStream(), StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.vega.hrm.wrapper;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletOutputStream;
|
||||||
|
import jakarta.servlet.WriteListener;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpServletResponseWrapper;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class CustomResponseWrapper extends HttpServletResponseWrapper {
|
||||||
|
|
||||||
|
private final ByteArrayOutputStream byteArrayOutputStream;
|
||||||
|
private final PrintWriter printWriter;
|
||||||
|
|
||||||
|
public CustomResponseWrapper(HttpServletResponse response) {
|
||||||
|
super(response);
|
||||||
|
this.byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
this.printWriter = new PrintWriter(byteArrayOutputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServletOutputStream getOutputStream() {
|
||||||
|
return new ServletOutputStream() {
|
||||||
|
@Override
|
||||||
|
public void write(int b) {
|
||||||
|
byteArrayOutputStream.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setWriteListener(WriteListener writeListener) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrintWriter getWriter() {
|
||||||
|
return printWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return byteArrayOutputStream.toString(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user