test: 删除根目录下的非核心E2E测试文件(任务 2/8)

This commit is contained in:
张翔
2026-04-07 21:45:28 +08:00
parent a01ed2553e
commit 0c8c993995
63 changed files with 1005 additions and 7331 deletions
@@ -1,42 +0,0 @@
package cn.novalon.manage.app.config;
import io.r2dbc.spi.ConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer;
import org.springframework.r2dbc.connection.init.ResourceDatabasePopulator;
/**
* R2DBC数据库初始化配置
*
* 用于测试环境的H2数据库初始化
*
* @author 张翔
* @date 2026-04-03
*/
@Configuration
@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "test")
public class R2dbcInitConfig {
private static final Logger logger = LoggerFactory.getLogger(R2dbcInitConfig.class);
@Bean
public ConnectionFactoryInitializer connectionFactoryInitializer(ConnectionFactory connectionFactory) {
logger.info("Initializing R2DBC database with H2 schema and data");
ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
initializer.setConnectionFactory(connectionFactory);
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.addScript(new ClassPathResource("schema-h2.sql"));
populator.addScript(new ClassPathResource("data-h2.sql"));
initializer.setDatabasePopulator(populator);
return initializer;
}
}
@@ -1,54 +0,0 @@
# H2数据库配置(用于测试环境)
spring:
r2dbc:
url: r2dbc:h2:mem:///testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: sa
password:
pool:
initial-size: 5
max-size: 20
max-idle-time: 30m
max-life-time: 1h
acquire-timeout: 5s
datasource:
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: sa
password:
driver-class-name: org.h2.Driver
h2:
console:
enabled: true
path: /h2-console
settings:
web-allow-others: true
flyway:
enabled: false
sql:
init:
mode: always
continue-on-error: false
schema-locations: classpath:schema-h2.sql
data-locations: classpath:data-h2.sql
# 测试专用配置
test:
database:
type: h2
in-memory: true
cleanup:
enabled: true
strategy: truncate
# 日志配置
logging:
level:
cn.novalon.manage: DEBUG
org.springframework.r2dbc: DEBUG
org.springframework.jdbc: DEBUG
org.flywaydb: INFO
com.h2database: WARN
@@ -5,28 +5,23 @@ spring:
application:
name: manage-app
r2dbc:
url: r2dbc:h2:mem:///testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: sa
password:
url: r2dbc:postgresql://localhost:55432/manage_system
username: novalon
password: novalon123
pool:
initial-size: 5
max-size: 20
max-idle-time: 30m
max-life-time: 1h
acquire-timeout: 5s
datasource:
url: jdbc:h2:mem:///testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: sa
password:
driver-class-name: org.h2.Driver
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: true
h2:
console:
enabled: true
path: /h2-console
validate-on-migrate: true
sql:
init:
mode: never
security:
user:
name: disabled
@@ -2,7 +2,8 @@
-- 用于测试环境
-- 插入测试角色
INSERT INTO sys_role (id, role_name, role_key, role_sort, status, create_by, update_by)
MERGE INTO sys_role (id, role_name, role_key, role_sort, status, create_by, update_by)
KEY(id)
VALUES
(1, '超级管理员', 'admin', 1, 1, 'system', 'system'),
(2, '测试管理员', 'test_admin', 2, 1, 'system', 'system'),
@@ -11,7 +12,8 @@ VALUES
-- 插入测试用户
-- BCrypt哈希值对应明文密码: Test@123
INSERT INTO sys_user (id, username, password, email, phone, nickname, status, create_by, update_by)
MERGE INTO sys_user (id, username, password, email, phone, nickname, status, create_by, update_by)
KEY(id)
VALUES
(1, 'admin', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'admin@novalon.com', '13800138000', '超级管理员', 1, 'system', 'system'),
(2, 'testadmin', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'testadmin@novalon.com', '13800138001', '测试管理员', 1, 'system', 'system'),
@@ -1,253 +0,0 @@
-- H2 Database Schema for Integration Testing
-- Create user table
CREATE TABLE IF NOT EXISTS sys_user (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
email VARCHAR(100),
phone VARCHAR(20),
nickname VARCHAR(100),
role_id BIGINT,
status INTEGER DEFAULT 1,
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- Create role table
CREATE TABLE IF NOT EXISTS sys_role (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
role_name VARCHAR(100) NOT NULL,
role_key VARCHAR(100) NOT NULL UNIQUE,
role_sort INTEGER DEFAULT 0,
status INTEGER DEFAULT 1,
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- Create user role relation table
CREATE TABLE IF NOT EXISTS user_role (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL,
role_id BIGINT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(50),
CONSTRAINT fk_user_role_user FOREIGN KEY (user_id) REFERENCES sys_user(id) ON DELETE CASCADE,
CONSTRAINT fk_user_role_role FOREIGN KEY (role_id) REFERENCES sys_role(id) ON DELETE CASCADE,
CONSTRAINT uk_user_role UNIQUE (user_id, role_id)
);
-- Create menu table
CREATE TABLE IF NOT EXISTS sys_menu (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
menu_name VARCHAR(50) NOT NULL,
parent_id BIGINT DEFAULT 0,
order_num INTEGER DEFAULT 0,
path VARCHAR(200),
component VARCHAR(200),
menu_type VARCHAR(1) DEFAULT 'C',
visible VARCHAR(1) DEFAULT '1',
status VARCHAR(1) DEFAULT '1',
perms VARCHAR(100),
icon VARCHAR(100),
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- Create permission table
CREATE TABLE IF NOT EXISTS sys_permission (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
permission_name VARCHAR(100) NOT NULL,
permission_code VARCHAR(100) NOT NULL UNIQUE,
resource VARCHAR(200),
action VARCHAR(20),
description VARCHAR(500),
status INTEGER DEFAULT 1,
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- Create role permission relation table
CREATE TABLE IF NOT EXISTS sys_role_permission (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
role_id BIGINT NOT NULL,
permission_id BIGINT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(50),
updated_by VARCHAR(50),
CONSTRAINT fk_role_permission_role FOREIGN KEY (role_id) REFERENCES sys_role(id) ON DELETE CASCADE,
CONSTRAINT fk_role_permission_permission FOREIGN KEY (permission_id) REFERENCES sys_permission(id) ON DELETE CASCADE,
CONSTRAINT uk_role_permission UNIQUE (role_id, permission_id)
);
-- Create dict type table
CREATE TABLE IF NOT EXISTS sys_dict_type (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
dict_name VARCHAR(100) NOT NULL,
dict_type VARCHAR(100) NOT NULL UNIQUE,
status VARCHAR(1) DEFAULT '0',
remark VARCHAR(500),
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- Create dict data table
CREATE TABLE IF NOT EXISTS sys_dict_data (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
dict_sort INTEGER DEFAULT 0,
dict_label VARCHAR(100) NOT NULL,
dict_value VARCHAR(100) NOT NULL,
dict_type VARCHAR(100) NOT NULL,
css_class VARCHAR(100),
list_class VARCHAR(100),
is_default VARCHAR(1) DEFAULT 'N',
status VARCHAR(1) DEFAULT '0',
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- Create dictionary table (general)
CREATE TABLE IF NOT EXISTS sys_dictionary (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(100) NOT NULL,
code VARCHAR(100) NOT NULL,
name VARCHAR(100) NOT NULL,
dict_value VARCHAR(500),
remark VARCHAR(500),
sort INTEGER DEFAULT 0,
create_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- Create system config table
CREATE TABLE IF NOT EXISTS sys_config (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
config_name VARCHAR(100) NOT NULL,
config_key VARCHAR(100) NOT NULL UNIQUE,
config_value VARCHAR(500) NOT NULL,
config_type VARCHAR(1) DEFAULT 'N',
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- Create login log table
CREATE TABLE IF NOT EXISTS sys_login_log (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50),
ip VARCHAR(50),
location VARCHAR(255),
browser VARCHAR(50),
os VARCHAR(50),
status VARCHAR(1),
message VARCHAR(255),
login_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Create exception log table
CREATE TABLE IF NOT EXISTS sys_exception_log (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50),
title VARCHAR(100),
exception_name VARCHAR(100),
method_name VARCHAR(255),
method_params TEXT,
exception_msg TEXT,
exception_stack TEXT,
ip VARCHAR(50),
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Create operation log table
CREATE TABLE IF NOT EXISTS operation_log (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50),
operation VARCHAR(100),
method VARCHAR(200),
params TEXT,
result TEXT,
ip VARCHAR(50),
duration BIGINT,
status VARCHAR(1) DEFAULT '0',
error_msg TEXT,
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- Create system notice table
CREATE TABLE IF NOT EXISTS sys_notice (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
notice_title VARCHAR(50) NOT NULL,
notice_type VARCHAR(1) NOT NULL,
notice_content TEXT,
status VARCHAR(1) DEFAULT '0',
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- Create user message table
CREATE TABLE IF NOT EXISTS sys_user_message (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL,
notice_id BIGINT,
message_title VARCHAR(255),
message_content TEXT,
is_read VARCHAR(1) DEFAULT '0',
read_time TIMESTAMP,
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- Create file management table
CREATE TABLE IF NOT EXISTS sys_file (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
file_name VARCHAR(255) NOT NULL,
file_path VARCHAR(500) NOT NULL,
file_size BIGINT,
file_type VARCHAR(100),
file_extension VARCHAR(10),
storage_type VARCHAR(50),
create_by VARCHAR(50),
update_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
-- Create indexes
CREATE INDEX IF NOT EXISTS idx_user_role_user_id ON user_role(user_id);
CREATE INDEX IF NOT EXISTS idx_user_role_role_id ON user_role(role_id);
CREATE INDEX IF NOT EXISTS idx_sys_menu_parent_id ON sys_menu(parent_id);
CREATE INDEX IF NOT EXISTS idx_sys_dict_type ON sys_dict_data(dict_type);
CREATE INDEX IF NOT EXISTS idx_sys_login_log_username ON sys_login_log(username);
CREATE INDEX IF NOT EXISTS idx_operation_log_username ON operation_log(username);
@@ -1,30 +0,0 @@
package cn.novalon.manage.app.config;
import io.r2dbc.spi.ConnectionFactory;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer;
import org.springframework.r2dbc.connection.init.ResourceDatabasePopulator;
/**
* 测试数据库配置类
*
* 初始化H2内存数据库schema
*
* @author 张翔
* @date 2026-04-02
*/
@TestConfiguration
public class TestDatabaseConfig {
@Bean
public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {
ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
initializer.setConnectionFactory(connectionFactory);
initializer.setDatabasePopulator(new ResourceDatabasePopulator(
new ClassPathResource("schema-h2.sql"),
new ClassPathResource("data-h2.sql")));
return initializer;
}
}
@@ -1,6 +1,5 @@
package cn.novalon.manage.app.integration;
import cn.novalon.manage.app.config.TestDatabaseConfig;
import cn.novalon.manage.common.util.StatusConstants;
import cn.novalon.manage.sys.core.domain.SysUser;
import cn.novalon.manage.sys.core.domain.SysRole;
@@ -14,7 +13,6 @@ import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.test.context.ActiveProfiles;
@@ -27,7 +25,7 @@ import static org.junit.jupiter.api.Assertions.*;
/**
* 用户服务集成测试
*
* 使用H2内存数据库进行集成测试
* 使用PostgreSQL数据库进行集成测试
*
* 注意:此测试需要完整的Spring上下文,暂时禁用。
* TODO: 优化集成测试配置
@@ -38,7 +36,6 @@ import static org.junit.jupiter.api.Assertions.*;
@Disabled("暂时禁用:集成测试配置需要优化")
@SpringBootTest
@ActiveProfiles("test")
@Import(TestDatabaseConfig.class)
class SysUserServiceIntegrationTest {
@Autowired
@@ -1,27 +1,22 @@
spring:
r2dbc:
url: r2dbc:h2:mem:///testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: sa
password:
url: r2dbc:postgresql://localhost:55432/manage_system
username: novalon
password: novalon123
pool:
enabled: true
initial-size: 2
max-size: 10
h2:
console:
enabled: true
path: /h2-console
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: true
validate-on-migrate: true
sql:
init:
mode: always
continue-on-error: false
schema-locations: classpath:schema-h2.sql
data-locations: classpath:data-h2.sql
flyway:
enabled: false
mode: never
security:
enabled: false
@@ -1,6 +1,7 @@
package cn.novalon.manage.db.entity;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Persistable;
import org.springframework.data.relational.core.mapping.Column;
import java.time.LocalDateTime;
@@ -11,7 +12,7 @@ import java.time.LocalDateTime;
* @author 张翔
* @date 2026-03-13
*/
public abstract class BaseEntity {
public abstract class BaseEntity implements Persistable<Long> {
@Id
private Long id;
@@ -31,6 +32,7 @@ public abstract class BaseEntity {
@Column("deleted_at")
private LocalDateTime deletedAt;
@Override
public Long getId() {
return id;
}
@@ -78,4 +80,13 @@ public abstract class BaseEntity {
public void setDeletedAt(LocalDateTime deletedAt) {
this.deletedAt = deletedAt;
}
/**
* 判断实体是否为新的
* 如果createdAt为null,则认为是新实体
*/
@Override
public boolean isNew() {
return createdAt == null;
}
}
@@ -0,0 +1,51 @@
-- Novalon管理系统普通用户角色和数据
-- 版本: V10
-- 描述: 创建普通用户角色并分配权限
-- 插入普通用户角色
INSERT INTO sys_role (role_name, role_key, role_sort, status, create_by, update_by)
VALUES ('普通用户', 'user', 2, 1, 'system', 'system')
ON CONFLICT (role_key) DO UPDATE SET
role_name = EXCLUDED.role_name,
role_sort = EXCLUDED.role_sort,
status = EXCLUDED.status;
-- 为普通用户分配基本权限(查看个人信息、修改密码等)
-- 注意:这里只分配基本权限,不包含管理功能权限
INSERT INTO sys_permission (permission_name, permission_key, permission_type, parent_id, path, component, icon, sort, status, create_by, update_by)
VALUES
('个人中心', 'profile', 'MENU', 0, '/profile', 'views/profile/index', 'user', 1, 1, 'system', 'system'),
('个人信息', 'profile:info', 'BUTTON', (SELECT id FROM sys_permission WHERE permission_key = 'profile'), '', '', '', 1, 1, 'system', 'system'),
('修改密码', 'profile:password', 'BUTTON', (SELECT id FROM sys_permission WHERE permission_key = 'profile'), '', '', '', 2, 1, 'system', 'system')
ON CONFLICT (permission_key) DO NOTHING;
-- 为普通用户角色分配权限
INSERT INTO sys_role_permission (role_id, permission_id, create_by, update_by)
SELECT
r.id as role_id,
p.id as permission_id,
'system' as create_by,
'system' as update_by
FROM sys_role r
CROSS JOIN sys_permission p
WHERE r.role_key = 'user'
AND p.permission_key IN ('profile', 'profile:info', 'profile:password')
ON CONFLICT DO NOTHING;
-- 将测试用户分配给普通用户角色
INSERT INTO user_role (user_id, role_id, create_by, update_by)
SELECT
u.id as user_id,
r.id as role_id,
'system' as create_by,
'system' as update_by
FROM sys_user u
CROSS JOIN sys_role r
WHERE u.username = 'user' AND r.role_key = 'user'
ON CONFLICT DO NOTHING;
-- 重置序列值
SELECT setval('sys_role_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_role));
SELECT setval('sys_permission_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_permission));
SELECT setval('sys_role_permission_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_role_permission));
SELECT setval('user_role_id_seq', (SELECT COALESCE(MAX(id), 1) FROM user_role));
@@ -0,0 +1,46 @@
-- Novalon管理系统测试数据脚本
-- 版本: V11
-- 描述: 更新测试用户密码为Test@123,插入E2E测试所需数据
-- 更新admin用户密码为Test@123
-- BCrypt哈希值对应明文密码: Test@123
UPDATE sys_user
SET password = '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C'
WHERE username = 'admin';
-- 更新user用户密码为Test@123
UPDATE sys_user
SET password = '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C'
WHERE username = 'user';
-- 插入测试角色(如果不存在)
INSERT INTO sys_role (role_name, role_key, role_sort, status, create_by, update_by)
VALUES
('测试管理员', 'test_admin', 2, 1, 'system', 'system'),
('普通用户', 'normal_user', 3, 1, 'system', 'system'),
('访客', 'guest', 4, 1, 'system', 'system')
ON CONFLICT (role_key) DO NOTHING;
-- 为admin用户分配超级管理员角色
INSERT INTO user_role (user_id, role_id, created_by)
SELECT 1, id, 'system' FROM sys_role WHERE role_key = 'admin'
ON CONFLICT DO NOTHING;
-- 为user用户分配普通用户角色
INSERT INTO user_role (user_id, role_id, created_by)
SELECT 2, id, 'system' FROM sys_role WHERE role_key = 'normal_user'
ON CONFLICT DO NOTHING;
-- 插入E2E测试专用用户
-- BCrypt哈希值对应明文密码: Test@123
INSERT INTO sys_user (id, username, password, email, phone, nickname, status, create_by, update_by)
VALUES
(10, 'e2e_test_user', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'e2e@test.com', '13900139000', 'E2E测试用户', 1, 'system', 'system')
ON CONFLICT (username) DO UPDATE SET
password = EXCLUDED.password,
status = EXCLUDED.status;
-- 为E2E测试用户分配超级管理员角色
INSERT INTO user_role (user_id, role_id, created_by)
SELECT 10, id, 'system' FROM sys_role WHERE role_key = 'admin'
ON CONFLICT DO NOTHING;
@@ -3,7 +3,7 @@
-- 描述: 创建所有核心表结构
-- 用户表
CREATE TABLE IF NOT EXISTS sys_user (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
email VARCHAR(100),
@@ -19,7 +19,7 @@ CREATE TABLE IF NOT EXISTS sys_user (
);
-- 角色表
CREATE TABLE IF NOT EXISTS sys_role (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
role_name VARCHAR(100) NOT NULL,
role_key VARCHAR(100) NOT NULL UNIQUE,
role_sort INTEGER DEFAULT 0,
@@ -32,7 +32,7 @@ CREATE TABLE IF NOT EXISTS sys_role (
);
-- 菜单表(统一使用sys_menu表名)
CREATE TABLE IF NOT EXISTS sys_menu (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
menu_name VARCHAR(50) NOT NULL,
parent_id BIGINT DEFAULT 0,
order_num INTEGER DEFAULT 0,
@@ -48,7 +48,7 @@ CREATE TABLE IF NOT EXISTS sys_menu (
);
-- 字典类型表
CREATE TABLE IF NOT EXISTS sys_dict_type (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
dict_name VARCHAR(100) NOT NULL,
dict_type VARCHAR(100) NOT NULL UNIQUE,
status VARCHAR(1) DEFAULT '0',
@@ -61,7 +61,7 @@ CREATE TABLE IF NOT EXISTS sys_dict_type (
);
-- 字典数据表
CREATE TABLE IF NOT EXISTS sys_dict_data (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
dict_sort INTEGER DEFAULT 0,
dict_label VARCHAR(100) NOT NULL,
dict_value VARCHAR(100) NOT NULL,
@@ -78,7 +78,7 @@ CREATE TABLE IF NOT EXISTS sys_dict_data (
);
-- 字典表(通用字典)
CREATE TABLE IF NOT EXISTS sys_dictionary (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
type VARCHAR(100) NOT NULL,
code VARCHAR(100) NOT NULL,
name VARCHAR(100) NOT NULL,
@@ -92,7 +92,7 @@ CREATE TABLE IF NOT EXISTS sys_dictionary (
);
-- 系统配置表
CREATE TABLE IF NOT EXISTS sys_config (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
config_name VARCHAR(100) NOT NULL,
config_key VARCHAR(100) NOT NULL UNIQUE,
config_value VARCHAR(500) NOT NULL,
@@ -105,7 +105,7 @@ CREATE TABLE IF NOT EXISTS sys_config (
);
-- 登录日志表
CREATE TABLE IF NOT EXISTS sys_login_log (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
username VARCHAR(50),
ip VARCHAR(50),
location VARCHAR(255),
@@ -117,7 +117,7 @@ CREATE TABLE IF NOT EXISTS sys_login_log (
);
-- 异常日志表
CREATE TABLE IF NOT EXISTS sys_exception_log (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
username VARCHAR(50),
title VARCHAR(100),
exception_name VARCHAR(100),
@@ -130,7 +130,7 @@ CREATE TABLE IF NOT EXISTS sys_exception_log (
);
-- 操作日志表
CREATE TABLE IF NOT EXISTS operation_log (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
username VARCHAR(50),
operation VARCHAR(100),
method VARCHAR(200),
@@ -148,7 +148,7 @@ CREATE TABLE IF NOT EXISTS operation_log (
);
-- 系统公告表
CREATE TABLE IF NOT EXISTS sys_notice (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
notice_title VARCHAR(50) NOT NULL,
notice_type VARCHAR(1) NOT NULL,
notice_content TEXT,
@@ -161,7 +161,7 @@ CREATE TABLE IF NOT EXISTS sys_notice (
);
-- 用户消息表
CREATE TABLE IF NOT EXISTS sys_user_message (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL,
notice_id BIGINT,
message_title VARCHAR(255),
@@ -176,7 +176,7 @@ CREATE TABLE IF NOT EXISTS sys_user_message (
);
-- 文件管理表
CREATE TABLE IF NOT EXISTS sys_file (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
file_name VARCHAR(255) NOT NULL,
file_path VARCHAR(500) NOT NULL,
file_size BIGINT,
@@ -191,7 +191,7 @@ CREATE TABLE IF NOT EXISTS sys_file (
);
-- OAuth2客户端表
CREATE TABLE IF NOT EXISTS oauth2_client (
id BIGSERIAL PRIMARY KEY,
id BIGINT PRIMARY KEY,
client_id VARCHAR(100) NOT NULL UNIQUE,
client_secret VARCHAR(255) NOT NULL,
client_name VARCHAR(100),
@@ -1,5 +1,6 @@
package cn.novalon.manage.sys.core.domain;
import cn.novalon.manage.common.util.SnowflakeId;
import java.time.LocalDateTime;
/**
@@ -64,4 +65,14 @@ public abstract class BaseDomain {
public void setDeletedAt(LocalDateTime deletedAt) {
this.deletedAt = deletedAt;
}
/**
* 生成主键ID
*
* @return 主键ID
*/
public Long generateId() {
this.id = SnowflakeId.nextId();
return this.id;
}
}
@@ -78,16 +78,6 @@ public class SysPermission extends BaseDomain {
this.status = status;
}
/**
* 生成主键ID
*
* @return 主键ID
*/
public Long generateId() {
this.id = SnowflakeId.nextId();
return this.id;
}
/**
* 删除权限
*/
@@ -58,16 +58,6 @@ public class SysRole extends BaseDomain {
this.status = status;
}
/**
* 生成主键ID
*
* @return 主键ID
*/
public Long generateId() {
this.id = SnowflakeId.nextId();
return this.id;
}
/**
* 删除角色
*/
@@ -33,14 +33,4 @@ public class SysRolePermission extends BaseDomain {
public void setPermissionId(Long permissionId) {
this.permissionId = permissionId;
}
/**
* 生成主键ID
*
* @return 主键ID
*/
public Long generateId() {
this.id = SnowflakeId.nextId();
return this.id;
}
}
@@ -101,16 +101,6 @@ public class SysUser extends BaseDomain {
this.status = status;
}
/**
* 生成主键ID
*
* @return 主键ID
*/
public Long generateId() {
this.id = SnowflakeId.nextId();
return this.id;
}
/**
* 删除用户
*/
@@ -82,6 +82,7 @@ public class SysRoleService implements ISysRoleService {
@Override
public Mono<SysRole> createRole(CreateRoleCommand command) {
SysRole role = new SysRole();
role.generateId();
role.setRoleName(command.roleName());
role.setRoleKey(command.roleKey());
role.setRoleSort(command.roleSort());
@@ -44,15 +44,15 @@ public class SysUserService implements ISysUserService {
private final IUserRoleRepository userRoleRepository;
private final PasswordEncoder passwordEncoder;
public SysUserService(ISysUserRepository userRepository,
ISysRoleRepository roleRepository,
IUserRoleRepository userRoleRepository,
@Qualifier("passwordEncoder") PasswordEncoder passwordEncoder) {
public SysUserService(ISysUserRepository userRepository,
ISysRoleRepository roleRepository,
IUserRoleRepository userRoleRepository,
@Qualifier("passwordEncoder") PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
this.userRoleRepository = userRoleRepository;
this.passwordEncoder = passwordEncoder;
logger.info("使用的密码编码器类型: {}", passwordEncoder.getClass().getName());
}
@@ -98,6 +98,7 @@ public class SysUserService implements ISysUserService {
logger.info("SysUserService.createUser - 用户名: {}, 密码前缀: {}",
user.getUsername(),
user.getPassword() != null ? user.getPassword().substring(0, 7) : "null");
user.generateId();
if (user.getPassword() != null && !user.getPassword().startsWith("$2a$")
&& !user.getPassword().startsWith("$2b$")) {
logger.info("密码不以$2a$或$2b$开头,重新编码");
@@ -106,7 +107,6 @@ public class SysUserService implements ISysUserService {
} else {
logger.info("密码已编码,跳过重新编码");
}
user.setCreatedAt(LocalDateTime.now());
if (user.getStatus() == null) {
user.setStatus(StatusConstants.ENABLED);
}
@@ -116,6 +116,7 @@ public class SysUserService implements ISysUserService {
@Override
public Mono<SysUser> createUser(CreateUserCommand command) {
SysUser user = new SysUser();
user.generateId();
user.setUsername(command.username().getValue());
user.setPassword(passwordEncoder.encode(command.password().getValue()));
user.setEmail(command.email().getValue());
@@ -123,7 +124,6 @@ public class SysUserService implements ISysUserService {
user.setPhone(command.phone());
user.setRoleId(command.roleId());
user.setStatus(command.status() != null ? command.status() : StatusConstants.ENABLED);
user.setCreatedAt(LocalDateTime.now());
return userRepository.save(user);
}
@@ -164,7 +164,7 @@ public class SysUserService implements ISysUserService {
@Transactional
public Mono<Void> deleteUser(Long id) {
logger.debug("开始删除用户,ID: {}", id);
return userRepository.findById(id)
.switchIfEmpty(Mono.error(new RuntimeException("User not found")))
.flatMap(user -> {
@@ -244,31 +244,30 @@ public class SysUserService implements ISysUserService {
@Transactional
public Mono<Void> assignRolesToUser(Long userId, List<Long> roleIds) {
logger.debug("开始为用户分配角色,用户ID: {}, 角色IDs: {}", userId, roleIds);
if (roleIds == null || roleIds.isEmpty()) {
logger.debug("角色列表为空,删除用户的所有角色关联");
return userRoleRepository.deleteByUserId(userId)
.doOnSuccess(v -> logger.debug("成功删除用户的所有角色关联"))
.doOnError(e -> logger.error("删除用户角色关联失败", e));
}
return userRoleRepository.deleteByUserId(userId)
.doOnSuccess(v -> logger.debug("成功删除用户的旧角色关联"))
.doOnError(e -> logger.error("删除用户旧角色关联失败", e))
.then(
Flux.fromIterable(roleIds)
.concatMap(roleId -> {
logger.debug("为用户分配角色ID: {}", roleId);
UserRole userRole = new UserRole();
userRole.setUserId(userId);
userRole.setRoleId(roleId);
userRole.setCreatedAt(LocalDateTime.now());
return userRoleRepository.save(userRole)
.doOnSuccess(v -> logger.debug("成功保存用户角色关联"))
.doOnError(e -> logger.error("保存用户角色关联失败", e));
})
.then()
);
Flux.fromIterable(roleIds)
.concatMap(roleId -> {
logger.debug("为用户分配角色ID: {}", roleId);
UserRole userRole = new UserRole();
userRole.setUserId(userId);
userRole.setRoleId(roleId);
userRole.setCreatedAt(LocalDateTime.now());
return userRoleRepository.save(userRole)
.doOnSuccess(v -> logger.debug("成功保存用户角色关联"))
.doOnError(e -> logger.error("保存用户角色关联失败", e));
})
.then());
}
@Override
@@ -0,0 +1,15 @@
package cn.novalon.manage.sys.dto.request;
import java.util.List;
public class AssignRolesRequest {
private List<Long> roleIds;
public List<Long> getRoleIds() {
return roleIds;
}
public void setRoleIds(List<Long> roleIds) {
this.roleIds = roleIds;
}
}
@@ -6,6 +6,8 @@ import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import java.util.List;
/**
* 用户注册请求DTO
*
@@ -42,6 +44,9 @@ public class UserRegisterRequest {
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
@Schema(description = "角色ID列表", example = "[1, 2]")
private List<Long> roles;
public String getUsername() {
return username;
}
@@ -81,4 +86,12 @@ public class UserRegisterRequest {
public void setPhone(String phone) {
this.phone = phone;
}
public List<Long> getRoles() {
return roles;
}
public void setRoles(List<Long> roles) {
this.roles = roles;
}
}
@@ -3,6 +3,7 @@ package cn.novalon.manage.sys.handler.user;
import cn.novalon.manage.sys.core.domain.SysUser;
import cn.novalon.manage.sys.core.service.ISysUserService;
import cn.novalon.manage.common.dto.PageRequest;
import cn.novalon.manage.sys.dto.request.AssignRolesRequest;
import cn.novalon.manage.sys.dto.request.PasswordChangeRequest;
import cn.novalon.manage.sys.dto.request.UserRegisterRequest;
import cn.novalon.manage.sys.dto.request.UserUpdateRequest;
@@ -135,6 +136,14 @@ public class SysUserHandler {
null
))
.flatMap(userService::createUser)
.flatMap(user -> {
if (req.getRoles() != null && !req.getRoles().isEmpty()) {
logger.info("为用户 {} 分配角色: {}", user.getUsername(), req.getRoles());
return userService.assignRolesToUser(user.getId(), req.getRoles())
.then(Mono.just(user));
}
return Mono.just(user);
})
.flatMap(user -> ServerResponse.status(HttpStatus.CREATED).bodyValue(user));
});
}
@@ -249,9 +258,8 @@ public class SysUserHandler {
@OperationLog(operation = "分配角色", module = "用户管理")
public Mono<ServerResponse> assignRoles(ServerRequest request) {
Long id = Long.valueOf(request.pathVariable("id"));
return request.bodyToMono(new org.springframework.core.ParameterizedTypeReference<List<Long>>() {
})
.flatMap(roleIds -> userService.assignRolesToUser(id, roleIds))
return request.bodyToMono(AssignRolesRequest.class)
.flatMap(req -> userService.assignRolesToUser(id, req.getRoleIds()))
.then(ServerResponse.ok().build())
.onErrorResume(error -> {
logger.error("分配角色失败", error);