feat: 统一JWT密钥配置并修复签名验证问题
修复前端签名生成中bodyString硬编码问题 添加start-frontend.sh脚本启动前端服务 统一manage-app和gateway的JWT密钥配置 修复Repository扫描路径问题 更新测试配置和依赖 重构表名映射为sys_user和sys_role 完善用户实体类字段映射 添加集成测试配置和测试用例
This commit is contained in:
+1
-1
@@ -12,7 +12,7 @@ import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
|
||||
@SpringBootApplication(exclude = {ReactiveUserDetailsServiceAutoConfiguration.class})
|
||||
@ConfigurationPropertiesScan(basePackages = "cn.novalon.manage")
|
||||
@ComponentScan(basePackages = "cn.novalon.manage")
|
||||
@EnableR2dbcRepositories(basePackages = {"cn.novalon.manage.db.dao"})
|
||||
@EnableR2dbcRepositories(basePackages = {"cn.novalon.manage.db.dao", "cn.novalon.manage.sys.audit.repository"})
|
||||
public class ManageApplication {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ManageApplication.class);
|
||||
|
||||
@@ -46,6 +46,10 @@ logging:
|
||||
org.springframework.r2dbc: DEBUG
|
||||
cn.novalon.manage.db: DEBUG
|
||||
|
||||
jwt:
|
||||
secret: ${JWT_SECRET:U2FsdGVkX1+vZ5Y9QmKxL8nN3rP7tW2jH4fG6dA8sB1cE5yN0zX3qV7wM4}
|
||||
expiration: ${JWT_EXPIRATION:86400000}
|
||||
|
||||
springdoc:
|
||||
api-docs:
|
||||
path: /api-docs
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
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")));
|
||||
return initializer;
|
||||
}
|
||||
}
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
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;
|
||||
import cn.novalon.manage.sys.core.domain.UserRole;
|
||||
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.service.impl.SysUserService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
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;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* 用户服务集成测试
|
||||
*
|
||||
* 使用H2内存数据库进行集成测试
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-04-02
|
||||
*/
|
||||
@SpringBootTest
|
||||
@ActiveProfiles("test")
|
||||
@Import(TestDatabaseConfig.class)
|
||||
class SysUserServiceIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private ISysUserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private ISysRoleRepository roleRepository;
|
||||
|
||||
@Autowired
|
||||
private IUserRoleRepository userRoleRepository;
|
||||
|
||||
@Autowired
|
||||
private R2dbcEntityTemplate r2dbcEntityTemplate;
|
||||
|
||||
@Autowired
|
||||
private SysUserService userService;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
r2dbcEntityTemplate.delete(SysUser.class).all().block();
|
||||
r2dbcEntityTemplate.delete(SysRole.class).all().block();
|
||||
r2dbcEntityTemplate.delete(UserRole.class).all().block();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateAndFindUser() {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("testuser");
|
||||
user.setPassword("password123");
|
||||
user.setEmail("test@example.com");
|
||||
user.setNickname("Test User");
|
||||
user.setPhone("13800138000");
|
||||
|
||||
StepVerifier.create(userService.createUser(user))
|
||||
.expectNextMatches(createdUser -> {
|
||||
assertNotNull(createdUser.getId());
|
||||
assertEquals("testuser", createdUser.getUsername());
|
||||
assertEquals("test@example.com", createdUser.getEmail());
|
||||
assertTrue(createdUser.getPassword().startsWith("$2"));
|
||||
assertEquals(StatusConstants.ENABLED, createdUser.getStatus());
|
||||
return true;
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
StepVerifier.create(userService.findByUsername("testuser"))
|
||||
.expectNextMatches(foundUser -> {
|
||||
assertEquals("testuser", foundUser.getUsername());
|
||||
assertEquals("test@example.com", foundUser.getEmail());
|
||||
return true;
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateUser() {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("updateuser");
|
||||
user.setPassword("password123");
|
||||
user.setEmail("update@example.com");
|
||||
|
||||
SysUser createdUser = userService.createUser(user).block();
|
||||
assertNotNull(createdUser);
|
||||
|
||||
createdUser.setEmail("updated@example.com");
|
||||
createdUser.setNickname("Updated User");
|
||||
|
||||
StepVerifier.create(userService.updateUser(createdUser))
|
||||
.expectNextMatches(updatedUser -> {
|
||||
assertEquals("updated@example.com", updatedUser.getEmail());
|
||||
assertEquals("Updated User", updatedUser.getNickname());
|
||||
return true;
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteUser() {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("deleteuser");
|
||||
user.setPassword("password123");
|
||||
user.setEmail("delete@example.com");
|
||||
|
||||
SysUser createdUser = userService.createUser(user).block();
|
||||
assertNotNull(createdUser);
|
||||
|
||||
StepVerifier.create(userService.deleteUser(createdUser.getId()))
|
||||
.verifyComplete();
|
||||
|
||||
StepVerifier.create(userService.findById(createdUser.getId()))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testChangePassword() {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("pwduser");
|
||||
user.setPassword("oldPassword");
|
||||
user.setEmail("pwd@example.com");
|
||||
|
||||
SysUser createdUser = userService.createUser(user).block();
|
||||
assertNotNull(createdUser);
|
||||
|
||||
StepVerifier.create(userService.changePassword(createdUser.getId(), "oldPassword", "newPassword"))
|
||||
.expectNextMatches(updatedUser -> {
|
||||
assertNotEquals(createdUser.getPassword(), updatedUser.getPassword());
|
||||
assertTrue(passwordEncoder.matches("newPassword", updatedUser.getPassword()));
|
||||
return true;
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAssignRolesToUser() {
|
||||
SysRole role1 = new SysRole();
|
||||
role1.setRoleName("Test Role 1");
|
||||
role1.setRoleKey("test_role_1");
|
||||
role1.setStatus(1);
|
||||
|
||||
SysRole role2 = new SysRole();
|
||||
role2.setRoleName("Test Role 2");
|
||||
role2.setRoleKey("test_role_2");
|
||||
role2.setStatus(1);
|
||||
|
||||
SysRole createdRole1 = roleRepository.save(role1).block();
|
||||
SysRole createdRole2 = roleRepository.save(role2).block();
|
||||
assertNotNull(createdRole1);
|
||||
assertNotNull(createdRole2);
|
||||
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("roleuser");
|
||||
user.setPassword("password123");
|
||||
user.setEmail("role@example.com");
|
||||
|
||||
SysUser createdUser = userService.createUser(user).block();
|
||||
assertNotNull(createdUser);
|
||||
|
||||
StepVerifier.create(userService.assignRolesToUser(createdUser.getId(),
|
||||
Arrays.asList(createdRole1.getId(), createdRole2.getId())))
|
||||
.verifyComplete();
|
||||
|
||||
StepVerifier.create(userRoleRepository.findByUserId(createdUser.getId()).collectList())
|
||||
.expectNextMatches(userRoles -> {
|
||||
assertEquals(2, userRoles.size());
|
||||
return true;
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFindAllUsers() {
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("user" + i);
|
||||
user.setPassword("password" + i);
|
||||
user.setEmail("user" + i + "@example.com");
|
||||
userService.createUser(user).block();
|
||||
}
|
||||
|
||||
StepVerifier.create(userService.findAll(false).collectList())
|
||||
.expectNextMatches(users -> {
|
||||
assertEquals(3, users.size());
|
||||
return true;
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExistsByUsername() {
|
||||
SysUser user = new SysUser();
|
||||
user.setUsername("existinguser");
|
||||
user.setPassword("password123");
|
||||
user.setEmail("existing@example.com");
|
||||
userService.createUser(user).block();
|
||||
|
||||
StepVerifier.create(userService.existsByUsername("existinguser"))
|
||||
.expectNext(true)
|
||||
.verifyComplete();
|
||||
|
||||
StepVerifier.create(userService.existsByUsername("nonexistinguser"))
|
||||
.expectNext(false)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,24 @@
|
||||
spring.r2dbc.url=r2dbc:h2:mem:///testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
|
||||
spring.r2dbc.username=sa
|
||||
spring.r2dbc.password=
|
||||
spring.r2dbc.pool.enabled=true
|
||||
spring.r2dbc.pool.initial-size=5
|
||||
spring.r2dbc.pool.max-size=20
|
||||
|
||||
spring.sql.init.mode=always
|
||||
spring.sql.init.schema-locations=classpath:schema-h2.sql
|
||||
spring.sql.init.data-locations=classpath:data-h2.sql
|
||||
|
||||
logging.level.org.springframework.r2dbc=DEBUG
|
||||
logging.level.cn.novalon.manage=DEBUG
|
||||
|
||||
spring.flyway.enabled=false
|
||||
|
||||
server.port=8085
|
||||
|
||||
jwt.secret=test-secret-key-for-testing-purposes-only-minimum-256-bits
|
||||
jwt.expiration=3600000
|
||||
|
||||
signature.enabled=false
|
||||
spring:
|
||||
r2dbc:
|
||||
url: r2dbc:h2:mem:///testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
|
||||
username: sa
|
||||
password:
|
||||
pool:
|
||||
enabled: true
|
||||
initial-size: 2
|
||||
max-size: 10
|
||||
|
||||
flyway:
|
||||
enabled: false
|
||||
|
||||
security:
|
||||
enabled: false
|
||||
|
||||
jwt:
|
||||
secret: test-secret-key-for-integration-testing
|
||||
expiration: 86400000
|
||||
|
||||
logging:
|
||||
level:
|
||||
cn.novalon.manage: DEBUG
|
||||
org.springframework.r2dbc: DEBUG
|
||||
|
||||
@@ -1,189 +1,47 @@
|
||||
-- H2数据库Schema
|
||||
-- 用于测试环境
|
||||
|
||||
-- 用户表
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
-- H2数据库Schema for Integration Testing
|
||||
-- 创建用户表
|
||||
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) NOT NULL UNIQUE,
|
||||
email VARCHAR(100),
|
||||
phone VARCHAR(20),
|
||||
nickname VARCHAR(50),
|
||||
avatar VARCHAR(255),
|
||||
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,
|
||||
created_by VARCHAR(50) DEFAULT 'system',
|
||||
updated_by VARCHAR(50) DEFAULT 'system',
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- 角色表
|
||||
CREATE TABLE IF NOT EXISTS roles (
|
||||
-- 创建角色表
|
||||
CREATE TABLE IF NOT EXISTS sys_role (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
role_name VARCHAR(50) NOT NULL,
|
||||
role_key VARCHAR(50) NOT NULL UNIQUE,
|
||||
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,
|
||||
created_by VARCHAR(50) DEFAULT 'system',
|
||||
updated_by VARCHAR(50) DEFAULT 'system',
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- 用户角色关联表
|
||||
CREATE TABLE IF NOT EXISTS user_roles (
|
||||
-- 创建用户角色关联表
|
||||
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,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_by VARCHAR(50) DEFAULT 'system',
|
||||
updated_by VARCHAR(50) DEFAULT 'system',
|
||||
UNIQUE(user_id, role_id)
|
||||
);
|
||||
|
||||
-- 菜单表
|
||||
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(255),
|
||||
menu_type CHAR(1) DEFAULT 'C',
|
||||
visible CHAR(1) DEFAULT '1',
|
||||
status CHAR(1) DEFAULT '1',
|
||||
perms VARCHAR(100),
|
||||
icon VARCHAR(100),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_by VARCHAR(50) DEFAULT 'system',
|
||||
updated_by VARCHAR(50) DEFAULT 'system',
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- 权限表
|
||||
CREATE TABLE IF NOT EXISTS sys_permission (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
permission_name VARCHAR(50) NOT NULL,
|
||||
permission_key VARCHAR(100) NOT NULL UNIQUE,
|
||||
permission_type VARCHAR(20) DEFAULT 'menu',
|
||||
parent_id BIGINT DEFAULT 0,
|
||||
status INTEGER DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_by VARCHAR(50) DEFAULT 'system',
|
||||
updated_by VARCHAR(50) DEFAULT 'system',
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- 角色权限关联表
|
||||
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,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_by VARCHAR(50) DEFAULT 'system',
|
||||
updated_by VARCHAR(50) DEFAULT 'system',
|
||||
UNIQUE(role_id, permission_id)
|
||||
);
|
||||
|
||||
-- 字典类型表
|
||||
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 CHAR(1) DEFAULT '0',
|
||||
remark VARCHAR(500),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_by VARCHAR(50) DEFAULT 'system',
|
||||
updated_by VARCHAR(50) DEFAULT 'system',
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- 字典数据表
|
||||
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 CHAR(1) DEFAULT 'N',
|
||||
status CHAR(1) DEFAULT '0',
|
||||
remark VARCHAR(500),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_by VARCHAR(50) DEFAULT 'system',
|
||||
updated_by VARCHAR(50) DEFAULT 'system',
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- 系统配置表
|
||||
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 CHAR(1) DEFAULT 'N',
|
||||
remark VARCHAR(500),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_by VARCHAR(50) DEFAULT 'system',
|
||||
updated_by VARCHAR(50) DEFAULT 'system',
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- 操作日志表
|
||||
CREATE TABLE IF NOT EXISTS operation_log (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id BIGINT,
|
||||
username VARCHAR(50),
|
||||
operation VARCHAR(100),
|
||||
method VARCHAR(200),
|
||||
params TEXT,
|
||||
time BIGINT,
|
||||
ip VARCHAR(64),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 登录日志表
|
||||
CREATE TABLE IF NOT EXISTS sys_login_log (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id BIGINT,
|
||||
username VARCHAR(50),
|
||||
ip VARCHAR(64),
|
||||
location VARCHAR(255),
|
||||
browser VARCHAR(100),
|
||||
os VARCHAR(100),
|
||||
status INTEGER DEFAULT 1,
|
||||
msg VARCHAR(255),
|
||||
login_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 异常日志表
|
||||
CREATE TABLE IF NOT EXISTS sys_exception_log (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id BIGINT,
|
||||
username VARCHAR(50),
|
||||
method VARCHAR(200),
|
||||
params TEXT,
|
||||
exception TEXT,
|
||||
ip VARCHAR(64),
|
||||
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 INDEX idx_users_username ON users(username);
|
||||
CREATE INDEX idx_users_email ON users(email);
|
||||
CREATE INDEX idx_users_status ON users(status);
|
||||
CREATE INDEX idx_user_roles_user_id ON user_roles(user_id);
|
||||
CREATE INDEX idx_user_roles_role_id ON user_roles(role_id);
|
||||
CREATE INDEX idx_sys_menu_parent_id ON sys_menu(parent_id);
|
||||
CREATE INDEX idx_sys_permission_key ON sys_permission(permission_key);
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user