feat: 统一JWT密钥配置并修复签名验证问题

修复前端签名生成中bodyString硬编码问题
添加start-frontend.sh脚本启动前端服务
统一manage-app和gateway的JWT密钥配置
修复Repository扫描路径问题
更新测试配置和依赖
重构表名映射为sys_user和sys_role
完善用户实体类字段映射
添加集成测试配置和测试用例
This commit is contained in:
张翔
2026-04-02 12:28:49 +08:00
parent 6392c08560
commit b0f91d74f5
63 changed files with 3287 additions and 889 deletions
+5
View File
@@ -90,6 +90,11 @@
<artifactId>r2dbc-h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>r2dbc-postgresql</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
@@ -1,7 +1,7 @@
package cn.novalon.manage.sys.audit;
import cn.novalon.manage.sys.audit.domain.AuditLog;
import cn.novalon.manage.sys.audit.repository.AuditLogRepository;
import cn.novalon.manage.sys.audit.repository.IAuditLogRepository;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
@@ -34,10 +34,10 @@ public class AuditLogAspect {
private static final Logger logger = LoggerFactory.getLogger(AuditLogAspect.class);
private final AuditLogRepository auditLogRepository;
private final IAuditLogRepository auditLogRepository;
private final ObjectMapper objectMapper;
public AuditLogAspect(AuditLogRepository auditLogRepository, ObjectMapper objectMapper) {
public AuditLogAspect(IAuditLogRepository auditLogRepository, ObjectMapper objectMapper) {
this.auditLogRepository = auditLogRepository;
this.objectMapper = objectMapper;
}
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
* @date 2026-04-01
*/
@Repository
public interface AuditLogArchiveRepository extends R2dbcRepository<AuditLogArchive, Long> {
public interface IAuditLogArchiveRepository extends R2dbcRepository<AuditLogArchive, Long> {
Flux<AuditLogArchive> findByEntityType(String entityType);
@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
* @date 2026-04-01
*/
@Repository
public interface AuditLogRepository extends R2dbcRepository<AuditLog, Long> {
public interface IAuditLogRepository extends R2dbcRepository<AuditLog, Long> {
Flux<AuditLog> findByEntityType(String entityType);
@@ -2,8 +2,8 @@ package cn.novalon.manage.sys.audit.service;
import cn.novalon.manage.sys.audit.domain.AuditLog;
import cn.novalon.manage.sys.audit.domain.AuditLogArchive;
import cn.novalon.manage.sys.audit.repository.AuditLogArchiveRepository;
import cn.novalon.manage.sys.audit.repository.AuditLogRepository;
import cn.novalon.manage.sys.audit.repository.IAuditLogArchiveRepository;
import cn.novalon.manage.sys.audit.repository.IAuditLogRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@@ -28,11 +28,11 @@ public class AuditLogArchiveService {
private static final Logger logger = LoggerFactory.getLogger(AuditLogArchiveService.class);
private final AuditLogRepository auditLogRepository;
private final AuditLogArchiveRepository auditLogArchiveRepository;
private final IAuditLogRepository auditLogRepository;
private final IAuditLogArchiveRepository auditLogArchiveRepository;
public AuditLogArchiveService(AuditLogRepository auditLogRepository,
AuditLogArchiveRepository auditLogArchiveRepository) {
public AuditLogArchiveService(IAuditLogRepository auditLogRepository,
IAuditLogArchiveRepository auditLogArchiveRepository) {
this.auditLogRepository = auditLogRepository;
this.auditLogArchiveRepository = auditLogArchiveRepository;
}
@@ -1,7 +1,7 @@
package cn.novalon.manage.sys.audit.service;
import cn.novalon.manage.sys.audit.domain.AuditLog;
import cn.novalon.manage.sys.audit.repository.AuditLogRepository;
import cn.novalon.manage.sys.audit.repository.IAuditLogRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
@@ -28,10 +28,10 @@ public class AuditLogService {
private static final Logger logger = LoggerFactory.getLogger(AuditLogService.class);
private final AuditLogRepository auditLogRepository;
private final IAuditLogRepository auditLogRepository;
private final Executor auditLogExecutor;
public AuditLogService(AuditLogRepository auditLogRepository,
public AuditLogService(IAuditLogRepository auditLogRepository,
Executor auditLogExecutor) {
this.auditLogRepository = auditLogRepository;
this.auditLogExecutor = auditLogExecutor;
@@ -0,0 +1,29 @@
package cn.novalon.manage.sys.config;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* 集成测试配置类
*
* 为@DataR2dbcTest提供必要的Spring Boot配置
*
* @author 张翔
* @date 2026-04-02
*/
@SpringBootConfiguration
@EnableAutoConfiguration
@EnableR2dbcRepositories(basePackages = {
"cn.novalon.manage.db.repository"
})
public class IntegrationTestConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
}
@@ -1,6 +1,7 @@
package cn.novalon.manage.sys.core.service.impl;
import cn.novalon.manage.common.util.StatusConstants;
import cn.novalon.manage.sys.config.IntegrationTestConfig;
import cn.novalon.manage.sys.core.domain.SysUser;
import cn.novalon.manage.sys.core.domain.SysRole;
import cn.novalon.manage.sys.core.domain.UserRole;
@@ -11,20 +12,19 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.r2dbc.DataR2dbcTest;
import org.springframework.context.annotation.Import;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.time.LocalDateTime;
import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.*;
@@ -40,6 +40,7 @@ import static org.junit.jupiter.api.Assertions.*;
@DataR2dbcTest
@Testcontainers
@ActiveProfiles("test")
@ContextConfiguration(classes = IntegrationTestConfig.class)
class SysUserServiceIntegrationTest {
@Container
@@ -50,10 +51,9 @@ class SysUserServiceIntegrationTest {
@DynamicPropertySource
static void postgresProperties(DynamicPropertyRegistry registry) {
registry.add("spring.r2dbc.url", () ->
String.format("r2dbc:postgresql://%s:%d/%s",
postgres.getHost(),
postgres.getFirstMappedPort(),
registry.add("spring.r2dbc.url", () -> String.format("r2dbc:postgresql://%s:%d/%s",
postgres.getHost(),
postgres.getFirstMappedPort(),
postgres.getDatabaseName()));
registry.add("spring.r2dbc.username", postgres::getUsername);
registry.add("spring.r2dbc.password", postgres::getPassword);
@@ -78,7 +78,7 @@ class SysUserServiceIntegrationTest {
void setUp() {
passwordEncoder = new BCryptPasswordEncoder(12);
userService = new SysUserService(userRepository, roleRepository, userRoleRepository, passwordEncoder);
r2dbcEntityTemplate.delete(SysUser.class).all().block();
r2dbcEntityTemplate.delete(SysRole.class).all().block();
r2dbcEntityTemplate.delete(UserRole.class).all().block();
@@ -196,7 +196,7 @@ class SysUserServiceIntegrationTest {
SysUser createdUser = userService.createUser(user).block();
assertNotNull(createdUser);
StepVerifier.create(userService.assignRolesToUser(createdUser.getId(),
StepVerifier.create(userService.assignRolesToUser(createdUser.getId(),
Arrays.asList(createdRole1.getId(), createdRole2.getId())))
.verifyComplete();
@@ -2,15 +2,11 @@ package cn.novalon.manage.sys.core.service.impl;
import cn.novalon.manage.common.util.StatusConstants;
import cn.novalon.manage.sys.core.domain.SysUser;
import cn.novalon.manage.sys.core.domain.SysRole;
import cn.novalon.manage.sys.core.domain.UserRole;
import cn.novalon.manage.common.dto.PageRequest;
import cn.novalon.manage.common.dto.PageResponse;
import cn.novalon.manage.sys.core.repository.ISysUserRepository;
import cn.novalon.manage.sys.core.repository.ISysRoleRepository;
import cn.novalon.manage.sys.core.repository.IUserRoleRepository;
import cn.novalon.manage.sys.core.command.CreateUserCommand;
import cn.novalon.manage.sys.core.command.UpdateUserCommand;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -21,7 +17,6 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.time.LocalDateTime;
import java.util.Arrays;
import static org.mockito.ArgumentMatchers.any;
@@ -0,0 +1,11 @@
spring:
r2dbc:
pool:
enabled: true
initial-size: 2
max-size: 10
logging:
level:
cn.novalon.manage: DEBUG
org.springframework.r2dbc: DEBUG