chore: top.charles7c.continew => top.continew

1.groupId 及基础包名调整,更短的包名,优化品牌形象
2.全局代码格式化
This commit is contained in:
2024-04-22 20:29:17 +08:00
parent da3a4e0756
commit 08eeabc47d
238 changed files with 1121 additions and 1154 deletions

View File

@@ -0,0 +1,62 @@
/*
* 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;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
import java.util.Objects;
/**
* Web MVC 配置
*
* @author Charles7c
* @since 2022/12/11 19:40
*/
@EnableWebMvc
@Configuration
@RequiredArgsConstructor
public class WebMvcConfiguration implements WebMvcConfigurer {
private final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;
/**
* 解决 Jackson2ObjectMapperBuilderCustomizer 配置不生效的问题
* <p>
* MappingJackson2HttpMessageConverter 对象在程序启动时创建了多个,移除多余的,保证只有一个
* </p>
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.removeIf(MappingJackson2HttpMessageConverter.class::isInstance);
if (Objects.isNull(mappingJackson2HttpMessageConverter)) {
converters.add(0, new MappingJackson2HttpMessageConverter());
} else {
converters.add(0, mappingJackson2HttpMessageConverter);
}
// 自定义 converters 时,需要手动在最前面添加 ByteArrayHttpMessageConverter
// 否则 Spring Doc OpenAPI 的 /*/api-docs/**(例如:/v3/api-docs/default接口响应内容会变为 Base64 编码后的内容,最终导致接口文档解析失败
// 详情请参阅https://github.com/springdoc/springdoc-openapi/issues/2143
converters.add(0, new ByteArrayHttpMessageConverter());
}
}

View File

@@ -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.config.jackson;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import top.continew.starter.data.mybatis.plus.base.IBaseEnum;
import java.io.IOException;
import java.lang.reflect.Field;
/**
* 通用枚举接口 IBaseEnum 反序列化器
*
* @author Charles7c
* @see IBaseEnum
* @since 2023/1/8 13:56
*/
@JacksonStdImpl
public class BaseEnumDeserializer extends JsonDeserializer<IBaseEnum> {
/**
* 静态实例
*/
public static final BaseEnumDeserializer SERIALIZER_INSTANCE = new BaseEnumDeserializer();
@Override
public IBaseEnum deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws IOException {
Class<?> targetClass = jsonParser.getCurrentValue().getClass();
String fieldName = jsonParser.getCurrentName();
String value = jsonParser.getText();
return this.getEnum(targetClass, value, fieldName);
}
/**
* 通过某字段对应值获取枚举实例,获取不到时为 {@code null}
*
* @param targetClass 目标类型
* @param value 字段值
* @param fieldName 字段名
* @return 对应枚举实例 ,获取不到时为 {@code null}
*/
private IBaseEnum getEnum(Class<?> targetClass, String value, String fieldName) {
Field field = ReflectUtil.getField(targetClass, fieldName);
Class<?> fieldTypeClass = field.getType();
Object[] enumConstants = fieldTypeClass.getEnumConstants();
for (Object enumConstant : enumConstants) {
if (ClassUtil.isAssignable(IBaseEnum.class, fieldTypeClass)) {
IBaseEnum baseEnum = (IBaseEnum)enumConstant;
if (baseEnum.getValue().equals(Integer.valueOf(value))) {
return baseEnum;
}
}
}
return null;
}
}

View File

@@ -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.config.jackson;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import top.continew.starter.data.mybatis.plus.base.IBaseEnum;
import java.io.IOException;
/**
* 通用枚举接口 IBaseEnum 序列化器
*
* @author Charles7c
* @see IBaseEnum
* @since 2023/1/8 13:56
*/
@JacksonStdImpl
public class BaseEnumSerializer extends JsonSerializer<IBaseEnum> {
/**
* 静态实例
*/
public static final BaseEnumSerializer SERIALIZER_INSTANCE = new BaseEnumSerializer();
@Override
public void serialize(IBaseEnum value, JsonGenerator generator, SerializerProvider serializers) throws IOException {
generator.writeObject(value.getValue());
}
}

View File

@@ -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.config.jackson;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import top.continew.starter.data.mybatis.plus.base.IBaseEnum;
/**
* Jackson 配置
*
* @author Charles7c
* @see IBaseEnum
* @since 2022/12/11 13:23
*/
@Slf4j
@Configuration
public class JacksonConfiguration {
/**
* 针对枚举接口 IBaseEnum 的序列化和反序列化
*/
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(IBaseEnum.class, BaseEnumSerializer.SERIALIZER_INSTANCE);
SimpleDeserializersWrapper deserializers = new SimpleDeserializersWrapper();
deserializers.addDeserializer(IBaseEnum.class, BaseEnumDeserializer.SERIALIZER_INSTANCE);
simpleModule.setDeserializers(deserializers);
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
objectMapper.registerModule(simpleModule);
return objectMapper;
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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.jackson;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
import com.fasterxml.jackson.databind.type.ClassKey;
import lombok.extern.slf4j.Slf4j;
/**
* 反序列化器包装类(重写 Jackson 反序列化枚举方法参阅FasterXML/jackson-databind#2842
*
* <p>
* 默认处理:<br>
* 1. Jackson 会先查找指定枚举类型对应的反序列化器例如GenderEnum 枚举类型,则是找 GenderEnum 枚举类型的对应反序列化器);<br>
* 2. 如果找不到则开始查找 Enum 类型(所有枚举父类)的反序列化器;<br>
* 3. 如果都找不到则会采用默认的枚举反序列化器(它仅能根据枚举类型的 name、ordinal 来进行反序列化)。
* </p>
* <p>
* 重写增强后:<br>
* 1. 同默认 1<br>
* 2. 同默认 2<br>
* 3. 如果也找不到 Enum 类型所有枚举父类的反序列化器开始查找指定枚举类型的接口的反序列化器例如GenderEnum 枚举类型,则是找它的接口 IBaseEnum 的反序列化器);<br>
* 4. 同默认 3。
* </p>
*
* @author Charles7c
* @since 2023/1/8 13:28
*/
@Slf4j
public class SimpleDeserializersWrapper extends SimpleDeserializers {
@Override
public JsonDeserializer<?> findEnumDeserializer(Class<?> type,
DeserializationConfig config,
BeanDescription beanDesc) throws JsonMappingException {
JsonDeserializer<?> deser = super.findEnumDeserializer(type, config, beanDesc);
if (null != deser) {
return deser;
}
// 重写增强开始查找指定枚举类型的接口的反序列化器例如GenderEnum 枚举类型,则是找它的接口 BaseEnum 的反序列化器)
for (Class<?> typeInterface : type.getInterfaces()) {
deser = this._classMappings.get(new ClassKey(typeInterface));
if (null != deser) {
return deser;
}
}
return null;
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,56 @@
/*
* 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.model.dto.LoginUser;
import top.continew.admin.common.util.helper.LoginHelper;
import top.continew.starter.data.mybatis.plus.datapermission.DataPermissionCurrentUser;
import top.continew.starter.data.mybatis.plus.datapermission.DataPermissionFilter;
import top.continew.starter.data.mybatis.plus.datapermission.DataScope;
import java.util.stream.Collectors;
/**
* 数据权限过滤器实现类
*
* @author Charles7c
* @since 2023/12/21 21:19
*/
public class DataPermissionFilterImpl implements DataPermissionFilter {
@Override
public boolean isFilter() {
LoginUser loginUser = LoginHelper.getLoginUser();
return !loginUser.isAdmin();
}
@Override
public DataPermissionCurrentUser getCurrentUser() {
LoginUser loginUser = LoginHelper.getLoginUser();
DataPermissionCurrentUser currentUser = new DataPermissionCurrentUser();
currentUser.setUserId(Convert.toStr(loginUser.getId()));
currentUser.setDeptId(Convert.toStr(loginUser.getDeptId()));
currentUser.setRoles(loginUser.getRoles()
.stream()
.map(r -> new DataPermissionCurrentUser.CurrentUserRole(Convert.toStr(r.getId()), DataScope.valueOf(r
.getDataScope()
.name())))
.collect(Collectors.toSet()));
return currentUser;
}
}

View File

@@ -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.mybatis.plus.base.BaseMapper;
import top.continew.starter.data.mybatis.plus.datapermission.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);
}

View File

@@ -0,0 +1,123 @@
/*
* 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.util.helper.LoginHelper;
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 = LoginHelper.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 = LoginHelper.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);
}
}
}

View File

@@ -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.data.mybatis.plus.datapermission.DataPermissionFilter;
/**
* MyBatis Plus 配置
*
* @author Charles7c
* @since 2022/12/22 19:51
*/
@Configuration
public class MybatisPlusConfiguration {
/**
* 元对象处理器配置(插入或修改时自动填充)
*/
@Bean
public MetaObjectHandler metaObjectHandler() {
return new MyBatisPlusMetaObjectHandler();
}
/**
* 数据权限过滤器
*/
@Bean
public DataPermissionFilter dataPermissionFilter() {
return new DataPermissionFilterImpl();
}
/**
* BCrypt 加/解密处理器
*/
@Bean
public BCryptEncryptor bCryptEncryptor(PasswordEncoder passwordEncoder) {
return new BCryptEncryptor(passwordEncoder);
}
}

View File

@@ -0,0 +1,97 @@
/*
* 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 long limitInSeconds;
/**
* 模板路径
*/
private String templatePath;
}
/**
* 短信验证码配置
*/
@Data
public static class CaptchaSms {
/**
* 内容长度
*/
private int length;
/**
* 过期时间
*/
private long expirationInMinutes;
/**
* 模板 ID
*/
private String templateId;
}
}

