fix(flyway): 修复Flyway初始化问题并完善测试覆盖

- 修复数据库连接配置,确保Flyway迁移正常执行
- 完善Repository接口的查询方法,支持审计日志和操作日志查询
- 增强Service层业务逻辑,优化用户、角色、菜单等核心功能
- 补充单元测试和集成测试,确保系统稳定性
- 添加测试数据初始化脚本,支持自动化测试环境搭建

关联任务:Flyway数据库迁移优化
This commit was merged in pull request #5.
This commit is contained in:
张翔
2026-04-24 15:01:59 +08:00
parent d2cef85187
commit f853cb73b5
32 changed files with 798 additions and 121 deletions
@@ -2,6 +2,8 @@ server:
port: 8084
spring:
aop:
proxy-target-class: true
application:
name: gym-manage-api
main:
@@ -5,17 +5,12 @@ import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.annotation.Transient;
import org.springframework.data.domain.Persistable;
import org.springframework.data.relational.core.mapping.Column;
import java.time.LocalDateTime;
/**
* 数据库实体基类
*
* @author 张翔
* @date 2026-03-13
*/
public abstract class BaseEntity implements Persistable<Long> {
@Id
@@ -40,6 +35,9 @@ public abstract class BaseEntity implements Persistable<Long> {
@Column("deleted_at")
private LocalDateTime deletedAt;
@Transient
private boolean newEntity = true;
@Override
public Long getId() {
return id;
@@ -89,12 +87,16 @@ public abstract class BaseEntity implements Persistable<Long> {
this.deletedAt = deletedAt;
}
/**
* 判断实体是否为新的
* 如果createdAt为null,则认为是新实体
*/
@Override
public boolean isNew() {
return createdAt == null;
return newEntity;
}
public void markNotNew() {
this.newEntity = false;
}
public void markNew() {
this.newEntity = true;
}
}
@@ -7,6 +7,7 @@ import cn.novalon.gym.manage.db.dao.AuditLogDao;
import cn.novalon.gym.manage.db.entity.AuditLogEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -26,10 +27,12 @@ public class AuditLogRepository implements IAuditLogRepository {
private final AuditLogDao auditLogDao;
private final AuditLogConverter auditLogConverter;
private final R2dbcEntityTemplate r2dbcEntityTemplate;
public AuditLogRepository(AuditLogDao auditLogDao, AuditLogConverter auditLogConverter) {
public AuditLogRepository(AuditLogDao auditLogDao, AuditLogConverter auditLogConverter, R2dbcEntityTemplate r2dbcEntityTemplate) {
this.auditLogDao = auditLogDao;
this.auditLogConverter = auditLogConverter;
this.r2dbcEntityTemplate = r2dbcEntityTemplate;
}
@Override
@@ -41,6 +44,12 @@ public class AuditLogRepository implements IAuditLogRepository {
@Override
public Mono<AuditLog> save(AuditLog auditLog) {
AuditLogEntity entity = auditLogConverter.toEntity(auditLog);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(AuditLogEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(auditLogConverter::toDomain);
}
return auditLogDao.save(entity)
.map(auditLogConverter::toDomain);
}
@@ -49,6 +49,12 @@ public class OperationLogRepository implements IOperationLogRepository {
@Override
public Mono<OperationLog> save(OperationLog operationLog) {
OperationLogEntity entity = operationLogConverter.toEntity(operationLog);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(OperationLogEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(operationLogConverter::toDomain);
}
return operationLogDao.save(entity)
.map(operationLogConverter::toDomain);
}
@@ -60,6 +60,20 @@ public class SysMenuRepository implements ISysMenuRepository {
@Override
public Mono<SysMenu> save(SysMenu sysMenu) {
SysMenuEntity entity = sysMenuConverter.toEntity(sysMenu);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(SysMenuEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(sysMenuConverter::toDomain);
}
return sysMenuDao.save(entity)
.map(sysMenuConverter::toDomain);
}
@Override
public Mono<SysMenu> update(SysMenu sysMenu) {
SysMenuEntity entity = sysMenuConverter.toEntity(sysMenu);
entity.markNotNew();
return sysMenuDao.save(entity)
.map(sysMenuConverter::toDomain);
}
@@ -4,7 +4,9 @@ import cn.novalon.gym.manage.sys.core.domain.SysPermission;
import cn.novalon.gym.manage.sys.core.repository.ISysPermissionRepository;
import cn.novalon.gym.manage.db.converter.SysPermissionConverter;
import cn.novalon.gym.manage.db.dao.SysPermissionDao;
import cn.novalon.gym.manage.db.entity.SysPermissionEntity;
import org.springframework.data.domain.Sort;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -20,10 +22,12 @@ public class SysPermissionRepository implements ISysPermissionRepository {
private final SysPermissionDao sysPermissionDao;
private final SysPermissionConverter sysPermissionConverter;
private final R2dbcEntityTemplate r2dbcEntityTemplate;
public SysPermissionRepository(SysPermissionDao sysPermissionDao, SysPermissionConverter sysPermissionConverter) {
public SysPermissionRepository(SysPermissionDao sysPermissionDao, SysPermissionConverter sysPermissionConverter, R2dbcEntityTemplate r2dbcEntityTemplate) {
this.sysPermissionDao = sysPermissionDao;
this.sysPermissionConverter = sysPermissionConverter;
this.r2dbcEntityTemplate = r2dbcEntityTemplate;
}
@Override
@@ -40,7 +44,14 @@ public class SysPermissionRepository implements ISysPermissionRepository {
@Override
public Mono<SysPermission> save(SysPermission sysPermission) {
return sysPermissionDao.save(sysPermissionConverter.toEntity(sysPermission))
SysPermissionEntity entity = sysPermissionConverter.toEntity(sysPermission);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(SysPermissionEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(sysPermissionConverter::toDomain);
}
return sysPermissionDao.save(entity)
.map(sysPermissionConverter::toDomain);
}
@@ -4,6 +4,8 @@ import cn.novalon.gym.manage.sys.core.domain.SysRolePermission;
import cn.novalon.gym.manage.sys.core.repository.ISysRolePermissionRepository;
import cn.novalon.gym.manage.db.converter.SysRolePermissionConverter;
import cn.novalon.gym.manage.db.dao.SysRolePermissionDao;
import cn.novalon.gym.manage.db.entity.SysRolePermissionEntity;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -19,15 +21,24 @@ public class SysRolePermissionRepository implements ISysRolePermissionRepository
private final SysRolePermissionDao sysRolePermissionDao;
private final SysRolePermissionConverter sysRolePermissionConverter;
private final R2dbcEntityTemplate r2dbcEntityTemplate;
public SysRolePermissionRepository(SysRolePermissionDao sysRolePermissionDao, SysRolePermissionConverter sysRolePermissionConverter) {
public SysRolePermissionRepository(SysRolePermissionDao sysRolePermissionDao, SysRolePermissionConverter sysRolePermissionConverter, R2dbcEntityTemplate r2dbcEntityTemplate) {
this.sysRolePermissionDao = sysRolePermissionDao;
this.sysRolePermissionConverter = sysRolePermissionConverter;
this.r2dbcEntityTemplate = r2dbcEntityTemplate;
}
@Override
public Mono<SysRolePermission> save(SysRolePermission rolePermission) {
return sysRolePermissionDao.save(sysRolePermissionConverter.toEntity(rolePermission))
SysRolePermissionEntity entity = sysRolePermissionConverter.toEntity(rolePermission);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(SysRolePermissionEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(sysRolePermissionConverter::toDomain);
}
return sysRolePermissionDao.save(entity)
.map(sysRolePermissionConverter::toDomain);
}
@@ -53,6 +53,12 @@ public class SysRoleRepository implements ISysRoleRepository {
@Override
public Mono<SysRole> save(SysRole sysRole) {
SysRoleEntity entity = sysRoleConverter.toEntity(sysRole);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(SysRoleEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(sysRoleConverter::toDomain);
}
return sysRoleDao.save(entity)
.map(sysRoleConverter::toDomain);
}
@@ -156,6 +162,7 @@ public class SysRoleRepository implements ISysRoleRepository {
@Override
public Mono<SysRole> updateRole(SysRole role) {
SysRoleEntity entity = sysRoleConverter.toEntity(role);
entity.markNotNew();
return sysRoleDao.save(entity)
.map(sysRoleConverter::toDomain);
}
@@ -70,6 +70,20 @@ public class SysUserRepository implements ISysUserRepository {
@Override
public Mono<SysUser> save(SysUser sysUser) {
SysUserEntity entity = sysUserConverter.toEntity(sysUser);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(SysUserEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(sysUserConverter::toDomain);
}
return sysUserDao.save(entity)
.map(sysUserConverter::toDomain);
}
@Override
public Mono<SysUser> update(SysUser sysUser) {
SysUserEntity entity = sysUserConverter.toEntity(sysUser);
entity.markNotNew();
return sysUserDao.save(entity)
.map(sysUserConverter::toDomain);
}
@@ -176,6 +190,7 @@ public class SysUserRepository implements ISysUserRepository {
public Mono<Void> logicalDeleteById(Long id) {
return sysUserDao.findById(id)
.flatMap(entity -> {
entity.markNotNew();
entity.setDeletedAt(java.time.LocalDateTime.now());
return sysUserDao.save(entity).then();
});
@@ -192,6 +207,7 @@ public class SysUserRepository implements ISysUserRepository {
public Mono<Void> restoreById(Long id) {
return sysUserDao.findById(id)
.flatMap(entity -> {
entity.markNotNew();
entity.setDeletedAt(null);
return sysUserDao.save(entity).then();
});
@@ -0,0 +1,157 @@
package cn.novalon.gym.manage.sys.audit;
import cn.novalon.gym.manage.sys.audit.domain.AuditLog;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Aspect
@Component
@Deprecated
public class AuditLogAspect {
private static final Logger logger = LoggerFactory.getLogger(AuditLogAspect.class);
private final IAuditLogService auditLogService;
public AuditLogAspect(IAuditLogService auditLogService) {
this.auditLogService = auditLogService;
logger.info("=== AuditLogAspect 初始化完成 ===");
}
@Before("execution(* cn.novalon.gym.manage.sys.core.service.impl.SysUserService.createUser(..))")
public void testAopWorking() {
logger.info("=== AuditLogAspect @Before 测试: SysUserService.createUser 被调用 ===");
}
@Around("@annotation(auditable)")
public Object logAuditEvent(ProceedingJoinPoint joinPoint, Auditable auditable) throws Throwable {
String methodName = ((MethodSignature) joinPoint.getSignature()).getName();
String className = joinPoint.getTarget().getClass().getSimpleName();
String entityType = auditable.entityType();
String operationType = auditable.operationType();
logger.debug("审计切面拦截: {}.{}(), entityType={}, operationType={}", className, methodName, entityType, operationType);
try {
Object result = joinPoint.proceed();
if (result instanceof Mono) {
return ((Mono<Object>) result).flatMap(retValue -> {
Long entityId = extractIdFromResult(retValue);
String afterData = serializeEntity(retValue);
return createAndSaveAuditLog(
entityType, entityId, operationType,
null, afterData
).thenReturn(retValue);
});
} else if (result instanceof Flux) {
return ((Flux<Object>) result).collectList()
.flatMapMany(list -> {
String afterData = serializeEntity(list);
return createAndSaveAuditLog(
entityType, null, operationType,
null, afterData
).thenMany(Flux.fromIterable(list));
});
}
return result;
} catch (Throwable error) {
logger.error("审计日志记录失败: {}.{}()", className, methodName, error);
throw error;
}
}
private Mono<Void> createAndSaveAuditLog(String entityType, Long entityId,
String operationType, String beforeData,
String afterData) {
logger.debug("创建审计日志: entityType={}, entityId={}, operationType={}", entityType, entityId, operationType);
return ReactiveSecurityContextHolder.getContext()
.map(ctx -> ctx.getAuthentication().getPrincipal())
.defaultIfEmpty("system")
.flatMap(principal -> {
AuditLog auditLog = new AuditLog();
auditLog.setEntityType(entityType);
auditLog.setEntityId(entityId != null ? entityId : 0L);
auditLog.setOperationType(operationType);
auditLog.setOperator(principal instanceof String ? (String) principal : "system");
auditLog.setBeforeData(beforeData);
auditLog.setAfterData(afterData);
auditLog.setDescription(generateDescription(entityType, operationType, entityId));
return auditLogService.saveAsync(auditLog)
.doOnSuccess(saved -> logger.debug("审计日志保存成功: {} - {}, ID={}",
entityType, operationType, saved.getId()))
.doOnError(error -> logger.error("审计日志保存失败: {}", error.getMessage()))
.then();
})
.onErrorResume(error -> {
logger.error("创建审计日志失败,但不影响主流程: {}", error.getMessage(), error);
return Mono.empty();
});
}
private Long extractIdFromResult(Object result) {
if (result == null) {
return null;
}
try {
var getIdMethod = result.getClass().getMethod("getId");
Object id = getIdMethod.invoke(result);
if (id instanceof Number) {
return ((Number) id).longValue();
}
if (id instanceof String) {
try {
return Long.parseLong((String) id);
} catch (NumberFormatException e) {
return null;
}
}
} catch (NoSuchMethodException e) {
logger.debug("结果对象没有getId方法: {}", result.getClass().getSimpleName());
} catch (Exception e) {
logger.debug("提取结果ID失败: {}", e.getMessage());
}
return null;
}
private String serializeEntity(Object entity) {
try {
ObjectMapper mapper = new ObjectMapper()
.registerModule(new JavaTimeModule())
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.disable(SerializationFeature.FAIL_ON_SELF_REFERENCES);
return mapper.writeValueAsString(entity);
} catch (Exception e) {
logger.error("序列化实体失败: {}", e.getMessage());
return null;
}
}
private String generateDescription(String entityType, String operationType, Long entityId) {
String operation = switch (operationType) {
case "CREATE" -> "创建";
case "UPDATE" -> "更新";
case "DELETE" -> "删除";
default -> "操作";
};
return String.format("%s%s (ID: %s)", operation, entityType,
entityId != null ? entityId : "未知");
}
}
@@ -0,0 +1,80 @@
package cn.novalon.gym.manage.sys.audit;
import cn.novalon.gym.manage.sys.audit.domain.AuditLog;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import reactor.core.publisher.Mono;
public final class AuditLogHelper {
private static final Logger logger = LoggerFactory.getLogger(AuditLogHelper.class);
private static final ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule())
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.disable(SerializationFeature.FAIL_ON_SELF_REFERENCES);
private AuditLogHelper() {}
public static Mono<Void> record(IAuditLogService auditLogService,
String entityType, Long entityId,
String operationType, Object afterEntity) {
return record(auditLogService, entityType, entityId, operationType, null, afterEntity);
}
public static Mono<Void> record(IAuditLogService auditLogService,
String entityType, Long entityId,
String operationType, Object beforeEntity, Object afterEntity) {
return ReactiveSecurityContextHolder.getContext()
.map(ctx -> ctx.getAuthentication().getPrincipal())
.defaultIfEmpty("system")
.flatMap(principal -> {
AuditLog auditLog = new AuditLog();
auditLog.generateId();
auditLog.setEntityType(entityType);
auditLog.setEntityId(entityId != null ? entityId : 0L);
auditLog.setOperationType(operationType);
auditLog.setOperator(principal instanceof String ? (String) principal : "system");
auditLog.setBeforeData(serializeEntity(beforeEntity));
auditLog.setAfterData(serializeEntity(afterEntity));
auditLog.setDescription(generateDescription(entityType, operationType, entityId));
logger.info("记录审计日志: {} {} ID={}, operator={}", operationType, entityType, entityId, auditLog.getOperator());
return auditLogService.saveAsync(auditLog)
.doOnSuccess(saved -> logger.info("审计日志保存成功: {} - {}, ID={}",
entityType, operationType, saved.getId()))
.doOnError(error -> logger.error("审计日志保存失败: {}", error.getMessage()))
.then();
})
.onErrorResume(error -> {
logger.error("记录审计日志失败,但不影响主流程: {}", error.getMessage(), error);
return Mono.empty();
});
}
private static String serializeEntity(Object entity) {
try {
if (entity == null) return null;
return objectMapper.writeValueAsString(entity);
} catch (Exception e) {
logger.error("序列化实体失败: {}", e.getMessage());
return null;
}
}
private static String generateDescription(String entityType, String operationType, Long entityId) {
String operation = switch (operationType) {
case "CREATE" -> "创建";
case "UPDATE" -> "更新";
case "DELETE" -> "删除";
default -> "操作";
};
return String.format("%s%s (ID: %s)", operation, entityType,
entityId != null ? entityId : "未知");
}
}
@@ -0,0 +1,15 @@
package cn.novalon.gym.manage.sys.audit;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Auditable {
String entityType();
String operationType() default "CREATE";
String description() default "";
}
@@ -24,6 +24,8 @@ public interface ISysMenuRepository {
Mono<SysMenu> save(SysMenu sysMenu);
Mono<SysMenu> update(SysMenu sysMenu);
Mono<Void> deleteById(Long id);
Flux<SysMenu> findAll();
@@ -28,6 +28,8 @@ public interface ISysUserRepository {
Mono<SysUser> save(SysUser sysUser);
Mono<SysUser> update(SysUser sysUser);
Mono<Void> deleteById(Long id);
Flux<SysUser> findAll();
@@ -48,13 +48,11 @@ public class DictionaryService implements IDictionaryService {
@Override
public Mono<Dictionary> save(Dictionary dictionary) {
if (dictionary.getId() == null) {
dictionary.setCreatedAt(LocalDateTime.now());
return checkTypeAndCodeExists(dictionary.getType(), dictionary.getCode())
.flatMap(exists -> {
if (exists) {
return Mono.error(new DictionaryAlreadyExistsException(dictionary.getType(), dictionary.getCode()));
}
dictionary.setUpdatedAt(LocalDateTime.now());
return repository.save(dictionary);
});
}
@@ -1,5 +1,7 @@
package cn.novalon.gym.manage.sys.core.service.impl;
import cn.novalon.gym.manage.sys.audit.AuditLogHelper;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import cn.novalon.gym.manage.sys.core.domain.SysConfig;
import cn.novalon.gym.manage.sys.core.repository.ISysConfigRepository;
import cn.novalon.gym.manage.sys.core.service.ISysConfigService;
@@ -7,19 +9,15 @@ import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* 系统配置服务实现类
*
* @author 张翔
* @date 2026-03-14
*/
@Service
public class SysConfigService implements ISysConfigService {
private final ISysConfigRepository repository;
private final IAuditLogService auditLogService;
public SysConfigService(ISysConfigRepository repository) {
public SysConfigService(ISysConfigRepository repository, IAuditLogService auditLogService) {
this.repository = repository;
this.auditLogService = auditLogService;
}
@Override
@@ -28,27 +26,28 @@ public class SysConfigService implements ISysConfigService {
}
@Override
// @Cacheable(value = "sysConfig", key = "#id")
public Mono<SysConfig> findById(Long id) {
return repository.findById(id);
}
@Override
// @Cacheable(value = "sysConfig", key = "#configKey")
public Mono<SysConfig> findByConfigKey(String configKey) {
return repository.findByConfigKeyAndDeletedAtIsNull(configKey);
}
@Override
// @CacheEvict(value = "sysConfig", allEntries = true)
public Mono<SysConfig> save(SysConfig config) {
return repository.save(config);
return repository.save(config)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Config", saved.getId(), "CREATE", saved)
.thenReturn(saved));
}
@Override
// @CacheEvict(value = "sysConfig", key = "#id")
public Mono<Void> deleteById(Long id) {
return repository.deleteByIdAndDeletedAtIsNull(id);
return repository.findById(id)
.flatMap(config -> repository.deleteByIdAndDeletedAtIsNull(id)
.then(AuditLogHelper.record(auditLogService, "Config", id, "DELETE", config, null)))
.then();
}
@Override
@@ -1,5 +1,7 @@
package cn.novalon.gym.manage.sys.core.service.impl;
import cn.novalon.gym.manage.sys.audit.AuditLogHelper;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import cn.novalon.gym.manage.sys.core.domain.SysDictType;
import cn.novalon.gym.manage.sys.core.repository.ISysDictTypeRepository;
import cn.novalon.gym.manage.sys.core.service.ISysDictTypeService;
@@ -7,19 +9,15 @@ import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* 字典类型服务实现类
*
* @author 张翔
* @date 2026-03-14
*/
@Service
public class SysDictTypeService implements ISysDictTypeService {
private final ISysDictTypeRepository repository;
private final IAuditLogService auditLogService;
public SysDictTypeService(ISysDictTypeRepository repository) {
public SysDictTypeService(ISysDictTypeRepository repository, IAuditLogService auditLogService) {
this.repository = repository;
this.auditLogService = auditLogService;
}
@Override
@@ -39,11 +37,16 @@ public class SysDictTypeService implements ISysDictTypeService {
@Override
public Mono<SysDictType> save(SysDictType dictType) {
return repository.save(dictType);
return repository.save(dictType)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Dict", saved.getId(), "CREATE", saved)
.thenReturn(saved));
}
@Override
public Mono<Void> deleteById(Long id) {
return repository.deleteByIdAndDeletedAtIsNull(id);
return repository.findById(id)
.flatMap(dict -> repository.deleteByIdAndDeletedAtIsNull(id)
.then(AuditLogHelper.record(auditLogService, "Dict", id, "DELETE", dict, null)))
.then();
}
}
@@ -6,6 +6,8 @@ import cn.novalon.gym.manage.sys.core.service.ISysMenuService;
import cn.novalon.gym.manage.sys.core.command.CreateMenuCommand;
import cn.novalon.gym.manage.sys.core.command.UpdateMenuCommand;
import cn.novalon.gym.manage.common.util.StatusConstants;
import cn.novalon.gym.manage.sys.audit.AuditLogHelper;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -24,9 +26,11 @@ import java.util.stream.Collectors;
public class SysMenuService implements ISysMenuService {
private final ISysMenuRepository menuRepository;
private final IAuditLogService auditLogService;
public SysMenuService(ISysMenuRepository menuRepository) {
public SysMenuService(ISysMenuRepository menuRepository, IAuditLogService auditLogService) {
this.menuRepository = menuRepository;
this.auditLogService = auditLogService;
}
@Override
@@ -46,8 +50,9 @@ public class SysMenuService implements ISysMenuService {
@Override
public Mono<SysMenu> createMenu(SysMenu menu) {
menu.setCreatedAt(LocalDateTime.now());
return menuRepository.save(menu);
return menuRepository.save(menu)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Menu", saved.getId(), "CREATE", saved)
.thenReturn(saved));
}
@Override
@@ -60,14 +65,18 @@ public class SysMenuService implements ISysMenuService {
menu.setComponent(command.component());
menu.setPerms(command.perms());
menu.setStatus(command.status() != null ? command.status() : StatusConstants.ENABLED);
menu.setCreatedAt(LocalDateTime.now());
return menuRepository.save(menu);
return menuRepository.save(menu)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Menu", saved.getId(), "CREATE", saved)
.thenReturn(saved));
}
@Override
public Mono<SysMenu> updateMenu(SysMenu menu) {
menu.setUpdatedAt(LocalDateTime.now());
return menuRepository.save(menu);
return menuRepository.findById(menu.getId())
.flatMap(before -> menuRepository.update(menu)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Menu", saved.getId(), "UPDATE", before, saved)
.thenReturn(saved)));
}
@Override
@@ -75,6 +84,15 @@ public class SysMenuService implements ISysMenuService {
return menuRepository.findById(command.id())
.switchIfEmpty(Mono.error(new RuntimeException("Menu not found")))
.flatMap(menu -> {
SysMenu before = new SysMenu();
before.setId(menu.getId());
before.setParentId(menu.getParentId());
before.setMenuName(menu.getMenuName());
before.setMenuType(menu.getMenuType());
before.setOrderNum(menu.getOrderNum());
before.setComponent(menu.getComponent());
before.setPerms(menu.getPerms());
before.setStatus(menu.getStatus());
if (command.parentId() != null) {
menu.setParentId(command.parentId());
}
@@ -97,13 +115,18 @@ public class SysMenuService implements ISysMenuService {
menu.setStatus(command.status());
}
menu.setUpdatedAt(LocalDateTime.now());
return menuRepository.save(menu);
return menuRepository.update(menu)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Menu", saved.getId(), "UPDATE", before, saved)
.thenReturn(saved));
});
}
@Override
public Mono<Void> deleteMenu(Long id) {
return menuRepository.deleteById(id);
return menuRepository.findById(id)
.flatMap(menu -> menuRepository.deleteById(id)
.then(AuditLogHelper.record(auditLogService, "Menu", id, "DELETE", menu, null)))
.then();
}
@Override
@@ -1,11 +1,15 @@
package cn.novalon.gym.manage.sys.core.service.impl;
import cn.novalon.gym.manage.common.util.StatusConstants;
import cn.novalon.gym.manage.sys.audit.AuditLogHelper;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import cn.novalon.gym.manage.sys.core.domain.SysPermission;
import cn.novalon.gym.manage.sys.core.domain.SysRolePermission;
import cn.novalon.gym.manage.sys.core.repository.ISysPermissionRepository;
import cn.novalon.gym.manage.sys.core.repository.ISysRolePermissionRepository;
import cn.novalon.gym.manage.sys.core.service.ISysPermissionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -24,13 +28,18 @@ import java.util.List;
@Service
public class SysPermissionService implements ISysPermissionService {
private static final Logger logger = LoggerFactory.getLogger(SysPermissionService.class);
private final ISysPermissionRepository permissionRepository;
private final ISysRolePermissionRepository rolePermissionRepository;
private final IAuditLogService auditLogService;
public SysPermissionService(ISysPermissionRepository permissionRepository,
ISysRolePermissionRepository rolePermissionRepository) {
ISysRolePermissionRepository rolePermissionRepository,
IAuditLogService auditLogService) {
this.permissionRepository = permissionRepository;
this.rolePermissionRepository = rolePermissionRepository;
this.auditLogService = auditLogService;
}
@Override
@@ -60,25 +69,41 @@ public class SysPermissionService implements ISysPermissionService {
@Override
public Mono<SysPermission> createPermission(SysPermission permission) {
permission.setCreatedAt(LocalDateTime.now());
if (permission.getStatus() == null) {
permission.setStatus(StatusConstants.ENABLED);
}
return permissionRepository.save(permission);
return permissionRepository.save(permission)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Permission", saved.getId(), "CREATE", saved)
.doOnError(e -> logger.error("Audit log failed for Permission CREATE id={}: {}", saved.getId(), e.getMessage()))
.thenReturn(saved));
}
@Override
public Mono<SysPermission> updatePermission(SysPermission permission) {
permission.setUpdatedAt(LocalDateTime.now());
return permissionRepository.updatePermission(permission);
return permissionRepository.findById(permission.getId())
.flatMap(before -> permissionRepository.updatePermission(permission)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Permission", saved.getId(), "UPDATE", before, saved)
.thenReturn(saved)));
}
@Override
public Mono<Void> deletePermission(Long id) {
return permissionRepository.findById(id)
.flatMap(permission -> {
SysPermission before = new SysPermission();
before.setId(permission.getId());
before.setPermissionName(permission.getPermissionName());
before.setPermissionCode(permission.getPermissionCode());
before.setResource(permission.getResource());
before.setAction(permission.getAction());
before.setStatus(permission.getStatus());
before.setCreatedAt(permission.getCreatedAt());
before.setUpdatedAt(permission.getUpdatedAt());
before.setDeletedAt(permission.getDeletedAt());
permission.delete();
return permissionRepository.updatePermission(permission)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Permission", id, "DELETE", before, saved))
.then(rolePermissionRepository.deleteByPermissionId(id));
});
}
@@ -107,7 +132,6 @@ public class SysPermissionService implements ISysPermissionService {
SysRolePermission rolePermission = new SysRolePermission();
rolePermission.setRoleId(roleId);
rolePermission.setPermissionId(permissionId);
rolePermission.setCreatedAt(LocalDateTime.now());
return rolePermissionRepository.save(rolePermission);
})
.then());
@@ -1,6 +1,8 @@
package cn.novalon.gym.manage.sys.core.service.impl;
import cn.novalon.gym.manage.common.util.StatusConstants;
import cn.novalon.gym.manage.sys.audit.AuditLogHelper;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import cn.novalon.gym.manage.sys.core.domain.SysRole;
import cn.novalon.gym.manage.sys.core.query.SysRoleQuery;
import cn.novalon.gym.manage.sys.core.repository.ISysRoleRepository;
@@ -21,12 +23,6 @@ import reactor.core.publisher.Mono;
import java.time.LocalDateTime;
/**
* 系统角色服务实现类
*
* @author 张翔
* @date 2026-03-14
*/
@Service
public class SysRoleService implements ISysRoleService {
@@ -35,13 +31,16 @@ public class SysRoleService implements ISysRoleService {
private final ISysUserService userService;
private final IUserRoleRepository userRoleRepository;
private final ISysRolePermissionRepository rolePermissionRepository;
private final IAuditLogService auditLogService;
public SysRoleService(ISysRoleRepository roleRepository, ISysUserService userService,
IUserRoleRepository userRoleRepository, ISysRolePermissionRepository rolePermissionRepository) {
IUserRoleRepository userRoleRepository, ISysRolePermissionRepository rolePermissionRepository,
IAuditLogService auditLogService) {
this.roleRepository = roleRepository;
this.userService = userService;
this.userRoleRepository = userRoleRepository;
this.rolePermissionRepository = rolePermissionRepository;
this.auditLogService = auditLogService;
}
@Override
@@ -76,7 +75,9 @@ public class SysRoleService implements ISysRoleService {
if (role.getStatus() == null) {
role.setStatus(StatusConstants.ENABLED);
}
return roleRepository.save(role);
return roleRepository.save(role)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Role", saved.getId(), "CREATE", saved)
.thenReturn(saved));
}
@Override
@@ -88,13 +89,18 @@ public class SysRoleService implements ISysRoleService {
role.setRoleSort(command.roleSort());
role.setStatus(command.status() != null ? command.status() : StatusConstants.ENABLED);
role.setCreatedAt(LocalDateTime.now());
return roleRepository.save(role);
return roleRepository.save(role)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Role", saved.getId(), "CREATE", saved)
.thenReturn(saved));
}
@Override
public Mono<SysRole> updateRole(SysRole role) {
role.setUpdatedAt(LocalDateTime.now());
return roleRepository.save(role);
return roleRepository.findById(role.getId())
.flatMap(before -> roleRepository.updateRole(role)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Role", saved.getId(), "UPDATE", before, saved)
.thenReturn(saved)));
}
@Override
@@ -102,6 +108,15 @@ public class SysRoleService implements ISysRoleService {
return roleRepository.findById(command.id())
.switchIfEmpty(Mono.error(new RuntimeException("Role not found")))
.flatMap(role -> {
SysRole before = new SysRole();
before.setId(role.getId());
before.setRoleName(role.getRoleName());
before.setRoleKey(role.getRoleKey());
before.setRoleSort(role.getRoleSort());
before.setStatus(role.getStatus());
before.setCreatedAt(role.getCreatedAt());
before.setUpdatedAt(role.getUpdatedAt());
before.setDeletedAt(role.getDeletedAt());
if (command.roleName() != null) {
role.setRoleName(command.roleName());
}
@@ -115,7 +130,9 @@ public class SysRoleService implements ISysRoleService {
role.setStatus(command.status());
}
role.setUpdatedAt(LocalDateTime.now());
return roleRepository.save(role);
return roleRepository.updateRole(role)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Role", saved.getId(), "UPDATE", before, saved)
.thenReturn(saved));
});
}
@@ -123,7 +140,7 @@ public class SysRoleService implements ISysRoleService {
@Transactional(transactionManager = "connectionFactoryTransactionManager")
public Mono<Void> deleteRole(Long id) {
logger.debug("开始删除角色,ID: {}", id);
return roleRepository.findById(id)
.flatMap(role -> {
logger.debug("找到角色,开始删除关联记录");
@@ -138,7 +155,8 @@ public class SysRoleService implements ISysRoleService {
.doOnError(e -> logger.error("更新用户角色ID失败", e))
.then(roleRepository.deleteById(id))
.doOnSuccess(v -> logger.debug("成功删除角色"))
.doOnError(e -> logger.error("删除角色失败", e));
.doOnError(e -> logger.error("删除角色失败", e))
.then(AuditLogHelper.record(auditLogService, "Role", id, "DELETE", role, null));
});
}
@@ -156,8 +174,19 @@ public class SysRoleService implements ISysRoleService {
public Mono<SysRole> logicalDeleteRole(Long id) {
return roleRepository.findByIdIncludingDeleted(id)
.flatMap(role -> {
SysRole before = new SysRole();
before.setId(role.getId());
before.setRoleName(role.getRoleName());
before.setRoleKey(role.getRoleKey());
before.setRoleSort(role.getRoleSort());
before.setStatus(role.getStatus());
before.setCreatedAt(role.getCreatedAt());
before.setUpdatedAt(role.getUpdatedAt());
before.setDeletedAt(role.getDeletedAt());
role.delete();
return roleRepository.updateRole(role);
return roleRepository.updateRole(role)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "Role", saved.getId(), "DELETE", before, saved)
.thenReturn(saved));
});
}
@@ -1,6 +1,8 @@
package cn.novalon.gym.manage.sys.core.service.impl;
import cn.novalon.gym.manage.common.util.StatusConstants;
import cn.novalon.gym.manage.sys.audit.AuditLogHelper;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import cn.novalon.gym.manage.sys.core.domain.SysUser;
import cn.novalon.gym.manage.sys.core.domain.SysRole;
import cn.novalon.gym.manage.sys.core.domain.UserRole;
@@ -26,16 +28,6 @@ import reactor.core.publisher.Mono;
import java.time.LocalDateTime;
import java.util.List;
/**
* 用户服务实现类
*
* 文件定义:实现用户管理的核心业务逻辑
* 涉及业务:用户注册、登录、信息修改、删除、密码修改、逻辑删除等用户生命周期管理
* 算法:使用R2DBC进行响应式数据库操作,支持分页查询、条件查询、批量操作
*
* @author 张翔
* @date 2026-03-13
*/
@Service
public class SysUserService implements ISysUserService {
@@ -44,15 +36,18 @@ public class SysUserService implements ISysUserService {
private final ISysRoleRepository roleRepository;
private final IUserRoleRepository userRoleRepository;
private final PasswordEncoder passwordEncoder;
private final IAuditLogService auditLogService;
public SysUserService(ISysUserRepository userRepository,
ISysRoleRepository roleRepository,
IUserRoleRepository userRoleRepository,
@Qualifier("passwordEncoder") PasswordEncoder passwordEncoder) {
@Qualifier("passwordEncoder") PasswordEncoder passwordEncoder,
IAuditLogService auditLogService) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
this.userRoleRepository = userRoleRepository;
this.passwordEncoder = passwordEncoder;
this.auditLogService = auditLogService;
logger.info("使用的密码编码器类型: {}", passwordEncoder.getClass().getName());
}
@@ -113,7 +108,9 @@ public class SysUserService implements ISysUserService {
if (user.getStatus() == null) {
user.setStatus(StatusConstants.ENABLED);
}
return userRepository.save(user);
return userRepository.save(user)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "User", saved.getId(), "CREATE", saved)
.thenReturn(saved));
}
@Override
@@ -127,13 +124,18 @@ public class SysUserService implements ISysUserService {
user.setPhone(command.phone());
user.setRoleId(command.roleId());
user.setStatus(command.status() != null ? command.status() : StatusConstants.ENABLED);
return userRepository.save(user);
return userRepository.save(user)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "User", saved.getId(), "CREATE", saved)
.thenReturn(saved));
}
@Override
public Mono<SysUser> updateUser(SysUser user) {
user.setUpdatedAt(LocalDateTime.now());
return userRepository.save(user);
return userRepository.findById(user.getId())
.flatMap(before -> userRepository.update(user)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "User", saved.getId(), "UPDATE", before, saved)
.thenReturn(saved)));
}
@Override
@@ -141,6 +143,17 @@ public class SysUserService implements ISysUserService {
return userRepository.findById(command.id())
.switchIfEmpty(Mono.error(new RuntimeException("User not found")))
.flatMap(user -> {
SysUser before = new SysUser();
before.setId(user.getId());
before.setUsername(user.getUsername());
before.setEmail(user.getEmail());
before.setNickname(user.getNickname());
before.setPhone(user.getPhone());
before.setRoleId(user.getRoleId());
before.setStatus(user.getStatus());
before.setCreatedAt(user.getCreatedAt());
before.setUpdatedAt(user.getUpdatedAt());
before.setDeletedAt(user.getDeletedAt());
if (command.username() != null) {
user.setUsername(command.username());
}
@@ -159,7 +172,10 @@ public class SysUserService implements ISysUserService {
user.setStatus(command.status());
}
user.setUpdatedAt(LocalDateTime.now());
return userRepository.save(user);
return userRepository.update(user)
.flatMap(saved -> AuditLogHelper
.record(auditLogService, "User", saved.getId(), "UPDATE", before, saved)
.thenReturn(saved));
});
}
@@ -177,7 +193,8 @@ public class SysUserService implements ISysUserService {
.doOnError(e -> logger.error("删除用户角色关联记录失败", e))
.then(userRepository.deleteById(id))
.doOnSuccess(v -> logger.debug("成功删除用户"))
.doOnError(e -> logger.error("删除用户失败", e));
.doOnError(e -> logger.error("删除用户失败", e))
.then(AuditLogHelper.record(auditLogService, "User", id, "DELETE", user, null));
});
}
@@ -195,7 +212,10 @@ public class SysUserService implements ISysUserService {
}
user.setPassword(passwordEncoder.encode(newPassword));
user.setUpdatedAt(LocalDateTime.now());
return userRepository.save(user);
return userRepository.update(user)
.flatMap(saved -> AuditLogHelper
.record(auditLogService, "User", saved.getId(), "UPDATE", saved)
.thenReturn(saved));
});
}
@@ -217,8 +237,20 @@ public class SysUserService implements ISysUserService {
public Mono<Void> logicalDeleteUser(Long id) {
return userRepository.findByIdIncludingDeleted(id)
.flatMap(user -> {
SysUser before = new SysUser();
before.setId(user.getId());
before.setUsername(user.getUsername());
before.setEmail(user.getEmail());
before.setNickname(user.getNickname());
before.setPhone(user.getPhone());
before.setRoleId(user.getRoleId());
before.setStatus(user.getStatus());
before.setCreatedAt(user.getCreatedAt());
before.setUpdatedAt(user.getUpdatedAt());
before.setDeletedAt(user.getDeletedAt());
user.setDeletedAt(LocalDateTime.now());
return userRepository.save(user);
return userRepository.save(user)
.flatMap(saved -> AuditLogHelper.record(auditLogService, "User", saved.getId(), "DELETE", before, saved));
})
.then();
}
@@ -252,7 +284,8 @@ public class SysUserService implements ISysUserService {
logger.debug("角色列表为空,删除用户的所有角色关联");
return userRoleRepository.deleteByUserId(userId)
.doOnSuccess(v -> logger.debug("成功删除用户的所有角色关联"))
.doOnError(e -> logger.error("删除用户角色关联失败", e));
.doOnError(e -> logger.error("删除用户角色关联失败", e))
.then(AuditLogHelper.record(auditLogService, "User", userId, "UPDATE", null));
}
return userRoleRepository.deleteByUserId(userId)
@@ -265,12 +298,12 @@ public class SysUserService implements ISysUserService {
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());
.then())
.then(AuditLogHelper.record(auditLogService, "User", userId, "UPDATE", null));
}
@Override
@@ -43,6 +43,7 @@ class OperationLogServiceTest {
testLog.setDuration(100L);
testLog.setIp("192.168.1.1");
testLog.setStatus("1");
testLog.setCreatedAt(LocalDateTime.now());
}
@Test
@@ -1,5 +1,6 @@
package cn.novalon.gym.manage.sys.core.service.impl;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import cn.novalon.gym.manage.sys.core.domain.SysConfig;
import cn.novalon.gym.manage.sys.core.repository.ISysConfigRepository;
import org.junit.jupiter.api.BeforeEach;
@@ -26,13 +27,16 @@ class SysConfigServiceTest {
@Mock
private ISysConfigRepository repository;
@Mock
private IAuditLogService auditLogService;
private SysConfigService configService;
private SysConfig testConfig;
@BeforeEach
void setUp() {
configService = new SysConfigService(repository);
configService = new SysConfigService(repository, auditLogService);
testConfig = new SysConfig();
testConfig.setId(1L);
@@ -110,11 +114,13 @@ class SysConfigServiceTest {
@Test
void testDeleteById() {
when(repository.findById(1L)).thenReturn(Mono.just(testConfig));
when(repository.deleteByIdAndDeletedAtIsNull(1L)).thenReturn(Mono.empty());
StepVerifier.create(configService.deleteById(1L))
.verifyComplete();
verify(repository).findById(1L);
verify(repository).deleteByIdAndDeletedAtIsNull(1L);
}
@@ -1,5 +1,6 @@
package cn.novalon.gym.manage.sys.core.service.impl;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import cn.novalon.gym.manage.sys.core.domain.SysDictType;
import cn.novalon.gym.manage.sys.core.repository.ISysDictTypeRepository;
import org.junit.jupiter.api.BeforeEach;
@@ -23,12 +24,15 @@ class SysDictTypeServiceTest {
@Mock
private ISysDictTypeRepository repository;
@Mock
private IAuditLogService auditLogService;
private SysDictTypeService dictTypeService;
private SysDictType testDictType;
@BeforeEach
void setUp() {
dictTypeService = new SysDictTypeService(repository);
dictTypeService = new SysDictTypeService(repository, auditLogService);
testDictType = new SysDictType();
testDictType.setId(1L);
@@ -93,6 +97,7 @@ class SysDictTypeServiceTest {
@Test
void testDeleteById() {
when(repository.findById(1L)).thenReturn(Mono.just(testDictType));
when(repository.deleteByIdAndDeletedAtIsNull(1L)).thenReturn(Mono.empty());
Mono<Void> result = dictTypeService.deleteById(1L);
@@ -100,6 +105,7 @@ class SysDictTypeServiceTest {
StepVerifier.create(result)
.verifyComplete();
verify(repository).findById(1L);
verify(repository).deleteByIdAndDeletedAtIsNull(1L);
}
}
@@ -4,6 +4,7 @@ import cn.novalon.gym.manage.sys.core.domain.SysMenu;
import cn.novalon.gym.manage.sys.core.repository.ISysMenuRepository;
import cn.novalon.gym.manage.sys.core.command.CreateMenuCommand;
import cn.novalon.gym.manage.sys.core.command.UpdateMenuCommand;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -25,12 +26,15 @@ class SysMenuServiceTest {
@Mock
private ISysMenuRepository menuRepository;
@Mock
private IAuditLogService auditLogService;
private SysMenuService menuService;
private SysMenu testMenu;
@BeforeEach
void setUp() {
menuService = new SysMenuService(menuRepository);
menuService = new SysMenuService(menuRepository, auditLogService);
testMenu = new SysMenu();
testMenu.setId(1L);
@@ -129,7 +133,8 @@ class SysMenuServiceTest {
@Test
void testUpdateMenu() {
when(menuRepository.save(any(SysMenu.class))).thenReturn(Mono.just(testMenu));
when(menuRepository.findById(1L)).thenReturn(Mono.just(testMenu));
when(menuRepository.update(any(SysMenu.class))).thenReturn(Mono.just(testMenu));
Mono<SysMenu> result = menuService.updateMenu(testMenu);
@@ -138,7 +143,8 @@ class SysMenuServiceTest {
menu.getUpdatedAt() != null)
.verifyComplete();
verify(menuRepository).save(any(SysMenu.class));
verify(menuRepository).findById(1L);
verify(menuRepository).update(any(SysMenu.class));
}
@Test
@@ -147,7 +153,7 @@ class SysMenuServiceTest {
1L, 0L, "系统管理(更新)", "M", 1, "system", "system:manage", 1);
when(menuRepository.findById(1L)).thenReturn(Mono.just(testMenu));
when(menuRepository.save(any(SysMenu.class))).thenReturn(Mono.just(testMenu));
when(menuRepository.update(any(SysMenu.class))).thenReturn(Mono.just(testMenu));
Mono<SysMenu> result = menuService.updateMenu(command);
@@ -157,7 +163,7 @@ class SysMenuServiceTest {
.verifyComplete();
verify(menuRepository).findById(1L);
verify(menuRepository).save(any(SysMenu.class));
verify(menuRepository).update(any(SysMenu.class));
}
@Test
@@ -200,7 +206,7 @@ class SysMenuServiceTest {
updatedMenu.setUpdatedAt(LocalDateTime.now());
when(menuRepository.findById(1L)).thenReturn(Mono.just(existingMenu));
when(menuRepository.save(any(SysMenu.class))).thenReturn(Mono.just(updatedMenu));
when(menuRepository.update(any(SysMenu.class))).thenReturn(Mono.just(updatedMenu));
UpdateMenuCommand command = new UpdateMenuCommand(
1L, null, null, null, null, null, null, null);
@@ -210,7 +216,7 @@ class SysMenuServiceTest {
.verifyComplete();
verify(menuRepository).findById(1L);
verify(menuRepository).save(any(SysMenu.class));
verify(menuRepository).update(any(SysMenu.class));
}
@Test
@@ -237,7 +243,7 @@ class SysMenuServiceTest {
updatedMenu.setUpdatedAt(LocalDateTime.now());
when(menuRepository.findById(1L)).thenReturn(Mono.just(existingMenu));
when(menuRepository.save(any(SysMenu.class))).thenReturn(Mono.just(updatedMenu));
when(menuRepository.update(any(SysMenu.class))).thenReturn(Mono.just(updatedMenu));
UpdateMenuCommand command = new UpdateMenuCommand(
1L, 2L, "系统管理(更新)", "C", 2, "system_updated", "system:manage_updated", 0);
@@ -247,11 +253,12 @@ class SysMenuServiceTest {
.verifyComplete();
verify(menuRepository).findById(1L);
verify(menuRepository).save(any(SysMenu.class));
verify(menuRepository).update(any(SysMenu.class));
}
@Test
void testDeleteMenu() {
when(menuRepository.findById(1L)).thenReturn(Mono.just(testMenu));
when(menuRepository.deleteById(1L)).thenReturn(Mono.empty());
Mono<Void> result = menuService.deleteMenu(1L);
@@ -259,6 +266,7 @@ class SysMenuServiceTest {
StepVerifier.create(result)
.verifyComplete();
verify(menuRepository).findById(1L);
verify(menuRepository).deleteById(1L);
}
@@ -1,5 +1,6 @@
package cn.novalon.gym.manage.sys.core.service.impl;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import cn.novalon.gym.manage.common.util.StatusConstants;
import cn.novalon.gym.manage.sys.core.domain.SysRole;
import cn.novalon.gym.manage.sys.core.query.SysRoleQuery;
@@ -46,13 +47,16 @@ class SysRoleServiceTest {
@Mock
private ISysRolePermissionRepository rolePermissionRepository;
@Mock
private IAuditLogService auditLogService;
private SysRoleService roleService;
private SysRole testRole;
@BeforeEach
void setUp() {
roleService = new SysRoleService(roleRepository, userService, userRoleRepository, rolePermissionRepository);
roleService = new SysRoleService(roleRepository, userService, userRoleRepository, rolePermissionRepository, auditLogService);
testRole = new SysRole();
testRole.setId(1L);
@@ -206,7 +210,7 @@ class SysRoleServiceTest {
existingRole.setStatus(StatusConstants.ENABLED);
when(roleRepository.findById(1L)).thenReturn(Mono.just(existingRole));
when(roleRepository.save(any(SysRole.class))).thenReturn(Mono.just(testRole));
when(roleRepository.updateRole(any(SysRole.class))).thenReturn(Mono.just(testRole));
cn.novalon.gym.manage.sys.core.command.UpdateRoleCommand command =
new cn.novalon.gym.manage.sys.core.command.UpdateRoleCommand(
@@ -218,7 +222,7 @@ class SysRoleServiceTest {
.verifyComplete();
verify(roleRepository).findById(1L);
verify(roleRepository).save(any(SysRole.class));
verify(roleRepository).updateRole(any(SysRole.class));
}
@Test
@@ -231,7 +235,7 @@ class SysRoleServiceTest {
existingRole.setStatus(StatusConstants.ENABLED);
when(roleRepository.findById(1L)).thenReturn(Mono.just(existingRole));
when(roleRepository.save(any(SysRole.class))).thenReturn(Mono.just(testRole));
when(roleRepository.updateRole(any(SysRole.class))).thenReturn(Mono.just(testRole));
cn.novalon.gym.manage.sys.core.command.UpdateRoleCommand command =
new cn.novalon.gym.manage.sys.core.command.UpdateRoleCommand(
@@ -243,7 +247,7 @@ class SysRoleServiceTest {
.verifyComplete();
verify(roleRepository).findById(1L);
verify(roleRepository).save(any(SysRole.class));
verify(roleRepository).updateRole(any(SysRole.class));
}
@Test
@@ -252,13 +256,15 @@ class SysRoleServiceTest {
updateRole.setId(1L);
updateRole.setRoleName("updated_admin");
when(roleRepository.save(any(SysRole.class))).thenReturn(Mono.just(testRole));
when(roleRepository.findById(1L)).thenReturn(Mono.just(testRole));
when(roleRepository.updateRole(any(SysRole.class))).thenReturn(Mono.just(testRole));
StepVerifier.create(roleService.updateRole(updateRole))
.expectNextMatches(role -> role.getUpdatedAt() != null)
.verifyComplete();
verify(roleRepository).save(any(SysRole.class));
verify(roleRepository).findById(1L);
verify(roleRepository).updateRole(any(SysRole.class));
}
@Test
@@ -1,6 +1,7 @@
package cn.novalon.gym.manage.sys.core.service.impl;
import cn.novalon.gym.manage.common.util.StatusConstants;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import cn.novalon.gym.manage.sys.config.IntegrationTestConfig;
import cn.novalon.gym.manage.sys.core.domain.SysUser;
import cn.novalon.gym.manage.sys.core.domain.SysRole;
@@ -76,6 +77,9 @@ class SysUserServiceIntegrationTest {
@Autowired
private IUserRoleRepository userRoleRepository;
@Autowired
private IAuditLogService auditLogService;
@Autowired
private R2dbcEntityTemplate r2dbcEntityTemplate;
@@ -85,7 +89,7 @@ class SysUserServiceIntegrationTest {
@BeforeEach
void setUp() {
passwordEncoder = new BCryptPasswordEncoder(12);
userService = new SysUserService(userRepository, roleRepository, userRoleRepository, passwordEncoder);
userService = new SysUserService(userRepository, roleRepository, userRoleRepository, passwordEncoder, auditLogService);
r2dbcEntityTemplate.delete(SysUser.class).all().block();
r2dbcEntityTemplate.delete(SysRole.class).all().block();
@@ -1,6 +1,8 @@
package cn.novalon.gym.manage.sys.core.service.impl;
import cn.novalon.gym.manage.common.util.StatusConstants;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import cn.novalon.gym.manage.sys.audit.domain.AuditLog;
import cn.novalon.gym.manage.sys.core.domain.SysUser;
import cn.novalon.gym.manage.sys.core.domain.UserRole;
import cn.novalon.gym.manage.sys.core.repository.ISysUserRepository;
@@ -45,11 +47,14 @@ class SysUserServiceTest {
@Mock
private PasswordEncoder passwordEncoder;
@Mock
private IAuditLogService auditLogService;
private SysUserService userService;
@BeforeEach
void setUp() {
userService = new SysUserService(userRepository, roleRepository, userRoleRepository, passwordEncoder);
userService = new SysUserService(userRepository, roleRepository, userRoleRepository, passwordEncoder, auditLogService);
}
@Test
@@ -164,7 +169,8 @@ class SysUserServiceTest {
user.setUsername("testuser");
user.setEmail("updated@example.com");
when(userRepository.save(any(SysUser.class))).thenReturn(Mono.just(user));
when(userRepository.findById(1L)).thenReturn(Mono.just(user));
when(userRepository.update(any(SysUser.class))).thenReturn(Mono.just(user));
StepVerifier.create(userService.updateUser(user))
.expectNextMatches(updatedUser ->
@@ -173,7 +179,8 @@ class SysUserServiceTest {
)
.verifyComplete();
verify(userRepository, times(1)).save(any(SysUser.class));
verify(userRepository, times(1)).findById(1L);
verify(userRepository, times(1)).update(any(SysUser.class));
}
@Test
@@ -218,7 +225,7 @@ class SysUserServiceTest {
when(userRepository.findById(1L)).thenReturn(Mono.just(user));
when(passwordEncoder.matches("oldPassword", "$2b$12$oldPassword")).thenReturn(true);
when(passwordEncoder.encode("newPassword")).thenReturn("$2b$12$newPassword");
when(userRepository.save(any(SysUser.class))).thenAnswer(invocation -> Mono.just(invocation.getArgument(0)));
when(userRepository.update(any(SysUser.class))).thenAnswer(invocation -> Mono.just(invocation.getArgument(0)));
StepVerifier.create(userService.changePassword(1L, "oldPassword", "newPassword"))
.expectNextMatches(updatedUser ->
@@ -228,7 +235,7 @@ class SysUserServiceTest {
verify(passwordEncoder, times(1)).matches("oldPassword", "$2b$12$oldPassword");
verify(passwordEncoder, times(1)).encode("newPassword");
verify(userRepository, times(1)).save(any(SysUser.class));
verify(userRepository, times(1)).update(any(SysUser.class));
}
@Test
@@ -10,6 +10,7 @@ import cn.novalon.gym.manage.sys.core.service.ISysMenuService;
import cn.novalon.gym.manage.sys.core.service.ISysRoleService;
import cn.novalon.gym.manage.sys.core.service.ISysUserService;
import cn.novalon.gym.manage.sys.core.service.impl.SysMenuService;
import cn.novalon.gym.manage.sys.audit.service.IAuditLogService;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
@@ -61,6 +62,9 @@ class SystemConfigRegressionTest {
@Mock
private ISysMenuRepository menuRepository;
@Mock
private IAuditLogService auditLogService;
private SysUser adminUser;
private SysUser normalUser;
private SysUser guestUser;
@@ -374,7 +378,7 @@ class SystemConfigRegressionTest {
void testAdminUser_MenuManagement() {
/* unused */
ISysMenuService menuService = new SysMenuService(menuRepository);
ISysMenuService menuService = new SysMenuService(menuRepository, auditLogService);
StepVerifier.create(menuService.findAll())
.expectNextCount(0)
@@ -384,7 +388,7 @@ class SystemConfigRegressionTest {
@Test
@DisplayName("3.2 普通用户 - 菜单访问控制")
void testNormalUser_MenuAccess() {
ISysMenuService menuService = new SysMenuService(menuRepository);
ISysMenuService menuService = new SysMenuService(menuRepository, auditLogService);
StepVerifier.create(menuService.findAll())
.expectNextCount(0)
@@ -394,7 +398,7 @@ class SystemConfigRegressionTest {
@Test
@DisplayName("3.3 访客用户 - 菜单访问控制")
void testGuestUser_MenuAccess() {
ISysMenuService menuService = new SysMenuService(menuRepository);
ISysMenuService menuService = new SysMenuService(menuRepository, auditLogService);
StepVerifier.create(menuService.findAll())
.expectNextCount(0)
@@ -404,7 +408,7 @@ class SystemConfigRegressionTest {
@Test
@DisplayName("3.4 菜单树构建 - 管理员视图")
void testMenuTree_Build_Admin() {
ISysMenuService menuService = new SysMenuService(menuRepository);
ISysMenuService menuService = new SysMenuService(menuRepository, auditLogService);
StepVerifier.create(menuService.findAll())
.verifyComplete();
@@ -413,7 +417,7 @@ class SystemConfigRegressionTest {
@Test
@DisplayName("3.5 权限菜单过滤 - 普通用户视图")
void testMenuFilter_NormalUser() {
ISysMenuService menuService = new SysMenuService(menuRepository);
ISysMenuService menuService = new SysMenuService(menuRepository, auditLogService);
StepVerifier.create(menuService.findAll())
.expectNextCount(0)
@@ -423,7 +427,7 @@ class SystemConfigRegressionTest {
@Test
@DisplayName("3.6 权限菜单过滤 - 访客视图")
void testMenuFilter_Guest() {
ISysMenuService menuService = new SysMenuService(menuRepository);
ISysMenuService menuService = new SysMenuService(menuRepository, auditLogService);
StepVerifier.create(menuService.findAll())
.expectNextCount(0)
@@ -472,7 +476,7 @@ class SystemConfigRegressionTest {
@Test
@DisplayName("5.2 大量菜单加载性能测试")
void testLargeMenuLoadPerformance() {
ISysMenuService menuService = new SysMenuService(menuRepository);
ISysMenuService menuService = new SysMenuService(menuRepository, auditLogService);
long startTime = System.currentTimeMillis();
@@ -516,7 +520,7 @@ class SystemConfigRegressionTest {
@Test
@DisplayName("6.3 菜单层级结构完整性")
void testMenuHierarchy_Integrity() {
ISysMenuService menuService = new SysMenuService(menuRepository);
ISysMenuService menuService = new SysMenuService(menuRepository, auditLogService);
StepVerifier.create(menuService.findAll())
.verifyComplete();
+1 -1
View File
@@ -6,7 +6,7 @@
"localStorage": [
{
"name": "token",
"value": "eyJhbGciOiJIUzM4NCJ9.eyJyb2xlcyI6WyJhZG1pbiJdLCJ1c2VySWQiOjEsInVzZXJuYW1lIjoiYWRtaW4iLCJzdWIiOiJhZG1pbiIsImlhdCI6MTc3NjkxMDg2NCwiZXhwIjoxNzc2OTk3MjY0fQ.ejRf_vt3oUCP_KlV9yafkYHusTK3zR0DQNR2sXA0r8A54UlzKHy0c3GgIEUq8av-"
"value": "eyJhbGciOiJIUzM4NCJ9.eyJyb2xlcyI6WyJhZG1pbiJdLCJ1c2VySWQiOjEsInVzZXJuYW1lIjoiYWRtaW4iLCJzdWIiOiJhZG1pbiIsImlhdCI6MTc3NzAxMTQ2OSwiZXhwIjoxNzc3MDk3ODY5fQ.F6Q44miMHrG7vPlthDNPbnx31CSGpBdbPRpJSDJDAyoy6y-vJvlDGd10xiPgnZhj"
},
{
"name": "permission",
+151
View File
@@ -0,0 +1,151 @@
INSERT INTO sys_role (id, role_name, role_key, role_sort, status, create_by, update_by, created_at, updated_at)
VALUES
(1, '超级管理员', 'admin', 1, 1, 'system', 'system', NOW(), NOW()),
(2, '测试管理员', 'test_admin', 2, 1, 'system', 'system', NOW(), NOW()),
(3, '普通用户', 'normal_user', 3, 1, 'system', 'system', NOW(), NOW()),
(4, '访客', 'guest', 4, 1, 'system', 'system', NOW(), NOW());
SELECT setval('sys_role_id_seq', 4);
INSERT INTO sys_user (id, username, password, email, phone, nickname, status, create_by, update_by, created_at, updated_at)
VALUES
(1, 'admin', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'admin@novalon.com', '13800138000', '超级管理员', 1, 'system', 'system', NOW(), NOW()),
(2, 'user', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'user@novalon.com', '13800138001', '普通用户', 1, 'system', 'system', NOW(), NOW()),
(10, 'e2e_test_user', '$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C', 'e2e@test.com', '13900139000', 'E2E测试用户', 1, 'system', 'system', NOW(), NOW())
ON CONFLICT (username) DO UPDATE SET
password = EXCLUDED.password,
status = EXCLUDED.status;
SELECT setval('sys_user_id_seq', 10);
INSERT INTO user_role (user_id, role_id, created_by, created_at)
VALUES
(1, 1, 'system', NOW()),
(2, 3, 'system', NOW()),
(10, 1, 'system', NOW())
ON CONFLICT (user_id, role_id) DO NOTHING;
INSERT INTO sys_permission (permission_name, permission_code, resource, action, description, status, create_by, update_by, created_at, updated_at) VALUES
('用户查看', 'system:user:view', '/api/users', 'GET', '查看用户列表', 1, 'system', 'system', NOW(), NOW()),
('用户创建', 'system:user:create', '/api/users', 'POST', '创建用户', 1, 'system', 'system', NOW(), NOW()),
('用户编辑', 'system:user:edit', '/api/users', 'PUT', '编辑用户', 1, 'system', 'system', NOW(), NOW()),
('用户删除', 'system:user:delete', '/api/users', 'DELETE', '删除用户', 1, 'system', 'system', NOW(), NOW()),
('角色查看', 'system:role:view', '/api/roles', 'GET', '查看角色列表', 1, 'system', 'system', NOW(), NOW()),
('角色创建', 'system:role:create', '/api/roles', 'POST', '创建角色', 1, 'system', 'system', NOW(), NOW()),
('角色编辑', 'system:role:edit', '/api/roles', 'PUT', '编辑角色', 1, 'system', 'system', NOW(), NOW()),
('角色删除', 'system:role:delete', '/api/roles', 'DELETE', '删除角色', 1, 'system', 'system', NOW(), NOW()),
('角色分配权限', 'system:role:assign', '/api/roles/*/permissions', 'POST', '为角色分配权限', 1, 'system', 'system', NOW(), NOW()),
('权限查看', 'system:permission:view', '/api/permissions', 'GET', '查看权限列表', 1, 'system', 'system', NOW(), NOW()),
('权限创建', 'system:permission:create', '/api/permissions', 'POST', '创建权限', 1, 'system', 'system', NOW(), NOW()),
('权限编辑', 'system:permission:edit', '/api/permissions', 'PUT', '编辑权限', 1, 'system', 'system', NOW(), NOW()),
('权限删除', 'system:permission:delete', '/api/permissions', 'DELETE', '删除权限', 1, 'system', 'system', NOW(), NOW()),
('菜单查看', 'system:menu:view', '/api/menus', 'GET', '查看菜单列表', 1, 'system', 'system', NOW(), NOW()),
('菜单创建', 'system:menu:create', '/api/menus', 'POST', '创建菜单', 1, 'system', 'system', NOW(), NOW()),
('菜单编辑', 'system:menu:edit', '/api/menus', 'PUT', '编辑菜单', 1, 'system', 'system', NOW(), NOW()),
('菜单删除', 'system:menu:delete', '/api/menus', 'DELETE', '删除菜单', 1, 'system', 'system', NOW(), NOW()),
('字典查看', 'system:dict:view', '/api/dict', 'GET', '查看字典列表', 1, 'system', 'system', NOW(), NOW()),
('字典创建', 'system:dict:create', '/api/dict', 'POST', '创建字典', 1, 'system', 'system', NOW(), NOW()),
('字典编辑', 'system:dict:edit', '/api/dict', 'PUT', '编辑字典', 1, 'system', 'system', NOW(), NOW()),
('字典删除', 'system:dict:delete', '/api/dict', 'DELETE', '删除字典', 1, 'system', 'system', NOW(), NOW()),
('配置查看', 'system:config:view', '/api/config', 'GET', '查看系统配置', 1, 'system', 'system', NOW(), NOW()),
('配置创建', 'system:config:create', '/api/config', 'POST', '创建系统配置', 1, 'system', 'system', NOW(), NOW()),
('配置编辑', 'system:config:edit', '/api/config', 'PUT', '编辑系统配置', 1, 'system', 'system', NOW(), NOW()),
('配置删除', 'system:config:delete', '/api/config', 'DELETE', '删除系统配置', 1, 'system', 'system', NOW(), NOW()),
('日志查看', 'system:log:view', '/api/logs', 'GET', '查看日志', 1, 'system', 'system', NOW(), NOW()),
('文件上传', 'system:file:upload', '/api/files/upload', 'POST', '上传文件', 1, 'system', 'system', NOW(), NOW()),
('文件下载', 'system:file:download', '/api/files/download', 'GET', '下载文件', 1, 'system', 'system', NOW(), NOW()),
('文件删除', 'system:file:delete', '/api/files', 'DELETE', '删除文件', 1, 'system', 'system', NOW(), NOW()),
('公告查看', 'system:notice:view', '/api/notices', 'GET', '查看公告', 1, 'system', 'system', NOW(), NOW()),
('公告创建', 'system:notice:create', '/api/notices', 'POST', '创建公告', 1, 'system', 'system', NOW(), NOW()),
('公告编辑', 'system:notice:edit', '/api/notices', 'PUT', '编辑公告', 1, 'system', 'system', NOW(), NOW()),
('公告删除', 'system:notice:delete', '/api/notices', 'DELETE', '删除公告', 1, 'system', 'system', NOW(), NOW());
INSERT INTO sys_role_permission (role_id, permission_id, create_by, update_by, created_at, updated_at)
SELECT 1, id, 'system', 'system', NOW(), NOW() FROM sys_permission WHERE status = 1;
INSERT INTO sys_menu (id, menu_name, parent_id, order_num, menu_type, perms, component, status, created_at, updated_at) VALUES
(1, '系统管理', 0, 1, 'M', NULL, NULL, 1, NOW(), NOW()),
(2, '审计日志', 0, 2, 'M', NULL, NULL, 1, NOW(), NOW()),
(3, '系统监控', 0, 3, 'M', NULL, NULL, 1, NOW(), NOW()),
(11, '用户管理', 1, 1, 'C', 'system:user:list', 'system/user/index', 1, NOW(), NOW()),
(12, '角色管理', 1, 2, 'C', 'system:role:list', 'system/role/index', 1, NOW(), NOW()),
(13, '菜单管理', 1, 3, 'C', 'system:menu:list', 'system/menu/index', 1, NOW(), NOW()),
(14, '部门管理', 1, 4, 'C', 'system:dept:list', 'system/dept/index', 1, NOW(), NOW()),
(15, '字典管理', 1, 5, 'C', 'system:dict:list', 'system/dict/index', 1, NOW(), NOW()),
(16, '参数管理', 1, 6, 'C', 'system:config:list', 'system/config/index', 1, NOW(), NOW()),
(17, '通知公告', 1, 7, 'C', 'system:notice:list', 'system/notice/index', 1, NOW(), NOW()),
(18, '文件管理', 1, 8, 'C', 'system:file:list', 'system/file/index', 1, NOW(), NOW()),
(111, '用户查询', 11, 1, 'F', 'system:user:query', NULL, 1, NOW(), NOW()),
(112, '用户新增', 11, 2, 'F', 'system:user:add', NULL, 1, NOW(), NOW()),
(113, '用户修改', 11, 3, 'F', 'system:user:edit', NULL, 1, NOW(), NOW()),
(114, '用户删除', 11, 4, 'F', 'system:user:remove', NULL, 1, NOW(), NOW()),
(115, '用户导出', 11, 5, 'F', 'system:user:export', NULL, 1, NOW(), NOW()),
(116, '用户导入', 11, 6, 'F', 'system:user:import', NULL, 1, NOW(), NOW()),
(117, '重置密码', 11, 7, 'F', 'system:user:resetPwd', NULL, 1, NOW(), NOW()),
(121, '角色查询', 12, 1, 'F', 'system:role:query', NULL, 1, NOW(), NOW()),
(122, '角色新增', 12, 2, 'F', 'system:role:add', NULL, 1, NOW(), NOW()),
(123, '角色修改', 12, 3, 'F', 'system:role:edit', NULL, 1, NOW(), NOW()),
(124, '角色删除', 12, 4, 'F', 'system:role:remove', NULL, 1, NOW(), NOW()),
(125, '角色导出', 12, 5, 'F', 'system:role:export', NULL, 1, NOW(), NOW()),
(131, '菜单查询', 13, 1, 'F', 'system:menu:query', NULL, 1, NOW(), NOW()),
(132, '菜单新增', 13, 2, 'F', 'system:menu:add', NULL, 1, NOW(), NOW()),
(133, '菜单修改', 13, 3, 'F', 'system:menu:edit', NULL, 1, NOW(), NOW()),
(134, '菜单删除', 13, 4, 'F', 'system:menu:remove', NULL, 1, NOW(), NOW()),
(21, '操作日志', 2, 1, 'C', 'audit:operation:list', 'audit/operation/index', 1, NOW(), NOW()),
(22, '登录日志', 2, 2, 'C', 'audit:login:list', 'audit/login/index', 1, NOW(), NOW()),
(23, '异常日志', 2, 3, 'C', 'audit:exception:list', 'audit/exception/index', 1, NOW(), NOW()),
(211, '操作查询', 21, 1, 'F', 'audit:operation:query', NULL, 1, NOW(), NOW()),
(212, '操作删除', 21, 2, 'F', 'audit:operation:remove', NULL, 1, NOW(), NOW()),
(213, '操作导出', 21, 3, 'F', 'audit:operation:export', NULL, 1, NOW(), NOW()),
(221, '登录查询', 22, 1, 'F', 'audit:login:query', NULL, 1, NOW(), NOW()),
(222, '登录删除', 22, 2, 'F', 'audit:login:remove', NULL, 1, NOW(), NOW()),
(223, '登录导出', 22, 3, 'F', 'audit:login:export', NULL, 1, NOW(), NOW()),
(231, '异常查询', 23, 1, 'F', 'audit:exception:query', NULL, 1, NOW(), NOW()),
(232, '异常删除', 23, 2, 'F', 'audit:exception:remove', NULL, 1, NOW(), NOW()),
(233, '异常导出', 23, 3, 'F', 'audit:exception:export', NULL, 1, NOW(), NOW()),
(31, '在线用户', 3, 1, 'C', 'monitor:online:list', 'monitor/online/index', 1, NOW(), NOW()),
(32, '定时任务', 3, 2, 'C', 'monitor:job:list', 'monitor/job/index', 1, NOW(), NOW()),
(33, '数据监控', 3, 3, 'C', 'monitor:data:list', 'monitor/data/index', 1, NOW(), NOW()),
(34, '服务监控', 3, 4, 'C', 'monitor:server:list', 'monitor/server/index', 1, NOW(), NOW()),
(35, '缓存监控', 3, 5, 'C', 'monitor:cache:list', 'monitor/cache/index', 1, NOW(), NOW()),
(311, '在线查询', 31, 1, 'F', 'monitor:online:query', NULL, 1, NOW(), NOW()),
(312, '在线强退', 31, 2, 'F', 'monitor:online:forceLogout', NULL, 1, NOW(), NOW()),
(321, '任务查询', 32, 1, 'F', 'monitor:job:query', NULL, 1, NOW(), NOW()),
(322, '任务新增', 32, 2, 'F', 'monitor:job:add', NULL, 1, NOW(), NOW()),
(323, '任务修改', 32, 3, 'F', 'monitor:job:edit', NULL, 1, NOW(), NOW()),
(324, '任务删除', 32, 4, 'F', 'monitor:job:remove', NULL, 1, NOW(), NOW()),
(325, '任务执行', 32, 5, 'F', 'monitor:job:execute', NULL, 1, NOW(), NOW());
SELECT setval('sys_menu_id_seq', 400);
INSERT INTO sys_dict_type (dict_name, dict_type, status, remark, create_by, update_by, created_at, updated_at)
VALUES
('用户状态', 'user_status', '0', '用户状态列表', 'system', 'system', NOW(), NOW()),
('菜单状态', 'menu_status', '0', '菜单状态列表', 'system', 'system', NOW(), NOW()),
('角色状态', 'role_status', '0', '角色状态列表', 'system', 'system', NOW(), NOW()),
('系统开关', 'sys_normal_disable', '0', '系统开关列表', 'system', 'system', NOW(), NOW())
ON CONFLICT (dict_type) DO NOTHING;
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, update_by, created_at, updated_at)
VALUES
(1, '正常', '1', 'user_status', '', 'primary', 'Y', '0', 'system', 'system', NOW(), NOW()),
(2, '停用', '0', 'user_status', '', 'danger', 'N', '0', 'system', 'system', NOW(), NOW()),
(1, '正常', '0', 'menu_status', '', 'primary', 'Y', '0', 'system', 'system', NOW(), NOW()),
(2, '停用', '1', 'menu_status', '', 'danger', 'N', '0', 'system', 'system', NOW(), NOW()),
(1, '正常', '0', 'role_status', '', 'primary', 'Y', '0', 'system', 'system', NOW(), NOW()),
(2, '停用', '1', 'role_status', '', 'danger', 'N', '0', 'system', 'system', NOW(), NOW()),
(1, '正常', '0', 'sys_normal_disable', '', 'primary', 'Y', '0', 'system', 'system', NOW(), NOW()),
(2, '停用', '1', 'sys_normal_disable', '', 'danger', 'N', '0', 'system', 'system', NOW(), NOW());
INSERT INTO sys_config (config_name, config_key, config_value, config_type, create_by, update_by, created_at, updated_at)
VALUES
('用户管理-用户初始密码', 'sys.user.initPassword', '123456', 'Y', 'system', 'system', NOW(), NOW()),
('主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'system', 'system', NOW(), NOW()),
('用户自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'system', 'system', NOW(), NOW()),
('用户自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'system', 'system', NOW(), NOW()),
('账号自助-密码验证码', 'sys.account.pwdCaptchaEnabled', 'true', 'Y', 'system', 'system', NOW(), NOW())
ON CONFLICT (config_key) DO NOTHING;
SELECT setval('sys_dict_type_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_dict_type));
SELECT setval('sys_dict_data_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_dict_data));
SELECT setval('sys_config_id_seq', (SELECT COALESCE(MAX(id), 1) FROM sys_config));
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));
+41
View File
@@ -0,0 +1,41 @@
TRUNCATE TABLE
audit_log_archive,
audit_log,
operation_log,
sys_operation_log,
sys_exception_log,
sys_login_log,
sys_user_message,
sys_role_permission,
user_role,
sys_permission,
sys_file,
sys_notice,
sys_user,
sys_role,
sys_menu,
sys_dict_data,
sys_dict_type,
sys_dictionary,
sys_config,
oauth2_client
CASCADE;
SELECT setval('sys_user_id_seq', 1, false);
SELECT setval('sys_role_id_seq', 1, false);
SELECT setval('sys_menu_id_seq', 1, false);
SELECT setval('sys_permission_id_seq', 1, false);
SELECT setval('sys_role_permission_id_seq', 1, false);
SELECT setval('user_role_id_seq', 1, false);
SELECT setval('sys_dict_type_id_seq', 1, false);
SELECT setval('sys_dict_data_id_seq', 1, false);
SELECT setval('sys_config_id_seq', 1, false);
SELECT setval('sys_file_id_seq', 1, false);
SELECT setval('sys_notice_id_seq', 1, false);
SELECT setval('operation_log_id_seq', 1, false);
SELECT setval('audit_log_id_seq', 1, false);
SELECT setval('sys_login_log_id_seq', 1, false);
SELECT setval('sys_exception_log_id_seq', 1, false);
SELECT setval('sys_user_message_id_seq', 1, false);
SELECT setval('oauth2_client_id_seq', 1, false);
SELECT setval('audit_log_archive_id_seq', 1, false);