mirror of
https://github.com/continew-org/continew-admin.git
synced 2025-09-12 05:01:39 +08:00
refactor: 优化项目模块命名(简化、分类、统一)
This commit is contained in:
157
continew-common/pom.xml
Normal file
157
continew-common/pom.xml
Normal file
@@ -0,0 +1,157 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-admin</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>continew-common</artifactId>
|
||||
<description>公共模块(存放公共工具类,公共配置等)</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- CosId(通用、灵活、高性能的分布式 ID 生成器) -->
|
||||
<dependency>
|
||||
<groupId>me.ahoo.cosid</groupId>
|
||||
<artifactId>cosid-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.ahoo.cosid</groupId>
|
||||
<artifactId>cosid-spring-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SMS4J(短信聚合框架,轻松集成多家短信服务,解决接入多个短信 SDK 的繁琐流程) -->
|
||||
<dependency>
|
||||
<groupId>org.dromara.sms4j</groupId>
|
||||
<artifactId>sms4j-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- X File Storage(一行代码将文件存储到本地、FTP、SFTP、WebDAV、阿里云 OSS、华为云 OBS...等其它兼容 S3 协议的存储平台) -->
|
||||
<dependency>
|
||||
<groupId>org.dromara.x-file-storage</groupId>
|
||||
<artifactId>x-file-storage-spring</artifactId>
|
||||
</dependency>
|
||||
<!-- Amazon S3(Amazon Simple Storage Service,亚马逊简单存储服务,通用存储协议 S3,兼容主流云厂商对象存储) -->
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- FreeMarker(模板引擎) -->
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- MySQL Java 驱动 -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 扩展模块 - CURD(增删改查) -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-extension-crud-mp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 认证模块 - JustAuth -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-auth-justauth</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 数据权限模块 - MyBatis Plus -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-extension-datapermission-mp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 数据访问模块 - MyBatis Plus -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-data-mp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 缓存模块 - JetCache -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-cache-jetcache</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 消息模块 - WebSocket -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-messaging-websocket</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 消息模块 - 邮件 -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-messaging-mail</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 验证码模块 - 图形验证码 -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-captcha-graphic</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 验证码模块 - 行为验证码 -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-captcha-behavior</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 文件处理模块 - Excel -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-file-excel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 安全模块 - 限流器 -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-security-limiter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 安全模块 - 加密 -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-security-crypto</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 安全模块 - 脱敏 -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-security-mask</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter 安全模块 - 密码编码器 -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-security-password</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter API 文档模块 -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-api-doc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- ContiNew Starter JSON 模块 - Jackson -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-json-jackson</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.config.exception;
|
||||
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
import top.continew.starter.core.exception.BadRequestException;
|
||||
import top.continew.starter.core.exception.BusinessException;
|
||||
import top.continew.starter.web.model.R;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2024/8/7 20:21
|
||||
*/
|
||||
@Slf4j
|
||||
@Order(99)
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
/**
|
||||
* 拦截业务异常
|
||||
*/
|
||||
@ExceptionHandler(BusinessException.class)
|
||||
public R handleBusinessException(BusinessException e, HttpServletRequest request) {
|
||||
log.error("[{}] {}", request.getMethod(), request.getRequestURI(), e);
|
||||
return R.fail(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截自定义验证异常-错误请求
|
||||
*/
|
||||
@ExceptionHandler(BadRequestException.class)
|
||||
public R handleBadRequestException(BadRequestException e, HttpServletRequest request) {
|
||||
log.error("[{}] {}", request.getMethod(), request.getRequestURI(), e);
|
||||
return R.fail(String.valueOf(HttpStatus.BAD_REQUEST.value()), e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截文件上传异常-超过上传大小限制
|
||||
*/
|
||||
@ExceptionHandler(MultipartException.class)
|
||||
public R handleRequestTooBigException(MultipartException e, HttpServletRequest request) {
|
||||
log.error("[{}] {}", request.getMethod(), request.getRequestURI(), e);
|
||||
String msg = e.getMessage();
|
||||
R defaultFail = R.fail(String.valueOf(HttpStatus.BAD_REQUEST.value()), msg);
|
||||
if (CharSequenceUtil.isBlank(msg)) {
|
||||
return defaultFail;
|
||||
}
|
||||
String sizeLimit;
|
||||
Throwable cause = e.getCause();
|
||||
if (null != cause) {
|
||||
msg = msg.concat(cause.getMessage().toLowerCase());
|
||||
}
|
||||
if (msg.contains("size") && msg.contains("exceed")) {
|
||||
sizeLimit = CharSequenceUtil.subBetween(msg, "the maximum size ", " for");
|
||||
} else if (msg.contains("larger than")) {
|
||||
sizeLimit = CharSequenceUtil.subAfter(msg, "larger than ", true);
|
||||
} else {
|
||||
return defaultFail;
|
||||
}
|
||||
String errorMsg = "请上传小于 %sKB 的文件".formatted(NumberUtil.parseLong(sizeLimit) / 1024);
|
||||
return R.fail(String.valueOf(HttpStatus.BAD_REQUEST.value()), errorMsg);
|
||||
}
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.config.exception;
|
||||
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.exception.NotPermissionException;
|
||||
import cn.dev33.satoken.exception.NotRoleException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import top.continew.starter.web.model.R;
|
||||
|
||||
/**
|
||||
* 全局 SaToken 异常处理器
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2024/8/7 20:21
|
||||
*/
|
||||
@Slf4j
|
||||
@Order(99)
|
||||
@RestControllerAdvice
|
||||
public class GlobalSaTokenExceptionHandler {
|
||||
|
||||
/**
|
||||
* 认证异常-登录认证
|
||||
*/
|
||||
@ExceptionHandler(NotLoginException.class)
|
||||
public R handleNotLoginException(NotLoginException e, HttpServletRequest request) {
|
||||
log.error("[{}] {}", request.getMethod(), request.getRequestURI(), e);
|
||||
String errorMsg = switch (e.getType()) {
|
||||
case NotLoginException.KICK_OUT -> "您已被踢下线";
|
||||
case NotLoginException.BE_REPLACED_MESSAGE -> "您已被顶下线";
|
||||
default -> "您的登录状态已过期,请重新登录";
|
||||
};
|
||||
return R.fail(String.valueOf(HttpStatus.UNAUTHORIZED.value()), errorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证异常-权限认证
|
||||
*/
|
||||
@ExceptionHandler(NotPermissionException.class)
|
||||
public R handleNotPermissionException(NotPermissionException e, HttpServletRequest request) {
|
||||
log.error("[{}] {}", request.getMethod(), request.getRequestURI(), e);
|
||||
return R.fail(String.valueOf(HttpStatus.FORBIDDEN.value()), "没有访问权限,请联系管理员授权");
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证异常-角色认证
|
||||
*/
|
||||
@ExceptionHandler(NotRoleException.class)
|
||||
public R handleNotRoleException(NotRoleException e, HttpServletRequest request) {
|
||||
log.error("[{}] {}", request.getMethod(), request.getRequestURI(), e);
|
||||
return R.fail(String.valueOf(HttpStatus.FORBIDDEN.value()), "没有访问权限,请联系管理员授权");
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.config.mybatis;
|
||||
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import top.continew.starter.security.crypto.encryptor.IEncryptor;
|
||||
|
||||
/**
|
||||
* BCrypt 加/解密处理器(不可逆)
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2024/2/8 22:29
|
||||
*/
|
||||
public class BCryptEncryptor implements IEncryptor {
|
||||
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
public BCryptEncryptor(PasswordEncoder passwordEncoder) {
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encrypt(String plaintext, String password, String publicKey) throws Exception {
|
||||
return passwordEncoder.encode(plaintext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decrypt(String ciphertext, String password, String privateKey) throws Exception {
|
||||
return ciphertext;
|
||||
}
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.config.mybatis;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import top.continew.starter.data.mp.base.BaseMapper;
|
||||
import top.continew.starter.extension.datapermission.annotation.DataPermission;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据权限 Mapper 基类
|
||||
*
|
||||
* @param <T> 实体类
|
||||
* @author Charles7c
|
||||
* @since 2023/9/3 21:50
|
||||
*/
|
||||
public interface DataPermissionMapper<T> extends BaseMapper<T> {
|
||||
|
||||
/**
|
||||
* 根据 entity 条件,查询全部记录
|
||||
*
|
||||
* @param queryWrapper 实体对象封装操作类(可以为 null)
|
||||
* @return 全部记录
|
||||
*/
|
||||
@Override
|
||||
@DataPermission
|
||||
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
|
||||
|
||||
/**
|
||||
* 根据 entity 条件,查询全部记录(并翻页)
|
||||
*
|
||||
* @param page 分页查询条件
|
||||
* @param queryWrapper 实体对象封装操作类(可以为 null)
|
||||
* @return 全部记录(并翻页)
|
||||
*/
|
||||
@Override
|
||||
@DataPermission
|
||||
List<T> selectList(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.config.mybatis;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import top.continew.admin.common.context.UserContextHolder;
|
||||
import top.continew.starter.extension.datapermission.enums.DataScope;
|
||||
import top.continew.starter.extension.datapermission.filter.DataPermissionUserContextProvider;
|
||||
import top.continew.starter.extension.datapermission.model.RoleContext;
|
||||
import top.continew.starter.extension.datapermission.model.UserContext;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 数据权限用户上下文提供者
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/12/21 21:19
|
||||
*/
|
||||
public class DefaultDataPermissionUserContextProvider implements DataPermissionUserContextProvider {
|
||||
|
||||
@Override
|
||||
public boolean isFilter() {
|
||||
return !UserContextHolder.isAdmin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserContext getUserContext() {
|
||||
top.continew.admin.common.context.UserContext context = UserContextHolder.getContext();
|
||||
UserContext userContext = new UserContext();
|
||||
userContext.setUserId(Convert.toStr(context.getId()));
|
||||
userContext.setDeptId(Convert.toStr(context.getDeptId()));
|
||||
userContext.setRoles(context.getRoles()
|
||||
.stream()
|
||||
.map(r -> new RoleContext(Convert.toStr(r.getId()), DataScope.valueOf(r.getDataScope().name())))
|
||||
.collect(Collectors.toSet()));
|
||||
return userContext;
|
||||
}
|
||||
}
|
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.config.mybatis;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import top.continew.admin.common.context.UserContextHolder;
|
||||
import top.continew.starter.core.exception.BusinessException;
|
||||
import top.continew.starter.extension.crud.model.entity.BaseDO;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* MyBatis Plus 元对象处理器配置(插入或修改时自动填充)
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/22 19:52
|
||||
*/
|
||||
public class MyBatisPlusMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private static final String CREATE_USER = "createUser";
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private static final String CREATE_TIME = "createTime";
|
||||
/**
|
||||
* 修改人
|
||||
*/
|
||||
private static final String UPDATE_USER = "updateUser";
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private static final String UPDATE_TIME = "updateTime";
|
||||
|
||||
/**
|
||||
* 插入数据时填充
|
||||
*
|
||||
* @param metaObject 元对象
|
||||
*/
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
try {
|
||||
if (null == metaObject) {
|
||||
return;
|
||||
}
|
||||
Long createUser = UserContextHolder.getUserId();
|
||||
LocalDateTime createTime = LocalDateTime.now();
|
||||
if (metaObject.getOriginalObject() instanceof BaseDO baseDO) {
|
||||
// 继承了 BaseDO 的类,填充创建信息字段
|
||||
baseDO.setCreateUser(ObjectUtil.defaultIfNull(baseDO.getCreateUser(), createUser));
|
||||
baseDO.setCreateTime(ObjectUtil.defaultIfNull(baseDO.getCreateTime(), createTime));
|
||||
} else {
|
||||
// 未继承 BaseDO 的类,如存在创建信息字段则进行填充
|
||||
this.fillFieldValue(metaObject, CREATE_USER, createUser, false);
|
||||
this.fillFieldValue(metaObject, CREATE_TIME, createTime, false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException("插入数据时自动填充异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据时填充
|
||||
*
|
||||
* @param metaObject 元对象
|
||||
*/
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
try {
|
||||
if (null == metaObject) {
|
||||
return;
|
||||
}
|
||||
Long updateUser = UserContextHolder.getUserId();
|
||||
LocalDateTime updateTime = LocalDateTime.now();
|
||||
if (metaObject.getOriginalObject() instanceof BaseDO baseDO) {
|
||||
// 继承了 BaseDO 的类,填充修改信息
|
||||
baseDO.setUpdateUser(updateUser);
|
||||
baseDO.setUpdateTime(updateTime);
|
||||
} else {
|
||||
// 未继承 BaseDO 的类,根据类中拥有的修改信息字段进行填充,不存在修改信息字段不进行填充
|
||||
this.fillFieldValue(metaObject, UPDATE_USER, updateUser, true);
|
||||
this.fillFieldValue(metaObject, UPDATE_TIME, updateTime, true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException("修改数据时自动填充异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充字段值
|
||||
*
|
||||
* @param metaObject 元数据对象
|
||||
* @param fieldName 要填充的字段名
|
||||
* @param fillFieldValue 要填充的字段值
|
||||
* @param isOverride 如果字段值不为空,是否覆盖(true:覆盖;false:不覆盖)
|
||||
*/
|
||||
private void fillFieldValue(MetaObject metaObject, String fieldName, Object fillFieldValue, boolean isOverride) {
|
||||
if (metaObject.hasSetter(fieldName)) {
|
||||
Object fieldValue = metaObject.getValue(fieldName);
|
||||
setFieldValByName(fieldName, null != fieldValue && !isOverride ? fieldValue : fillFieldValue, metaObject);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.config.mybatis;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import top.continew.starter.extension.datapermission.filter.DataPermissionUserContextProvider;
|
||||
|
||||
/**
|
||||
* MyBatis Plus 配置
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/22 19:51
|
||||
*/
|
||||
@Configuration
|
||||
public class MybatisPlusConfiguration {
|
||||
|
||||
/**
|
||||
* 元对象处理器配置(插入或修改时自动填充)
|
||||
*/
|
||||
@Bean
|
||||
public MetaObjectHandler metaObjectHandler() {
|
||||
return new MyBatisPlusMetaObjectHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据权限用户上下文提供者
|
||||
*/
|
||||
@Bean
|
||||
public DataPermissionUserContextProvider dataPermissionUserContextProvider() {
|
||||
return new DefaultDataPermissionUserContextProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* BCrypt 加/解密处理器
|
||||
*/
|
||||
@Bean
|
||||
public BCryptEncryptor bCryptEncryptor(PasswordEncoder passwordEncoder) {
|
||||
return new BCryptEncryptor(passwordEncoder);
|
||||
}
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 验证码配置属性
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/11 13:35
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "captcha")
|
||||
public class CaptchaProperties {
|
||||
|
||||
/**
|
||||
* 图形验证码过期时间
|
||||
*/
|
||||
@Value("${continew-starter.captcha.graphic.expirationInMinutes}")
|
||||
private long expirationInMinutes;
|
||||
|
||||
/**
|
||||
* 邮箱验证码配置
|
||||
*/
|
||||
private CaptchaMail mail;
|
||||
|
||||
/**
|
||||
* 短信验证码配置
|
||||
*/
|
||||
private CaptchaSms sms;
|
||||
|
||||
/**
|
||||
* 邮箱验证码配置
|
||||
*/
|
||||
@Data
|
||||
public static class CaptchaMail {
|
||||
/**
|
||||
* 内容长度
|
||||
*/
|
||||
private int length;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private long expirationInMinutes;
|
||||
|
||||
/**
|
||||
* 模板路径
|
||||
*/
|
||||
private String templatePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信验证码配置
|
||||
*/
|
||||
@Data
|
||||
public static class CaptchaSms {
|
||||
/**
|
||||
* 内容长度
|
||||
*/
|
||||
private int length;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private long expirationInMinutes;
|
||||
|
||||
/**
|
||||
* 模板 ID
|
||||
*/
|
||||
private String templateId;
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.config.properties;
|
||||
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
|
||||
/**
|
||||
* RSA 配置属性
|
||||
*
|
||||
* @author Zheng Jie(ELADMIN)
|
||||
* @author Charles7c
|
||||
* @since 2022/12/21 20:21
|
||||
*/
|
||||
public class RsaProperties {
|
||||
|
||||
/**
|
||||
* 私钥
|
||||
*/
|
||||
public static final String PRIVATE_KEY;
|
||||
public static final String PUBLIC_KEY;
|
||||
|
||||
static {
|
||||
PRIVATE_KEY = SpringUtil.getProperty("continew-starter.security.crypto.private-key");
|
||||
PUBLIC_KEY = SpringUtil.getProperty("continew-starter.security.crypto.public-key");
|
||||
}
|
||||
|
||||
private RsaProperties() {
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.config.websocket;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
import top.continew.starter.core.exception.BusinessException;
|
||||
import top.continew.starter.messaging.websocket.core.WebSocketClientService;
|
||||
|
||||
/**
|
||||
* 当前登录用户 Provider
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2024/6/4 22:13
|
||||
*/
|
||||
@Component
|
||||
public class WebSocketClientServiceImpl implements WebSocketClientService {
|
||||
|
||||
@Override
|
||||
public String getClientId(ServletServerHttpRequest request) {
|
||||
HttpServletRequest servletRequest = request.getServletRequest();
|
||||
String token = servletRequest.getParameter("token");
|
||||
if (null == StpUtil.getLoginIdByToken(token)) {
|
||||
throw new BusinessException("登录已过期,请重新登录");
|
||||
}
|
||||
return token;
|
||||
}
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.constant;
|
||||
|
||||
import top.continew.starter.core.constant.StringConstants;
|
||||
|
||||
/**
|
||||
* 缓存相关常量
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/22 19:30
|
||||
*/
|
||||
public class CacheConstants {
|
||||
|
||||
/**
|
||||
* 分隔符
|
||||
*/
|
||||
public static final String DELIMITER = StringConstants.COLON;
|
||||
|
||||
/**
|
||||
* 验证码键前缀
|
||||
*/
|
||||
public static final String CAPTCHA_KEY_PREFIX = "CAPTCHA" + DELIMITER;
|
||||
|
||||
/**
|
||||
* 用户缓存键前缀
|
||||
*/
|
||||
public static final String USER_KEY_PREFIX = "USER" + DELIMITER;
|
||||
|
||||
/**
|
||||
* 菜单缓存键前缀
|
||||
*/
|
||||
public static final String MENU_KEY_PREFIX = "MENU" + DELIMITER;
|
||||
|
||||
/**
|
||||
* 字典缓存键前缀
|
||||
*/
|
||||
public static final String DICT_KEY_PREFIX = "DICT" + DELIMITER;
|
||||
|
||||
/**
|
||||
* 参数缓存键前缀
|
||||
*/
|
||||
public static final String OPTION_KEY_PREFIX = "OPTION" + DELIMITER;
|
||||
|
||||
/**
|
||||
* 仪表盘缓存键前缀
|
||||
*/
|
||||
public static final String DASHBOARD_KEY_PREFIX = "DASHBOARD" + DELIMITER;
|
||||
|
||||
/**
|
||||
* 用户密码错误次数缓存键前缀
|
||||
*/
|
||||
public static final String USER_PASSWORD_ERROR_KEY_PREFIX = USER_KEY_PREFIX + "PASSWORD_ERROR" + DELIMITER;
|
||||
|
||||
/**
|
||||
* 数据导入临时会话key
|
||||
*/
|
||||
public static final String DATA_IMPORT_KEY = "SYSTEM" + DELIMITER + "DATA_IMPORT" + DELIMITER;
|
||||
|
||||
private CacheConstants() {
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.constant;
|
||||
|
||||
import top.continew.starter.extension.crud.constant.ContainerPool;
|
||||
|
||||
/**
|
||||
* 数据源容器相关常量(Crane4j 数据填充组件使用)
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2024/1/20 12:33
|
||||
*/
|
||||
public class ContainerConstants extends ContainerPool {
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
public static final String USER_NICKNAME = ContainerPool.USER_NICKNAME;
|
||||
|
||||
/**
|
||||
* 用户角色 ID 列表
|
||||
*/
|
||||
public static final String USER_ROLE_ID_LIST = "UserRoleIdList";
|
||||
|
||||
/**
|
||||
* 用户角色名称列表
|
||||
*/
|
||||
public static final String USER_ROLE_NAME_LIST = "UserRoleNameList";
|
||||
|
||||
private ContainerConstants() {
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.constant;
|
||||
|
||||
/**
|
||||
* 正则相关常量
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/10 20:06
|
||||
*/
|
||||
public class RegexConstants {
|
||||
|
||||
/**
|
||||
* 用户名正则(用户名长度为 4-64 个字符,支持大小写字母、数字、下划线,以字母开头)
|
||||
*/
|
||||
public static final String USERNAME = "^[a-zA-Z][a-zA-Z0-9_]{3,64}$";
|
||||
|
||||
/**
|
||||
* 密码正则模板(密码长度为 min-max 个字符,支持大小写字母、数字、特殊字符,至少包含字母和数字)
|
||||
*/
|
||||
public static final String PASSWORD_TEMPLATE = "^(?=.*\\d)(?=.*[a-z]).{%s,%s}$";
|
||||
|
||||
/**
|
||||
* 密码正则(密码长度为 8-32 个字符,支持大小写字母、数字、特殊字符,至少包含字母和数字)
|
||||
*/
|
||||
public static final String PASSWORD = "^(?=.*\\d)(?=.*[a-z]).{8,32}$";
|
||||
|
||||
/**
|
||||
* 特殊字符正则
|
||||
*/
|
||||
public static final String SPECIAL_CHARACTER = "[-_`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]|\\n|\\r|\\t";
|
||||
|
||||
/**
|
||||
* 通用编码正则(长度为 2-30 个字符,支持大小写字母、数字、下划线,以字母开头)
|
||||
*/
|
||||
public static final String GENERAL_CODE = "^[a-zA-Z][a-zA-Z0-9_]{1,29}$";
|
||||
|
||||
/**
|
||||
* 通用名称正则(长度为 2-30 个字符,支持中文、字母、数字、下划线,短横线)
|
||||
*/
|
||||
public static final String GENERAL_NAME = "^[\\u4e00-\\u9fa5a-zA-Z0-9_-]{2,30}$";
|
||||
|
||||
/**
|
||||
* 包名正则(可以包含大小写字母、数字、下划线,每一级包名不能以数字开头)
|
||||
*/
|
||||
public static final String PACKAGE_NAME = "^(?:[a-zA-Z_][a-zA-Z0-9_]*\\.)*[a-zA-Z_][a-zA-Z0-9_]*$";
|
||||
|
||||
private RegexConstants() {
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.constant;
|
||||
|
||||
/**
|
||||
* 系统相关常量
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/2/9 22:11
|
||||
*/
|
||||
public class SysConstants {
|
||||
|
||||
/**
|
||||
* 否
|
||||
*/
|
||||
public static final Integer NO = 0;
|
||||
|
||||
/**
|
||||
* 是
|
||||
*/
|
||||
public static final Integer YES = 1;
|
||||
|
||||
/**
|
||||
* 管理员角色编码
|
||||
*/
|
||||
public static final String ADMIN_ROLE_CODE = "admin";
|
||||
/**
|
||||
* 超管角色组ID
|
||||
*/
|
||||
public static final Long SUPER_ROLE_ID = 1L;
|
||||
/**
|
||||
* 超管账号ID
|
||||
*/
|
||||
public static final Long SUPER_ADMIN_ID = 1L;
|
||||
|
||||
/**
|
||||
* 顶级部门 ID
|
||||
*/
|
||||
public static final Long SUPER_DEPT_ID = 1L;
|
||||
|
||||
/**
|
||||
* 顶级父 ID
|
||||
*/
|
||||
public static final Long SUPER_PARENT_ID = 0L;
|
||||
|
||||
/**
|
||||
* 全部权限标识
|
||||
*/
|
||||
public static final String ALL_PERMISSION = "*:*:*";
|
||||
|
||||
/**
|
||||
* 账号登录 URI
|
||||
*/
|
||||
public static final String LOGIN_URI = "/auth/account";
|
||||
|
||||
/**
|
||||
* 退出 URI
|
||||
*/
|
||||
public static final String LOGOUT_URI = "/auth/logout";
|
||||
|
||||
/**
|
||||
* 描述类字段后缀
|
||||
*/
|
||||
public static final String DESCRIPTION_FIELD_SUFFIX = "String";
|
||||
|
||||
private SysConstants() {
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.constant;
|
||||
|
||||
/**
|
||||
* UI 相关常量
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/9/17 14:12
|
||||
*/
|
||||
public class UiConstants {
|
||||
|
||||
/**
|
||||
* 主色(极致蓝)
|
||||
*/
|
||||
public static final String COLOR_PRIMARY = "arcoblue";
|
||||
|
||||
/**
|
||||
* 成功色(仙野绿)
|
||||
*/
|
||||
public static final String COLOR_SUCCESS = "green";
|
||||
|
||||
/**
|
||||
* 警告色(活力橙)
|
||||
*/
|
||||
public static final String COLOR_WARNING = "orangered";
|
||||
|
||||
/**
|
||||
* 错误色(浪漫红)
|
||||
*/
|
||||
public static final String COLOR_ERROR = "red";
|
||||
|
||||
/**
|
||||
* 默认色(中性灰)
|
||||
*/
|
||||
public static final String COLOR_DEFAULT = "gray";
|
||||
|
||||
private UiConstants() {
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.context;
|
||||
|
||||
import lombok.Data;
|
||||
import top.continew.admin.common.enums.DataScopeEnum;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 角色上下文
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/3/7 22:08
|
||||
*/
|
||||
@Data
|
||||
public class RoleContext implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 角色编码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 数据权限
|
||||
*/
|
||||
private DataScopeEnum dataScope;
|
||||
}
|
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.context;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import top.continew.admin.common.constant.SysConstants;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 用户上下文
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2024/10/9 20:29
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class UserContext implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 部门 ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 最后一次修改密码时间
|
||||
*/
|
||||
private LocalDateTime pwdResetTime;
|
||||
|
||||
/**
|
||||
* 登录时系统设置的密码过期天数
|
||||
*/
|
||||
private Integer passwordExpirationDays;
|
||||
|
||||
/**
|
||||
* 权限码集合
|
||||
*/
|
||||
private Set<String> permissions;
|
||||
|
||||
/**
|
||||
* 角色编码集合
|
||||
*/
|
||||
private Set<String> roleCodes;
|
||||
|
||||
/**
|
||||
* 角色集合
|
||||
*/
|
||||
private Set<RoleContext> roles;
|
||||
|
||||
public UserContext(Set<String> permissions, Set<RoleContext> roles, Integer passwordExpirationDays) {
|
||||
this.permissions = permissions;
|
||||
this.setRoles(roles);
|
||||
this.passwordExpirationDays = passwordExpirationDays;
|
||||
}
|
||||
|
||||
public void setRoles(Set<RoleContext> roles) {
|
||||
this.roles = roles;
|
||||
this.roleCodes = roles.stream().map(RoleContext::getCode).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为管理员
|
||||
*
|
||||
* @return true:是;false:否
|
||||
*/
|
||||
public boolean isAdmin() {
|
||||
if (CollUtil.isEmpty(roleCodes)) {
|
||||
return false;
|
||||
}
|
||||
return roleCodes.contains(SysConstants.ADMIN_ROLE_CODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码是否已过期
|
||||
*
|
||||
* @return 是否过期
|
||||
*/
|
||||
public boolean isPasswordExpired() {
|
||||
// 永久有效
|
||||
if (this.passwordExpirationDays == null || this.passwordExpirationDays <= SysConstants.NO) {
|
||||
return false;
|
||||
}
|
||||
// 初始密码(第三方登录用户)暂不提示修改
|
||||
if (this.pwdResetTime == null) {
|
||||
return false;
|
||||
}
|
||||
return this.pwdResetTime.plusDays(this.passwordExpirationDays).isBefore(LocalDateTime.now());
|
||||
}
|
||||
}
|
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.context;
|
||||
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import top.continew.starter.core.util.ExceptionUtils;
|
||||
import top.continew.starter.extension.crud.service.CommonUserService;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 用户上下文 Holder
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/24 12:58
|
||||
*/
|
||||
public class UserContextHolder {
|
||||
|
||||
private static final ThreadLocal<UserContext> CONTEXT_HOLDER = new ThreadLocal<>();
|
||||
private static final ThreadLocal<UserExtraContext> EXTRA_CONTEXT_HOLDER = new ThreadLocal<>();
|
||||
|
||||
private UserContextHolder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置上下文
|
||||
*
|
||||
* @param context 上下文
|
||||
*/
|
||||
public static void setContext(UserContext context) {
|
||||
setContext(context, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置上下文
|
||||
*
|
||||
* @param context 上下文
|
||||
* @param isUpdate 是否更新
|
||||
*/
|
||||
public static void setContext(UserContext context, boolean isUpdate) {
|
||||
CONTEXT_HOLDER.set(context);
|
||||
if (isUpdate) {
|
||||
StpUtil.getSessionByLoginId(context.getId()).set(SaSession.USER, context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上下文
|
||||
*
|
||||
* @return 上下文
|
||||
*/
|
||||
public static UserContext getContext() {
|
||||
UserContext context = CONTEXT_HOLDER.get();
|
||||
if (null == context) {
|
||||
context = StpUtil.getSession().getModel(SaSession.USER, UserContext.class);
|
||||
CONTEXT_HOLDER.set(context);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定用户的上下文
|
||||
*
|
||||
* @param userId 用户 ID
|
||||
* @return 上下文
|
||||
*/
|
||||
public static UserContext getContext(Long userId) {
|
||||
SaSession session = StpUtil.getSessionByLoginId(userId, false);
|
||||
if (null == session) {
|
||||
return null;
|
||||
}
|
||||
return session.getModel(SaSession.USER, UserContext.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置额外上下文
|
||||
*
|
||||
* @param context 额外上下文
|
||||
*/
|
||||
public static void setExtraContext(UserExtraContext context) {
|
||||
EXTRA_CONTEXT_HOLDER.set(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取额外上下文
|
||||
*
|
||||
* @return 额外上下文
|
||||
*/
|
||||
public static UserExtraContext getExtraContext() {
|
||||
UserExtraContext context = EXTRA_CONTEXT_HOLDER.get();
|
||||
if (null == context) {
|
||||
context = getExtraContext(StpUtil.getTokenValue());
|
||||
EXTRA_CONTEXT_HOLDER.set(context);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取额外上下文
|
||||
*
|
||||
* @param token 令牌
|
||||
* @return 额外上下文
|
||||
*/
|
||||
public static UserExtraContext getExtraContext(String token) {
|
||||
UserExtraContext context = new UserExtraContext();
|
||||
context.setIp(Convert.toStr(StpUtil.getExtra(token, "ip")));
|
||||
context.setAddress(Convert.toStr(StpUtil.getExtra(token, "address")));
|
||||
context.setBrowser(Convert.toStr(StpUtil.getExtra(token, "browser")));
|
||||
context.setOs(Convert.toStr(StpUtil.getExtra(token, "os")));
|
||||
context.setLoginTime(Convert.toLocalDateTime(StpUtil.getExtra(token, "loginTime")));
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除上下文
|
||||
*/
|
||||
public static void clearContext() {
|
||||
CONTEXT_HOLDER.remove();
|
||||
EXTRA_CONTEXT_HOLDER.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户 ID
|
||||
*
|
||||
* @return 用户 ID
|
||||
*/
|
||||
public static Long getUserId() {
|
||||
return Optional.ofNullable(getContext()).map(UserContext::getId).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户名
|
||||
*
|
||||
* @return 用户名
|
||||
*/
|
||||
public static String getUsername() {
|
||||
return Optional.ofNullable(getContext()).map(UserContext::getUsername).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户昵称
|
||||
*
|
||||
* @return 用户昵称
|
||||
*/
|
||||
public static String getNickname() {
|
||||
return getNickname(getUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户昵称
|
||||
*
|
||||
* @param userId 登录用户 ID
|
||||
* @return 用户昵称
|
||||
*/
|
||||
public static String getNickname(Long userId) {
|
||||
return ExceptionUtils.exToNull(() -> SpringUtil.getBean(CommonUserService.class).getNicknameById(userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为管理员
|
||||
*
|
||||
* @return 是否为管理员
|
||||
*/
|
||||
public static Boolean isAdmin() {
|
||||
StpUtil.checkLogin();
|
||||
return getContext().isAdmin();
|
||||
}
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.context;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.servlet.JakartaServletUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import top.continew.starter.core.util.ExceptionUtils;
|
||||
import top.continew.starter.core.util.IpUtils;
|
||||
import top.continew.starter.web.util.ServletUtils;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 用户额外上下文
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2024/10/9 20:29
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class UserExtraContext implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* IP
|
||||
*/
|
||||
private String ip;
|
||||
|
||||
/**
|
||||
* IP 归属地
|
||||
*/
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* 浏览器
|
||||
*/
|
||||
private String browser;
|
||||
|
||||
/**
|
||||
* 操作系统
|
||||
*/
|
||||
private String os;
|
||||
|
||||
/**
|
||||
* 登录时间
|
||||
*/
|
||||
private LocalDateTime loginTime;
|
||||
|
||||
public UserExtraContext(HttpServletRequest request) {
|
||||
this.ip = JakartaServletUtil.getClientIP(request);
|
||||
this.address = ExceptionUtils.exToNull(() -> IpUtils.getIpv4Address(this.ip));
|
||||
this.setBrowser(ServletUtils.getBrowser(request));
|
||||
this.setLoginTime(LocalDateTime.now());
|
||||
this.setOs(StrUtil.subBefore(ServletUtils.getOs(request), " or", false));
|
||||
}
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 数据权限枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/2/8 22:58
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum DataScopeEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 全部数据权限
|
||||
*/
|
||||
ALL(1, "全部数据权限"),
|
||||
|
||||
/**
|
||||
* 本部门及以下数据权限
|
||||
*/
|
||||
DEPT_AND_CHILD(2, "本部门及以下数据权限"),
|
||||
|
||||
/**
|
||||
* 本部门数据权限
|
||||
*/
|
||||
DEPT(3, "本部门数据权限"),
|
||||
|
||||
/**
|
||||
* 仅本人数据权限
|
||||
*/
|
||||
SELF(4, "仅本人数据权限"),
|
||||
|
||||
/**
|
||||
* 自定义数据权限
|
||||
*/
|
||||
CUSTOM(5, "自定义数据权限"),;
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.admin.common.constant.UiConstants;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 启用/禁用状态枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 22:38
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum DisEnableStatusEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 启用
|
||||
*/
|
||||
ENABLE(1, "启用", UiConstants.COLOR_SUCCESS),
|
||||
|
||||
/**
|
||||
* 禁用
|
||||
*/
|
||||
DISABLE(2, "禁用", UiConstants.COLOR_ERROR),;
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
private final String color;
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 性别枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/29 21:59
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum GenderEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 未知
|
||||
*/
|
||||
UNKNOWN(0, "未知"),
|
||||
|
||||
/**
|
||||
* 男
|
||||
*/
|
||||
MALE(1, "男"),
|
||||
|
||||
/**
|
||||
* 女
|
||||
*/
|
||||
FEMALE(2, "女"),;
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.admin.common.constant.UiConstants;
|
||||
import top.continew.starter.core.enums.BaseEnum;
|
||||
|
||||
/**
|
||||
* 成功/失败状态枚举
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/2/26 21:35
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum SuccessFailureStatusEnum implements BaseEnum<Integer> {
|
||||
|
||||
/**
|
||||
* 成功
|
||||
*/
|
||||
SUCCESS(1, "成功", UiConstants.COLOR_SUCCESS),
|
||||
|
||||
/**
|
||||
* 失败
|
||||
*/
|
||||
FAILURE(2, "失败", UiConstants.COLOR_ERROR),;
|
||||
|
||||
private final Integer value;
|
||||
private final String description;
|
||||
private final String color;
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.admin.common.util;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.asymmetric.KeyType;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import top.continew.admin.common.config.properties.RsaProperties;
|
||||
import top.continew.starter.core.exception.BusinessException;
|
||||
import top.continew.starter.core.util.validate.ValidationUtils;
|
||||
import top.continew.starter.security.crypto.autoconfigure.CryptoProperties;
|
||||
import top.continew.starter.security.crypto.encryptor.AesEncryptor;
|
||||
import top.continew.starter.security.crypto.encryptor.IEncryptor;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 加密/解密工具类
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/21 21:41
|
||||
*/
|
||||
public class SecureUtils {
|
||||
|
||||
private SecureUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥解密
|
||||
*
|
||||
* @param data 要解密的内容(Base64 加密过)
|
||||
* @return 解密后的内容
|
||||
*/
|
||||
public static String decryptByRsaPrivateKey(String data) {
|
||||
String privateKey = RsaProperties.PRIVATE_KEY;
|
||||
ValidationUtils.throwIfBlank(privateKey, "请配置 RSA 私钥");
|
||||
return decryptByRsaPrivateKey(data, privateKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥解密
|
||||
*
|
||||
* @param data 要解密的内容(Base64 加密过)
|
||||
* @param privateKey 私钥
|
||||
* @return 解密后的内容
|
||||
*/
|
||||
public static String decryptByRsaPrivateKey(String data, String privateKey) {
|
||||
return new String(SecureUtil.rsa(privateKey, null).decrypt(Base64.decode(data), KeyType.PrivateKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对普通加密字段列表进行AES加密,优化starter加密模块后优化这个方法
|
||||
*
|
||||
* @param values 待加密内容
|
||||
* @return 加密后内容
|
||||
*/
|
||||
public static List<String> encryptFieldByAes(List<String> values) {
|
||||
IEncryptor encryptor = new AesEncryptor();
|
||||
CryptoProperties properties = SpringUtil.getBean(CryptoProperties.class);
|
||||
return values.stream().map(value -> {
|
||||
try {
|
||||
return encryptor.encrypt(value, properties.getPassword(), properties.getPublicKey());
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException("字段加密异常");
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user