View File

@@ -0,0 +1,41 @@
/*
* 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 JieELADMIN
* @author Charles7c
* @since 2022/12/21 20:21
*/
public class RsaProperties {
/**
* 私钥
*/
public static final String PRIVATE_KEY;
static {
PRIVATE_KEY = SpringUtil.getProperty("continew-starter.security.crypto.private-key");
}
private RsaProperties() {
}
}

View File

@@ -0,0 +1,71 @@
/*
* 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 LOGIN_USER_KEY = "LOGIN_USER";
/**
* 验证码键前缀
*/
public static final String CAPTCHA_KEY_PREFIX = "CAPTCHA" + DELIMITER;
/**
* 限流键前缀
*/
public static final String LIMIT_KEY_PREFIX = "LIMIT" + DELIMITER;
/**
* 用户缓存键前缀
*/
public static final String USER_KEY_PREFIX = "USER" + DELIMITER;
/**
* 菜单缓存键前缀
*/
public static final String MENU_KEY_PREFIX = "MENU" + DELIMITER;
/**
* 参数缓存键前缀
*/
public static final String OPTION_KEY_PREFIX = "OPTION" + DELIMITER;
/**
* 仪表盘缓存键前缀
*/
public static final String DASHBOARD_KEY_PREFIX = "DASHBOARD" + DELIMITER;
private CacheConstants() {
}
}

