diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..336f6a3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +# https://hub.docker.com/_/eclipse-temurin/tags?page=1&name=alpine +FROM eclipse-temurin:17.0.7_7-jre-alpine +COPY ./bootstrap/target/*.jar ./app.jar +COPY entrypoint.sh / +RUN chmod +x ./entrypoint.sh && \ + ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone +ENTRYPOINT ["./entrypoint.sh"] diff --git a/api/admin-api/pom.xml b/api/admin-api/pom.xml index b2ff804..a39fabc 100644 --- a/api/admin-api/pom.xml +++ b/api/admin-api/pom.xml @@ -8,19 +8,19 @@ cc.uncarbon.module helio-boot-modular - 2.1.0 + 2.2.0 ../../pom.xml admin-api - 2.1.0 + 2.2.0 - 2.1.0 + 2.2.0 - 2.1.0 + 2.2.0 diff --git a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/aspect/extension/SysLogAspectExtensionForSysUserLogin.java b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/aspect/extension/SysLogAspectExtensionForSysUserLogin.java index abccd92..ad50d81 100644 --- a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/aspect/extension/SysLogAspectExtensionForSysUserLogin.java +++ b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/aspect/extension/SysLogAspectExtensionForSysUserLogin.java @@ -1,24 +1,24 @@ -package cc.uncarbon.module.adminapi.aspect.extension; - -import cc.uncarbon.module.sys.annotation.SysLog; -import cc.uncarbon.module.sys.extension.impl.DefaultSysLogAspectExtension; -import cc.uncarbon.module.sys.model.request.AdminInsertSysLogDTO; -import cc.uncarbon.module.sys.model.request.SysUserLoginDTO; -import lombok.NoArgsConstructor; -import org.aspectj.lang.JoinPoint; - -/** - * SysLog 切面实现类扩展 for 登录后台用户 - */ -@NoArgsConstructor -public class SysLogAspectExtensionForSysUserLogin extends DefaultSysLogAspectExtension { - - @Override - public void beforeSaving(AdminInsertSysLogDTO insertSysLogDTO, JoinPoint joinPoint, SysLog annotation, Throwable e, Object ret) { - for (Object arg : joinPoint.getArgs()) { - if (arg instanceof SysUserLoginDTO dto) { - insertSysLogDTO.setUsername(dto.getUsername()); - } - } - } -} +package cc.uncarbon.module.adminapi.aspect.extension; + +import cc.uncarbon.module.sys.annotation.SysLog; +import cc.uncarbon.module.sys.extension.impl.DefaultSysLogAspectExtension; +import cc.uncarbon.module.sys.model.request.AdminInsertSysLogDTO; +import cc.uncarbon.module.sys.model.request.SysUserLoginDTO; +import lombok.NoArgsConstructor; +import org.aspectj.lang.JoinPoint; + +/** + * SysLog 切面实现类扩展 for 登录后台用户 + */ +@NoArgsConstructor +public class SysLogAspectExtensionForSysUserLogin extends DefaultSysLogAspectExtension { + + @Override + public void beforeSaving(AdminInsertSysLogDTO insertSysLogDTO, JoinPoint joinPoint, SysLog annotation, Throwable e, Object ret) { + for (Object arg : joinPoint.getArgs()) { + if (arg instanceof SysUserLoginDTO dto) { + insertSysLogDTO.setUsername(dto.getUsername()); + } + } + } +} diff --git a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/constant/AdminApiConstant.java b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/constant/AdminApiConstant.java index 980204a..f67b564 100644 --- a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/constant/AdminApiConstant.java +++ b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/constant/AdminApiConstant.java @@ -1,16 +1,16 @@ -package cc.uncarbon.module.adminapi.constant; - - -/** - * 后台管理接口常量 - */ -public final class AdminApiConstant { - private AdminApiConstant() { - } - - /** - * HTTP-API路由前缀 - */ - public static final String HTTP_API_URL_PREFIX = "/admin"; - -} +package cc.uncarbon.module.adminapi.constant; + + +/** + * 后台管理接口常量 + */ +public final class AdminApiConstant { + private AdminApiConstant() { + } + + /** + * HTTP-API路由前缀 + */ + public static final String HTTP_API_URL_PREFIX = "/admin"; + +} diff --git a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/enums/AdminApiErrorEnum.java b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/enums/AdminApiErrorEnum.java index de2f518..4367b2f 100644 --- a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/enums/AdminApiErrorEnum.java +++ b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/enums/AdminApiErrorEnum.java @@ -13,13 +13,9 @@ public enum AdminApiErrorEnum implements HelioBaseEnum { CAPTCHA_GENERATE_FAILED(500, "验证码生成失败,请稍后再试"), - CAPTCHA_VALIDATE_FAILED(400, "验证码不正确,请重新输入"), - - /** - * 很少遇到;但是如果出现了只会提示默认的「请稍后再试」,不方便排查,还是整个文案比较好 - */ - UPLOAD_FILE_NOT_EXIST(400, "欲上传的文件可能已被删除,请重新选择"); + // 很少遇到;但是如果出现了只会提示默认的「请稍后再试」,不方便排查,还是整个文案比较好 + UPLOAD_FILE_NOT_EXIST(400, "欲上传的文件可能已被删除,请重新选择"),; private final Integer value; private final String label; diff --git a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/event/KickOutSysUsersEvent.java b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/event/KickOutSysUsersEvent.java index f256442..bd38b77 100644 --- a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/event/KickOutSysUsersEvent.java +++ b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/event/KickOutSysUsersEvent.java @@ -1,32 +1,32 @@ -package cc.uncarbon.module.adminapi.event; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.springframework.context.ApplicationEvent; - -import java.util.Collection; - -/** - * 强制登出后台用户事件 - */ -@Getter -public final class KickOutSysUsersEvent extends ApplicationEvent { - - private final transient EventData data; - - public KickOutSysUsersEvent(EventData data) { - super(data); - this.data = data; - } - - @Getter - @RequiredArgsConstructor - public static final class EventData { - - /** - * 需要被强制登出的后台用户IDs - */ - private final Collection sysUserIds; - - } -} +package cc.uncarbon.module.adminapi.event; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEvent; + +import java.util.Collection; + +/** + * 强制登出后台用户事件 + */ +@Getter +public final class KickOutSysUsersEvent extends ApplicationEvent { + + private final transient EventData data; + + public KickOutSysUsersEvent(EventData data) { + super(data); + this.data = data; + } + + @Getter + @RequiredArgsConstructor + public static final class EventData { + + /** + * 需要被强制登出的后台用户IDs + */ + private final Collection sysUserIds; + + } +} diff --git a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/helper/CaptchaHelper.java b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/helper/CaptchaHelper.java index 46880d4..ea40059 100644 --- a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/helper/CaptchaHelper.java +++ b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/helper/CaptchaHelper.java @@ -1,94 +1,94 @@ -package cc.uncarbon.module.adminapi.helper; - -import cc.uncarbon.framework.core.exception.BusinessException; -import cc.uncarbon.module.adminapi.enums.AdminApiErrorEnum; -import cc.uncarbon.module.adminapi.model.interior.AdminCaptchaContainer; -import cn.hutool.captcha.CaptchaUtil; -import cn.hutool.captcha.ShearCaptcha; -import cn.hutool.core.date.LocalDateTimeUtil; -import cn.hutool.core.lang.UUID; -import cn.hutool.core.text.CharSequenceUtil; -import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Component; - -import java.time.LocalDateTime; -import java.time.temporal.ChronoUnit; -import java.util.concurrent.TimeUnit; - -/** - * 验证码助手类;可将验证码答案缓存至 Redis - * - * @author Uncarbon - */ -@Component -@RequiredArgsConstructor -public class CaptchaHelper { - - private final RedisTemplate stringRedisTemplate; - - private static final String CACHE_KEY_CAPTCHA_ANSWER = "Authorization:captcha:uuid_%s"; - - /** - * 验证码答案长度 - */ - private static final int CAPTCHA_ANSWER_LENGTH = 4; - - /** - * 生成一个验证码 - */ - public AdminCaptchaContainer generate() { - // redis预占位;随机10个UUID,应该有个能成的吧…… - UUID uuid = UUID.randomUUID(); - String captchaCacheKey = null; - Boolean stubFlag = Boolean.FALSE; - for (int count = 0; count < 10; count++) { - captchaCacheKey = String.format(CACHE_KEY_CAPTCHA_ANSWER, uuid.toString(true)); - stubFlag = stringRedisTemplate.opsForValue().setIfAbsent(captchaCacheKey, CharSequenceUtil.EMPTY); - if (Boolean.TRUE.equals(stubFlag)) { - break; - } - uuid = UUID.randomUUID(); - } - if (!Boolean.TRUE.equals(stubFlag)) { - throw new BusinessException(AdminApiErrorEnum.CAPTCHA_GENERATE_FAILED); - } - - // 定义图形验证码的长、宽、验证码字符数、干扰线宽度 - ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(196, 50, CAPTCHA_ANSWER_LENGTH, 4); - - // 将验证码答案保存至 redis, 有效期5分钟 - stringRedisTemplate.opsForValue().set(captchaCacheKey, captcha.getCode(), 300, TimeUnit.SECONDS); - LocalDateTime expiredAt = LocalDateTimeUtil.offset(LocalDateTimeUtil.now(), 300, ChronoUnit.SECONDS); - - return new AdminCaptchaContainer(captcha, uuid.toString(true), expiredAt); - } - - /** - * 核验验证码是否输入正确 - * - * @param uuid 验证码唯一标识(UUID) - * @param captchaAnswer 验证码答案 - * @return 是否正确 - */ - public boolean validate(String uuid, String captchaAnswer) { - if (CharSequenceUtil.hasBlank(uuid, captchaAnswer)) { - return false; - } - - String cacheKey = String.format(CACHE_KEY_CAPTCHA_ANSWER, uuid); - boolean equals; - try { - if (CharSequenceUtil.length(captchaAnswer) != CAPTCHA_ANSWER_LENGTH) { - // 长度不同 - return false; - } - - String answerInRedis = stringRedisTemplate.opsForValue().get(cacheKey); - equals = CharSequenceUtil.equalsIgnoreCase(answerInRedis, captchaAnswer); - } finally { - stringRedisTemplate.delete(cacheKey); - } - return equals; - } -} +package cc.uncarbon.module.adminapi.helper; + +import cc.uncarbon.framework.core.exception.BusinessException; +import cc.uncarbon.module.adminapi.enums.AdminApiErrorEnum; +import cc.uncarbon.module.adminapi.model.interior.AdminCaptchaContainer; +import cn.hutool.captcha.CaptchaUtil; +import cn.hutool.captcha.ShearCaptcha; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.lang.UUID; +import cn.hutool.core.text.CharSequenceUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.concurrent.TimeUnit; + +/** + * 验证码助手类;可将验证码答案缓存至 Redis + * + * @author Uncarbon + */ +@Component +@RequiredArgsConstructor +public class CaptchaHelper { + + private final RedisTemplate stringRedisTemplate; + + private static final String CACHE_KEY_CAPTCHA_ANSWER = "Authorization:captcha:uuid_%s"; + + /** + * 验证码答案长度 + */ + private static final int CAPTCHA_ANSWER_LENGTH = 4; + + /** + * 生成一个验证码 + */ + public AdminCaptchaContainer generate() { + // redis预占位;随机10个UUID,应该有个能成的吧…… + UUID uuid = UUID.randomUUID(); + String captchaCacheKey = null; + Boolean stubFlag = Boolean.FALSE; + for (int count = 0; count < 10; count++) { + captchaCacheKey = String.format(CACHE_KEY_CAPTCHA_ANSWER, uuid.toString(true)); + stubFlag = stringRedisTemplate.opsForValue().setIfAbsent(captchaCacheKey, CharSequenceUtil.EMPTY); + if (Boolean.TRUE.equals(stubFlag)) { + break; + } + uuid = UUID.randomUUID(); + } + if (!Boolean.TRUE.equals(stubFlag)) { + throw new BusinessException(AdminApiErrorEnum.CAPTCHA_GENERATE_FAILED); + } + + // 定义图形验证码的长、宽、验证码字符数、干扰线宽度 + ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(196, 50, CAPTCHA_ANSWER_LENGTH, 4); + + // 将验证码答案保存至 redis, 有效期5分钟 + stringRedisTemplate.opsForValue().set(captchaCacheKey, captcha.getCode(), 300, TimeUnit.SECONDS); + LocalDateTime expiredAt = LocalDateTimeUtil.offset(LocalDateTimeUtil.now(), 300, ChronoUnit.SECONDS); + + return new AdminCaptchaContainer(captcha, uuid.toString(true), expiredAt); + } + + /** + * 核验验证码是否输入正确 + * + * @param uuid 验证码唯一标识(UUID) + * @param captchaAnswer 验证码答案 + * @return 是否正确 + */ + public boolean validate(String uuid, String captchaAnswer) { + if (CharSequenceUtil.hasBlank(uuid, captchaAnswer)) { + return false; + } + + String cacheKey = String.format(CACHE_KEY_CAPTCHA_ANSWER, uuid); + boolean equals; + try { + if (CharSequenceUtil.length(captchaAnswer) != CAPTCHA_ANSWER_LENGTH) { + // 长度不同 + return false; + } + + String answerInRedis = stringRedisTemplate.opsForValue().get(cacheKey); + equals = CharSequenceUtil.equalsIgnoreCase(answerInRedis, captchaAnswer); + } finally { + stringRedisTemplate.delete(cacheKey); + } + return equals; + } +} diff --git a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/helper/RolePermissionCacheHelper.java b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/helper/RolePermissionCacheHelper.java index 464272c..d5ac51a 100644 --- a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/helper/RolePermissionCacheHelper.java +++ b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/helper/RolePermissionCacheHelper.java @@ -1,82 +1,82 @@ -package cc.uncarbon.module.adminapi.helper; - -import cc.uncarbon.framework.core.context.UserContextHolder; -import cn.hutool.core.collection.CollUtil; -import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Component; - -import java.util.*; - -/** - * 将角色对应权限,缓存至 Redis - * 参考文章: https://sa-token.cc/doc.html#/fun/jur-cache - * - * @author Uncarbon - */ -@Component -@RequiredArgsConstructor -public class RolePermissionCacheHelper { - - private final RedisTemplate> stringSetRedisTemplate; - - private static final String CACHE_KEY_ROLE_PERMISSIONS = "Authorization:rolePermissions:roleId_%s"; - - - /** - * 从缓存中取得当前用户拥有的所有权限名集合 - * - * @return List - */ - public List getUserPermissions() { - Set rolesIds = UserContextHolder.getUserContext().getRolesIds(); - // aka * 64 - List ret = new ArrayList<>(rolesIds.size() << 6); - - rolesIds.forEach( - roleId -> { - String cacheKey = String.format(CACHE_KEY_ROLE_PERMISSIONS, roleId); - ret.addAll(CollUtil.emptyIfNull(stringSetRedisTemplate.opsForValue().get(cacheKey))); - } - ); - - return ret; - } - - /** - * 覆盖更新角色对应权限至 Redis - * - * @param map key=角色ID value=权限集合 - */ - public void putCache(Map> map) { - Set>> entries = map.entrySet(); - entries.forEach( - entry -> this.putCache(entry.getKey(), entry.getValue()) - ); - } - - /** - * 覆盖更新角色对应权限至 Redis - * - * @param roleId 角色ID - * @param newPermissions 新权限名集合 - */ - public void putCache(Long roleId, Set newPermissions) { - String cacheKey = String.format(CACHE_KEY_ROLE_PERMISSIONS, roleId); - stringSetRedisTemplate.opsForValue().set(cacheKey, newPermissions); - } - - /** - * 删除角色ID对应的权限缓存 - * - * @param roleIds 角色ID集合 - */ - public void deleteCache(Collection roleIds) { - roleIds.forEach( - roleId -> { - String cacheKey = String.format(CACHE_KEY_ROLE_PERMISSIONS, roleId); - stringSetRedisTemplate.delete(cacheKey); - } - ); - } -} +package cc.uncarbon.module.adminapi.helper; + +import cc.uncarbon.framework.core.context.UserContextHolder; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.util.*; + +/** + * 将角色对应权限,缓存至 Redis + * 参考文章: https://sa-token.cc/doc.html#/fun/jur-cache + * + * @author Uncarbon + */ +@Component +@RequiredArgsConstructor +public class RolePermissionCacheHelper { + + private final RedisTemplate> stringSetRedisTemplate; + + private static final String CACHE_KEY_ROLE_PERMISSIONS = "Authorization:rolePermissions:roleId_%s"; + + + /** + * 从缓存中取得当前用户拥有的所有权限名集合 + * + * @return List + */ + public List getUserPermissions() { + Set rolesIds = UserContextHolder.getUserContext().getRolesIds(); + // aka * 64 + List ret = new ArrayList<>(rolesIds.size() << 6); + + rolesIds.forEach( + roleId -> { + String cacheKey = String.format(CACHE_KEY_ROLE_PERMISSIONS, roleId); + ret.addAll(CollUtil.emptyIfNull(stringSetRedisTemplate.opsForValue().get(cacheKey))); + } + ); + + return ret; + } + + /** + * 覆盖更新角色对应权限至 Redis + * + * @param map key=角色ID value=权限集合 + */ + public void putCache(Map> map) { + Set>> entries = map.entrySet(); + entries.forEach( + entry -> this.putCache(entry.getKey(), entry.getValue()) + ); + } + + /** + * 覆盖更新角色对应权限至 Redis + * + * @param roleId 角色ID + * @param newPermissions 新权限名集合 + */ + public void putCache(Long roleId, Set newPermissions) { + String cacheKey = String.format(CACHE_KEY_ROLE_PERMISSIONS, roleId); + stringSetRedisTemplate.opsForValue().set(cacheKey, newPermissions); + } + + /** + * 删除角色ID对应的权限缓存 + * + * @param roleIds 角色ID集合 + */ + public void deleteCache(Collection roleIds) { + roleIds.forEach( + roleId -> { + String cacheKey = String.format(CACHE_KEY_ROLE_PERMISSIONS, roleId); + stringSetRedisTemplate.delete(cacheKey); + } + ); + } +} diff --git a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/listener/AdminApiEventListener.java b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/listener/AdminApiEventListener.java index 83c9412..c5d0218 100644 --- a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/listener/AdminApiEventListener.java +++ b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/listener/AdminApiEventListener.java @@ -1,31 +1,31 @@ -package cc.uncarbon.module.adminapi.listener; - -import cc.uncarbon.module.adminapi.event.KickOutSysUsersEvent; -import cc.uncarbon.module.adminapi.util.AdminStpUtil; -import cn.hutool.core.collection.CollUtil; -import lombok.RequiredArgsConstructor; -import org.springframework.context.event.EventListener; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.stereotype.Component; - -import java.util.Collection; - -/** - * admin-api模块事件监听器 - */ -@Component -@RequiredArgsConstructor -public class AdminApiEventListener { - - private final ThreadPoolTaskExecutor taskExecutor; - - - @EventListener(value = KickOutSysUsersEvent.class) - public void handleKickOutSysUsersEvent(KickOutSysUsersEvent event) { - Collection sysUserIds = event.getData().getSysUserIds(); - if (CollUtil.isNotEmpty(sysUserIds)) { - // 异步强制登出;同一时间大量登出,会操作大量Redis键,可能存在缓存雪崩的风险 - taskExecutor.submit(() -> sysUserIds.forEach(AdminStpUtil::kickout)); - } - } -} +package cc.uncarbon.module.adminapi.listener; + +import cc.uncarbon.module.adminapi.event.KickOutSysUsersEvent; +import cc.uncarbon.module.adminapi.util.AdminStpUtil; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Component; + +import java.util.Collection; + +/** + * admin-api模块事件监听器 + */ +@Component +@RequiredArgsConstructor +public class AdminApiEventListener { + + private final ThreadPoolTaskExecutor taskExecutor; + + + @EventListener(value = KickOutSysUsersEvent.class) + public void handleKickOutSysUsersEvent(KickOutSysUsersEvent event) { + Collection sysUserIds = event.getData().getSysUserIds(); + if (CollUtil.isNotEmpty(sysUserIds)) { + // 异步强制登出;同一时间大量登出,会操作大量Redis键,可能存在缓存雪崩的风险 + taskExecutor.submit(() -> sysUserIds.forEach(AdminStpUtil::kickout)); + } + } +} diff --git a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/model/interior/AdminCaptchaContainer.java b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/model/interior/AdminCaptchaContainer.java index 335923c..68120df 100644 --- a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/model/interior/AdminCaptchaContainer.java +++ b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/model/interior/AdminCaptchaContainer.java @@ -1,31 +1,15 @@ -package cc.uncarbon.module.adminapi.model.interior; - -import cn.hutool.captcha.AbstractCaptcha; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.time.LocalDateTime; - -/** - * 后台管理-验证码容器 - */ -@RequiredArgsConstructor -@Getter -public class AdminCaptchaContainer { - - /** - * 验证码图片对象 - */ - private final AbstractCaptcha image; - - /** - * 验证码唯一标识(UUID) - */ - private final String uuid; - - /** - * 验证码失效时刻 - */ - private final LocalDateTime expiredAt; - -} +package cc.uncarbon.module.adminapi.model.interior; + +import cn.hutool.captcha.AbstractCaptcha; + +import java.time.LocalDateTime; + +/** + * 后台管理-验证码容器 + * + * @param image 验证码图片对象 + * @param uuid 验证码唯一标识(UUID) + * @param expiredAt 验证码失效时刻 + */ +public record AdminCaptchaContainer(AbstractCaptcha image, String uuid, LocalDateTime expiredAt) { +} diff --git a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/model/response/AdminCaptchaVO.java b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/model/response/AdminCaptchaVO.java index 4844007..9f03b12 100644 --- a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/model/response/AdminCaptchaVO.java +++ b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/model/response/AdminCaptchaVO.java @@ -1,30 +1,30 @@ -package cc.uncarbon.module.adminapi.model.response; - -import cc.uncarbon.module.adminapi.model.interior.AdminCaptchaContainer; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Getter; - -import java.time.LocalDateTime; - -/** - * 后台管理-验证码 VO - */ -@Getter -public class AdminCaptchaVO { - - @Schema(description = "验证码图片Base64") - private final String captchaImage; - - @Schema(description = "验证码唯一标识") - private final String captchaId; - - @Schema(description = "验证码失效时刻") - private final LocalDateTime expiredAt; - - - public AdminCaptchaVO(AdminCaptchaContainer source) { - this.captchaImage = source.getImage().getImageBase64Data(); - this.captchaId = source.getUuid(); - this.expiredAt = source.getExpiredAt(); - } -} +package cc.uncarbon.module.adminapi.model.response; + +import cc.uncarbon.module.adminapi.model.interior.AdminCaptchaContainer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +import java.time.LocalDateTime; + +/** + * 后台管理-验证码 VO + */ +@Getter +public class AdminCaptchaVO { + + @Schema(description = "验证码图片Base64") + private final String captchaImage; + + @Schema(description = "验证码唯一标识") + private final String captchaId; + + @Schema(description = "验证码失效时刻") + private final LocalDateTime expiredAt; + + + public AdminCaptchaVO(AdminCaptchaContainer source) { + this.captchaImage = source.image().getImageBase64Data(); + this.captchaId = source.uuid(); + this.expiredAt = source.expiredAt(); + } +} diff --git a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/model/response/SelectOptionItemVO.java b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/model/response/SelectOptionItemVO.java index d92fc56..4bd28be 100644 --- a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/model/response/SelectOptionItemVO.java +++ b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/model/response/SelectOptionItemVO.java @@ -9,7 +9,6 @@ import lombok.Setter; import lombok.experimental.Accessors; -import java.io.Serial; import java.io.Serializable; import java.util.Arrays; import java.util.Collection; @@ -27,9 +26,6 @@ @Getter public class SelectOptionItemVO implements Serializable { - @Serial - private static final long serialVersionUID = 1L; - // ID👉名称 一对(用于关联各种实体) @Schema(description = "ID") private Number id; diff --git a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/web/oss/AdminOssUploadDownloadController.java b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/web/oss/AdminOssUploadDownloadController.java index e906748..f9bdabb 100644 --- a/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/web/oss/AdminOssUploadDownloadController.java +++ b/api/admin-api/src/main/java/cc/uncarbon/module/adminapi/web/oss/AdminOssUploadDownloadController.java @@ -1,14 +1,17 @@ package cc.uncarbon.module.adminapi.web.oss; +import cc.uncarbon.framework.core.exception.BusinessException; import cc.uncarbon.framework.web.model.response.ApiResult; import cc.uncarbon.module.adminapi.constant.AdminApiConstant; import cc.uncarbon.module.adminapi.enums.AdminApiErrorEnum; import cc.uncarbon.module.adminapi.util.AdminStpUtil; +import cc.uncarbon.module.oss.enums.UploadFileCheckResultEnum; import cc.uncarbon.module.oss.facade.OssUploadDownloadFacade; import cc.uncarbon.module.oss.model.request.UploadFileAttributeDTO; import cc.uncarbon.module.oss.model.response.OssFileDownloadReplyBO; import cc.uncarbon.module.oss.model.response.OssFileInfoBO; import cc.uncarbon.module.oss.model.response.OssFileUploadResultVO; +import cc.uncarbon.module.oss.util.UploadFileChecker; import cn.dev33.satoken.annotation.SaCheckLogin; import cn.hutool.core.io.IoUtil; import cn.hutool.core.text.CharSequenceUtil; @@ -50,6 +53,13 @@ public ApiResult upload( HttpServletRequest request ) throws IOException { AdminApiErrorEnum.UPLOAD_FILE_NOT_EXIST.assertNotNull(file); + UploadFileCheckResultEnum checkResult = UploadFileChecker.check(file, + // 默认只能上传10MB之内的文件,且约束后缀名 + UploadFileChecker.FILE_SIZE_1MB * 10, + new String[]{"jpg", "png", "webp", "gif", "xlsx"}); + if (checkResult.isNotOK()) { + throw new BusinessException(checkResult.getLabel()); + } /* 1. 已存在相同 MD5 文件,直接返回 URL @@ -65,7 +75,10 @@ public ApiResult upload( attr .setOriginalFilename(file.getOriginalFilename()) .setContentType(file.getContentType()) - .setMd5(md5); + .setMd5(md5) + // 手动覆盖前端传参 + .setPlatform(null) + .setUseOriginalFilenameAsDownloadFileName(false); bo = ossUploadDownloadFacade.upload(file.getBytes(), attr); } diff --git a/api/app-api/pom.xml b/api/app-api/pom.xml index d660956..4fc597b 100644 --- a/api/app-api/pom.xml +++ b/api/app-api/pom.xml @@ -8,12 +8,12 @@ cc.uncarbon.module helio-boot-modular - 2.1.0 + 2.2.0 ../../pom.xml app-api - 2.1.0 + 2.2.0 diff --git a/attachments/db/MySQL/upgrade/1.10.0_to_1.11.0.sql b/attachments/db/MySQL/upgrade/1.10.0_to_1.11.0.sql index d970c56..c08e549 100644 --- a/attachments/db/MySQL/upgrade/1.10.0_to_1.11.0.sql +++ b/attachments/db/MySQL/upgrade/1.10.0_to_1.11.0.sql @@ -1,12 +1,12 @@ --- v1.11.0 - 「后台角色」中,`title`字段更名为「角色名」,`value`字段更名为「角色编码」 -ALTER TABLE sys_role - MODIFY COLUMN title varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色名', - MODIFY COLUMN `value` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色编码'; - --- v1.11.0 - 「数据字典」中,`value`字段更名为「数据值」 -ALTER TABLE sys_data_dict - MODIFY COLUMN `value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '数据值'; - --- v1.11.0 - 扩充「后台用户」数据表,「昵称」字段的长度上限为255 -ALTER TABLE sys_user - MODIFY COLUMN `nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '昵称'; +-- v1.11.0 - 「后台角色」中,`title`字段更名为「角色名」,`value`字段更名为「角色编码」 +ALTER TABLE sys_role + MODIFY COLUMN title varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色名', + MODIFY COLUMN `value` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色编码'; + +-- v1.11.0 - 「数据字典」中,`value`字段更名为「数据值」 +ALTER TABLE sys_data_dict + MODIFY COLUMN `value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '数据值'; + +-- v1.11.0 - 扩充「后台用户」数据表,「昵称」字段的长度上限为255 +ALTER TABLE sys_user + MODIFY COLUMN `nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '昵称'; diff --git a/attachments/db/MySQL/upgrade/1.7.1_to_1.7.2.sql b/attachments/db/MySQL/upgrade/1.7.1_to_1.7.2.sql index 83fe053..a26fd60 100644 --- a/attachments/db/MySQL/upgrade/1.7.1_to_1.7.2.sql +++ b/attachments/db/MySQL/upgrade/1.7.1_to_1.7.2.sql @@ -1,48 +1,48 @@ --- v1.7.2 - Uncarbon - 默认内置文件上传功能 --- 建表 oss_file_info -DROP TABLE IF EXISTS `oss_file_info`; -CREATE TABLE `oss_file_info` -( - `id` bigint(20) NOT NULL COMMENT '主键ID', - `tenant_id` bigint(20) NULL DEFAULT NULL COMMENT '租户ID', - `revision` bigint(20) NOT NULL DEFAULT 1 COMMENT '乐观锁', - `del_flag` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '逻辑删除标识', - `created_at` datetime(0) NOT NULL COMMENT '创建时刻', - `created_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建者', - `updated_at` datetime(0) NOT NULL COMMENT '更新时刻', - `updated_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新者', - `storage_platform` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '存储平台', - `storage_base_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '基础存储路径', - `storage_path` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '存储路径', - `storage_filename` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '存储文件名', - `original_filename` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '原始文件名', - `extend_name` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '扩展名', - `file_size` bigint(20) NOT NULL COMMENT '文件大小', - `md5` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'MD5', - `classified` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件类别', - `direct_url` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '对象存储直链', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '上传文件信息' ROW_FORMAT = Dynamic; - --- v1.7.2 - Uncarbon - 新增上传文件信息后台管理菜单 -INSERT INTO `sys_menu` (`id`, `tenant_id`, `revision`, `del_flag`, `created_at`, `created_by`, `updated_at`, - `updated_by`, `title`, `parent_id`, `type`, `permission`, `icon`, `sort`, `status`, `component`, - `external_link`) -VALUES (20220922152710, NULL, 1, 0, '2022-12-25 23:09:30', 'admin', '2022-12-26 22:02:31', 'admin', '文件管理', 0, 0, - 'Oss', 'ant-design:file-outlined', 4, 1, NULL, ''); -INSERT INTO `sys_menu` (`id`, `tenant_id`, `revision`, `del_flag`, `created_at`, `created_by`, `updated_at`, - `updated_by`, `title`, `parent_id`, `type`, `permission`, `icon`, `sort`, `status`, `component`, - `external_link`) -VALUES (20220922152714, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-12-26 22:03:14', 'admin', - '上传文件信息管理', 20220922152710, 1, 'OssFileInfo', 'ant-design:save-twotone', 1, 1, '/oss/OssFileInfo/index', - ''); -INSERT INTO `sys_menu` (`id`, `tenant_id`, `revision`, `del_flag`, `created_at`, `created_by`, `updated_at`, - `updated_by`, `title`, `parent_id`, `type`, `permission`, `icon`, `sort`, `status`, `component`, - `external_link`) -VALUES (20220922152715, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-12-26 22:01:58', 'admin', '查询', - 20220922152714, 2, 'OssFileInfo:retrieve', NULL, 1, 1, NULL, ''); -INSERT INTO `sys_menu` (`id`, `tenant_id`, `revision`, `del_flag`, `created_at`, `created_by`, `updated_at`, - `updated_by`, `title`, `parent_id`, `type`, `permission`, `icon`, `sort`, `status`, `component`, - `external_link`) -VALUES (20220922152718, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-12-26 22:02:09', 'admin', '删除', - 20220922152714, 2, 'OssFileInfo:delete', NULL, 2, 1, NULL, ''); +-- v1.7.2 - Uncarbon - 默认内置文件上传功能 +-- 建表 oss_file_info +DROP TABLE IF EXISTS `oss_file_info`; +CREATE TABLE `oss_file_info` +( + `id` bigint(20) NOT NULL COMMENT '主键ID', + `tenant_id` bigint(20) NULL DEFAULT NULL COMMENT '租户ID', + `revision` bigint(20) NOT NULL DEFAULT 1 COMMENT '乐观锁', + `del_flag` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '逻辑删除标识', + `created_at` datetime(0) NOT NULL COMMENT '创建时刻', + `created_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建者', + `updated_at` datetime(0) NOT NULL COMMENT '更新时刻', + `updated_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新者', + `storage_platform` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '存储平台', + `storage_base_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '基础存储路径', + `storage_path` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '存储路径', + `storage_filename` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '存储文件名', + `original_filename` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '原始文件名', + `extend_name` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '扩展名', + `file_size` bigint(20) NOT NULL COMMENT '文件大小', + `md5` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'MD5', + `classified` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件类别', + `direct_url` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '对象存储直链', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '上传文件信息' ROW_FORMAT = Dynamic; + +-- v1.7.2 - Uncarbon - 新增上传文件信息后台管理菜单 +INSERT INTO `sys_menu` (`id`, `tenant_id`, `revision`, `del_flag`, `created_at`, `created_by`, `updated_at`, + `updated_by`, `title`, `parent_id`, `type`, `permission`, `icon`, `sort`, `status`, `component`, + `external_link`) +VALUES (20220922152710, NULL, 1, 0, '2022-12-25 23:09:30', 'admin', '2022-12-26 22:02:31', 'admin', '文件管理', 0, 0, + 'Oss', 'ant-design:file-outlined', 4, 1, NULL, ''); +INSERT INTO `sys_menu` (`id`, `tenant_id`, `revision`, `del_flag`, `created_at`, `created_by`, `updated_at`, + `updated_by`, `title`, `parent_id`, `type`, `permission`, `icon`, `sort`, `status`, `component`, + `external_link`) +VALUES (20220922152714, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-12-26 22:03:14', 'admin', + '上传文件信息管理', 20220922152710, 1, 'OssFileInfo', 'ant-design:save-twotone', 1, 1, '/oss/OssFileInfo/index', + ''); +INSERT INTO `sys_menu` (`id`, `tenant_id`, `revision`, `del_flag`, `created_at`, `created_by`, `updated_at`, + `updated_by`, `title`, `parent_id`, `type`, `permission`, `icon`, `sort`, `status`, `component`, + `external_link`) +VALUES (20220922152715, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-12-26 22:01:58', 'admin', '查询', + 20220922152714, 2, 'OssFileInfo:retrieve', NULL, 1, 1, NULL, ''); +INSERT INTO `sys_menu` (`id`, `tenant_id`, `revision`, `del_flag`, `created_at`, `created_by`, `updated_at`, + `updated_by`, `title`, `parent_id`, `type`, `permission`, `icon`, `sort`, `status`, `component`, + `external_link`) +VALUES (20220922152718, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-12-26 22:02:09', 'admin', '删除', + 20220922152714, 2, 'OssFileInfo:delete', NULL, 2, 1, NULL, ''); diff --git a/attachments/db/MySQL/upgrade/1.7.3_to_1.8.0.sql b/attachments/db/MySQL/upgrade/1.7.3_to_1.8.0.sql index 0ecb659..17b2f52 100644 --- a/attachments/db/MySQL/upgrade/1.7.3_to_1.8.0.sql +++ b/attachments/db/MySQL/upgrade/1.7.3_to_1.8.0.sql @@ -1,9 +1,9 @@ --- v1.8.0 - Uncarbon - 新增错误原因堆栈、用户UA、IP属地字段;表注释更新 -ALTER TABLE sys_log - ADD COLUMN error_stacktrace varchar(3000) NOT NULL DEFAULT '' COMMENT '错误原因堆栈' AFTER status, - ADD COLUMN user_agent varchar(255) NOT NULL DEFAULT '' COMMENT '用户UA' AFTER error_stacktrace, - ADD COLUMN ip_location_region_name varchar(100) NOT NULL DEFAULT '' COMMENT 'IP地址属地-国家或地区名' AFTER user_agent, - ADD COLUMN ip_location_province_name varchar(100) NOT NULL DEFAULT '' COMMENT 'IP地址属地-省级行政区名' AFTER ip_location_region_name, - ADD COLUMN ip_location_city_name varchar(100) NOT NULL DEFAULT '' COMMENT 'IP地址属地-市级行政区名' AFTER ip_location_province_name, - ADD COLUMN ip_location_district_name varchar(100) NOT NULL DEFAULT '' COMMENT 'IP地址属地-县级行政区名' AFTER ip_location_city_name; -ALTER TABLE sys_log COMMENT = '系统日志'; +-- v1.8.0 - Uncarbon - 新增错误原因堆栈、用户UA、IP属地字段;表注释更新 +ALTER TABLE sys_log + ADD COLUMN error_stacktrace varchar(3000) NOT NULL DEFAULT '' COMMENT '错误原因堆栈' AFTER status, + ADD COLUMN user_agent varchar(255) NOT NULL DEFAULT '' COMMENT '用户UA' AFTER error_stacktrace, + ADD COLUMN ip_location_region_name varchar(100) NOT NULL DEFAULT '' COMMENT 'IP地址属地-国家或地区名' AFTER user_agent, + ADD COLUMN ip_location_province_name varchar(100) NOT NULL DEFAULT '' COMMENT 'IP地址属地-省级行政区名' AFTER ip_location_region_name, + ADD COLUMN ip_location_city_name varchar(100) NOT NULL DEFAULT '' COMMENT 'IP地址属地-市级行政区名' AFTER ip_location_province_name, + ADD COLUMN ip_location_district_name varchar(100) NOT NULL DEFAULT '' COMMENT 'IP地址属地-县级行政区名' AFTER ip_location_city_name; +ALTER TABLE sys_log COMMENT = '系统日志'; diff --git a/attachments/db/PostgreSQL/helio_boot.sql b/attachments/db/PostgreSQL/helio_boot.sql index b361a63..eaadbde 100644 --- a/attachments/db/PostgreSQL/helio_boot.sql +++ b/attachments/db/PostgreSQL/helio_boot.sql @@ -939,32 +939,27 @@ ALTER TABLE "oss_file_info" -- v1.7.2 - Uncarbon - 新增上传文件信息管理菜单 -INSERT INTO "sys_menu"("id", "tenant_id", "revision", "del_flag", "created_at", "created_by", "updated_at", - "updated_by", "title", "parent_id", "type", "permission", "icon", "sort", "status", "component", - "external_link") -VALUES (20220922152714, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-09-22 15:27:14', - 'helio-generator', '上传文件信息管理', 0, 1, 'OssFileInfo', 'ant-design:flag-outlined', 100, 1, - '/oss/OssFileInfo/index', ''); -INSERT INTO "sys_menu"("id", "tenant_id", "revision", "del_flag", "created_at", "created_by", "updated_at", - "updated_by", "title", "parent_id", "type", "permission", "icon", "sort", "status", "component", - "external_link") -VALUES (20220922152715, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-09-22 15:27:14', - 'helio-generator', '查询', 1572848462892752896, 2, 'OssFileInfo:retrieve', NULL, 1, 1, NULL, ''); -INSERT INTO "sys_menu"("id", "tenant_id", "revision", "del_flag", "created_at", "created_by", "updated_at", - "updated_by", "title", "parent_id", "type", "permission", "icon", "sort", "status", "component", - "external_link") -VALUES (20220922152716, NULL, 1, 1, '2022-09-22 15:27:14', 'helio-generator', '2022-09-22 15:35:48', 'admin', - '新增', 1572848462892752896, 2, 'OssFileInfo:create', NULL, 2, 1, NULL, ''); -INSERT INTO "sys_menu"("id", "tenant_id", "revision", "del_flag", "created_at", "created_by", "updated_at", - "updated_by", "title", "parent_id", "type", "permission", "icon", "sort", "status", "component", - "external_link") -VALUES (20220922152717, NULL, 1, 1, '2022-09-22 15:27:14', 'helio-generator', '2022-09-22 15:35:55', 'admin', - '编辑', 1572848462892752896, 2, 'OssFileInfo:update', NULL, 4, 1, NULL, ''); -INSERT INTO "sys_menu"("id", "tenant_id", "revision", "del_flag", "created_at", "created_by", "updated_at", - "updated_by", "title", "parent_id", "type", "permission", "icon", "sort", "status", "component", - "external_link") -VALUES (20220922152718, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-09-22 15:36:03', 'admin', - '删除', 1572848462892752896, 2, 'OssFileInfo:delete', NULL, 2, 1, NULL, ''); +INSERT INTO sys_menu (id, tenant_id, revision, del_flag, created_at, created_by, updated_at, + updated_by, title, parent_id, type, permission, icon, sort, status, component, + external_link) +VALUES (20220922152710, NULL, 1, 0, '2022-12-25 23:09:30', 'admin', '2022-12-26 22:02:31', 'admin', '文件管理', 0, 0, + 'Oss', 'ant-design:file-outlined', 4, 1, NULL, ''); +INSERT INTO sys_menu (id, tenant_id, revision, del_flag, created_at, created_by, updated_at, + updated_by, title, parent_id, type, permission, icon, sort, status, component, + external_link) +VALUES (20220922152714, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-12-26 22:03:14', 'admin', + '上传文件信息管理', 20220922152710, 1, 'OssFileInfo', 'ant-design:save-twotone', 1, 1, '/oss/OssFileInfo/index', + ''); +INSERT INTO sys_menu (id, tenant_id, revision, del_flag, created_at, created_by, updated_at, + updated_by, title, parent_id, type, permission, icon, sort, status, component, + external_link) +VALUES (20220922152715, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-12-26 22:01:58', 'admin', '查询', + 20220922152714, 2, 'OssFileInfo:retrieve', NULL, 1, 1, NULL, ''); +INSERT INTO sys_menu (id, tenant_id, revision, del_flag, created_at, created_by, updated_at, + updated_by, title, parent_id, type, permission, icon, sort, status, component, + external_link) +VALUES (20220922152718, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-12-26 22:02:09', 'admin', '删除', + 20220922152714, 2, 'OssFileInfo:delete', NULL, 2, 1, NULL, ''); -- v1.8.0 - Uncarbon - 新增错误原因堆栈、用户UA、IP属地字段;表注释更新 ALTER TABLE sys_log diff --git a/attachments/db/PostgreSQL/upgrade/1.10.0_to_1.11.0.sql b/attachments/db/PostgreSQL/upgrade/1.10.0_to_1.11.0.sql index 72a3f51..7bcfdea 100644 --- a/attachments/db/PostgreSQL/upgrade/1.10.0_to_1.11.0.sql +++ b/attachments/db/PostgreSQL/upgrade/1.10.0_to_1.11.0.sql @@ -1,10 +1,10 @@ --- v1.11.0 - 「后台角色」中,`title`字段更名为「角色名」,`value`字段更名为「角色编码」 -COMMENT ON COLUMN "sys_role"."title" IS '角色名'; -COMMENT ON COLUMN "sys_role"."value" IS '角色编码'; - --- v1.11.0 - 「数据字典」中,`value`字段更名为「数据值」 -COMMENT ON COLUMN "sys_data_dict"."value" IS '数据值'; - --- v1.11.0 - 扩充「后台用户」数据表,「昵称」字段的长度上限为255 -ALTER TABLE "sys_user" - ALTER COLUMN "nickname" TYPE varchar(255); +-- v1.11.0 - 「后台角色」中,`title`字段更名为「角色名」,`value`字段更名为「角色编码」 +COMMENT ON COLUMN "sys_role"."title" IS '角色名'; +COMMENT ON COLUMN "sys_role"."value" IS '角色编码'; + +-- v1.11.0 - 「数据字典」中,`value`字段更名为「数据值」 +COMMENT ON COLUMN "sys_data_dict"."value" IS '数据值'; + +-- v1.11.0 - 扩充「后台用户」数据表,「昵称」字段的长度上限为255 +ALTER TABLE "sys_user" + ALTER COLUMN "nickname" TYPE varchar(255); diff --git a/attachments/db/PostgreSQL/upgrade/1.7.1_to_1.7.2.sql b/attachments/db/PostgreSQL/upgrade/1.7.1_to_1.7.2.sql index acb850d..9dbc5f2 100644 --- a/attachments/db/PostgreSQL/upgrade/1.7.1_to_1.7.2.sql +++ b/attachments/db/PostgreSQL/upgrade/1.7.1_to_1.7.2.sql @@ -1,94 +1,89 @@ --- 建表 oss_file_info -DROP TABLE IF EXISTS "oss_file_info"; -CREATE TABLE "oss_file_info" -( - "id" int8 NOT NULL, - "tenant_id" int8, - "revision" int8 NOT NULL, - "del_flag" int2 NOT NULL, - "created_at" timestamp(6) NOT NULL, - "created_by" varchar(255), - "updated_at" timestamp(6) NOT NULL, - "updated_by" varchar(255), - "storage_platform" varchar(50) NOT NULL, - "storage_base_path" varchar(255) NOT NULL, - "storage_path" varchar(512) NOT NULL, - "storage_filename" varchar(255) NOT NULL, - "original_filename" varchar(255) NOT NULL, - "extend_name" varchar(16) NOT NULL, - "file_size" int8 NOT NULL, - "md5" varchar(32) NOT NULL, - "classified" varchar(50), - "direct_url" varchar(512) -) -; -COMMENT -ON COLUMN "oss_file_info"."id" IS '主键ID'; -COMMENT -ON COLUMN "oss_file_info"."tenant_id" IS '租户ID'; -COMMENT -ON COLUMN "oss_file_info"."revision" IS '乐观锁'; -COMMENT -ON COLUMN "oss_file_info"."del_flag" IS '逻辑删除标识'; -COMMENT -ON COLUMN "oss_file_info"."created_at" IS '创建时刻'; -COMMENT -ON COLUMN "oss_file_info"."created_by" IS '创建者'; -COMMENT -ON COLUMN "oss_file_info"."updated_at" IS '更新时刻'; -COMMENT -ON COLUMN "oss_file_info"."updated_by" IS '更新者'; -COMMENT -ON COLUMN "oss_file_info"."storage_platform" IS '存储平台'; -COMMENT -ON COLUMN "oss_file_info"."storage_base_path" IS '基础存储路径'; -COMMENT -ON COLUMN "oss_file_info"."storage_path" IS '存储路径'; -COMMENT -ON COLUMN "oss_file_info"."storage_filename" IS '存储文件名'; -COMMENT -ON COLUMN "oss_file_info"."original_filename" IS '原始文件名'; -COMMENT -ON COLUMN "oss_file_info"."extend_name" IS '扩展名'; -COMMENT -ON COLUMN "oss_file_info"."file_size" IS '文件大小'; -COMMENT -ON COLUMN "oss_file_info"."md5" IS 'MD5'; -COMMENT -ON COLUMN "oss_file_info"."classified" IS '文件类别'; -COMMENT -ON COLUMN "oss_file_info"."direct_url" IS '对象存储直链'; -COMMENT -ON TABLE "oss_file_info" IS '上传文件信息'; - --- 主键 -ALTER TABLE "oss_file_info" - ADD CONSTRAINT "oss_file_info_pkey" PRIMARY KEY ("id"); - --- 增加对应后台管理菜单 -INSERT INTO "sys_menu"("id", "tenant_id", "revision", "del_flag", "created_at", "created_by", "updated_at", - "updated_by", "title", "parent_id", "type", "permission", "icon", "sort", "status", "component", - "external_link") -VALUES (20220922152714, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-09-22 15:27:14', - 'helio-generator', '上传文件信息管理', 0, 1, 'OssFileInfo', 'ant-design:flag-outlined', 100, 1, - '/oss/OssFileInfo/index', ''); -INSERT INTO "sys_menu"("id", "tenant_id", "revision", "del_flag", "created_at", "created_by", "updated_at", - "updated_by", "title", "parent_id", "type", "permission", "icon", "sort", "status", "component", - "external_link") -VALUES (20220922152715, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-09-22 15:27:14', - 'helio-generator', '查询', 1572848462892752896, 2, 'OssFileInfo:retrieve', NULL, 1, 1, NULL, ''); -INSERT INTO "sys_menu"("id", "tenant_id", "revision", "del_flag", "created_at", "created_by", "updated_at", - "updated_by", "title", "parent_id", "type", "permission", "icon", "sort", "status", "component", - "external_link") -VALUES (20220922152716, NULL, 1, 1, '2022-09-22 15:27:14', 'helio-generator', '2022-09-22 15:35:48', 'admin', - '新增', 1572848462892752896, 2, 'OssFileInfo:create', NULL, 2, 1, NULL, ''); -INSERT INTO "sys_menu"("id", "tenant_id", "revision", "del_flag", "created_at", "created_by", "updated_at", - "updated_by", "title", "parent_id", "type", "permission", "icon", "sort", "status", "component", - "external_link") -VALUES (20220922152717, NULL, 1, 1, '2022-09-22 15:27:14', 'helio-generator', '2022-09-22 15:35:55', 'admin', - '编辑', 1572848462892752896, 2, 'OssFileInfo:update', NULL, 4, 1, NULL, ''); -INSERT INTO "sys_menu"("id", "tenant_id", "revision", "del_flag", "created_at", "created_by", "updated_at", - "updated_by", "title", "parent_id", "type", "permission", "icon", "sort", "status", "component", - "external_link") -VALUES (20220922152718, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-09-22 15:36:03', 'admin', - '删除', 1572848462892752896, 2, 'OssFileInfo:delete', NULL, 2, 1, NULL, ''); +-- 建表 oss_file_info +DROP TABLE IF EXISTS "oss_file_info"; +CREATE TABLE "oss_file_info" +( + "id" int8 NOT NULL, + "tenant_id" int8, + "revision" int8 NOT NULL, + "del_flag" int2 NOT NULL, + "created_at" timestamp(6) NOT NULL, + "created_by" varchar(255), + "updated_at" timestamp(6) NOT NULL, + "updated_by" varchar(255), + "storage_platform" varchar(50) NOT NULL, + "storage_base_path" varchar(255) NOT NULL, + "storage_path" varchar(512) NOT NULL, + "storage_filename" varchar(255) NOT NULL, + "original_filename" varchar(255) NOT NULL, + "extend_name" varchar(16) NOT NULL, + "file_size" int8 NOT NULL, + "md5" varchar(32) NOT NULL, + "classified" varchar(50), + "direct_url" varchar(512) +) +; +COMMENT +ON COLUMN "oss_file_info"."id" IS '主键ID'; +COMMENT +ON COLUMN "oss_file_info"."tenant_id" IS '租户ID'; +COMMENT +ON COLUMN "oss_file_info"."revision" IS '乐观锁'; +COMMENT +ON COLUMN "oss_file_info"."del_flag" IS '逻辑删除标识'; +COMMENT +ON COLUMN "oss_file_info"."created_at" IS '创建时刻'; +COMMENT +ON COLUMN "oss_file_info"."created_by" IS '创建者'; +COMMENT +ON COLUMN "oss_file_info"."updated_at" IS '更新时刻'; +COMMENT +ON COLUMN "oss_file_info"."updated_by" IS '更新者'; +COMMENT +ON COLUMN "oss_file_info"."storage_platform" IS '存储平台'; +COMMENT +ON COLUMN "oss_file_info"."storage_base_path" IS '基础存储路径'; +COMMENT +ON COLUMN "oss_file_info"."storage_path" IS '存储路径'; +COMMENT +ON COLUMN "oss_file_info"."storage_filename" IS '存储文件名'; +COMMENT +ON COLUMN "oss_file_info"."original_filename" IS '原始文件名'; +COMMENT +ON COLUMN "oss_file_info"."extend_name" IS '扩展名'; +COMMENT +ON COLUMN "oss_file_info"."file_size" IS '文件大小'; +COMMENT +ON COLUMN "oss_file_info"."md5" IS 'MD5'; +COMMENT +ON COLUMN "oss_file_info"."classified" IS '文件类别'; +COMMENT +ON COLUMN "oss_file_info"."direct_url" IS '对象存储直链'; +COMMENT +ON TABLE "oss_file_info" IS '上传文件信息'; + +-- 主键 +ALTER TABLE "oss_file_info" + ADD CONSTRAINT "oss_file_info_pkey" PRIMARY KEY ("id"); + +-- 增加对应后台管理菜单 +INSERT INTO sys_menu (id, tenant_id, revision, del_flag, created_at, created_by, updated_at, + updated_by, title, parent_id, type, permission, icon, sort, status, component, + external_link) +VALUES (20220922152710, NULL, 1, 0, '2022-12-25 23:09:30', 'admin', '2022-12-26 22:02:31', 'admin', '文件管理', 0, 0, + 'Oss', 'ant-design:file-outlined', 4, 1, NULL, ''); +INSERT INTO sys_menu (id, tenant_id, revision, del_flag, created_at, created_by, updated_at, + updated_by, title, parent_id, type, permission, icon, sort, status, component, + external_link) +VALUES (20220922152714, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-12-26 22:03:14', 'admin', + '上传文件信息管理', 20220922152710, 1, 'OssFileInfo', 'ant-design:save-twotone', 1, 1, '/oss/OssFileInfo/index', + ''); +INSERT INTO sys_menu (id, tenant_id, revision, del_flag, created_at, created_by, updated_at, + updated_by, title, parent_id, type, permission, icon, sort, status, component, + external_link) +VALUES (20220922152715, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-12-26 22:01:58', 'admin', '查询', + 20220922152714, 2, 'OssFileInfo:retrieve', NULL, 1, 1, NULL, ''); +INSERT INTO sys_menu (id, tenant_id, revision, del_flag, created_at, created_by, updated_at, + updated_by, title, parent_id, type, permission, icon, sort, status, component, + external_link) +VALUES (20220922152718, NULL, 1, 0, '2022-09-22 15:27:14', 'helio-generator', '2022-12-26 22:02:09', 'admin', '删除', + 20220922152714, 2, 'OssFileInfo:delete', NULL, 2, 1, NULL, ''); diff --git a/attachments/db/PostgreSQL/upgrade/1.7.3_to_1.8.0.sql b/attachments/db/PostgreSQL/upgrade/1.7.3_to_1.8.0.sql index 0f2ef22..6f2e5c9 100644 --- a/attachments/db/PostgreSQL/upgrade/1.7.3_to_1.8.0.sql +++ b/attachments/db/PostgreSQL/upgrade/1.7.3_to_1.8.0.sql @@ -1,21 +1,21 @@ --- v1.8.0 - Uncarbon - 新增错误原因堆栈、用户UA、IP属地字段;表注释更新 -ALTER TABLE sys_log - ADD COLUMN error_stacktrace varchar(3000) NOT NULL DEFAULT '', - ADD COLUMN user_agent varchar(255) NOT NULL DEFAULT '', - ADD COLUMN ip_location_region_name varchar(100) NOT NULL DEFAULT '', - ADD COLUMN ip_location_province_name varchar(100) NOT NULL DEFAULT '', - ADD COLUMN ip_location_city_name varchar(100) NOT NULL DEFAULT '', - ADD COLUMN ip_location_district_name varchar(100) NOT NULL DEFAULT ''; - -COMMENT ON COLUMN sys_log.error_stacktrace IS '错误原因堆栈'; -COMMENT ON COLUMN sys_log.user_agent IS '用户UA'; -COMMENT ON COLUMN sys_log.ip_location_region_name IS 'IP地址属地-国家或地区名'; -COMMENT ON COLUMN sys_log.ip_location_province_name IS 'IP地址属地-省级行政区名'; -COMMENT ON COLUMN sys_log.ip_location_city_name IS 'IP地址属地-市级行政区名'; -COMMENT ON COLUMN sys_log.ip_location_district_name IS 'IP地址属地-县级行政区名'; - -COMMENT ON TABLE sys_log IS '系统日志'; - --- v1.8.0 - Uncarbon - 订正系统菜单-权限串缺少默认值问题 -ALTER TABLE "sys_menu" - ALTER COLUMN "permission" SET DEFAULT ''; +-- v1.8.0 - Uncarbon - 新增错误原因堆栈、用户UA、IP属地字段;表注释更新 +ALTER TABLE sys_log + ADD COLUMN error_stacktrace varchar(3000) NOT NULL DEFAULT '', + ADD COLUMN user_agent varchar(255) NOT NULL DEFAULT '', + ADD COLUMN ip_location_region_name varchar(100) NOT NULL DEFAULT '', + ADD COLUMN ip_location_province_name varchar(100) NOT NULL DEFAULT '', + ADD COLUMN ip_location_city_name varchar(100) NOT NULL DEFAULT '', + ADD COLUMN ip_location_district_name varchar(100) NOT NULL DEFAULT ''; + +COMMENT ON COLUMN sys_log.error_stacktrace IS '错误原因堆栈'; +COMMENT ON COLUMN sys_log.user_agent IS '用户UA'; +COMMENT ON COLUMN sys_log.ip_location_region_name IS 'IP地址属地-国家或地区名'; +COMMENT ON COLUMN sys_log.ip_location_province_name IS 'IP地址属地-省级行政区名'; +COMMENT ON COLUMN sys_log.ip_location_city_name IS 'IP地址属地-市级行政区名'; +COMMENT ON COLUMN sys_log.ip_location_district_name IS 'IP地址属地-县级行政区名'; + +COMMENT ON TABLE sys_log IS '系统日志'; + +-- v1.8.0 - Uncarbon - 订正系统菜单-权限串缺少默认值问题 +ALTER TABLE "sys_menu" + ALTER COLUMN "permission" SET DEFAULT ''; diff --git a/attachments/db/PostgreSQL/upgrade/1.9.0_to_1.10.0.sql b/attachments/db/PostgreSQL/upgrade/1.9.0_to_1.10.0.sql index 41ab022..85eea77 100644 --- a/attachments/db/PostgreSQL/upgrade/1.9.0_to_1.10.0.sql +++ b/attachments/db/PostgreSQL/upgrade/1.9.0_to_1.10.0.sql @@ -1,4 +1,4 @@ --- v1.10.0 - 补充遗漏的数据表默认值 -ALTER TABLE "oss_file_info" - ALTER COLUMN "revision" SET DEFAULT 1, - ALTER COLUMN "del_flag" SET DEFAULT 0; +-- v1.10.0 - 补充遗漏的数据表默认值 +ALTER TABLE "oss_file_info" + ALTER COLUMN "revision" SET DEFAULT 1, + ALTER COLUMN "del_flag" SET DEFAULT 0; diff --git a/bootstrap/Dockerfile b/bootstrap/Dockerfile deleted file mode 100644 index 2fb54de..0000000 --- a/bootstrap/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -# https://hub.docker.com/_/eclipse-temurin/tags?page=1&name=alpine -FROM eclipse-temurin:17.0.7_7-jre-alpine -COPY ./target/*.jar ./app.jar -COPY entrypoint.sh / -RUN chmod +x ./entrypoint.sh -ENTRYPOINT ["./entrypoint.sh"] diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml index e29d6d0..f3d9522 100644 --- a/bootstrap/pom.xml +++ b/bootstrap/pom.xml @@ -8,7 +8,7 @@ cc.uncarbon.module helio-boot-modular - 2.1.0 + 2.2.0 bootstrap @@ -17,16 +17,16 @@ - 2.1.0 + 2.2.0 helio-boot - 2.1.0 + 2.2.0 - 2.1.0 + 2.2.0 diff --git a/bootstrap/src/main/java/cc/uncarbon/module/config/NotFoundConfiguration.java b/bootstrap/src/main/java/cc/uncarbon/module/config/NotFoundConfiguration.java index c63b91d..45a8354 100644 --- a/bootstrap/src/main/java/cc/uncarbon/module/config/NotFoundConfiguration.java +++ b/bootstrap/src/main/java/cc/uncarbon/module/config/NotFoundConfiguration.java @@ -1,28 +1,28 @@ -package cc.uncarbon.module.config; - -import io.swagger.v3.oas.annotations.Operation; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.boot.web.servlet.error.ErrorController; -import org.springframework.http.HttpHeaders; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.NoHandlerFoundException; - -/** - * 由于除 404 以外的异常都会被全局异常处理掉,所以走到这里的请求都是 404 了 - * - * @author Uncarbon - */ -@RestController -public class NotFoundConfiguration implements ErrorController { - - /** - * 不生成接口文档 - * 主动抛出异常,由全局异常处理接管 - */ - @Operation(hidden = true) - @RequestMapping(value = "/error") - public void error(HttpServletRequest request) throws NoHandlerFoundException { - throw new NoHandlerFoundException(request.getMethod(), request.getRequestURI(), new HttpHeaders()); - } -} +package cc.uncarbon.module.config; + +import io.swagger.v3.oas.annotations.Operation; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.boot.web.servlet.error.ErrorController; +import org.springframework.http.HttpHeaders; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.NoHandlerFoundException; + +/** + * 由于除 404 以外的异常都会被全局异常处理掉,所以走到这里的请求都是 404 了 + * + * @author Uncarbon + */ +@RestController +public class NotFoundConfiguration implements ErrorController { + + /** + * 不生成接口文档 + * 主动抛出异常,由全局异常处理接管 + */ + @Operation(hidden = true) + @RequestMapping(value = "/error") + public void error(HttpServletRequest request) throws NoHandlerFoundException { + throw new NoHandlerFoundException(request.getMethod(), request.getRequestURI(), new HttpHeaders()); + } +} diff --git a/bootstrap/src/main/resources/i18n/messages_en_US.properties b/bootstrap/src/main/resources/i18n/messages_en_US.properties index 9160b56..55b2182 100644 --- a/bootstrap/src/main/resources/i18n/messages_en_US.properties +++ b/bootstrap/src/main/resources/i18n/messages_en_US.properties @@ -1,24 +1,24 @@ -#-- Web 全局异常处理国际化消息 - 美式英语 -GLOBAL__NO_LOGIN=No login -GLOBAL__PERMISSION_NOT_MATCH=Permission not match -GLOBAL__ROLE_NOT_MATCH=Role not match -GLOBAL__NOT_FOUND=Page not found -GLOBAL__UNACCEPTABLE_PARAMETERS=Unacceptable parameters -GLOBAL__METHOD_NOT_ALLOWED=Method not allowed -GLOBAL__INTERNAL_ERROR=Please try again later - -#-- SysErrorEnum -SysErrorEnum.INVALID_ID=Invalid id -SysErrorEnum.INCORRECT_PIN_OR_PWD=Incorrect username or password -SysErrorEnum.BANNED_USER=Banned user -SysErrorEnum.INVALID_TENANT=Invalid tenant -SysErrorEnum.DISABLED_TENANT=Disabled tenant -SysErrorEnum.INCORRECT_OLD_PASSWORD=Old password is incorrect -SysErrorEnum.NO_ROLE_AVAILABLE_FOR_CURRENT_USER=No role available for current user -SysErrorEnum.NO_MENU_AVAILABLE_FOR_CURRENT_ROLE=No menu available for current role -SysErrorEnum.UUID_CANNOT_BE_BLANK=UUID cannot be blank - -#-- OssErrorEnum -OssErrorEnum.INVALID_ID=Invalid id -OssErrorEnum.FILE_UPLOAD_FAILED=File upload failed, please contact administrator -OssErrorEnum.FILE_DOWNLOAD_FAILED=File download failed, please contact administrator +#-- Web 全局异常处理国际化消息 - 美式英语 +GLOBAL__NO_LOGIN=No login +GLOBAL__PERMISSION_NOT_MATCH=Permission not match +GLOBAL__ROLE_NOT_MATCH=Role not match +GLOBAL__NOT_FOUND=Page not found +GLOBAL__UNACCEPTABLE_PARAMETERS=Unacceptable parameters +GLOBAL__METHOD_NOT_ALLOWED=Method not allowed +GLOBAL__INTERNAL_ERROR=Please try again later + +#-- SysErrorEnum +SysErrorEnum.INVALID_ID=Invalid id +SysErrorEnum.INCORRECT_PIN_OR_PWD=Incorrect username or password +SysErrorEnum.BANNED_USER=Banned user +SysErrorEnum.INVALID_TENANT=Invalid tenant +SysErrorEnum.DISABLED_TENANT=Disabled tenant +SysErrorEnum.INCORRECT_OLD_PASSWORD=Old password is incorrect +SysErrorEnum.NO_ROLE_AVAILABLE_FOR_CURRENT_USER=No role available for current user +SysErrorEnum.NO_MENU_AVAILABLE_FOR_CURRENT_ROLE=No menu available for current role +SysErrorEnum.UUID_CANNOT_BE_BLANK=UUID cannot be blank + +#-- OssErrorEnum +OssErrorEnum.INVALID_ID=Invalid id +OssErrorEnum.FILE_UPLOAD_FAILED=File upload failed, please contact administrator +OssErrorEnum.FILE_DOWNLOAD_FAILED=File download failed, please contact administrator diff --git a/bootstrap/src/main/resources/i18n/messages_zh_CN.properties b/bootstrap/src/main/resources/i18n/messages_zh_CN.properties index 515844e..dca120d 100644 --- a/bootstrap/src/main/resources/i18n/messages_zh_CN.properties +++ b/bootstrap/src/main/resources/i18n/messages_zh_CN.properties @@ -1,13 +1,13 @@ -#-- Web 全局异常处理国际化消息 - 中文简体 -GLOBAL__NO_LOGIN=请您先登录 -GLOBAL__PERMISSION_NOT_MATCH=您权限不足 -GLOBAL__ROLE_NOT_MATCH=您与要求角色不符 -GLOBAL__NOT_FOUND=你迷路啦 -GLOBAL__UNACCEPTABLE_PARAMETERS=错误参数格式或值 -GLOBAL__METHOD_NOT_ALLOWED=错误的请求方式 -GLOBAL__INTERNAL_ERROR=请稍后再试 - -#-- SysErrorEnum 不指定则使用原有定义的label作为提示消息 -# SysErrorEnum.INCORRECT_PIN_OR_PWD=你账号或者密码是不是有啥子输错了噢? - -#-- OssErrorEnum +#-- Web 全局异常处理国际化消息 - 中文简体 +GLOBAL__NO_LOGIN=请您先登录 +GLOBAL__PERMISSION_NOT_MATCH=您权限不足 +GLOBAL__ROLE_NOT_MATCH=您与要求角色不符 +GLOBAL__NOT_FOUND=你迷路啦 +GLOBAL__UNACCEPTABLE_PARAMETERS=错误参数格式或值 +GLOBAL__METHOD_NOT_ALLOWED=错误的请求方式 +GLOBAL__INTERNAL_ERROR=请稍后再试 + +#-- SysErrorEnum 不指定则使用原有定义的label作为提示消息 +# SysErrorEnum.INCORRECT_PIN_OR_PWD=你账号或者密码是不是有啥子输错了噢? + +#-- OssErrorEnum diff --git a/bootstrap/entrypoint.sh b/entrypoint.sh similarity index 100% rename from bootstrap/entrypoint.sh rename to entrypoint.sh diff --git a/pom.xml b/pom.xml index 79d5c73..3534a6b 100644 --- a/pom.xml +++ b/pom.xml @@ -8,18 +8,18 @@ cc.uncarbon.framework helio-starters - 2.1.0 + 2.2.0 cc.uncarbon.module helio-boot-modular Helio 多模块版单体脚手架 - 2.1.0 + 2.2.0 - 2.1.0 + 2.2.1 8.5.8 diff --git a/service-module/oss/oss-facade/pom.xml b/service-module/oss/oss-facade/pom.xml index 09f4cc7..c166435 100644 --- a/service-module/oss/oss-facade/pom.xml +++ b/service-module/oss/oss-facade/pom.xml @@ -8,7 +8,7 @@ cc.uncarbon.module oss - 2.1.0 + 2.2.0 oss-facade @@ -25,5 +25,11 @@ + + + org.springframework + spring-web + true + diff --git a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/constant/OssConstant.java b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/constant/OssConstant.java index 4ae8f0d..7fb6221 100644 --- a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/constant/OssConstant.java +++ b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/constant/OssConstant.java @@ -1,12 +1,12 @@ -package cc.uncarbon.module.oss.constant; - -public final class OssConstant { - private OssConstant() { - } - - /** - * 存储平台-本地存储-前缀 - */ - public static final String PLATFORM_PREFIX_LOCAL = "local"; - -} +package cc.uncarbon.module.oss.constant; + +public final class OssConstant { + private OssConstant() { + } + + /** + * 存储平台-本地存储-前缀 + */ + public static final String PLATFORM_PREFIX_LOCAL = "local"; + +} diff --git a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/enums/OssErrorEnum.java b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/enums/OssErrorEnum.java index f6d3685..9707f10 100644 --- a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/enums/OssErrorEnum.java +++ b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/enums/OssErrorEnum.java @@ -14,12 +14,9 @@ public enum OssErrorEnum implements HelioBaseEnum { INVALID_ID(400, "无效ID"), - FILE_UPLOAD_FAILED(500, "文件上传失败,请联系管理员"), + FILE_DOWNLOAD_FAILED(500, "文件下载失败,请联系管理员"),; - FILE_DOWNLOAD_FAILED(500, "文件下载失败,请联系管理员"), - - ; @EnumValue private final Integer value; private final String label; diff --git a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/enums/UploadFileCheckResultEnum.java b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/enums/UploadFileCheckResultEnum.java new file mode 100644 index 0000000..6823f7b --- /dev/null +++ b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/enums/UploadFileCheckResultEnum.java @@ -0,0 +1,34 @@ +package cc.uncarbon.module.oss.enums; + +import cc.uncarbon.framework.core.enums.HelioBaseEnum; +import com.baomidou.mybatisplus.annotation.EnumValue; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 前端上传文件检查结果枚举类 + */ +@AllArgsConstructor +@Getter +public enum UploadFileCheckResultEnum implements HelioBaseEnum { + + OK(200, "正常"), + NO_FILE(401, "缺少欲上传的文件"), + TOO_MANY_FILES(402, "欲上传的文件数量超出限制"), + TOO_LARGE_FILE_SIZE(403, "欲上传的文件大小超出限制"), + EMPTY_FILE(404, "欲上传的文件为空"), + ILLEGAL_FILE_SUFFIX(405, "欲上传的文件类型超出限制"),; + + @EnumValue + private final Integer value; + private final String label; + + public boolean isOK() { + return this == OK; + } + + public boolean isNotOK() { + return !isOK(); + } + +} diff --git a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/facade/OssUploadDownloadFacade.java b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/facade/OssUploadDownloadFacade.java index c083086..4589f5e 100644 --- a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/facade/OssUploadDownloadFacade.java +++ b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/facade/OssUploadDownloadFacade.java @@ -1,40 +1,40 @@ -package cc.uncarbon.module.oss.facade; - -import cc.uncarbon.framework.core.exception.BusinessException; -import cc.uncarbon.module.oss.model.request.UploadFileAttributeDTO; -import cc.uncarbon.module.oss.model.response.OssFileDownloadReplyBO; -import cc.uncarbon.module.oss.model.response.OssFileInfoBO; -import lombok.NonNull; - -/** - * 文件上传下载门面 - */ -public interface OssUploadDownloadFacade { - - /** - * 根据哈希值,查找是否已有文件 - */ - OssFileInfoBO findByHash(String md5); - - /** - * 正常上传文件到服务端 - * - * @param fileBytes 文件数据 - * @param attr 附加属性 - */ - OssFileInfoBO upload(byte[] fileBytes, @NonNull UploadFileAttributeDTO attr) throws BusinessException; - - /** - * 根据文件ID下载 - * - * @throws BusinessException 业务异常,如:文件ID无效;原始文件不存在 - */ - OssFileDownloadReplyBO downloadById(Long fileInfoId) throws BusinessException; - - /** - * 是否为本地存储平台 - * @param storagePlatform 存储平台名 - */ - boolean isLocalPlatform(String storagePlatform); - -} +package cc.uncarbon.module.oss.facade; + +import cc.uncarbon.framework.core.exception.BusinessException; +import cc.uncarbon.module.oss.model.request.UploadFileAttributeDTO; +import cc.uncarbon.module.oss.model.response.OssFileDownloadReplyBO; +import cc.uncarbon.module.oss.model.response.OssFileInfoBO; +import lombok.NonNull; + +/** + * 文件上传下载门面 + */ +public interface OssUploadDownloadFacade { + + /** + * 根据哈希值,查找是否已有文件 + */ + OssFileInfoBO findByHash(String md5); + + /** + * 正常上传文件到服务端 + * + * @param fileBytes 文件数据 + * @param attr 附加属性 + */ + OssFileInfoBO upload(byte[] fileBytes, @NonNull UploadFileAttributeDTO attr) throws BusinessException; + + /** + * 根据文件ID下载 + * + * @throws BusinessException 业务异常,如:文件ID无效;原始文件不存在 + */ + OssFileDownloadReplyBO downloadById(Long fileInfoId) throws BusinessException; + + /** + * 是否为本地存储平台 + * @param storagePlatform 存储平台名 + */ + boolean isLocalPlatform(String storagePlatform); + +} diff --git a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/request/AdminListOssFileInfoDTO.java b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/request/AdminListOssFileInfoDTO.java index 946513f..d8b128e 100644 --- a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/request/AdminListOssFileInfoDTO.java +++ b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/request/AdminListOssFileInfoDTO.java @@ -24,9 +24,6 @@ @Data public class AdminListOssFileInfoDTO implements Serializable { - private static final long serialVersionUID = 1L; - - @Schema(description = "原始文件名(关键词)") private String originalFilename; diff --git a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/request/UploadFileAttributeDTO.java b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/request/UploadFileAttributeDTO.java index a72bb09..6713d6d 100644 --- a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/request/UploadFileAttributeDTO.java +++ b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/request/UploadFileAttributeDTO.java @@ -18,8 +18,6 @@ @Data public class UploadFileAttributeDTO implements Serializable { - private static final long serialVersionUID = 1L; - @Schema(description = "文件类别", example = "id_card=身份证 driver_license=驾驶证") private String classified; @@ -35,4 +33,10 @@ public class UploadFileAttributeDTO implements Serializable { @Schema(description = "MD5", hidden = true) private String md5; + @Schema(description = "指定要上传到的平台名(null则取值默认平台)", hidden = true) + private String platform; + + @Schema(description = "从对象存储服务器中下载时,以原始文件名命名(通过指定 metadata 实现)", hidden = true) + private boolean useOriginalFilenameAsDownloadFileName; + } diff --git a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/response/OssFileDownloadReplyBO.java b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/response/OssFileDownloadReplyBO.java index d1915e0..b78a490 100644 --- a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/response/OssFileDownloadReplyBO.java +++ b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/response/OssFileDownloadReplyBO.java @@ -20,8 +20,6 @@ @Data public class OssFileDownloadReplyBO implements Serializable { - private static final long serialVersionUID = 1L; - @Schema(description = "是否直接重定向到对象存储直链", title = "如果允许客户端直接从“对象存储直链”下载,则本字段可以置 true") private boolean redirect2DirectUrl; diff --git a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/response/OssFileInfoBO.java b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/response/OssFileInfoBO.java index c0241b1..2aab386 100644 --- a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/response/OssFileInfoBO.java +++ b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/response/OssFileInfoBO.java @@ -24,8 +24,6 @@ @Data public class OssFileInfoBO implements Serializable { - private static final long serialVersionUID = 1L; - @Schema(description = "主键ID") private Long id; diff --git a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/response/OssFileUploadResultVO.java b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/response/OssFileUploadResultVO.java index 61086f0..ec43f71 100644 --- a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/response/OssFileUploadResultVO.java +++ b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/model/response/OssFileUploadResultVO.java @@ -18,8 +18,6 @@ @Data public class OssFileUploadResultVO implements Serializable { - private static final long serialVersionUID = 1L; - @Schema(description = "文件ID") private Long fileId; diff --git a/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/util/UploadFileChecker.java b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/util/UploadFileChecker.java new file mode 100644 index 0000000..1d961c5 --- /dev/null +++ b/service-module/oss/oss-facade/src/main/java/cc/uncarbon/module/oss/util/UploadFileChecker.java @@ -0,0 +1,96 @@ +package cc.uncarbon.module.oss.util; + +import cc.uncarbon.module.oss.enums.UploadFileCheckResultEnum; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.file.FileNameUtil; +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.util.ArrayUtil; +import jakarta.annotation.Nonnull; +import lombok.experimental.UtilityClass; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Collection; +import java.util.Locale; +import java.util.Objects; + +/** + * 前端上传文件检查器 + * 该检查器较为简易,请按照实际网络安全需要扩展 + */ +@UtilityClass +public class UploadFileChecker { + + // 最小文件数量 + private static final int FILE_QTY_MIN = 1; + // 最小文件尺寸 + private static final int FILE_SIZE_MIN = 1; + + // 文件尺寸 1MB + public static final long FILE_SIZE_1MB = 1024 * 1024L; + + + /** + * 批量检查 + * + * @param fileQtyMax 最大允许的文件数量 + * @param singleFileSizeMax 最大单文件尺寸,单位=KB + * @param allFileSizeMax 最大多文件累计尺寸,单位=KB + * @param allowedSuffixes 允许上传的文件后缀 + */ + public UploadFileCheckResultEnum check(Collection multipartFiles, int fileQtyMax, + long singleFileSizeMax, long allFileSizeMax, String[] allowedSuffixes) { + // 限制文件数量 + int fileQty = CollUtil.size(multipartFiles); + if (fileQty < FILE_QTY_MIN) { + return UploadFileCheckResultEnum.NO_FILE; + } else if (fileQty > fileQtyMax) { + return UploadFileCheckResultEnum.TOO_MANY_FILES; + } + // 限制所有文件总大小 + long allFileSize = multipartFiles.stream().mapToLong(MultipartFile::getSize).sum(); + // 除以1024 + allFileSize = allFileSize >> 10; + if (allFileSize > allFileSizeMax) { + return UploadFileCheckResultEnum.TOO_LARGE_FILE_SIZE; + } + + // 每个文件单独检查 + for (MultipartFile item : multipartFiles) { + UploadFileCheckResultEnum singleCheckRet = check(item, singleFileSizeMax, allowedSuffixes); + if (singleCheckRet.isNotOK()) { + return singleCheckRet; + } + } + return UploadFileCheckResultEnum.OK; + } + + /** + * 单个检查 + * @param singleFileSizeMax 最大单文件尺寸,单位=KB + * @param allowedSuffixes 允许上传的文件后缀 + */ + public UploadFileCheckResultEnum check(@Nonnull MultipartFile multipartFile, long singleFileSizeMax, String[] allowedSuffixes) { + long fileSize = multipartFile.getSize(); + + // 确定文件大小区间 + if (fileSize < FILE_SIZE_MIN) { + return UploadFileCheckResultEnum.EMPTY_FILE; + } + // 除以1024 + fileSize = fileSize >> 10; + if (fileSize > singleFileSizeMax) { + return UploadFileCheckResultEnum.TOO_LARGE_FILE_SIZE; + } + + // 确定后缀名 + String suffix = FileNameUtil.getSuffix(multipartFile.getOriginalFilename()); + if (CharSequenceUtil.isNotBlank(suffix)) { + suffix = suffix.toLowerCase(Locale.ROOT); + } + // 检查后缀名 + if (Objects.isNull(suffix) || !ArrayUtil.contains(allowedSuffixes, suffix)) { + return UploadFileCheckResultEnum.ILLEGAL_FILE_SUFFIX; + } + return UploadFileCheckResultEnum.OK; + } +} diff --git a/service-module/oss/oss-service/pom.xml b/service-module/oss/oss-service/pom.xml index d3117c7..864972a 100644 --- a/service-module/oss/oss-service/pom.xml +++ b/service-module/oss/oss-service/pom.xml @@ -8,14 +8,14 @@ cc.uncarbon.module oss - 2.1.0 + 2.2.0 oss-service - 2.1.0 + 2.2.0 @@ -23,7 +23,7 @@ cc.uncarbon.module oss-facade - 2.1.0 + ${parent.version} diff --git a/service-module/oss/oss-service/src/main/java/cc/uncarbon/module/oss/biz/OssUploadDownloadFacadeImpl.java b/service-module/oss/oss-service/src/main/java/cc/uncarbon/module/oss/biz/OssUploadDownloadFacadeImpl.java index 9f790a5..bbd021d 100644 --- a/service-module/oss/oss-service/src/main/java/cc/uncarbon/module/oss/biz/OssUploadDownloadFacadeImpl.java +++ b/service-module/oss/oss-service/src/main/java/cc/uncarbon/module/oss/biz/OssUploadDownloadFacadeImpl.java @@ -8,14 +8,21 @@ import cc.uncarbon.module.oss.model.response.OssFileInfoBO; import cc.uncarbon.module.oss.service.OssFileInfoService; import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.util.ObjectUtil; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.x.file.storage.core.FileInfo; import org.dromara.x.file.storage.core.FileStorageService; +import org.dromara.x.file.storage.core.constant.Constant; import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException; +import org.dromara.x.file.storage.core.upload.UploadPretreatment; import org.springframework.stereotype.Service; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; + /** * 文件上传下载门面 @@ -28,6 +35,7 @@ public class OssUploadDownloadFacadeImpl implements OssUploadDownloadFacade { private final OssFileInfoService ossFileInfoService; private final FileStorageService fileStorageService; + @Override public OssFileInfoBO findByHash(String md5) { return ossFileInfoService.getOneByMd5(md5); @@ -35,18 +43,26 @@ public OssFileInfoBO findByHash(String md5) { @Override public OssFileInfoBO upload(byte[] fileBytes, @NonNull UploadFileAttributeDTO attr) throws BusinessException { + // 要上传到的平台名 + String platform = ObjectUtil.defaultIfNull(attr.getPlatform(), fileStorageService.getProperties()::getDefaultPlatform); + + // 如果需要缩略图: .setSaveThFilename().setThContentType() + UploadPretreatment uploadPretreatment = fileStorageService + .of(fileBytes) + .setOriginalFilename(attr.getOriginalFilename()) + // 不手动指定,由框架自动生成存储文件名 + .setSaveFilename(null) + .setContentType(attr.getContentType()) + .setPlatform(platform) + .setPath(formatDatePath(LocalDateTime.now())); + if (attr.isUseOriginalFilenameAsDownloadFileName() && fileStorageService.isSupportMetadata(platform)) { + String downFileName = URLEncoder.encode(attr.getOriginalFilename(), StandardCharsets.UTF_8); + uploadPretreatment.putMetadata(Constant.Metadata.CONTENT_DISPOSITION, "attachment;filename=" + downFileName); + } + FileInfo fileInfo; try { - fileInfo = fileStorageService - .of(fileBytes) - .setOriginalFilename(attr.getOriginalFilename()) - // 不手动指定,由框架自动生成存储文件名 - .setSaveFilename(null) - .setContentType(attr.getContentType()) - // 如果需要缩略图 - // .setSaveThFilename() - // .setThContentType(contentType) - .upload(); + fileInfo = uploadPretreatment.upload(); } catch (FileStorageRuntimeException fsre) { log.error("[文件上传下载门面][上传] FileStorageRuntimeException >> ", fsre); throw new BusinessException(OssErrorEnum.FILE_UPLOAD_FAILED); @@ -62,6 +78,14 @@ public OssFileInfoBO upload(byte[] fileBytes, @NonNull UploadFileAttributeDTO at @Override public OssFileDownloadReplyBO downloadById(Long fileInfoId) throws BusinessException { + /* + 注:开启多租户后,因可能允许未登录下载,无法确定当前租户ID,导致查询 SQL 会错误地拼接 AND tenant_id = null 条件 + 解决方法1:Controller层方法解禁 @SaCheckLogin 注解,强制要求在 url-params 中传递 token 才可下载 + 解决方法2:后端使用 try-finally 临时设置特权租户上下文 + TenantContextHolder.setTenantContext(new TenantContext(HelioConstant.Tenant.DEFAULT_PRIVILEGED_TENANT_ID, "临时特权租户")) + 以绕过行级租户过滤器;数据源级租户同理,使其固定访问某个数据源来查询文件信息 + 解决方法3:改造Controller层方法参数,增加传递一个租户ID字段,并在此切换上下文 + */ OssFileInfoBO ossFileInfo = ossFileInfoService.getOneById(fileInfoId, true); /* @@ -99,4 +123,12 @@ public OssFileDownloadReplyBO downloadById(Long fileInfoId) throws BusinessExcep public boolean isLocalPlatform(String storagePlatform) { return OssFileInfoService.isLocalPlatform(storagePlatform); } + + /** + * 格式化日期为路径形式,如:2024/01/01/ + * @param date 任意日期,一般取今日 + */ + private String formatDatePath(LocalDateTime date) { + return String.format("%d/%02d/%02d/", date.getYear(), date.getMonthValue(), date.getDayOfMonth()); + } } diff --git a/service-module/oss/oss-service/src/main/java/cc/uncarbon/module/oss/config/FileStorageConfiguration.java b/service-module/oss/oss-service/src/main/java/cc/uncarbon/module/oss/config/FileStorageConfiguration.java index df5ecb5..c5f08dc 100644 --- a/service-module/oss/oss-service/src/main/java/cc/uncarbon/module/oss/config/FileStorageConfiguration.java +++ b/service-module/oss/oss-service/src/main/java/cc/uncarbon/module/oss/config/FileStorageConfiguration.java @@ -1,10 +1,10 @@ -package cc.uncarbon.module.oss.config; - -import org.dromara.x.file.storage.spring.EnableFileStorage; -import org.springframework.context.annotation.Configuration; - - -@EnableFileStorage -@Configuration -public class FileStorageConfiguration { -} +package cc.uncarbon.module.oss.config; + +import org.dromara.x.file.storage.spring.EnableFileStorage; +import org.springframework.context.annotation.Configuration; + + +@EnableFileStorage +@Configuration +public class FileStorageConfiguration { +} diff --git a/service-module/oss/oss-service/src/main/java/cc/uncarbon/module/oss/service/OssFileInfoService.java b/service-module/oss/oss-service/src/main/java/cc/uncarbon/module/oss/service/OssFileInfoService.java index 6667e13..8933f44 100644 --- a/service-module/oss/oss-service/src/main/java/cc/uncarbon/module/oss/service/OssFileInfoService.java +++ b/service-module/oss/oss-service/src/main/java/cc/uncarbon/module/oss/service/OssFileInfoService.java @@ -107,7 +107,7 @@ public void adminDelete(Collection ids) { } // 2. 删除文件记录 - ossFileInfoMapper.deleteBatchIds(ids); + ossFileInfoMapper.deleteByIds(ids); } /** diff --git a/service-module/oss/pom.xml b/service-module/oss/pom.xml index 243d915..09a927f 100644 --- a/service-module/oss/pom.xml +++ b/service-module/oss/pom.xml @@ -8,13 +8,13 @@ cc.uncarbon.module helio-boot-modular - 2.1.0 + 2.2.0 ../../pom.xml oss 文件上传下载服务 - 2.1.0 + 2.2.0 oss-facade diff --git a/service-module/sys/pom.xml b/service-module/sys/pom.xml index e4a7ea3..5819359 100644 --- a/service-module/sys/pom.xml +++ b/service-module/sys/pom.xml @@ -8,13 +8,13 @@ cc.uncarbon.module helio-boot-modular - 2.1.0 + 2.2.0 ../../pom.xml sys 后台系统管理服务 - 2.1.0 + 2.2.0 sys-facade diff --git a/service-module/sys/sys-facade/pom.xml b/service-module/sys/sys-facade/pom.xml index 533b560..f5079de 100644 --- a/service-module/sys/sys-facade/pom.xml +++ b/service-module/sys/sys-facade/pom.xml @@ -8,7 +8,7 @@ cc.uncarbon.module sys - 2.1.0 + 2.2.0 sys-facade diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysErrorEnum.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysErrorEnum.java index 62a2f8e..a8b2dba 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysErrorEnum.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysErrorEnum.java @@ -13,57 +13,33 @@ public enum SysErrorEnum implements HelioBaseEnum { INVALID_ID(400, "无效ID"), - INCORRECT_PIN_OR_PWD(400, "账号或密码不正确"), - BANNED_USER(400, "用户被封禁"), - INVALID_TENANT(400, "所属租户无效"), - DISABLED_TENANT(400, "所属租户已禁用"), - INCORRECT_OLD_PASSWORD(400, "原密码有误"), - NO_ROLE_AVAILABLE_FOR_CURRENT_USER(400, "当前用户没有可用角色"), - NO_MENU_AVAILABLE_FOR_CURRENT_ROLE(400, "当前角色没有可用菜单"), - /* - 以下8个枚举用于后台角色管理的越权检查 - */ - + // 以下8个枚举用于后台角色管理的越权检查 ROLE_VALUE_CANNOT_BE(403, "角色值 {} 不能用于新增或编辑,请选用其他值"), - CANNOT_DELETE_SUPER_ADMIN_ROLE(403, "不能删除超级管理员角色"), - CANNOT_DELETE_TENANT_ADMIN_ROLE(403, "为减少脏数据,不建议直接删除租户管理员角色,需通过【删除租户】关联删除"), - CANNOT_DELETE_SELF_ROLE(403, "不能删除自身角色"), - CANNOT_BIND_MENUS_FOR_SUPER_ADMIN_ROLE(403, "不能为超级管理员角色绑定菜单"), - CANNOT_BIND_MENUS_FOR_SELF(403, "不能为自身角色绑定菜单"), - BEYOND_AUTHORITY_BIND_MENUS(401, "不得超越自身菜单权限"), - CANNOT_BIND_MENUS_FOR_TENANT_ADMIN_ROLE(403, "无权为租户管理员绑定菜单"), - /* - 以下4个枚举用于后台用户管理的越权检查 - */ + // 以下4个枚举用于后台用户管理的越权检查 CANNOT_OPERATE_SELF_USER(403, "不能对自身进行此操作"), - CANNOT_OPERATE_THIS_USER(403, "不能该用户进行此操作"), - CANNOT_UNBIND_SELF_TENANT_ADMIN_ROLE(403, "自身的管理员角色不能被取消"), - BEYOND_AUTHORITY_BIND_ROLES(401, "不得超越自身角色权限"), CANNOT_DELETE_PRIVILEGED_TENANT(403, "不能删除超级租户"), + NEED_DELETE_EXISTING_TENANT_ADMIN_ROLE(500, "租户ID {} 对应的租户管理员角色已存在,请使用超级管理员账号删除"),; - NEED_DELETE_EXISTING_TENANT_ADMIN_ROLE(500, "租户ID {} 对应的租户管理员角色已存在,请使用超级管理员账号删除"), - - ; private final Integer value; private final String label; diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysLogStatusEnum.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysLogStatusEnum.java index 33c1c3f..622a457 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysLogStatusEnum.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysLogStatusEnum.java @@ -14,12 +14,9 @@ public enum SysLogStatusEnum implements HelioBaseEnum { NON_EXECUTION(0, "未执行"), - SUCCESS(1, "成功"), + FAILED(2, "失败"),; - FAILED(2, "失败"), - - ; @EnumValue private final Integer value; private final String label; diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysMenuTypeEnum.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysMenuTypeEnum.java index 81310f4..6708f40 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysMenuTypeEnum.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysMenuTypeEnum.java @@ -34,9 +34,8 @@ public enum SysMenuTypeEnum implements HelioBaseEnum { /** * 外链 */ - EXTERNAL_LINK(3, "外链"), + EXTERNAL_LINK(3, "外链"),; - ; @EnumValue private final Integer value; private final String label; diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysUserStatusEnum.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysUserStatusEnum.java index cafd9f2..652049f 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysUserStatusEnum.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/enums/SysUserStatusEnum.java @@ -14,9 +14,8 @@ public enum SysUserStatusEnum implements HelioBaseEnum { BANNED(0, "封禁"), - ENABLED(1, "正常"), + ENABLED(1, "正常"),; - ; @EnumValue private final Integer value; private final String label; diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/extension/SysLogAspectExtension.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/extension/SysLogAspectExtension.java index 83a3792..c4a85ff 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/extension/SysLogAspectExtension.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/extension/SysLogAspectExtension.java @@ -1,34 +1,34 @@ -package cc.uncarbon.module.sys.extension; - -import cc.uncarbon.module.sys.annotation.SysLog; -import cc.uncarbon.module.sys.model.request.AdminInsertSysLogDTO; -import cc.uncarbon.module.sys.model.response.IPLocationBO; -import org.aspectj.lang.JoinPoint; - -/** - * SysLog 切面实现类扩展 - * - */ -public interface SysLogAspectExtension { - - /** - * 查询IP地址属地 - * @param ip IPv4或IPv6地址 - */ - default IPLocationBO queryIPLocation(String ip) { - return IPLocationBO.unknown(); - } - - /** - * 保存到 DB 前 - * @param insertSysLogDTO 新系统日志DTO - * @param joinPoint 切点 - * @param annotation 注解实例 - * @param e 异常实例;如果没有发生异常则值为null - * @param ret 原始方法过程,于顺利运行时的返回值 - */ - default void beforeSaving(final AdminInsertSysLogDTO insertSysLogDTO, final JoinPoint joinPoint, SysLog annotation, final Throwable e, Object ret) { - - } - -} +package cc.uncarbon.module.sys.extension; + +import cc.uncarbon.module.sys.annotation.SysLog; +import cc.uncarbon.module.sys.model.request.AdminInsertSysLogDTO; +import cc.uncarbon.module.sys.model.response.IPLocationBO; +import org.aspectj.lang.JoinPoint; + +/** + * SysLog 切面实现类扩展 + * + */ +public interface SysLogAspectExtension { + + /** + * 查询IP地址属地 + * @param ip IPv4或IPv6地址 + */ + default IPLocationBO queryIPLocation(String ip) { + return IPLocationBO.unknown(); + } + + /** + * 保存到 DB 前 + * @param insertSysLogDTO 新系统日志DTO + * @param joinPoint 切点 + * @param annotation 注解实例 + * @param e 异常实例;如果没有发生异常则值为null + * @param ret 原始方法过程,于顺利运行时的返回值 + */ + default void beforeSaving(final AdminInsertSysLogDTO insertSysLogDTO, final JoinPoint joinPoint, SysLog annotation, final Throwable e, Object ret) { + + } + +} diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/extension/impl/DefaultSysLogAspectExtension.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/extension/impl/DefaultSysLogAspectExtension.java index b357810..77f5b81 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/extension/impl/DefaultSysLogAspectExtension.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/extension/impl/DefaultSysLogAspectExtension.java @@ -1,70 +1,70 @@ -package cc.uncarbon.module.sys.extension.impl; - -import cc.uncarbon.module.sys.extension.SysLogAspectExtension; -import cc.uncarbon.module.sys.model.response.IPLocationBO; -import cn.hutool.core.net.NetUtil; -import cn.hutool.core.text.CharSequenceUtil; -import cn.hutool.core.text.StrPool; -import cn.hutool.core.util.CharsetUtil; -import cn.hutool.http.Header; -import cn.hutool.http.HttpRequest; -import cn.hutool.http.HttpResponse; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class DefaultSysLogAspectExtension implements SysLogAspectExtension { - - @Override - public IPLocationBO queryIPLocation(String ip) { - if (CharSequenceUtil.contains(ip, StrPool.COLON)) { - // 仅根据冒号简易判断;暂不支持IPv6地址 - return IPLocationBO.unknown(); - } - - if (NetUtil.isInnerIP(ip)) { - return IPLocationBO.intranet(); - } - - // 该API主要支持中国内地 - HttpRequest httpRequest = HttpRequest.get("http://whois.pconline.com.cn/ipJson.jsp") - .form("ip", ip) - .form("json", Boolean.TRUE.toString()) - .charset(CharsetUtil.CHARSET_GBK) - // since 1.11.0,加个UA避免被当成恶意请求,造成查IP失败 - .header(Header.USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36") - .timeout(5000); - try (HttpResponse httpResponse = httpRequest.execute()) { - String repStr = httpResponse.body(); - if (JSONUtil.isTypeJSONObject(repStr)) { - /* - 返回文本是JSON对象 - example1: - {"ip":"39.156.66.10","pro":"北京市","proCode":"110000","city":"北京市","cityCode":"110000","region":"","regionCode":"0","addr":"北京市 移通","regionNames":"","err":""} - - example2: - {"ip":"1.1.1.1","pro":"","proCode":"999999","city":"","cityCode":"0","region":"","regionCode":"0","addr":" 美国APNIC&CloudFlare公共DNS服务器","regionNames":"","err":"noprovince"} - - example3: - {"ip":"8.8.8.8","pro":"","proCode":"999999","city":"","cityCode":"0","region":"","regionCode":"0","addr":" 美国","regionNames":"","err":"noprovince"} - */ - JSONObject repJson = JSONUtil.parseObj(repStr); - String pro = repJson.getStr("pro"); - String err = repJson.getStr("err"); - if (CharSequenceUtil.isEmpty(pro) || "noprovince".equals(err)) { - // 可能是非中国内地IP - String regionName = repJson.getStr("addr"); - return IPLocationBO.unknown().setRegionName(regionName); - } - return IPLocationBO.inChina() - .setProvinceName(pro) - .setCityName(repJson.getStr("city")); - } - } catch (Exception e) { - log.error("[SysLog切面][查询IP地址属地异常] >> ip={} \n", ip, e); - } - - return IPLocationBO.unknown(); - } -} +package cc.uncarbon.module.sys.extension.impl; + +import cc.uncarbon.module.sys.extension.SysLogAspectExtension; +import cc.uncarbon.module.sys.model.response.IPLocationBO; +import cn.hutool.core.net.NetUtil; +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.text.StrPool; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.http.Header; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class DefaultSysLogAspectExtension implements SysLogAspectExtension { + + @Override + public IPLocationBO queryIPLocation(String ip) { + if (CharSequenceUtil.contains(ip, StrPool.COLON)) { + // 仅根据冒号简易判断;暂不支持IPv6地址 + return IPLocationBO.unknown(); + } + + if (NetUtil.isInnerIP(ip)) { + return IPLocationBO.intranet(); + } + + // 该API主要支持中国内地 + HttpRequest httpRequest = HttpRequest.get("http://whois.pconline.com.cn/ipJson.jsp") + .form("ip", ip) + .form("json", Boolean.TRUE.toString()) + .charset(CharsetUtil.CHARSET_GBK) + // since 1.11.0,加个UA避免被当成恶意请求,造成查IP失败 + .header(Header.USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36") + .timeout(5000); + try (HttpResponse httpResponse = httpRequest.execute()) { + String repStr = httpResponse.body(); + if (JSONUtil.isTypeJSONObject(repStr)) { + /* + 返回文本是JSON对象 + example1: + {"ip":"39.156.66.10","pro":"北京市","proCode":"110000","city":"北京市","cityCode":"110000","region":"","regionCode":"0","addr":"北京市 移通","regionNames":"","err":""} + + example2: + {"ip":"1.1.1.1","pro":"","proCode":"999999","city":"","cityCode":"0","region":"","regionCode":"0","addr":" 美国APNIC&CloudFlare公共DNS服务器","regionNames":"","err":"noprovince"} + + example3: + {"ip":"8.8.8.8","pro":"","proCode":"999999","city":"","cityCode":"0","region":"","regionCode":"0","addr":" 美国","regionNames":"","err":"noprovince"} + */ + JSONObject repJson = JSONUtil.parseObj(repStr); + String pro = repJson.getStr("pro"); + String err = repJson.getStr("err"); + if (CharSequenceUtil.isEmpty(pro) || "noprovince".equals(err)) { + // 可能是非中国内地IP + String regionName = repJson.getStr("addr"); + return IPLocationBO.unknown().setRegionName(regionName); + } + return IPLocationBO.inChina() + .setProvinceName(pro) + .setCityName(repJson.getStr("city")); + } + } catch (Exception e) { + log.error("[SysLog切面][查询IP地址属地异常] >> ip={} \n", ip, e); + } + + return IPLocationBO.unknown(); + } +} diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/facade/SysTenantFacade.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/facade/SysTenantFacade.java index 8875384..766dd7b 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/facade/SysTenantFacade.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/facade/SysTenantFacade.java @@ -1,29 +1,29 @@ -package cc.uncarbon.module.sys.facade; - -import cc.uncarbon.module.sys.model.request.AdminInsertSysTenantDTO; -import cc.uncarbon.module.sys.model.request.AdminUpdateSysTenantDTO; -import cc.uncarbon.module.sys.model.response.SysTenantKickOutUsersBO; - -import java.util.Collection; - -/** - * 系统租户解耦层,用于解决循环依赖 - */ -public interface SysTenantFacade { - - /** - * 后台管理-新增 - */ - Long adminInsert(AdminInsertSysTenantDTO dto); - - /** - * 后台管理-编辑 - */ - SysTenantKickOutUsersBO adminUpdate(AdminUpdateSysTenantDTO dto); - - /** - * 后台管理-删除 - */ - SysTenantKickOutUsersBO adminDelete(Collection ids); - -} +package cc.uncarbon.module.sys.facade; + +import cc.uncarbon.module.sys.model.request.AdminInsertSysTenantDTO; +import cc.uncarbon.module.sys.model.request.AdminUpdateSysTenantDTO; +import cc.uncarbon.module.sys.model.response.SysTenantKickOutUsersBO; + +import java.util.Collection; + +/** + * 系统租户解耦层,用于解决循环依赖 + */ +public interface SysTenantFacade { + + /** + * 后台管理-新增 + */ + Long adminInsert(AdminInsertSysTenantDTO dto); + + /** + * 后台管理-编辑 + */ + SysTenantKickOutUsersBO adminUpdate(AdminUpdateSysTenantDTO dto); + + /** + * 后台管理-删除 + */ + SysTenantKickOutUsersBO adminDelete(Collection ids); + +} diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictClassifiedInsertOrUpdateDTO.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictClassifiedInsertOrUpdateDTO.java index d3faca6..57b5f13 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictClassifiedInsertOrUpdateDTO.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictClassifiedInsertOrUpdateDTO.java @@ -11,7 +11,6 @@ import lombok.experimental.Accessors; import lombok.experimental.SuperBuilder; -import java.io.Serial; import java.io.Serializable; @@ -25,10 +24,6 @@ @Data public class AdminSysDataDictClassifiedInsertOrUpdateDTO implements Serializable { - @Serial - private static final long serialVersionUID = 1L; - - @Schema(description = "主键ID", hidden = true, title = "仅更新时使用") private Long id; diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictClassifiedListDTO.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictClassifiedListDTO.java index 4eac478..9fd7b7c 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictClassifiedListDTO.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictClassifiedListDTO.java @@ -7,7 +7,6 @@ import lombok.experimental.Accessors; import lombok.experimental.SuperBuilder; -import java.io.Serial; import java.io.Serializable; @@ -21,10 +20,6 @@ @Data public class AdminSysDataDictClassifiedListDTO implements Serializable { - @Serial - private static final long serialVersionUID = 1L; - - @Schema(description = "分类编码") private String code; diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictItemInsertOrUpdateDTO.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictItemInsertOrUpdateDTO.java index 36e5dfa..9626365 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictItemInsertOrUpdateDTO.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictItemInsertOrUpdateDTO.java @@ -11,7 +11,6 @@ import lombok.experimental.Accessors; import lombok.experimental.SuperBuilder; -import java.io.Serial; import java.io.Serializable; @@ -25,10 +24,6 @@ @Data public class AdminSysDataDictItemInsertOrUpdateDTO implements Serializable { - @Serial - private static final long serialVersionUID = 1L; - - @Schema(description = "主键ID", hidden = true, title = "仅更新时使用") private Long id; diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictItemListDTO.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictItemListDTO.java index aa8471a..4f952bf 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictItemListDTO.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/request/AdminSysDataDictItemListDTO.java @@ -7,7 +7,6 @@ import lombok.experimental.Accessors; import lombok.experimental.SuperBuilder; -import java.io.Serial; import java.io.Serializable; @@ -21,10 +20,6 @@ @Data public class AdminSysDataDictItemListDTO implements Serializable { - @Serial - private static final long serialVersionUID = 1L; - - @Schema(description = "所属分类ID", hidden = true) private Long classifiedId; diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/IPLocationBO.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/IPLocationBO.java index 29621d6..25479ee 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/IPLocationBO.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/IPLocationBO.java @@ -1,53 +1,53 @@ -package cc.uncarbon.module.sys.model.response; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; - -import java.io.Serializable; - -/** - * IP地址属地 - * 首用于系统日志 - */ -@Accessors(chain = true) -@AllArgsConstructor -@NoArgsConstructor -@Data -public class IPLocationBO implements Serializable { - - @Schema(description = "国家或地区名") - private String regionName; - - @Schema(description = "省级行政区名") - private String provinceName; - - @Schema(description = "市级行政区名") - private String cityName; - - @Schema(description = "县级行政区名") - private String districtName; - - /** - * 未知属地 - */ - public static IPLocationBO unknown() { - return new IPLocationBO("未知", null, null, null); - } - - /** - * 内网地址 - */ - public static IPLocationBO intranet() { - return new IPLocationBO("内网", null, null, null); - } - - /** - * 位于中国内地 - */ - public static IPLocationBO inChina() { - return new IPLocationBO("中国", null, null, null); - } -} +package cc.uncarbon.module.sys.model.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * IP地址属地 + * 首用于系统日志 + */ +@Accessors(chain = true) +@AllArgsConstructor +@NoArgsConstructor +@Data +public class IPLocationBO implements Serializable { + + @Schema(description = "国家或地区名") + private String regionName; + + @Schema(description = "省级行政区名") + private String provinceName; + + @Schema(description = "市级行政区名") + private String cityName; + + @Schema(description = "县级行政区名") + private String districtName; + + /** + * 未知属地 + */ + public static IPLocationBO unknown() { + return new IPLocationBO("未知", null, null, null); + } + + /** + * 内网地址 + */ + public static IPLocationBO intranet() { + return new IPLocationBO("内网", null, null, null); + } + + /** + * 位于中国内地 + */ + public static IPLocationBO inChina() { + return new IPLocationBO("中国", null, null, null); + } +} diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/SysDataDictClassifiedBO.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/SysDataDictClassifiedBO.java index 3d7a039..a38c7d9 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/SysDataDictClassifiedBO.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/SysDataDictClassifiedBO.java @@ -11,7 +11,6 @@ import lombok.experimental.SuperBuilder; import org.springframework.format.annotation.DateTimeFormat; -import java.io.Serial; import java.io.Serializable; import java.time.LocalDateTime; @@ -26,10 +25,6 @@ @Data public class SysDataDictClassifiedBO implements Serializable { - @Serial - private static final long serialVersionUID = 1L; - - @Schema(description = "主键ID", hidden = true, title = "仅更新时使用") private Long id; diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/SysDataDictItemBO.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/SysDataDictItemBO.java index 08ba33b..b6a261d 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/SysDataDictItemBO.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/SysDataDictItemBO.java @@ -11,7 +11,6 @@ import lombok.experimental.SuperBuilder; import org.springframework.format.annotation.DateTimeFormat; -import java.io.Serial; import java.io.Serializable; import java.time.LocalDateTime; @@ -26,10 +25,6 @@ @Data public class SysDataDictItemBO implements Serializable { - @Serial - private static final long serialVersionUID = 1L; - - @Schema(description = "主键ID", hidden = true, title = "仅更新时使用") private Long id; diff --git a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/SysTenantKickOutUsersBO.java b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/SysTenantKickOutUsersBO.java index 1ce33a1..f47c288 100644 --- a/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/SysTenantKickOutUsersBO.java +++ b/service-module/sys/sys-facade/src/main/java/cc/uncarbon/module/sys/model/response/SysTenantKickOutUsersBO.java @@ -1,26 +1,26 @@ -package cc.uncarbon.module.sys.model.response; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Getter; - -import java.util.Collections; -import java.util.List; - -/** - * 系统租户-需强制登出用户 BO - * 同一时间大量登出,会操作大量Redis键,可能存在缓存雪崩的风险 - */ -@Getter -public class SysTenantKickOutUsersBO { - - @Schema(description = "后台用户IDs") - private final List sysUserIds; - - public SysTenantKickOutUsersBO() { - this.sysUserIds = Collections.emptyList(); - } - - public SysTenantKickOutUsersBO(List sysUserIds) { - this.sysUserIds = sysUserIds; - } -} +package cc.uncarbon.module.sys.model.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +import java.util.Collections; +import java.util.List; + +/** + * 系统租户-需强制登出用户 BO + * 同一时间大量登出,会操作大量Redis键,可能存在缓存雪崩的风险 + */ +@Getter +public class SysTenantKickOutUsersBO { + + @Schema(description = "后台用户IDs") + private final List sysUserIds; + + public SysTenantKickOutUsersBO() { + this.sysUserIds = Collections.emptyList(); + } + + public SysTenantKickOutUsersBO(List sysUserIds) { + this.sysUserIds = sysUserIds; + } +} diff --git a/service-module/sys/sys-service/pom.xml b/service-module/sys/sys-service/pom.xml index 897ed04..86eb6d8 100644 --- a/service-module/sys/sys-service/pom.xml +++ b/service-module/sys/sys-service/pom.xml @@ -8,7 +8,7 @@ cc.uncarbon.module sys - 2.1.0 + 2.2.0 sys-service @@ -21,7 +21,7 @@ cc.uncarbon.module sys-facade - 2.1.0 + ${parent.version} diff --git a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/model/interior/UserDeptContainer.java b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/model/interior/UserDeptContainer.java index d92403a..e33b078 100644 --- a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/model/interior/UserDeptContainer.java +++ b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/model/interior/UserDeptContainer.java @@ -1,81 +1,81 @@ -package cc.uncarbon.module.sys.model.interior; - -import cc.uncarbon.module.sys.entity.SysDeptEntity; -import cn.hutool.core.collection.CollUtil; -import lombok.Getter; - -import java.util.Collections; -import java.util.List; - -/** - * 用户关联部门容器 - */ -@Getter -public class UserDeptContainer { - - /** - * 直接关联的部门IDs - * 一般只有0或1个元素 - */ - private final List relatedDeptIds; - - /** - * 直接关联的部门实例集合 - * 一般只有0或1个元素 - */ - private final List relatedDepts; - - /** - * 可见的部门IDs - */ - private List visibleDeptIds; - - /** - * 可见的部门实例集合 - */ - private List visibleDepts; - - - public UserDeptContainer(List relatedDeptIds, List relatedDepts) { - this.relatedDeptIds = relatedDeptIds; - this.relatedDepts = relatedDepts; - this.visibleDeptIds = relatedDeptIds; - this.visibleDepts = relatedDepts; - } - - /** - * 用户是否有实际关联的部门 - */ - public boolean hasRelatedDepts() { - return CollUtil.isNotEmpty(relatedDeptIds) && CollUtil.isNotEmpty(relatedDepts); - } - - /** - * 用户主要关联的部门,默认取第一个元素 - * @return null or 部门实例 - */ - public SysDeptEntity primaryRelatedDept() { - return CollUtil.getFirst(relatedDepts); - } - - /** - * 用户是否有实际可见的部门 - * 也可视为部门的数据权限范围 - */ - public boolean hasVisibleDepts() { - return CollUtil.isNotEmpty(visibleDeptIds) && CollUtil.isNotEmpty(visibleDepts); - } - - /** - * 更新可见的部门 - */ - public void updateVisibleDepts(List visibleDepts) { - if (CollUtil.isEmpty(visibleDepts)) { - this.visibleDeptIds = Collections.emptyList(); - this.visibleDepts = Collections.emptyList(); - } else { - this.visibleDeptIds = visibleDepts.stream().map(SysDeptEntity::getId).toList(); - this.visibleDepts = visibleDepts; - } - } -} +package cc.uncarbon.module.sys.model.interior; + +import cc.uncarbon.module.sys.entity.SysDeptEntity; +import cn.hutool.core.collection.CollUtil; +import lombok.Getter; + +import java.util.Collections; +import java.util.List; + +/** + * 用户关联部门容器 + */ +@Getter +public class UserDeptContainer { + + /** + * 直接关联的部门IDs + * 一般只有0或1个元素 + */ + private final List relatedDeptIds; + + /** + * 直接关联的部门实例集合 + * 一般只有0或1个元素 + */ + private final List relatedDepts; + + /** + * 可见的部门IDs + */ + private List visibleDeptIds; + + /** + * 可见的部门实例集合 + */ + private List visibleDepts; + + + public UserDeptContainer(List relatedDeptIds, List relatedDepts) { + this.relatedDeptIds = relatedDeptIds; + this.relatedDepts = relatedDepts; + this.visibleDeptIds = relatedDeptIds; + this.visibleDepts = relatedDepts; + } + + /** + * 用户是否有实际关联的部门 + */ + public boolean hasRelatedDepts() { + return CollUtil.isNotEmpty(relatedDeptIds) && CollUtil.isNotEmpty(relatedDepts); + } + + /** + * 用户主要关联的部门,默认取第一个元素 + * @return null or 部门实例 + */ + public SysDeptEntity primaryRelatedDept() { + return CollUtil.getFirst(relatedDepts); + } + + /** + * 用户是否有实际可见的部门 + * 也可视为部门的数据权限范围 + */ + public boolean hasVisibleDepts() { + return CollUtil.isNotEmpty(visibleDeptIds) && CollUtil.isNotEmpty(visibleDepts); + } + + /** + * 更新可见的部门 + */ + public void updateVisibleDepts(List visibleDepts) { + if (CollUtil.isEmpty(visibleDepts)) { + this.visibleDeptIds = Collections.emptyList(); + this.visibleDepts = Collections.emptyList(); + } else { + this.visibleDeptIds = visibleDepts.stream().map(SysDeptEntity::getId).toList(); + this.visibleDepts = visibleDepts; + } + } +} diff --git a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/model/interior/UserRoleContainer.java b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/model/interior/UserRoleContainer.java index b02958e..5b60ce2 100644 --- a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/model/interior/UserRoleContainer.java +++ b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/model/interior/UserRoleContainer.java @@ -1,48 +1,48 @@ -package cc.uncarbon.module.sys.model.interior; - -import cc.uncarbon.module.sys.entity.SysRoleEntity; -import lombok.Getter; - -import java.util.List; -import java.util.Set; - -/** - * 用户关联角色容器 - */ -@Getter -public class UserRoleContainer { - - /** - * 直接关联的角色IDs - */ - private final Set relatedRoleIds; - - /** - * 直接关联的角色实例集合 - */ - private final List relatedRoles; - - /** - * 为超级管理员 - */ - private final boolean superAdmin; - - /** - * 为租户管理员 - */ - private final boolean tenantAdmin; - - /** - * 非级管理员or租户管理员 - */ - private final boolean notAnyAdmin; - - - public UserRoleContainer(Set relatedRoleIds, List relatedRoles) { - this.relatedRoleIds = relatedRoleIds; - this.relatedRoles = relatedRoles; - this.superAdmin = relatedRoles.stream().anyMatch(SysRoleEntity::isSuperAdmin); - this.tenantAdmin = relatedRoles.stream().anyMatch(SysRoleEntity::isTenantAdmin); - this.notAnyAdmin = !this.superAdmin && !this.tenantAdmin; - } -} +package cc.uncarbon.module.sys.model.interior; + +import cc.uncarbon.module.sys.entity.SysRoleEntity; +import lombok.Getter; + +import java.util.List; +import java.util.Set; + +/** + * 用户关联角色容器 + */ +@Getter +public class UserRoleContainer { + + /** + * 直接关联的角色IDs + */ + private final Set relatedRoleIds; + + /** + * 直接关联的角色实例集合 + */ + private final List relatedRoles; + + /** + * 为超级管理员 + */ + private final boolean superAdmin; + + /** + * 为租户管理员 + */ + private final boolean tenantAdmin; + + /** + * 非级管理员or租户管理员 + */ + private final boolean notAnyAdmin; + + + public UserRoleContainer(Set relatedRoleIds, List relatedRoles) { + this.relatedRoleIds = relatedRoleIds; + this.relatedRoles = relatedRoles; + this.superAdmin = relatedRoles.stream().anyMatch(SysRoleEntity::isSuperAdmin); + this.tenantAdmin = relatedRoles.stream().anyMatch(SysRoleEntity::isTenantAdmin); + this.notAnyAdmin = !this.superAdmin && !this.tenantAdmin; + } +} diff --git a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysDataDictService.java b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysDataDictService.java index 3041d51..5fe986c 100644 --- a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysDataDictService.java +++ b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysDataDictService.java @@ -97,7 +97,7 @@ public void adminUpdateClassified(AdminSysDataDictClassifiedInsertOrUpdateDTO dt @Transactional(rollbackFor = Exception.class) public void adminDeleteClassified(Collection ids) { log.info("[后台管理-删除数据字典分类] >> 入参={}", ids); - sysDataDictClassifiedMapper.deleteBatchIds(ids); + sysDataDictClassifiedMapper.deleteByIds(ids); } /** diff --git a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysDeptService.java b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysDeptService.java index 83a4ca3..4ac0b49 100644 --- a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysDeptService.java +++ b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysDeptService.java @@ -115,7 +115,7 @@ public void adminUpdate(AdminInsertOrUpdateSysDeptDTO dto) { @Transactional(rollbackFor = Exception.class) public void adminDelete(Collection ids) { log.info("[后台管理-删除部门] >> 入参={}", ids); - sysDeptMapper.deleteBatchIds(ids); + sysDeptMapper.deleteByIds(ids); } /** diff --git a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysMenuService.java b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysMenuService.java index 8c4e15c..143a95e 100644 --- a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysMenuService.java +++ b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysMenuService.java @@ -137,7 +137,7 @@ public void adminUpdate(AdminInsertOrUpdateSysMenuDTO dto) { @Transactional(rollbackFor = Exception.class) public void adminDelete(Collection ids) { log.info("[后台管理-删除后台菜单] >> 入参={}", ids); - sysMenuMapper.deleteBatchIds(ids); + sysMenuMapper.deleteByIds(ids); } /** diff --git a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysParamService.java b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysParamService.java index 2434e33..644a7fd 100644 --- a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysParamService.java +++ b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysParamService.java @@ -119,7 +119,7 @@ public void adminUpdate(AdminInsertOrUpdateSysParamDTO dto) { @Transactional(rollbackFor = Exception.class) public void adminDelete(Collection ids) { log.info("[后台管理-删除系统参数] >> 入参={}", ids); - sysParamMapper.deleteBatchIds(ids); + sysParamMapper.deleteByIds(ids); } /** diff --git a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysRoleService.java b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysRoleService.java index cb82d7c..d093b16 100644 --- a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysRoleService.java +++ b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysRoleService.java @@ -135,7 +135,7 @@ public void adminUpdate(AdminInsertOrUpdateSysRoleDTO dto) { public void adminDelete(Collection ids) { log.info("[后台管理-删除后台角色] >> 入参={}", ids); preDeleteCheck(ids); - sysRoleMapper.deleteBatchIds(ids); + sysRoleMapper.deleteByIds(ids); } /** diff --git a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysTenantService.java b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysTenantService.java index d466c7d..364e249 100644 --- a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysTenantService.java +++ b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysTenantService.java @@ -132,7 +132,7 @@ public void adminUpdate(SysTenantEntity entity) { @Transactional(rollbackFor = Exception.class) public void adminDelete(Collection ids) { log.info("[后台管理-删除系统租户] >> 入参={}", ids); - sysTenantMapper.deleteBatchIds(ids); + sysTenantMapper.deleteByIds(ids); } /** diff --git a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysUserService.java b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysUserService.java index b0cdc29..2ff2b06 100644 --- a/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysUserService.java +++ b/service-module/sys/sys-service/src/main/java/cc/uncarbon/module/sys/service/SysUserService.java @@ -197,7 +197,7 @@ public void adminUpdate(AdminInsertOrUpdateSysUserDTO dto) { public void adminDelete(Collection ids) { log.info("[后台管理-删除后台用户] >> 入参={}", ids); preDeleteCheck(ids); - sysUserMapper.deleteBatchIds(ids); + sysUserMapper.deleteByIds(ids); } /**