View File

@@ -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 ROLE_DEPT_ID_LIST = "RoleDeptIdList";
private ContainerConstants() {
}
}

View File

@@ -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;
/**
* 正则相关常量
*
* @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}$";
/**
* 密码正则(长度为 6 到 32 位,可以包含字母、数字、下划线,特殊字符,同时包含字母和数字)
*/
public static final String PASSWORD = "^(?=.*\\d)(?=.*[a-z]).{6,32}$";
/**
* 通用编码正则(长度为 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() {
}
}

View File

@@ -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/2/9 22:11
*/
public class SysConstants {
/**
* 管理员角色编码
*/
public static final String ADMIN_ROLE_CODE = "admin";
/**
* 顶级部门 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() {
}
}

View File

@@ -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() {
}
}

View File

@@ -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.data.mybatis.plus.base.IBaseEnum;
/**
* 数据权限枚举
*
* @author Charles7c
* @since 2023/2/8 22:58
*/
@Getter
@RequiredArgsConstructor
public enum DataScopeEnum implements IBaseEnum<Integer> {
/**
* 全部数据权限
*/
ALL(1, "全部数据权限"),
/**
* 本部门及以下数据权限
*/
DEPT_AND_CHILD(2, "本部门及以下数据权限"),
/**
* 本部门数据权限
*/
DEPT(3, "本部门数据权限"),
/**
* 仅本人数据权限
*/
SELF(4, "仅本人数据权限"),
/**
* 自定义数据权限
*/
CUSTOM(5, "自定义数据权限"),;
private final Integer value;
private final String description;
}

View File

@@ -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.data.mybatis.plus.base.IBaseEnum;
/**
* 启用/禁用状态枚举
*
* @author Charles7c
* @since 2022/12/29 22:38
*/
@Getter
@RequiredArgsConstructor
public enum DisEnableStatusEnum implements IBaseEnum<Integer> {
/**
* 启用
*/
ENABLE(1, "启用", UiConstants.COLOR_SUCCESS),
/**
* 禁用
*/
DISABLE(2, "禁用", UiConstants.COLOR_ERROR),;
private final Integer value;
private final String description;
private final String color;
}

View File

@@ -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.data.mybatis.plus.base.IBaseEnum;
/**
* 性别枚举
*
* @author Charles7c
* @since 2022/12/29 21:59
*/
@Getter
@RequiredArgsConstructor
public enum GenderEnum implements IBaseEnum<Integer> {
/**
* 未知
*/
UNKNOWN(0, "未知"),
/**
* 男
*/
MALE(1, ""),
/**
* 女
*/
FEMALE(2, ""),;
private final Integer value;
private final String description;
}

View File

@@ -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.data.mybatis.plus.base.IBaseEnum;
/**
* 菜单类型枚举
*
* @author Charles7c
* @since 2023/2/15 20:12
*/
@Getter
@RequiredArgsConstructor
public enum MenuTypeEnum implements IBaseEnum<Integer> {
/**
* 目录
*/
DIR(1, "目录"),
/**
* 菜单
*/
MENU(2, "菜单"),
/**
* 按钮
*/
BUTTON(3, "按钮"),;
private final Integer value;
private final String description;
}

View File

@@ -0,0 +1,42 @@
/*
* 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.data.mybatis.plus.base.IBaseEnum;
/**
* 消息类型枚举
*
* @author Charles7c
* @since 2023/11/2 20:08
*/
@Getter
@RequiredArgsConstructor
public enum MessageTypeEnum implements IBaseEnum<Integer> {
/**
* 系统消息
*/
SYSTEM(1, "系统消息", UiConstants.COLOR_PRIMARY),;
private final Integer value;
private final String description;
private final String color;
}

View File

@@ -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.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* 第三方账号平台枚举
*
* @author Charles7c
* @since 2023/10/19 21:22
*/
@Getter
@RequiredArgsConstructor
public enum SocialSourceEnum {
/**
* 码云
*/
GITEE("码云"),
/**
* GitHub
*/
GITHUB("GitHub"),;
private final String description;
}

View File

@@ -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.data.mybatis.plus.base.IBaseEnum;
/**
* 成功/失败状态枚举
*
* @author Charles7c
* @since 2023/2/26 21:35
*/
@Getter
@RequiredArgsConstructor
public enum SuccessFailureStatusEnum implements IBaseEnum<Integer> {
/**
* 成功
*/
SUCCESS(1, "成功", UiConstants.COLOR_SUCCESS),
/**
* 失败
*/
FAILURE(2, "失败", UiConstants.COLOR_ERROR),;
private final Integer value;
private final String description;
private final String color;
}

View File

@@ -0,0 +1,111 @@
/*
* 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.model.dto;
import cn.hutool.core.collection.CollUtil;
import lombok.Data;
import top.continew.admin.common.constant.SysConstants;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Set;
/**
* 登录用户信息
*
* @author Charles7c
* @since 2022/12/24 13:01
*/
@Data
public class LoginUser implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 用户名
*/
private String username;
/**
* 部门 ID
*/
private Long deptId;
/**
* 权限码集合
*/
private Set<String> permissions;
/**
* 角色编码集合
*/
private Set<String> roleCodes;
/**
* 角色集合
*/
private Set<RoleDTO> roles;
/**
* 令牌
*/
private String token;
/**
* IP
*/
private String ip;
/**
* IP 归属地
*/
private String address;
/**
* 浏览器
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 登录时间
*/
private LocalDateTime loginTime;
/**
* 是否为管理员
*
* @return truefalse
*/
public boolean isAdmin() {
if (CollUtil.isEmpty(roleCodes)) {
return false;
}
return roleCodes.contains(SysConstants.ADMIN_ROLE_CODE);
}
}

View File

@@ -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.model.dto;
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 RoleDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 角色编码
*/
private String code;
/**
* 数据权限
*/
private DataScopeEnum dataScope;
}

View File

@@ -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.model.resp;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 验证码信息
*
* @author Charles7c
* @since 2022/12/11 13:55
*/
@Data
@Builder
@Schema(description = "验证码信息")
public class CaptchaResp implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 验证码标识
*/
@Schema(description = "验证码标识", example = "090b9a2c-1691-4fca-99db-e4ed0cff362f")
private String uuid;
/**
* 验证码图片Base64编码带图片格式data:image/gif;base64
*/
@Schema(description = "验证码图片Base64编码带图片格式data:image/gif;base64", example = "data:image/png;base64,iVBORw0KGgoAAAAN...")
private String img;
}

View File

@@ -0,0 +1,71 @@
/*
* 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.model.resp;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* 键值对信息
*
* @param <T>
* @author Charles7c
* @since 2023/2/24 22:02
*/
@Data
@NoArgsConstructor
@Schema(description = "键值对信息")
public class LabelValueResp<T> implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 标签
*/
@Schema(description = "标签", example = "")
private String label;
/**
* 值
*/
@Schema(description = "", example = "1")
private T value;
/**
* 颜色
*/
@Schema(description = "颜色", example = "#165DFF")
@JsonInclude(JsonInclude.Include.NON_NULL)
private String color;
public LabelValueResp(String label, T value) {
this.label = label;
this.value = value;
}
public LabelValueResp(String label, T value, String color) {
this.label = label;
this.value = value;
this.color = color;
}
}

View File

@@ -0,0 +1,69 @@
/*
* 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 top.continew.admin.common.config.properties.RsaProperties;
import top.continew.starter.core.util.validate.ValidationUtils;
/**
* 加密/解密工具类
*
* @author Charles7c
* @since 2022/12/21 21:41
*/
public class SecureUtils {
private SecureUtils() {
}
/**
* 公钥加密
*
* @param data 要加密的内容
* @param publicKey 公钥
* @return 公钥加密并 Base64 加密后的内容
*/
public static String encryptByRsaPublicKey(String data, String publicKey) {
return Base64.encode(SecureUtil.rsa(null, publicKey).encrypt(data, KeyType.PublicKey));
}
/**
* 私钥解密
*
* @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));
}
}

View File

@@ -0,0 +1,139 @@
/*
* 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.helper;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import jakarta.servlet.http.HttpServletRequest;
import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.common.model.dto.LoginUser;
import top.continew.starter.core.util.ExceptionUtils;
import top.continew.starter.core.util.IpUtils;
import top.continew.starter.extension.crud.service.CommonUserService;
import top.continew.starter.web.util.ServletUtils;
import java.time.LocalDateTime;
/**
* 登录助手
*
* @author Charles7c
* @author Lion Li<a href="https://gitee.com/dromara/RuoYi-Vue-Plus">RuoYi-Vue-Plus</a>
* @since 2022/12/24 12:58
*/
public class LoginHelper {
private LoginHelper() {
}
/**
* 用户登录并缓存用户信息
*
* @param loginUser 登录用户信息
* @return 令牌
*/
public static String login(LoginUser loginUser) {
// 记录登录信息
HttpServletRequest request = ServletUtils.getRequest();
loginUser.setIp(JakartaServletUtil.getClientIP(request));
loginUser.setAddress(IpUtils.getAddress(loginUser.getIp()));
loginUser.setBrowser(ServletUtils.getBrowser(request));
loginUser.setLoginTime(LocalDateTime.now());
loginUser.setOs(StrUtil.subBefore(ServletUtils.getOs(request), " or", false));
// 登录并缓存用户信息
StpUtil.login(loginUser.getId());
SaHolder.getStorage().set(CacheConstants.LOGIN_USER_KEY, loginUser);
String tokenValue = StpUtil.getTokenValue();
loginUser.setToken(tokenValue);
StpUtil.getTokenSession().set(CacheConstants.LOGIN_USER_KEY, loginUser);
return tokenValue;
}
/**
* 获取登录用户信息
*
* @return 登录用户信息
* @throws NotLoginException 未登录异常
*/
public static LoginUser getLoginUser() throws NotLoginException {
StpUtil.checkLogin();
LoginUser loginUser = (LoginUser)SaHolder.getStorage().get(CacheConstants.LOGIN_USER_KEY);
if (null != loginUser) {
return loginUser;
}
SaSession tokenSession = StpUtil.getTokenSession();
loginUser = (LoginUser)tokenSession.get(CacheConstants.LOGIN_USER_KEY);
SaHolder.getStorage().set(CacheConstants.LOGIN_USER_KEY, loginUser);
return loginUser;
}
/**
* 根据 Token 获取登录用户信息
*
* @param token 用户 Token
* @return 登录用户信息
*/
public static LoginUser getLoginUser(String token) {
SaSession tokenSession = StpUtil.getTokenSessionByToken(token);
if (null == tokenSession) {
return null;
}
return (LoginUser)tokenSession.get(CacheConstants.LOGIN_USER_KEY);
}
/**
* 获取登录用户 ID
*
* @return 登录用户 ID
*/
public static Long getUserId() {
return getLoginUser().getId();
}
/**
* 获取登录用户名
*
* @return 登录用户名
*/
public static String getUsername() {
return getLoginUser().getUsername();
}
/**
* 获取登录用户昵称
*
* @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));
}
}