feat: 基础脚手架更新

This commit is contained in:
bootx
2025-03-02 00:27:06 +08:00
parent 52769e630a
commit 36a6901f8e
162 changed files with 1664 additions and 474 deletions

View File

@@ -7,7 +7,7 @@
<img src='https://gitee.com/bootx/dax-pay/badge/star.svg?theme=dark' alt='star'/>
<img src="https://img.shields.io/badge/Dax%20Pay-3.0.0-success.svg" alt="Build Status"/>
<img src="https://img.shields.io/badge/Author-Daxpay-orange.svg" alt="Build Status"/>
<img src="https://img.shields.io/badge/Spring%20Boot-3.3.4-blue.svg" alt="Downloads"/>
<img src="https://img.shields.io/badge/Spring%20Boot-3.4.3-blue.svg" alt="Downloads"/>
<img src="https://img.shields.io/badge/license-Apache%20License%202.0-green.svg"/>
</p>

View File

@@ -1,4 +1,6 @@
# CHANGELOG
## [v3.0.0.beta5] 2025-03-15
## [v3.0.0.beta4] 2025-01-10
- 新增: 微信服务商支付支持
- 新增: 支付宝服务商支付支持

View File

@@ -1,5 +1,5 @@
# 单商户
## 3.0.0.beta4 功能优化和服务商支付
## 3.0.0.beta5 功能优化和服务商支付
- [ ] 网关配套移动端开发
- [ ] 同步回调页
- [x] 对各种交易增加新的同步失败异常处理, 防止同步失败后无限进行同步

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform-common</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<artifactId>common-cache</artifactId>

View File

@@ -7,7 +7,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurer;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
@@ -31,7 +31,7 @@ import java.time.Duration;
@EnableConfigurationProperties(CachingProperties.class)
@ConditionalOnClass(CacheManager.class)
@ConditionalOnProperty(prefix = "bootx-platform.cache", value = "enabled", havingValue = "true", matchIfMissing = true)
public class CachingConfiguration implements CachingConfigurer {
public class CachingConfiguration extends CachingConfigurerSupport {
private final CachingProperties cachingProperties;

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform-common</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<artifactId>common-config</artifactId>

View File

@@ -1,11 +1,15 @@
package cn.bootx.platform.common.config;
import cn.bootx.platform.common.config.enums.DeployMode;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.ArrayList;
import java.util.List;
/**
* swagger配置
* 系统配置配置
*
* @author xxm
* @since 2020/4/9 13:36
@@ -16,6 +20,15 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
public class BootxConfigProperties {
/** 终端编码 */
@Deprecated
private String clientCode = "";
/**
* 终端列表, 开启融合模式后才会生效, 表示当前系统集成了哪些终端模块
*/
private List<String> clientCodes = new ArrayList<>();
/** 系统部署方式 */
private DeployMode deployMode = DeployMode.FUSION;
}

View File

@@ -0,0 +1,18 @@
package cn.bootx.platform.common.config.enums;
/**
* 部署模式
* @author xxm
* @since 2025/1/31
*/
public enum DeployMode {
/**
* 分模块部署, 如果有多个业务系统, 每套业务系统都是构建为独立的jar进行部署, 不同业务系统天生进行隔离
*/
MODULE,
/**
* 融合部署, 如果有多个业务系统, 但打包成一个jar进行部署的模式, 自行处理业务系统的隔离
*/
FUSION;
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform-common</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<artifactId>common-exception-handler</artifactId>

View File

@@ -18,6 +18,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@@ -86,6 +87,19 @@ public class RestExceptionHandler {
return Res.response(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, message.toString(), MDC.get(CommonCode.TRACE_ID));
}
/**
* 请求参数校验未通过
*/
@ExceptionHandler({ MethodArgumentNotValidException.class })
public Result<Void> handleBusinessException(MethodArgumentNotValidException ex) {
log.info(ex.getMessage(), ex);
StringBuilder message = new StringBuilder();
for (var violation : ex.getAllErrors()) {
message.append(violation.getDefaultMessage()).append(System.lineSeparator());
}
return Res.response(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, message.toString(), MDC.get(CommonCode.TRACE_ID));
}
/**
* 不支持 HTTP 请求方法异常
*/

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform-common</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<artifactId>common-header-holder</artifactId>

View File

@@ -1,7 +1,6 @@
package cn.bootx.platform.common.headerholder;
import cn.bootx.platform.common.headerholder.local.HolderContextHolder;
import cn.bootx.platform.core.code.WebHeaderCode;
import jakarta.servlet.http.HttpServletRequest;
import lombok.experimental.UtilityClass;
import org.springframework.web.context.request.RequestAttributes;
@@ -19,12 +18,6 @@ import java.util.Objects;
@UtilityClass
public class HeaderHolder {
/**
* 获取幂等令牌
*/
public String getIdempotentToken() {
return getHeader(WebHeaderCode.IDEMPOTENT_TOKEN);
}
/**
* 获取请求头参数

View File

@@ -8,20 +8,26 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.web.servlet.filter.OrderedFilter;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.util.Enumeration;
/**
* 请求头保存
* 请求头数据保存, 放在过滤链最前方
*
* @author xxm
* @since 2021/4/20
*/
@RequiredArgsConstructor
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class WebHeaderHolderInterceptor extends OncePerRequestFilter {
public class WebHeaderHolderInterceptor extends OncePerRequestFilter implements OrderedFilter {
@Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
}
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
@@ -36,7 +42,8 @@ public class WebHeaderHolderInterceptor extends OncePerRequestFilter {
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String header = headerNames.nextElement();
HolderContextHolder.put(header, request.getHeader(header));
// key值统一转换为小写
HolderContextHolder.put(header.toLowerCase(), request.getHeader(header));
}
chain.doFilter(request, response);
}
@@ -44,5 +51,4 @@ public class WebHeaderHolderInterceptor extends OncePerRequestFilter {
HolderContextHolder.clear();
}
}
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform-common</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<artifactId>common-jackson</artifactId>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform-common</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<artifactId>common-log</artifactId>

View File

@@ -9,7 +9,7 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.slf4j.MDC;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.annotation.Order;
import org.springframework.boot.web.servlet.filter.OrderedFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
@@ -21,11 +21,10 @@ import java.io.IOException;
* @author xxm
* @since 2021/4/20
*/
@Order(value = Integer.MIN_VALUE)
@Component
@RequiredArgsConstructor
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class LogTraceHeaderHolderFilter extends OncePerRequestFilter {
public class LogTraceHeaderHolderFilter extends OncePerRequestFilter implements OrderedFilter {
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
@@ -41,4 +40,8 @@ public class LogTraceHeaderHolderFilter extends OncePerRequestFilter {
}
}
@Override
public int getOrder() {
return HIGHEST_PRECEDENCE+100;
}
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform-common</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<artifactId>common-mybatis-plus</artifactId>
@@ -22,9 +22,8 @@
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- jdk 11+ 引入可选模块 -->
<!-- jdk 11+ 引入可选模块 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser</artifactId>
@@ -59,8 +58,12 @@
<artifactId>easy-trans-mybatis-plus-extend</artifactId>
<version>${easytrans.version}</version>
</dependency>
<dependency>
<groupId>cn.bootx.platform</groupId>
<artifactId>common-spring</artifactId>
<version>${bootx-platform.version}</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>

View File

@@ -0,0 +1,40 @@
package cn.bootx.platform.common.mybatisplus.aspect;
import cn.bootx.platform.common.mybatisplus.local.DataPermContextHolder;
import cn.bootx.platform.common.spring.util.AopUtil;
import cn.bootx.platform.core.annotation.DataPermScope;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
/**
* 数据权限注解处理切面
* @author xxm
* @since 2025/2/2
*/
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class DataPermScopeAspect {
/**
* 数据权限注解切面,用栈的方式进行储存, 处理数据权限注解嵌套的情况
*/
@Around("@annotation(dataPermScope)||@within(dataPermScope)")
public Object doAround(ProceedingJoinPoint pjp, DataPermScope dataPermScope) throws Throwable {
Object obj;
var methodAnnotation = AopUtil.getMethodAnnotation(pjp, DataPermScope.class);
DataPermContextHolder.push(methodAnnotation);
try {
obj = pjp.proceed();
}
finally {
DataPermContextHolder.pop();
}
return obj;
}
}

View File

@@ -1,5 +1,6 @@
package cn.bootx.platform.common.mybatisplus.handler;
package cn.bootx.platform.common.mybatisplus.aspect;
import cn.bootx.platform.core.annotation.IgnoreTenant;
import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
import lombok.RequiredArgsConstructor;
@@ -10,7 +11,7 @@ import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
/**
* 户租户切面
* 忽略租户(商户)数据权限切面服务
* @author xxm
* @since 2024/6/25
*/
@@ -20,8 +21,8 @@ import org.springframework.stereotype.Component;
@RequiredArgsConstructor
public class IgnoreTenantAspectHandler {
@Around("@annotation(cn.bootx.platform.core.annotation.IgnoreTenant)||within(@cn.bootx.platform.core.annotation.IgnoreTenant *)")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
@Around("@annotation(ignoreTenant)||@within(ignoreTenant)")
public Object doAround(ProceedingJoinPoint pjp, IgnoreTenant ignoreTenant) throws Throwable {
// 设置忽略租户插件
InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().tenantLine(true).build());
try {

View File

@@ -20,11 +20,14 @@ import java.util.List;
@MappedJdbcTypes({JdbcType.VARCHAR,JdbcType.LONGVARCHAR})
public class IntegerListTypeHandler extends AbstractJsonTypeHandler<List<Integer>> {
/**
* 默认初始化
*/
public IntegerListTypeHandler(Class<?> type) {
super(type);
}
public IntegerListTypeHandler(Class<?> type, Field field) {
super(type, field);
}

View File

@@ -20,7 +20,6 @@ import java.util.List;
@MappedJdbcTypes({JdbcType.VARCHAR,JdbcType.LONGVARCHAR})
public class LongListTypeHandler extends AbstractJsonTypeHandler<List<Long>> {
public LongListTypeHandler(Class<?> type) {
super(type);
}

View File

@@ -28,10 +28,11 @@ public class StringListTypeHandler extends AbstractJsonTypeHandler<List<String>>
public StringListTypeHandler(Class<?> type, Field field) {
super(type, field);
}
@Override
public List<String> parse(String json) {
if (StrUtil.isNotBlank(json)){
return JsonUtil.toBean(json, new TypeReference<>() {}, false);
return JSONUtil.toBean(json, new TypeReference<>() {}, false);
}
return List.of();
}

View File

@@ -1,7 +1,6 @@
package cn.bootx.platform.common.mybatisplus.interceptor;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
@@ -34,12 +33,4 @@ public class MpInterceptorConfiguration {
return new MpInterceptor(new OptimisticLockerInnerInterceptor(), 1);
}
/**
* 防止全表更新与删除
*/
@Bean
public MpInterceptor blockAttackInnerInterceptor() {
return new MpInterceptor(new BlockAttackInnerInterceptor(), 2);
}
}

View File

@@ -0,0 +1,55 @@
package cn.bootx.platform.common.mybatisplus.local;
import cn.bootx.platform.core.annotation.DataPermScope;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.ttl.TransmittableThreadLocal;
import java.util.Optional;
import java.util.Stack;
/**
* 忽略鉴权数据上下文
*
* @author xxm
* @since 2021/12/22
*/
public class DataPermContextHolder {
private static final ThreadLocal<Stack<DataPermScope>> PERMISSION_LOCAL = new TransmittableThreadLocal<>();
/**
* 设置 数据权限控制注解
*/
public static void push(DataPermScope permission) {
Stack<DataPermScope> stack = Optional.ofNullable(PERMISSION_LOCAL.get())
.orElse(new Stack<>());
stack.push(permission);
PERMISSION_LOCAL.set(stack);
}
/**
* 获取 数据权限控制注解
*/
public static DataPermScope peek() {
return PERMISSION_LOCAL.get().peek();
}
/**
* 弹出
*/
public static void pop() {
Stack<DataPermScope> stack = PERMISSION_LOCAL.get();
if (CollUtil.isNotEmpty(stack)) {
stack.pop();
}
}
/**
* 清除线程变量(数据权限控制和用户信息)
*/
public static void clear() {
PERMISSION_LOCAL.remove();
}
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform-common</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<artifactId>common-redis</artifactId>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform-common</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<artifactId>common-spring</artifactId>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform-common</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<artifactId>common-swagger</artifactId>
@@ -14,8 +14,9 @@
<description>接口文档</description>
<dependencies>
<!-- 官方4.5.0 与 最新Spring boot 3.4.x不兼容, 暂时使用第三方的包 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<groupId>com.github.xingfudeshi</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>

View File

@@ -1,30 +1,17 @@
package cn.bootx.platform.common.swagger;
import cn.hutool.core.util.ArrayUtil;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import java.util.concurrent.atomic.AtomicInteger;
/**
* swagger 自动配置
@@ -36,20 +23,9 @@ import java.util.concurrent.atomic.AtomicInteger;
@Configuration
@EnableConfigurationProperties(SwaggerProperties.class)
@RequiredArgsConstructor
public class SwaggerAutoConfiguration implements BeanDefinitionRegistryPostProcessor, EnvironmentAware {
public class SwaggerAutoConfiguration {
private final String swaggerPropertiesPrefix = "bootx-platform.common.swagger";
private SwaggerProperties swaggerProperties;
/**
* 创建swagger文档模块
* @param name 模块名称
* @param basePackage 扫描路径数组
*/
private GroupedOpenApi createApi(String name, String... basePackage) {
return GroupedOpenApi.builder().group(name).packagesToScan(basePackage).build();
}
private final SwaggerProperties swaggerProperties;
/**
* 空白分组(防止knife4j报错)
@@ -58,7 +34,7 @@ public class SwaggerAutoConfiguration implements BeanDefinitionRegistryPostProce
@ConditionalOnProperty(prefix = "bootx-platform.common.swagger", value = "enabled", havingValue = "true",
matchIfMissing = true)
public GroupedOpenApi blankApi() {
return this.createApi(" 空白页", "null.null");
return GroupedOpenApi.builder().group("空白页").packagesToScan("null.null").build();
}
@Bean
@@ -73,34 +49,4 @@ public class SwaggerAutoConfiguration implements BeanDefinitionRegistryPostProce
.license(new License().name(swaggerProperties.getLicenseName()).url(swaggerProperties.getLicenseUrl())))
.externalDocs(new ExternalDocumentation().url(swaggerProperties.getTermsOfServiceUrl()));
}
/**
* 手动注册swagger docket bean, 如果晚于swagger加载后, 再注入的bean将不会生效
*/
@Override
public void postProcessBeanDefinitionRegistry(@NotNull BeanDefinitionRegistry registry) throws BeansException {
var basePackages = this.swaggerProperties.getBasePackages();
AtomicInteger atomicInteger = new AtomicInteger(96);
basePackages.forEach((name, basePackage) -> {
var packages = ArrayUtil.toArray(basePackage, String.class);
var bean = new RootBeanDefinition(GroupedOpenApi.class, () -> this.createApi(name, packages));
registry.registerBeanDefinition((char) atomicInteger.incrementAndGet() + "ModelAPi", bean);
});
}
@Override
public void postProcessBeanFactory(@NotNull ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
/**
* 获取环境变量并设置到swaggerProperties对象中, bean注册时, 参数还未进行绑定
*/
@Override
public void setEnvironment(@NotNull Environment environment) {
BindResult<SwaggerProperties> bind = Binder.get(environment)
.bind(swaggerPropertiesPrefix, SwaggerProperties.class);
this.swaggerProperties = bind.orElse(new SwaggerProperties());
}
}

View File

@@ -0,0 +1,64 @@
package cn.bootx.platform.common.swagger;
import cn.hutool.core.util.ArrayUtil;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.util.concurrent.atomic.AtomicInteger;
/**
* swagger 自动配置
* @author xxm
* @since 2025/2/6
*/
@Slf4j
@Component
@EnableConfigurationProperties(SwaggerProperties.class)
public class SwaggerPostConfiguration implements BeanDefinitionRegistryPostProcessor, EnvironmentAware {
private final String swaggerPropertiesPrefix = "bootx-platform.common.swagger";
private SwaggerProperties swaggerProperties;
/**
* 手动注册swagger docket bean, 如果晚于swagger加载后, 再注入的bean将不会生效
*/
@Override
public void postProcessBeanDefinitionRegistry(@NotNull BeanDefinitionRegistry registry) throws BeansException {
var basePackages = this.swaggerProperties.getBasePackages();
AtomicInteger atomicInteger = new AtomicInteger(96);
basePackages.forEach((name, basePackage) -> {
var packages = ArrayUtil.toArray(basePackage, String.class);
var bean = new RootBeanDefinition(GroupedOpenApi.class, () -> GroupedOpenApi.builder().group(name).packagesToScan(packages).build());
registry.registerBeanDefinition((char) atomicInteger.incrementAndGet() + "ModelAPi", bean);
});
}
@Override
public void postProcessBeanFactory(@NotNull ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
/**
* 获取环境变量并设置到swaggerProperties对象中, bean注册时, 参数还未进行绑定
*/
@Override
public void setEnvironment(@NotNull Environment environment) {
BindResult<SwaggerProperties> bind = Binder.get(environment)
.bind(swaggerPropertiesPrefix, SwaggerProperties.class);
this.swaggerProperties = bind.orElse(new SwaggerProperties());
}
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,22 @@
package cn.bootx.platform.core.annotation;
import java.lang.annotation.*;
/**
* 终端类型注解, 如果添加控制器上添加了该类型. 进行访问时将会自动验证终端类型是否匹配, 不添加默认所有终端类型都可以访问
* 终端可以约等于业务系统概念, 但不是完全一对一的关系
* 在控制器类和方法上都可以使用该注解, 同时标注时会以方法上的为准, 并不会取这两者的终端合集, 而是方法上的直接覆盖掉类的注解
* @author xxm
* @since 2025/1/31
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface ClientCode {
/**
* 终端编码
*/
String[] value();
}

View File

@@ -0,0 +1,37 @@
package cn.bootx.platform.core.annotation;
import java.lang.annotation.*;
/**
* 数据权限控制注解 可以放在服务类和方法上,支持嵌套使用,嵌套使用时可以通过添加多个数据来控制不同作用域实现不同的控制
* A 使用部门数据权限控制
* ----- 根据部门进行控制
* - B 关闭数据权限
* ----- 数据权限不生效
* -- C 使用终端数据权限
* ----- 根据终端进行控制
* -- C 使用终端数据权限使用结束
* ----- 数据权限不生效
* - B 开启数据权限控制
* ----- 根据部门进行控制
* A 执行结束
* @author xxm
* @since 2021/12/22
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataPermScope {
/**
* 是否开启数据权限, 在嵌套情况下, 可以通过设置为false来临时关闭数据权限的控制
*/
boolean dataScope() default true;
/**
* 数据权限类型,不同类型需要有不同的数据权限处理实现
*/
String value();
}

View File

@@ -66,6 +66,11 @@ public @interface OperateLog {
*/
GRANT,
/**
* 同步
*/
SYNC,
/**
* 导出
*/

View File

@@ -15,6 +15,8 @@ import java.lang.annotation.*;
* <br/>
* 路径: 对应具体的一个具体请求方式(GET/POST)的请求路径
*
* 如果在多业务系统(终端)融合部署时, 可以通过添加 {@link ClientCode} 注解来区分不同的终端(业务系统), 来使当前请求路径归类带哪个终端中
*
* @author xxm
* @since 2024/7/4
*/
@@ -42,5 +44,4 @@ public @interface RequestGroup {
* 分组名称, 多次标注注解时, 同样的分组编码, 可以只写一个分组名称, 其他未写的会自动使用这个
*/
String groupName() default "";
}

View File

@@ -53,6 +53,9 @@ public interface CommonCode {
/** 追踪Id */
String TRACE_ID = "traceId";
/** 终端 */
String CLIENT = "x-client-code";
/** 用户 */
String USER = "user";

View File

@@ -1,5 +1,6 @@
package cn.bootx.platform.core.util;
import cn.hutool.core.date.DatePattern;
import lombok.experimental.UtilityClass;
import java.time.Instant;
@@ -82,4 +83,11 @@ public class DateTimeUtil {
return instant.toEpochMilli();
}
/**
* 格式化为标准时间日期
*/
public String formatDateTime(LocalDateTime localDateTime) {
return localDateTime.format(DatePattern.NORM_DATETIME_FORMATTER);
}
}

View File

@@ -5,8 +5,11 @@ import cn.hutool.core.lang.TypeReference;
import cn.hutool.json.*;
import lombok.experimental.UtilityClass;
import java.util.Collection;
/**
* json工具类, 基于hutool的进行封装, 对java8的LocalDateTime时间格式进行转换, 但无法处理LocalDate, LocalTime格式, 需要使用JacksonUtil进行处理
* json工具类, 基于hutool的进行封装,
* 对java8的LocalDateTime时间格式进行转换, 但无法处理LocalDate, LocalTime格式, 需要使用JacksonUtil进行处理
* @author xxm
* @since 2024/6/28
*/
@@ -49,6 +52,14 @@ public class JsonUtil {
return JSONUtil.toJsonStr(jsonObject);
}
/**
* 序列化为字符串
*/
public String toJsonStr(Collection<?> object){
JSONArray jsonObject = new JSONArray(object, JSON_CONFIG);
return JSONUtil.toJsonStr(jsonObject);
}
/**
* JSON字符串转JSONObject对象
*/

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<modules>
<module>service-baseapi</module>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform-service</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<artifactId>service-baseapi</artifactId>
@@ -55,12 +55,6 @@
<artifactId>hutool-cache</artifactId>
<version>${hutool.version}</version>
</dependency>
<!-- hutool 请求工具类 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
<version>${hutool.version}</version>
</dependency>
<!-- 安全认证 -->
<dependency>
<groupId>cn.bootx.platform</groupId>

View File

@@ -8,7 +8,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
@@ -22,7 +22,7 @@ import java.nio.charset.StandardCharsets;
* @author xxm
* @since 2023/10/14
*/
@Slf4j
@Validated
@Tag(name = "系统基础接口")
@RestController
@RequiredArgsConstructor
@@ -54,7 +54,7 @@ public class BaseController {
@IgnoreAuth
@Operation(summary = "将文件转换成base64")
@PostMapping("/readBase64")
public Result<String> readBase64(MultipartFile file){
public Result<String> readBase64(@RequestPart MultipartFile file){
return Res.ok(Base64.encode(file.getBytes()));
}

View File

@@ -3,18 +3,21 @@ package cn.bootx.platform.baseapi.controller.dict;
import cn.bootx.platform.baseapi.param.dict.DictionaryParam;
import cn.bootx.platform.baseapi.result.dict.DictionaryResult;
import cn.bootx.platform.baseapi.service.dict.DictionaryService;
import cn.bootx.platform.core.annotation.OperateLog;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.validation.ValidationGroup;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.param.PageParam;
import cn.bootx.platform.core.rest.result.PageResult;
import cn.bootx.platform.core.rest.result.Result;
import cn.bootx.platform.core.util.ValidationUtil;
import cn.bootx.platform.core.validation.ValidationGroup;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -25,9 +28,10 @@ import java.util.List;
* @author xxm
* @since 2021/8/4
*/
@Validated
@Tag(name = "字典")
@RestController
@RequestGroup(groupCode = "dict", groupName = "字典管理", moduleCode = "baseapi", moduleName = "基础API" )
@RequestGroup(groupCode = "dict", groupName = "字典管理", moduleCode = "baseapi" )
@RequestMapping("/dict")
@RequiredArgsConstructor
public class DictionaryController {
@@ -37,6 +41,7 @@ public class DictionaryController {
@RequestPath("添加字典")
@Operation(summary = "添加字典")
@PostMapping("/add")
@OperateLog(title = "添加字典", businessType = OperateLog.BusinessType.ADD, saveParam = true)
public Result<DictionaryResult> add(@RequestBody DictionaryParam param) {
ValidationUtil.validateParam(param, ValidationGroup.add.class);
return Res.ok(dictionaryService.add(param));
@@ -45,7 +50,8 @@ public class DictionaryController {
@RequestPath("根据主键删除字典")
@Operation(summary = "根据主键删除")
@PostMapping("/delete")
public Result<Boolean> delete(Long id) {
@OperateLog(title = "删除字典", businessType = OperateLog.BusinessType.DELETE, saveParam = true)
public Result<Boolean> delete(@NotNull(message = "主键不可为空") Long id) {
dictionaryService.delete(id);
return Res.ok();
}
@@ -53,6 +59,7 @@ public class DictionaryController {
@RequestPath("更新字典")
@Operation(summary = "更新字典")
@PostMapping("/update")
@OperateLog(title = "更新字典", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
public Result<DictionaryResult> update(@RequestBody DictionaryParam param) {
ValidationUtil.validateParam(param, ValidationGroup.edit.class);
return Res.ok(dictionaryService.update(param));
@@ -61,7 +68,7 @@ public class DictionaryController {
@RequestPath("根据主键获取字典")
@Operation(summary = "根据主键获取字典")
@GetMapping("/findById")
public Result<DictionaryResult> findById(Long id) {
public Result<DictionaryResult> findById(@NotNull(message = "主键不可为空") Long id) {
return Res.ok(dictionaryService.findById(id));
}
@@ -75,21 +82,21 @@ public class DictionaryController {
@RequestPath("字典分页")
@Operation(summary = "字典分页")
@GetMapping("/page")
public Result<PageResult<DictionaryResult>> page(@ParameterObject PageParam pageParam, DictionaryParam param) {
public Result<PageResult<DictionaryResult>> page(PageParam pageParam, DictionaryParam param) {
return Res.ok(dictionaryService.page(pageParam, param));
}
@RequestPath("字典编码是否被使用")
@Operation(summary = "字典编码是否被使用")
@GetMapping("/existsByCode")
public Result<Boolean> existsByCode(String code) {
public Result<Boolean> existsByCode(@NotBlank(message = "字典编码不可为空") String code) {
return Res.ok(dictionaryService.existsByCode(code));
}
@RequestPath("编码是否被使用(不包含自己)")
@Operation(summary = "编码是否被使用(不包含自己)")
@GetMapping("/existsByCodeNotId")
public Result<Boolean> existsByCode(String code, Long id) {
public Result<Boolean> existsByCode(@NotBlank(message = "字典编码不可为空") String code, @NotNull(message = "主键不可为空") Long id) {
return Res.ok(dictionaryService.existsByCode(code, id));
}

View File

@@ -4,18 +4,21 @@ import cn.bootx.platform.baseapi.param.dict.DictionaryItemParam;
import cn.bootx.platform.baseapi.result.dict.DictionaryItemResult;
import cn.bootx.platform.baseapi.service.dict.DictionaryItemService;
import cn.bootx.platform.core.annotation.IgnoreAuth;
import cn.bootx.platform.core.annotation.OperateLog;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.validation.ValidationGroup;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.param.PageParam;
import cn.bootx.platform.core.rest.result.PageResult;
import cn.bootx.platform.core.rest.result.Result;
import cn.bootx.platform.core.util.ValidationUtil;
import cn.bootx.platform.core.validation.ValidationGroup;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -24,8 +27,9 @@ import java.util.List;
* @author xxm
* @since 2020/4/18 19:03
*/
@Validated
@Tag(name = "字典项")
@RequestGroup(groupCode = "dict", groupName = "字典管理", moduleCode = "baseapi", moduleName = "基础API" )
@RequestGroup(groupCode = "dict", groupName = "字典管理", moduleCode = "baseapi", moduleName = "(Bootx)基础模块API" )
@RestController
@RequestMapping("/dict/item")
@AllArgsConstructor
@@ -36,17 +40,17 @@ public class DictionaryItemController {
@RequestPath("添加字典项")
@Operation(summary = "添加字典项")
@PostMapping("/add")
public Result<Void> add(@RequestBody DictionaryItemParam param) {
ValidationUtil.validateParam(param, ValidationGroup.add.class);
@OperateLog(title = "添加字典项", businessType = OperateLog.BusinessType.ADD, saveParam = true)
public Result<Void> add(@RequestBody @Validated(ValidationGroup.add.class) DictionaryItemParam param) {
dictionaryItemService.add(param);
return Res.ok();
}
@RequestPath("添加字典项")
@Operation(summary = "修改字典项(返回字典项对象)")
@RequestPath("修改字典项")
@Operation(summary = "修改字典项")
@PostMapping(value = "/update")
public Result<DictionaryItemResult> update(@RequestBody DictionaryItemParam param) {
ValidationUtil.validateParam(param, ValidationGroup.edit.class);
@OperateLog(title = "修改字典项", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
public Result<Void> update(@RequestBody @Validated(ValidationGroup.edit.class) DictionaryItemParam param) {
dictionaryItemService.update(param);
return Res.ok();
}
@@ -54,7 +58,8 @@ public class DictionaryItemController {
@RequestPath("删除字典项")
@Operation(summary = "删除字典项")
@PostMapping(value = "/delete")
public Result<Void> delete(Long id) {
@OperateLog(title = "删除字典项", businessType = OperateLog.BusinessType.DELETE, saveParam = true)
public Result<Void> delete(@NotNull(message = "主键不可为空") Long id) {
dictionaryItemService.delete(id);
return Res.ok();
}
@@ -62,14 +67,14 @@ public class DictionaryItemController {
@RequestPath("查询字典项")
@Operation(summary = "根据字典项ID查询")
@GetMapping("/findById")
public Result<DictionaryItemResult> findById(@Parameter(description = "字典项ID") Long id) {
public Result<DictionaryItemResult> findById(@NotNull(message = "字典项主键不可为空") Long id) {
return Res.ok(dictionaryItemService.findById(id));
}
@RequestPath("查询字典项列表")
@Operation(summary = "查询指定字典ID下的所有字典项")
@GetMapping("/findByDictionaryId")
public Result<List<DictionaryItemResult>> findByDictionaryId(@Parameter(description = "字典ID") Long dictId) {
public Result<List<DictionaryItemResult>> findByDictionaryId(@NotNull(message = "字典主键不可为空") Long dictId) {
return Res.ok(dictionaryItemService.findByDictionaryId(dictId));
}
@@ -97,16 +102,18 @@ public class DictionaryItemController {
@RequestPath("字典项编码是否被使用")
@Operation(summary = "字典项编码是否被使用")
@GetMapping("/existsByCode")
public Result<Boolean> existsByCode(@Parameter(description = "编码") String code,@Parameter(description = "字典ID") Long dictId) {
public Result<Boolean> existsByCode(
@Parameter(description = "编码") @NotBlank(message = "字典编码不可为空") String code,
@Parameter(description = "字典ID") @NotNull(message = "字典主键不可为空") Long dictId) {
return Res.ok(dictionaryItemService.existsByCode(code, dictId));
}
@RequestPath("字典项编码是否被使用(不包含自己)")
@Operation(summary = "字典项编码是否被使用(不包含自己)")
@GetMapping("/existsByCodeNotId")
public Result<Boolean> existsByCode(@Parameter(description = "编码") String code,
@Parameter(description = "字典ID") Long dictId,
@Parameter(description = "字典项ID") Long id) {
public Result<Boolean> existsByCode(@Parameter(description = "编码") @NotBlank(message = "字典编码不可为空") String code,
@Parameter(description = "字典ID") @NotNull(message = "字典主键不可为空") Long dictId,
@Parameter(description = "字典项ID") @NotNull(message = "字典项主键不可为空") Long id) {
return Res.ok(dictionaryItemService.existsByCode(code, dictId, id));
}

View File

@@ -4,18 +4,20 @@ import cn.bootx.platform.baseapi.param.parameter.SystemParameterParam;
import cn.bootx.platform.baseapi.result.parameter.SystemParameterResult;
import cn.bootx.platform.baseapi.service.parameter.SystemParamService;
import cn.bootx.platform.core.annotation.IgnoreAuth;
import cn.bootx.platform.core.annotation.OperateLog;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.param.PageParam;
import cn.bootx.platform.core.rest.result.PageResult;
import cn.bootx.platform.core.rest.result.Result;
import cn.bootx.platform.core.util.ValidationUtil;
import cn.bootx.platform.core.validation.ValidationGroup;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
@@ -24,6 +26,7 @@ import org.springframework.web.bind.annotation.*;
* @author xxm
* @since 2021/10/25
*/
@Validated
@Tag(name = "系统参数")
@RequestGroup(groupCode = "params", groupName = "系统参数", moduleCode = "baseapi" )
@RestController
@@ -36,8 +39,8 @@ public class SystemParamController {
@RequestPath("添加")
@Operation(summary = "添加")
@PostMapping("/add")
public Result<Void> add(@RequestBody SystemParameterParam param) {
ValidationUtil.validateParam(param, ValidationGroup.add.class);
@OperateLog(title = "添加系统参数", businessType = OperateLog.BusinessType.ADD, saveParam = true)
public Result<Void> add(@RequestBody @Validated(ValidationGroup.add.class) SystemParameterParam param) {
systemParamService.add(param);
return Res.ok();
}
@@ -45,8 +48,8 @@ public class SystemParamController {
@RequestPath("更新")
@Operation(summary = "更新")
@PostMapping("/update")
public Result<Void> update(@RequestBody SystemParameterParam param) {
ValidationUtil.validateParam(param, ValidationGroup.edit.class);
@OperateLog(title = "更新系统参数", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
public Result<Void> update(@RequestBody @Validated(ValidationGroup.edit.class) SystemParameterParam param) {
systemParamService.update(param);
return Res.ok();
}
@@ -61,14 +64,15 @@ public class SystemParamController {
@RequestPath("获取单条")
@Operation(summary = "获取单条")
@GetMapping("/findById")
public Result<SystemParameterResult> findById(@Parameter(description = "主键") Long id) {
public Result<SystemParameterResult> findById(@NotNull(message = "主键不可为空") Long id) {
return Res.ok(systemParamService.findById(id));
}
@RequestPath("删除")
@Operation(summary = "删除")
@PostMapping("/delete")
public Result<Void> delete(Long id) {
@OperateLog(title = "删除系统参数", businessType = OperateLog.BusinessType.DELETE, saveParam = true)
public Result<Void> delete(@NotNull(message = "主键不可为空") Long id) {
systemParamService.delete(id);
return Res.ok();
}
@@ -76,21 +80,21 @@ public class SystemParamController {
@RequestPath("判断编码是否存在")
@Operation(summary = "判断编码是否存在")
@GetMapping("/existsByKey")
public Result<Boolean> existsByKey(String key) {
public Result<Boolean> existsByKey(@NotBlank(message = "key不可为空") String key) {
return Res.ok(systemParamService.existsByKey(key));
}
@RequestPath("判断编码是否存在(不包含自己)")
@Operation(summary = "判断编码是否存在(不包含自己)")
@GetMapping("/existsByKeyNotId")
public Result<Boolean> existsByKeyNotId(String key, Long id) {
public Result<Boolean> existsByKeyNotId(@NotBlank(message = "key不可为空") String key,@NotNull(message = "主键不可为空") Long id) {
return Res.ok(systemParamService.existsByKey(key, id));
}
@IgnoreAuth
@Operation(summary = "根据键名获取键值")
@GetMapping("/findByKey")
public Result<String> findByKey(String key) {
public Result<String> findByKey(@NotBlank(message = "key不可为空") String key) {
return Res.ok(systemParamService.findByKey(key));
}

View File

@@ -0,0 +1,60 @@
package cn.bootx.platform.baseapi.controller.region;
import cn.bootx.platform.baseapi.result.region.RegionResult;
import cn.bootx.platform.baseapi.service.region.ChinaRegionService;
import cn.bootx.platform.core.annotation.IgnoreAuth;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 行政区划控制器
* @author xxm
* @since 2024/11/12
*/
@Validated
@IgnoreAuth
@Tag(name = "行政区划控制器")
@RestController
@RequestMapping("/china/region")
@RequiredArgsConstructor
public class ChinaRegionController {
private final ChinaRegionService chinaRegionService;
/**
* 获取所有省份
*/
@Operation(summary = "获取省份")
@GetMapping("/findAllProvince")
public Result<List<RegionResult>> findAllProvince() {
return Res.ok(chinaRegionService.findAllProvince());
}
@Operation(summary = "获取省市联动列表")
@GetMapping("/findAllProvinceAndCity")
public Result<List<RegionResult>> findAllProvinceAndCity() {
return Res.ok(chinaRegionService.findAllProvinceAndCity());
}
@Operation(summary = "获取省市区县联动列表")
@GetMapping("/findAllProvinceAndCityAndArea")
public Result<List<RegionResult>> findAllProvinceAndCityAndArea() {
return Res.ok(chinaRegionService.findAllProvinceAndCityAndArea());
}
@Operation(summary = "根据区划代码获取下级行政区划的列表")
@GetMapping("/findAllRegionByParentCode")
public Result<List<RegionResult>> findAllRegionByParentCode(@NotBlank(message = "区划代码不可为空") String code) {
return Res.ok(chinaRegionService.findAllRegionByParentCode(code));
}
}

View File

@@ -30,21 +30,21 @@ public class SystemParamManager extends BaseManager<SystemParamMapper, SystemPar
* 根据键名获取键值
*/
public Optional<SystemParameter> findByKey(String key) {
return this.findByField(SystemParameter::getParamKey, key);
return this.findByField(SystemParameter::getKey, key);
}
/**
* key重复检查
*/
public boolean existsByKey(String key) {
return existedByField(SystemParameter::getParamKey, key);
return existedByField(SystemParameter::getKey, key);
}
/**
* key重复检查
*/
public boolean existsByKey(String key, Long id) {
return existedByField(SystemParameter::getParamKey, key, id);
return existedByField(SystemParameter::getKey, key, id);
}
/**
@@ -54,7 +54,7 @@ public class SystemParamManager extends BaseManager<SystemParamMapper, SystemPar
Page<SystemParameter> mpPage = MpUtil.getMpPage(pageParam);
return lambdaQuery().orderByDesc(MpIdEntity::getId)
.like(StrUtil.isNotBlank(param.getName()), SystemParameter::getName, param.getName())
.like(StrUtil.isNotBlank(param.getParamKey()), SystemParameter::getParamKey, param.getParamKey())
.like(StrUtil.isNotBlank(param.getKey()), SystemParameter::getKey, param.getKey())
.page(mpPage);
}

View File

@@ -0,0 +1,24 @@
package cn.bootx.platform.baseapi.dao.region;
import cn.bootx.platform.baseapi.entity.region.Area;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 区域表
*
* @author xxm
* @since 2022-12-24
*/
@Repository
@RequiredArgsConstructor
public class AreaManager extends BaseManager<AreaMapper, Area> {
public List<Area> findAllByCityCode(String cityCode) {
return findAllByField(Area::getCityCode, cityCode);
}
}

View File

@@ -0,0 +1,16 @@
package cn.bootx.platform.baseapi.dao.region;
import cn.bootx.platform.baseapi.entity.region.Area;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 区域表
*
* @author xxm
* @since 2022-12-24
*/
@Mapper
public interface AreaMapper extends MPJBaseMapper<Area> {
}

View File

@@ -0,0 +1,24 @@
package cn.bootx.platform.baseapi.dao.region;
import cn.bootx.platform.baseapi.entity.region.City;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 城市表
*
* @author xxm
* @since 2022-12-24
*/
@Repository
@RequiredArgsConstructor
public class CityManager extends BaseManager<CityMapper, City> {
public List<City> findAllByProvinceCode(String provinceCode) {
return findAllByField(City::getProvinceCode, provinceCode);
}
}

View File

@@ -0,0 +1,16 @@
package cn.bootx.platform.baseapi.dao.region;
import cn.bootx.platform.baseapi.entity.region.City;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 城市表
*
* @author xxm
* @since 2022-12-24
*/
@Mapper
public interface CityMapper extends MPJBaseMapper<City> {
}

View File

@@ -0,0 +1,18 @@
package cn.bootx.platform.baseapi.dao.region;
import cn.bootx.platform.baseapi.entity.region.Province;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
/**
* 省份表
*
* @author xxm
* @since 2022-12-24
*/
@Repository
@RequiredArgsConstructor
public class ProvinceManager extends BaseManager<ProvinceMapper, Province> {
}

View File

@@ -0,0 +1,16 @@
package cn.bootx.platform.baseapi.dao.region;
import cn.bootx.platform.baseapi.entity.region.Province;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 省份表
*
* @author xxm
* @since 2022-12-24
*/
@Mapper
public interface ProvinceMapper extends MPJBaseMapper<Province> {
}

View File

@@ -0,0 +1,24 @@
package cn.bootx.platform.baseapi.dao.region;
import cn.bootx.platform.baseapi.entity.region.Street;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 街道表
*
* @author xxm
* @since 2022-12-24
*/
@Repository
@RequiredArgsConstructor
public class StreetManager extends BaseManager<StreetMapper, Street> {
public List<Street> findAllByAreaCode(String areaCode) {
return findAllByField(Street::getAreaCode, areaCode);
}
}

View File

@@ -0,0 +1,16 @@
package cn.bootx.platform.baseapi.dao.region;
import cn.bootx.platform.baseapi.entity.region.Street;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 街道表
*
* @author xxm
* @since 2022-12-24
*/
@Mapper
public interface StreetMapper extends MPJBaseMapper<Street> {
}

View File

@@ -28,7 +28,7 @@ public class SystemParameter extends MpBaseEntity implements ToResult<SystemPara
private String name;
/** 参数键名 */
private String paramKey;
private String key;
/** 参数值 */
private String value;

View File

@@ -0,0 +1,34 @@
package cn.bootx.platform.baseapi.entity.region;
import cn.bootx.platform.baseapi.result.region.RegionResult;
import cn.bootx.platform.common.mybatisplus.function.ToResult;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 区域表(县区)
*
* @author xxm
* @since 2022-12-24
*/
@Data
@TableName("base_area")
public class Area implements ToResult<RegionResult> {
/** 县区编码 */
@TableId
private String code;
/** 名称 */
private String name;
/** 城市code */
private String cityCode;
@Override
public RegionResult toResult() {
return new RegionResult(code, name, 3).setParentCode(cityCode);
}
}

View File

@@ -0,0 +1,34 @@
package cn.bootx.platform.baseapi.entity.region;
import cn.bootx.platform.baseapi.result.region.RegionResult;
import cn.bootx.platform.common.mybatisplus.function.ToResult;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 城市表
*
* @author xxm
* @since 2022-12-24
*/
@Data
@TableName("base_city")
public class City implements ToResult<RegionResult> {
/** 市/地区编码 */
@TableId
private String code;
/** 城市名称 */
private String name;
/** 省份code */
private String provinceCode;
@Override
public RegionResult toResult() {
return new RegionResult(code, name, 2).setParentCode(provinceCode);
}
}

View File

@@ -0,0 +1,32 @@
package cn.bootx.platform.baseapi.entity.region;
import cn.bootx.platform.baseapi.result.region.RegionResult;
import cn.bootx.platform.common.mybatisplus.function.ToResult;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 省份表
*
* @author xxm
* @since 2022-12-24
*/
@Data
@TableName("base_province")
public class Province implements ToResult<RegionResult> {
/** 省份编码 */
@TableId
private String code;
/** 省份名称 */
private String name;
@Override
public RegionResult toResult() {
return new RegionResult(code, name, 1);
}
}

View File

@@ -0,0 +1,34 @@
package cn.bootx.platform.baseapi.entity.region;
import cn.bootx.platform.baseapi.result.region.RegionResult;
import cn.bootx.platform.common.mybatisplus.function.ToResult;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 街道/乡镇表
*
* @author xxm
* @since 2022-12-24
*/
@Data
@TableName("base_street")
public class Street implements ToResult<RegionResult> {
/** 街道code */
@TableId
private String code;
/** 街道名称 */
private String name;
/** 区县code */
private String areaCode;
@Override
public RegionResult toResult() {
return new RegionResult(code, name, 4).setParentCode(areaCode);
}
}

View File

@@ -0,0 +1,47 @@
package cn.bootx.platform.baseapi.enums;
import cn.bootx.platform.core.exception.BizException;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 中国行政区划
*
* @author xxm
* @since 2023/2/7
*/
@Getter
@AllArgsConstructor
public enum ChinaRegionEnum {
/** 省份 */
IMPORT_TYPE_PROVINCE("province", 1, 2),
/** 城市 */
IMPORT_TYPE_CITY("city", 2, 4),
/** 县区 */
IMPORT_TYPE_AREA("area", 3, 6),
/** 街道乡镇 */
IMPORT_TYPE_STREET("street", 4, 9);
/** 类型 */
private final String type;
/** 级别 */
private final int level;
/** 长度 */
private final int length;
/**
* 根据编码判断级别
*/
public static ChinaRegionEnum findByCode(String code) {
return Arrays.stream(values())
.filter(e -> e.length == code.length())
.findFirst()
.orElseThrow(() -> new BizException("不支持的类型"));
}
}

View File

@@ -2,6 +2,7 @@ package cn.bootx.platform.baseapi.param.dict;
import cn.bootx.platform.core.validation.ValidationGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Null;
@@ -31,11 +32,11 @@ public class DictionaryItemParam {
@Schema(description = "字典编码")
private String dictCode;
@NotEmpty(message = "字典项编码不可为空", groups = ValidationGroup.add.class)
@NotBlank(message = "字典项编码不可为空", groups = ValidationGroup.add.class)
@Schema(description = "字典项编码")
private String code;
@NotEmpty(message = "字典项编码不可为空", groups = ValidationGroup.add.class)
@NotBlank(message = "字典项编码不可为空", groups = ValidationGroup.add.class)
@Schema(description = "名称")
private String name;

View File

@@ -2,7 +2,7 @@ package cn.bootx.platform.baseapi.param.dict;
import cn.bootx.platform.core.validation.ValidationGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Null;
import lombok.Data;
@@ -24,11 +24,11 @@ public class DictionaryParam implements Serializable {
@Schema(description = "主键")
private Long id;
@NotEmpty(message = "编码不可以为空", groups = ValidationGroup.add.class)
@NotBlank(message = "编码不可以为空", groups = ValidationGroup.add.class)
@Schema(description = "编码")
private String code;
@NotEmpty(message = "编码不可以为空", groups = ValidationGroup.add.class)
@NotBlank(message = "编码不可以为空", groups = ValidationGroup.add.class)
@Schema(description = "名称")
private String name;

View File

@@ -2,6 +2,7 @@ package cn.bootx.platform.baseapi.param.parameter;
import cn.bootx.platform.core.validation.ValidationGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Null;
@@ -25,15 +26,15 @@ public class SystemParameterParam {
@Schema(description = "主键")
private Long id;
@NotEmpty(message = "参数名称不可为空", groups = ValidationGroup.add.class)
@NotBlank(message = "参数名称不可为空", groups = ValidationGroup.add.class)
@Schema(description = "参数名称")
private String name;
@NotEmpty(message = "参数键名不可为空", groups = ValidationGroup.add.class)
@NotBlank(message = "参数键名不可为空", groups = ValidationGroup.add.class)
@Schema(description = "参数键名")
private String paramKey;
private String key;
@NotEmpty(message = "参数值不可为空", groups = ValidationGroup.add.class)
@NotBlank(message = "参数值不可为空", groups = ValidationGroup.add.class)
@Schema(description = "参数值")
private String value;

View File

@@ -24,7 +24,7 @@ public class SystemParameterResult {
private String name;
@Schema(description = "参数键名")
private String paramKey;
private String key;
@Schema(description = "参数值")
private String value;

View File

@@ -0,0 +1,43 @@
package cn.bootx.platform.baseapi.result.region;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 中国行政区域通用对象
*
* @author xxm
* @since 2022/12/24
*/
@Data
@Accessors(chain = true)
@Schema(title = "中国行政区域通用对象")
@RequiredArgsConstructor
@NoArgsConstructor
public class RegionResult {
@Schema(description = "主键编码")
@NonNull
private String code;
@Schema(description = "名称")
@NonNull
private String name;
@Schema(description = "级别")
@NonNull
private Integer level;
@Schema(description = "上级id")
private String parentCode;
@Schema(description = "下一级行政区域")
private List<RegionResult> children;
}

View File

@@ -36,7 +36,7 @@ public class SystemParamService {
*/
public void add(SystemParameterParam param) {
SystemParameter systemParameter = SystemParameter.init(param);
if (systemParamManager.existsByKey(systemParameter.getParamKey())) {
if (systemParamManager.existsByKey(systemParameter.getKey())) {
throw new BizException("key重复");
}
// 默认非内置
@@ -52,7 +52,7 @@ public class SystemParamService {
SystemParameter systemParameter = systemParamManager.findById(param.getId())
.orElseThrow(() -> new BizException("参数项不存在"));
if (systemParamManager.existsByKey(param.getParamKey(), param.getId())) {
if (systemParamManager.existsByKey(param.getKey(), param.getId())) {
throw new BizException("key重复");
}
BeanUtil.copyProperties(param, systemParameter, CopyOptions.create().ignoreNullValue());

View File

@@ -0,0 +1,101 @@
package cn.bootx.platform.baseapi.service.region;
import cn.bootx.platform.baseapi.dao.region.AreaManager;
import cn.bootx.platform.baseapi.dao.region.CityManager;
import cn.bootx.platform.baseapi.dao.region.ProvinceManager;
import cn.bootx.platform.baseapi.dao.region.StreetManager;
import cn.bootx.platform.baseapi.entity.region.Area;
import cn.bootx.platform.baseapi.entity.region.City;
import cn.bootx.platform.baseapi.entity.region.Province;
import cn.bootx.platform.baseapi.entity.region.Street;
import cn.bootx.platform.baseapi.enums.ChinaRegionEnum;
import cn.bootx.platform.baseapi.result.region.RegionResult;
import cn.bootx.platform.core.util.TreeBuildUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 中国行政区划
*
* @author xxm
* @since 2022/12/24
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ChinaRegionService {
private final ProvinceManager provinceManager;
private final CityManager cityManager;
private final AreaManager areaManager;
private final StreetManager streetManager;
/**
* 根据区划代码获取下级行政区划的列表
*/
public List<RegionResult> findAllRegionByParentCode(String parentCode) {
if (parentCode.length() == ChinaRegionEnum.IMPORT_TYPE_PROVINCE.getLength()) {
return cityManager.findAllByProvinceCode(parentCode).stream().map(City::toResult).collect(Collectors.toList());
}
else if (parentCode.length() == ChinaRegionEnum.IMPORT_TYPE_CITY.getLength()) {
return areaManager.findAllByCityCode(parentCode).stream().map(Area::toResult).collect(Collectors.toList());
}
else if (parentCode.length() == ChinaRegionEnum.IMPORT_TYPE_AREA.getLength()) {
return streetManager.findAllByAreaCode(parentCode).stream().map(Street::toResult).collect(Collectors.toList());
}
else {
return new ArrayList<>(0);
}
}
/**
* 获取一级行政区
*/
public List<RegionResult> findAllProvince() {
return provinceManager.findAll().stream().map(Province::toResult).collect(Collectors.toList());
}
/**
* 获取省市联动列表
*/
public List<RegionResult> findAllProvinceAndCity() {
List<RegionResult> provinceList = provinceManager.findAll()
.stream()
.map(Province::toResult)
.toList();
List<RegionResult> regionList = cityManager.findAll().stream().map(City::toResult).toList();
List<RegionResult> regions = new ArrayList<>(regionList.size() + regionList.size());
regions.addAll(provinceList);
regions.addAll(regionList);
// 构建树
return TreeBuildUtil.build(regions, null, RegionResult::getCode, RegionResult::getParentCode, RegionResult::setChildren);
}
/**
* 获取省市区县联动列表
*/
public List<RegionResult> findAllProvinceAndCityAndArea() {
List<RegionResult> provinceList = provinceManager.findAll()
.stream()
.map(Province::toResult)
.toList();
List<RegionResult> regionList = cityManager.findAll().stream().map(City::toResult).toList();
List<RegionResult> areaList = areaManager.findAll().stream().map(Area::toResult).toList();
List<RegionResult> regions = new ArrayList<>(regionList.size() + regionList.size() + areaList.size());
regions.addAll(provinceList);
regions.addAll(regionList);
regions.addAll(areaList);
// 构建树
return TreeBuildUtil.build(regions, null, RegionResult::getCode, RegionResult::getParentCode, RegionResult::setChildren);
}
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>bootx-platform-service</artifactId>
<version>3.0.0.beta4</version>
<version>3.0.0.beta5</version>
</parent>
<artifactId>service-iam</artifactId>

View File

@@ -2,14 +2,13 @@ package cn.bootx.platform.iam.auth.handler;
import cn.bootx.platform.common.spring.util.WebServletUtil;
import cn.bootx.platform.core.code.WebHeaderCode;
import cn.bootx.platform.starter.audit.log.service.ip2region.IpToRegionService;
import cn.bootx.platform.starter.audit.log.param.LoginLogParam;
import cn.bootx.platform.starter.audit.log.service.ip2region.IpToRegionService;
import cn.bootx.platform.starter.audit.log.service.log.LoginLogService;
import cn.bootx.platform.starter.auth.exception.LoginFailureException;
import cn.bootx.platform.starter.auth.handler.LoginFailureHandler;
import cn.bootx.platform.starter.auth.util.SecurityUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@@ -36,7 +35,7 @@ public class LoginFailureHandlerImpl implements LoginFailureHandler {
@Override
public void onLoginFailure(HttpServletRequest request, HttpServletResponse response, LoginFailureException e) {
UserAgent userAgent = UserAgentUtil.parse(request.getHeader(WebHeaderCode.USER_AGENT));
var userAgent = UserAgentUtil.parse(request.getHeader(WebHeaderCode.USER_AGENT));
// ip信息
String ip = "未知";
String location = "未知";

View File

@@ -2,13 +2,12 @@ package cn.bootx.platform.iam.auth.handler;
import cn.bootx.platform.common.spring.util.WebServletUtil;
import cn.bootx.platform.core.code.WebHeaderCode;
import cn.bootx.platform.starter.audit.log.service.ip2region.IpToRegionService;
import cn.bootx.platform.starter.audit.log.param.LoginLogParam;
import cn.bootx.platform.starter.audit.log.service.ip2region.IpToRegionService;
import cn.bootx.platform.starter.audit.log.service.log.LoginLogService;
import cn.bootx.platform.starter.auth.entity.AuthInfoResult;
import cn.bootx.platform.starter.auth.handler.LoginSuccessHandler;
import cn.hutool.extra.servlet.JakartaServletUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@@ -36,16 +35,16 @@ public class LoginSuccessHandlerImpl implements LoginSuccessHandler {
@Override
public void onLoginSuccess(HttpServletRequest request, HttpServletResponse response,
AuthInfoResult authInfoResult) {
UserAgent userAgent = UserAgentUtil.parse(request.getHeader(WebHeaderCode.USER_AGENT));
var userAgent = UserAgentUtil.parse(request.getHeader(WebHeaderCode.USER_AGENT));
// ip信息
String ip = "未知";
String location = "未知";
var ip = "未知";
var location = "未知";
Optional<String> ipOpt = Optional.ofNullable(WebServletUtil.getRequest()).map(JakartaServletUtil::getClientIP);
if (ipOpt.isPresent()){
ip = ipOpt.get();
location = ipToRegionService.getRegionStrByIp(ip);
}
LoginLogParam loginLog = new LoginLogParam().setLogin(true)
var loginLog = new LoginLogParam().setLogin(true)
.setUserId(authInfoResult.getUserDetail().getId())
.setClient(authInfoResult.getClient())
.setLoginType(authInfoResult.getLoginType())
@@ -56,7 +55,6 @@ public class LoginSuccessHandlerImpl implements LoginSuccessHandler {
.setBrowser(userAgent.getBrowser().getName() + " " + userAgent.getVersion())
.setLoginTime(LocalDateTime.now());
loginLogService.add(loginLog);
// userExpandInfoService.updateLoginTime(loginlog.getUserId());
}
}

View File

@@ -2,7 +2,7 @@ package cn.bootx.platform.iam.auth.login;
import cn.bootx.platform.core.entity.UserDetail;
import cn.bootx.platform.iam.result.user.UserInfoResult;
import cn.bootx.platform.iam.service.service.UserQueryService;
import cn.bootx.platform.iam.service.user.UserQueryService;
import cn.bootx.platform.starter.auth.authentication.AbstractAuthentication;
import cn.bootx.platform.starter.auth.code.AuthLoginTypeCode;
import cn.bootx.platform.starter.auth.entity.AuthInfoResult;

View File

@@ -34,7 +34,7 @@ public class AuthAssistService {
public void sendSmsCaptcha(String phone) {
// 判断用户是否存在
UserInfo userInfo = userInfoManager.findByPhone(phone).orElseThrow(UserInfoNotExistsException::new);
if (!Objects.equals(userInfo.getStatus(), UserStatusEnum.NORMAL.getCode())) {
if (!Objects.equals(userInfo.getStatus(), UserStatusEnum.NORMAL)) {
throw new BizException("用户状态异常");
}
}

View File

@@ -4,6 +4,8 @@ import cn.hutool.core.util.StrUtil;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 请求路径信息类
* @author xxm
@@ -16,6 +18,12 @@ public class RequestPathBo {
/** 主键, 只有通过数据库数据生成的才会有值 */
private Long id;
/** 是否归属所有终端 */
private boolean allClient;
/** 终端编码 */
private List<String> clientCodes;
/** 功能模块编码 */
private String moduleCode;

View File

@@ -4,8 +4,8 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 用户状态
*
* 用户状态
* 字典 user_status
* @author xxm
* @since 2021/9/9
*/

View File

@@ -1,18 +1,24 @@
package cn.bootx.platform.iam.controller.client;
import cn.bootx.platform.core.annotation.InternalPath;
import cn.bootx.platform.core.annotation.OperateLog;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.param.PageParam;
import cn.bootx.platform.core.rest.result.PageResult;
import cn.bootx.platform.core.rest.result.Result;
import cn.bootx.platform.core.validation.ValidationGroup;
import cn.bootx.platform.iam.param.client.ClientParam;
import cn.bootx.platform.iam.result.client.ClientResult;
import cn.bootx.platform.iam.service.client.ClientService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -23,11 +29,12 @@ import java.util.List;
* @author xxm
* @since 2022-06-27
*/
@Validated
@Tag(name = "认证终端")
@RestController
@RequestMapping("/client")
@RequiredArgsConstructor
@RequestGroup(groupCode = "client", groupName = "终端管理", moduleCode = "iam", moduleName = "身份识别与访问管理" )
@RequestGroup(groupCode = "client", groupName = "终端管理", moduleCode = "iam", moduleName = "(Bootx)身份识别与访问管理" )
public class ClientController {
private final ClientService clientService;
@@ -35,7 +42,8 @@ public class ClientController {
@InternalPath
@Operation(summary = "添加终端")
@PostMapping(value = "/add")
public Result<Void> add(@RequestBody ClientParam param) {
@OperateLog(title = "添加终端", businessType = OperateLog.BusinessType.ADD, saveParam = true)
public Result<Void> add(@RequestBody @Validated(ValidationGroup.add.class) ClientParam param) {
clientService.add(param);
return Res.ok();
}
@@ -43,7 +51,8 @@ public class ClientController {
@InternalPath
@Operation(summary = "修改")
@PostMapping(value = "/update")
public Result<Void> update(@RequestBody ClientParam param) {
@OperateLog(title = "修改终端", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
public Result<Void> update(@RequestBody @Validated(ValidationGroup.edit.class) ClientParam param) {
clientService.update(param);
return Res.ok();
}
@@ -51,7 +60,8 @@ public class ClientController {
@InternalPath
@Operation(summary = "删除")
@PostMapping(value = "/delete")
public Result<Void> delete(Long id) {
@OperateLog(title = "删除终端", businessType = OperateLog.BusinessType.DELETE, saveParam = true)
public Result<Void> delete(@NotNull(message = "主键不可为空") Long id) {
clientService.delete(id);
return Res.ok();
}
@@ -59,7 +69,7 @@ public class ClientController {
@RequestPath("通过ID查询终端")
@Operation(summary = "通过ID查询")
@GetMapping(value = "/findById")
public Result<ClientResult> findById(Long id) {
public Result<ClientResult> findById(@NotNull(message = "主键不可为空") Long id) {
return Res.ok(clientService.findById(id));
}
@@ -80,14 +90,16 @@ public class ClientController {
@RequestPath("编码是否被使用")
@Operation(summary = "编码是否被使用")
@GetMapping("/existsByCode")
public Result<Boolean> existsByCode(String code) {
public Result<Boolean> existsByCode(@NotBlank(message = "编码不可为空") @Parameter(description = "编码") String code) {
return Res.ok(clientService.existsByCode(code));
}
@RequestPath("编码是否被使用(不包含自己)")
@Operation(summary = "编码是否被使用(不包含自己)")
@GetMapping("/existsByCodeNotId")
public Result<Boolean> existsByCode(String code, Long id) {
public Result<Boolean> existsByCode(
@NotBlank(message = "编码不可为空") @Parameter(description = "编码") String code,
@NotNull(message = "主键不可为空") @Parameter(description = "主键") Long id) {
return Res.ok(clientService.existsByCode(code, id));
}

View File

@@ -1,20 +1,22 @@
package cn.bootx.platform.iam.controller.permission;
import cn.bootx.platform.core.annotation.IgnoreAuth;
import cn.bootx.platform.core.annotation.InternalPath;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.annotation.*;
import cn.bootx.platform.core.entity.UserDetail;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.result.Result;
import cn.bootx.platform.core.validation.ValidationGroup;
import cn.bootx.platform.iam.param.permission.PermCodeParam;
import cn.bootx.platform.iam.result.permission.PermCodeResult;
import cn.bootx.platform.iam.service.permission.PermCodeService;
import cn.bootx.platform.iam.service.upms.UserRolePremService;
import cn.bootx.platform.starter.auth.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -24,6 +26,7 @@ import java.util.List;
* @author xxm
* @since 2024/7/7
*/
@Validated
@Tag(name = "权限码管理")
@RestController
@RequestMapping("/perm/code")
@@ -38,14 +41,15 @@ public class PermCodeController {
@RequestPath("权限码详情")
@Operation(summary = "权限码详情")
@GetMapping("/findById")
public Result<PermCodeResult> findById(Long id) {
public Result<PermCodeResult> findById(@NotNull(message = "主键不可为空") Long id) {
return Res.ok(permCodeService.findById(id));
}
@InternalPath
@Operation(summary = "添加权限码")
@PostMapping("/add")
public Result<Void> add(@RequestBody PermCodeParam param) {
@OperateLog(title = "添加权限码", businessType = OperateLog.BusinessType.ADD, saveParam = true)
public Result<Void> add(@RequestBody @Validated(ValidationGroup.add.class) PermCodeParam param) {
permCodeService.add(param);
return Res.ok();
}
@@ -53,7 +57,8 @@ public class PermCodeController {
@InternalPath
@Operation(summary = "更新权限码")
@PostMapping("/update")
public Result<Void> update(@RequestBody PermCodeParam param) {
@OperateLog(title = "更新权限码", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
public Result<Void> update(@RequestBody @Validated(ValidationGroup.edit.class) PermCodeParam param) {
permCodeService.update(param);
return Res.ok();
}
@@ -61,7 +66,8 @@ public class PermCodeController {
@InternalPath
@Operation(summary = "删除权限码")
@PostMapping("/delete")
public Result<Void> delete(Long id) {
@OperateLog(title = "删除权限码", businessType = OperateLog.BusinessType.DELETE, saveParam = true)
public Result<Void> delete(@NotNull(message = "主键不可为空") Long id) {
permCodeService.delete(id);
return Res.ok();
}
@@ -99,14 +105,16 @@ public class PermCodeController {
@RequestPath("编码是否被使用")
@Operation(summary = "编码是否被使用")
@GetMapping("/existsByCode")
public Result<Boolean> existsByPermCode(String code) {
public Result<Boolean> existsByPermCode(@NotBlank(message = "编码不可为空") @Parameter(description = "编码") String code) {
return Res.ok(permCodeService.existsByCode(code));
}
@RequestPath("编码是否被使用(不包含自己)")
@Operation(summary = "编码是否被使用(不包含自己)")
@GetMapping("/existsByCodeNotId")
public Result<Boolean> existsByPermCode(String code, Long id) {
public Result<Boolean> existsByPermCode(
@NotBlank(message = "编码不可为空") @Parameter(description = "编码") String code,
@NotNull(message = "主键不可为空") @Parameter(description = "主键") Long id) {
return Res.ok(permCodeService.existsByPermCode(code, id));
}
}

View File

@@ -1,20 +1,22 @@
package cn.bootx.platform.iam.controller.permission;
import cn.bootx.platform.core.annotation.IgnoreAuth;
import cn.bootx.platform.core.annotation.InternalPath;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.annotation.*;
import cn.bootx.platform.core.entity.UserDetail;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.result.Result;
import cn.bootx.platform.core.validation.ValidationGroup;
import cn.bootx.platform.iam.param.permission.PermMenuParam;
import cn.bootx.platform.iam.result.permission.PermMenuResult;
import cn.bootx.platform.iam.service.permission.PermMenuService;
import cn.bootx.platform.iam.service.upms.UserRolePremService;
import cn.bootx.platform.starter.auth.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -24,6 +26,7 @@ import java.util.List;
* @author xxm
* @since 2020/5/11 9:36
*/
@Validated
@Tag(name = "菜单权限管理")
@RestController
@RequestMapping("/perm/menu")
@@ -38,7 +41,8 @@ public class PermMenuController {
@InternalPath
@Operation(summary = "添加菜单权限")
@PostMapping("/add")
public Result<Void> add(@RequestBody PermMenuParam param) {
@OperateLog(title = "添加菜单权限", businessType = OperateLog.BusinessType.ADD, saveParam = true)
public Result<Void> add(@RequestBody @Validated(ValidationGroup.add.class) PermMenuParam param) {
permMenuService.add(param);
return Res.ok();
}
@@ -46,16 +50,16 @@ public class PermMenuController {
@InternalPath
@Operation(summary = "修改菜单权限")
@PostMapping("/update")
public Result<Void> update(@RequestBody PermMenuParam param) {
@OperateLog(title = "修改菜单权限", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
public Result<Void> update(@RequestBody @Validated(ValidationGroup.edit.class) PermMenuParam param) {
permMenuService.update(param);
return Res.ok();
}
@IgnoreAuth
@Operation(summary = "获取菜单树")
@GetMapping("/tree")
public Result<List<PermMenuResult>> menuTree(String clientCode) {
public Result<List<PermMenuResult>> menuTree(@NotBlank(message = "终端编码不可为空") @Parameter(description = "终端编码") String clientCode) {
UserDetail user = SecurityUtil.getUser();
if (user.isAdmin()){
return Res.ok(permMenuService.tree(clientCode));
@@ -66,14 +70,15 @@ public class PermMenuController {
@RequestPath("根据id查询菜单")
@Operation(summary = "根据id查询")
@GetMapping("/findById")
public Result<PermMenuResult> findById(Long id) {
public Result<PermMenuResult> findById(@NotNull(message = "主键不可为空") Long id) {
return Res.ok(permMenuService.findById(id));
}
@InternalPath
@Operation(summary = "删除")
@Operation(summary = "删除菜单权限")
@PostMapping("/delete")
public Result<Void> delete(Long id) {
@OperateLog(title = "删除菜单权限", businessType = OperateLog.BusinessType.DELETE, saveParam = true)
public Result<Void> delete(@NotNull(message = "主键不可为空") Long id) {
permMenuService.delete(id);
return Res.ok();
}

View File

@@ -1,6 +1,7 @@
package cn.bootx.platform.iam.controller.permission;
import cn.bootx.platform.core.annotation.InternalPath;
import cn.bootx.platform.core.annotation.OperateLog;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.entity.UserDetail;
@@ -12,7 +13,10 @@ import cn.bootx.platform.iam.service.permission.PermPathSyncService;
import cn.bootx.platform.iam.service.upms.UserRolePremService;
import cn.bootx.platform.starter.auth.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
@@ -41,16 +45,16 @@ public class PermPathController {
private final PermPathSyncService permPathSyncService;
@RequestPath("获取请求权限详情")
@Operation(summary = "获取详情")
@Operation(summary = "获取请求权限详情")
@GetMapping("/findById")
public Result<PermPathResult> findById(Long id) {
public Result<PermPathResult> findById(@NotNull(message = "主键不可为空") Long id) {
return Res.ok(pathService.findById(id));
}
@RequestPath("请求权限树")
@Operation(summary = "请求权限树")
@GetMapping("/tree")
public Result<List<PermPathResult>> tree(String clientCode) {
public Result<List<PermPathResult>> tree(@NotBlank(message = "终端编码不可为空") @Parameter(description = "终端编码") String clientCode) {
UserDetail user = SecurityUtil.getUser();
if (user.isAdmin()){
return Res.ok(pathService.tree(clientCode));
@@ -61,6 +65,7 @@ public class PermPathController {
@InternalPath
@Operation(summary = "根据系统配置同步请求权限数据")
@PostMapping("/sync")
@OperateLog(title = "根据系统配置同步请求权限数据", businessType = OperateLog.BusinessType.SYNC, saveParam = true)
public Result<Void> sync() {
permPathSyncService.sync();
return Res.ok();

View File

@@ -1,19 +1,25 @@
package cn.bootx.platform.iam.controller.role;
import cn.bootx.platform.core.annotation.IgnoreAuth;
import cn.bootx.platform.core.annotation.OperateLog;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.dto.KeyValue;
import cn.bootx.platform.core.rest.result.Result;
import cn.bootx.platform.core.util.ValidationUtil;
import cn.bootx.platform.core.validation.ValidationGroup;
import cn.bootx.platform.iam.param.role.RoleParam;
import cn.bootx.platform.iam.result.role.RoleResult;
import cn.bootx.platform.iam.service.role.RoleQueryService;
import cn.bootx.platform.iam.service.role.RoleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -22,6 +28,7 @@ import java.util.List;
* @author xxm
* @since 2021/6/9
*/
@Validated
@Tag(name = "角色管理")
@RestController
@RequestMapping("/role")
@@ -33,29 +40,32 @@ public class RoleController {
private final RoleQueryService roleQueryService;
@IgnoreAuth
@RequestPath("添加角色")
@Operation(summary = "添加角色")
@PostMapping(value = "/add")
public Result<Void> add(@RequestBody RoleParam roleParam) {
@OperateLog(title = "添加角色", businessType = OperateLog.BusinessType.ADD, saveParam = true)
public Result<Void> add(@RequestBody @Validated(ValidationGroup.add.class) RoleParam roleParam) {
ValidationUtil.validateParam(roleParam);
roleService.add(roleParam);
return Res.ok();
}
@IgnoreAuth
@Operation(summary = "删除角色")
@PostMapping(value = "/delete")
public Result<Void> delete(Long id) {
roleService.delete(id);
@RequestPath("修改角色")
@Operation(summary = "修改角色")
@PostMapping(value = "/update")
@OperateLog(title = "修改角色", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
public Result<Void> update(@RequestBody @Validated(ValidationGroup.edit.class) RoleParam roleParam) {
ValidationUtil.validateParam(roleParam);
roleService.update(roleParam);
return Res.ok();
}
@IgnoreAuth
@Operation(summary = "修改角色")
@PostMapping(value = "/update")
public Result<Void> update(@RequestBody RoleParam roleParam) {
ValidationUtil.validateParam(roleParam);
roleService.update(roleParam);
@RequestPath("删除角色")
@Operation(summary = "删除角色")
@PostMapping(value = "/delete")
@OperateLog(title = "删除角色", businessType = OperateLog.BusinessType.DELETE, saveParam = true)
public Result<Void> delete(@NotNull(message = "主键不可为空") Long id) {
roleService.delete(id);
return Res.ok();
}
@@ -69,7 +79,7 @@ public class RoleController {
@RequestPath("通过ID查询角色")
@Operation(summary = "通过ID查询角色")
@GetMapping(value = "/findById")
public Result<RoleResult> findById(Long id) {
public Result<RoleResult> findById(@NotNull(message = "主键不可为空") Long id) {
return Res.ok(roleQueryService.findById(id));
}
@@ -90,28 +100,32 @@ public class RoleController {
@RequestPath("编码是否被使用")
@Operation(summary = "编码是否被使用")
@GetMapping("/existsByCode")
public Result<Boolean> existsByCode(String code) {
public Result<Boolean> existsByCode(@NotBlank(message = "角色编码不可为空") @Parameter(description = "编码") String code) {
return Res.ok(roleQueryService.existsByCode(code));
}
@RequestPath("编码是否被使用(不包含自己)")
@Operation(summary = "编码是否被使用(不包含自己)")
@GetMapping("/existsByCodeNotId")
public Result<Boolean> existsByCode(String code, Long id) {
public Result<Boolean> existsByCode(
@NotBlank(message = "编码不可为空") @Parameter(description = "编码") String code,
@NotNull(message = "主键不可为空") @Parameter(description = "主键") Long id) {
return Res.ok(roleQueryService.existsByCode(code, id));
}
@RequestPath("名称是否被使用")
@Operation(summary = "名称是否被使用")
@GetMapping("/existsByName")
public Result<Boolean> existsByName(String name) {
public Result<Boolean> existsByName(@NotBlank(message = "角色名称不可为空") @Parameter(description = "角色名称") String name) {
return Res.ok(roleQueryService.existsByName(name));
}
@RequestPath("名称是否被使用(不包含自己)")
@Operation(summary = "名称是否被使用(不包含自己)")
@GetMapping("/existsByNameNotId")
public Result<Boolean> existsByName(String name, Long id) {
public Result<Boolean> existsByName(
@NotBlank(message = "角色名称不可为空") @Parameter(description = "角色名称") String name,
@NotNull(message = "主键不可为空") @Parameter(description = "主键") Long id) {
return Res.ok(roleQueryService.existsByName(name, id));
}

View File

@@ -1,5 +1,6 @@
package cn.bootx.platform.iam.controller.upms;
import cn.bootx.platform.core.annotation.OperateLog;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.rest.Res;
@@ -9,6 +10,7 @@ import cn.bootx.platform.iam.result.permission.PermCodeResult;
import cn.bootx.platform.iam.service.upms.RoleCodeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -32,6 +34,7 @@ public class RoleCodeController {
@RequestPath("保存请求权限关系")
@Operation(summary = "保存请求权限关系")
@PostMapping("/save")
@OperateLog(title = "保存请求权限关系", businessType = OperateLog.BusinessType.GRANT, saveParam = true)
public Result<Boolean> save(@RequestBody @Validated PermCodeAssignParam param) {
roleCodeService.saveAssign(param);
return Res.ok(true);
@@ -40,14 +43,14 @@ public class RoleCodeController {
@RequestPath("指定角色下的请求权限树(分配时用)")
@Operation(summary = "指定角色下的请求权限树(分配时用)")
@GetMapping("/treeByRole")
public Result<List<PermCodeResult>> treeByRole(Long roleId) {
public Result<List<PermCodeResult>> treeByRole(@NotNull(message = "角色id不可为空") Long roleId) {
return Res.ok(roleCodeService.treeByRoleAssign(roleId));
}
@RequestPath("查询当前角色已经选择的菜单id")
@Operation(summary = "查询当前角色已经选择的菜单id")
@GetMapping("/findIdsByRole")
public Result<List<Long>> findIdsByRole(Long roleId) {
public Result<List<Long>> findIdsByRole(@NotNull(message = "角色id不可为空") Long roleId) {
return Res.ok(roleCodeService.findCodeIdsByRole(roleId));
}

View File

@@ -1,5 +1,6 @@
package cn.bootx.platform.iam.controller.upms;
import cn.bootx.platform.core.annotation.OperateLog;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.rest.Res;
@@ -9,8 +10,12 @@ import cn.bootx.platform.iam.param.permission.PermMenuAssignParam;
import cn.bootx.platform.iam.result.permission.PermMenuResult;
import cn.bootx.platform.iam.service.upms.RoleMenuService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -21,6 +26,7 @@ import java.util.List;
* @author xxm
* @since 2021/7/12
*/
@Validated
@Tag(name = "角色菜单权限关系")
@RestController
@RequestMapping("/role/menu")
@@ -33,7 +39,8 @@ public class RoleMenuController {
@RequestPath("保存请求权限关系")
@Operation(summary = "保存请求权限关系")
@PostMapping("/save")
public Result<Boolean> save(@RequestBody PermMenuAssignParam param) {
@OperateLog(title = "保存请求权限关系", businessType = OperateLog.BusinessType.GRANT, saveParam = true)
public Result<Boolean> save(@RequestBody @Validated PermMenuAssignParam param) {
ValidationUtil.validateParam(param);
rolePermService.saveAssign(param);
return Res.ok(true);
@@ -43,14 +50,18 @@ public class RoleMenuController {
@RequestPath("指定角色下的菜单权限树(分配时用)")
@Operation(summary = "指定角色下的菜单权限树(分配时用)")
@GetMapping("/treeByRole")
public Result<List<PermMenuResult>> treeByRole(Long roleId, String clientCode) {
public Result<List<PermMenuResult>> treeByRole(
@NotNull(message = "角色id不可为空") @Parameter(description = "角色id") Long roleId,
@NotBlank(message = "终端编码不可为空") @Parameter(description = "终端编码") String clientCode) {
return Res.ok(rolePermService.treeByRoleAssign(roleId,clientCode));
}
@RequestPath("查询当前角色已经选择的菜单id")
@Operation(summary = "查询当前角色已经选择的菜单id")
@GetMapping("/findIdsByRole")
public Result<List<Long>> findIdsByRole(Long roleId, String clientCode) {
public Result<List<Long>> findIdsByRole(
@NotNull(message = "角色id不可为空") @Parameter(description = "角色id") Long roleId,
@NotBlank(message = "终端编码不可为空") @Parameter(description = "终端编码") String clientCode) {
return Res.ok(rolePermService.findIdsByRoleAndClient(roleId,clientCode));
}

View File

@@ -1,16 +1,20 @@
package cn.bootx.platform.iam.controller.upms;
import cn.bootx.platform.core.annotation.OperateLog;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.result.Result;
import cn.bootx.platform.core.util.ValidationUtil;
import cn.bootx.platform.iam.param.permission.PermPathAssignParam;
import cn.bootx.platform.iam.result.permission.SimplePermPathResult;
import cn.bootx.platform.iam.service.upms.RolePathService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -19,6 +23,7 @@ import java.util.List;
* @author xxm
* @since 2021/6/9
*/
@Validated
@Tag(name = "角色请求权限消息关系")
@RestController
@RequestMapping("/role/path")
@@ -31,8 +36,8 @@ public class RolePathController {
@RequestPath("保存角色请求权限关联关系")
@Operation(summary = "保存角色请求权限关联关系")
@PostMapping("/save")
public Result<Void> save(@RequestBody PermPathAssignParam param) {
ValidationUtil.validateParam(param);
@OperateLog(title = "保存角色请求权限关联关系", businessType = OperateLog.BusinessType.GRANT, saveParam = true)
public Result<Void> save(@RequestBody @Validated PermPathAssignParam param) {
rolePathService.saveAssign(param);
return Res.ok();
}
@@ -40,14 +45,18 @@ public class RolePathController {
@RequestPath("指定角色下的请求权限树(分配时用)")
@Operation(summary = "指定角色下的请求权限树(分配时用)")
@GetMapping("/treeByRole")
public Result<List<SimplePermPathResult>> treeByRoleAndClient(Long roleId, String clientCode) {
public Result<List<SimplePermPathResult>> treeByRoleAndClient(
@NotNull(message = "角色id不可为空") @Parameter(description = "角色id") Long roleId,
@NotBlank(message = "终端编码不可为空") @Parameter(description = "终端编码") String clientCode) {
return Res.ok(rolePathService.treeByRoleAssign(roleId,clientCode));
}
@RequestPath("查询当前角色已经选择的请求路径")
@Operation(summary = "查询当前角色已经选择的请求路径")
@GetMapping("/findIdsByRole")
public Result<List<Long>> findIdsByRole(Long roleId, String clientCode) {
public Result<List<Long>> findIdsByRole(
@NotNull(message = "角色id不可为空") @Parameter(description = "角色id") Long roleId,
@NotBlank(message = "终端编码不可为空") @Parameter(description = "终端编码") String clientCode) {
return Res.ok(rolePathService.findIdsByRole(roleId, clientCode));
}

View File

@@ -1,16 +1,18 @@
package cn.bootx.platform.iam.controller.upms;
import cn.bootx.platform.core.annotation.OperateLog;
import cn.bootx.platform.core.annotation.RequestGroup;
import cn.bootx.platform.core.annotation.RequestPath;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.result.Result;
import cn.bootx.platform.core.util.ValidationUtil;
import cn.bootx.platform.iam.param.upms.UserRoleBatchParam;
import cn.bootx.platform.iam.param.upms.UserRoleParam;
import cn.bootx.platform.iam.result.role.RoleResult;
import cn.bootx.platform.iam.service.upms.UserRoleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -21,6 +23,7 @@ import java.util.List;
* @author xxm
* @since 2020/5/1 18:09
*/
@Validated
@Tag(name = "用户角色管理")
@RestController
@RequestMapping("/user/role")
@@ -33,6 +36,7 @@ public class UserRoleController {
@RequestPath("给用户分配角色")
@Operation(summary = "给用户分配角色")
@PostMapping(value = "/saveAssign")
@OperateLog(title = "给用户分配角色", businessType = OperateLog.BusinessType.GRANT, saveParam = true)
public Result<Void> saveAssign(@Validated @RequestBody UserRoleParam param) {
userRoleService.saveAssign(param.getUserId(), param.getRoleIds());
return Res.ok();
@@ -41,8 +45,8 @@ public class UserRoleController {
@RequestPath("给用户分配角色(批量)")
@Operation(summary = "给用户分配角色(批量)")
@PostMapping(value = "/saveAssignBatch")
public Result<Void> saveAssignBatch(@RequestBody UserRoleBatchParam param) {
ValidationUtil.validateParam(param);
@OperateLog(title = "给用户分配角色(批量)", businessType = OperateLog.BusinessType.GRANT, saveParam = true)
public Result<Void> saveAssignBatch(@RequestBody @Validated UserRoleBatchParam param) {
userRoleService.saveAssignBatch(param.getUserIds(), param.getRoleIds());
return Res.ok();
}
@@ -50,14 +54,14 @@ public class UserRoleController {
@RequestPath("根据用户ID获取到角色集合")
@Operation(summary = "根据用户ID获取到角色集合")
@GetMapping(value = "/findRolesByUser")
public Result<List<RoleResult>> findRolesByUser(Long userId) {
public Result<List<RoleResult>> findRolesByUser(@NotNull(message = "用户ID不可为空") @Parameter(description = "用户ID") Long userId) {
return Res.ok(userRoleService.findRolesByUser(userId));
}
@RequestPath("根据用户ID获取到角色id集合")
@Operation(summary = "根据用户ID获取到角色id集合")
@GetMapping(value = "/findRoleIdsByUser")
public Result<List<Long>> findRoleIdsByUser(Long userId) {
public Result<List<Long>> findRoleIdsByUser(@NotNull(message = "用户ID不可为空") @Parameter(description = "用户ID") Long userId) {
return Res.ok(userRoleService.findRoleIdsByUser(userId));
}

View File

@@ -14,8 +14,8 @@ import cn.bootx.platform.iam.param.user.UserInfoParam;
import cn.bootx.platform.iam.param.user.UserInfoQuery;
import cn.bootx.platform.iam.result.user.UserInfoResult;
import cn.bootx.platform.iam.result.user.UserWholeInfoResult;
import cn.bootx.platform.iam.service.service.UserAdminService;
import cn.bootx.platform.iam.service.service.UserQueryService;
import cn.bootx.platform.iam.service.user.UserAdminService;
import cn.bootx.platform.iam.service.user.UserQueryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotEmpty;
@@ -45,13 +45,14 @@ public class UserAdminController {
@RequestPath("根据用户id查询用户 ")
@Operation(summary = "根据用户id查询用户")
@GetMapping("/findById")
public Result<UserInfoResult> findById(Long id) {
public Result<UserInfoResult> findById(@NotNull(message = "主键不可为空") Long id) {
return Res.ok(userQueryService.findById(id));
}
@RequestPath("添加用户")
@Operation(summary = "添加用户")
@PostMapping("/add")
@OperateLog(title = "添加用户", businessType = OperateLog.BusinessType.ADD, saveParam = true)
public Result<Void> add(@RequestBody @Validated(ValidationGroup.add.class) UserInfoParam userInfoParam) {
userAdminService.add(userInfoParam);
return Res.ok();
@@ -60,6 +61,7 @@ public class UserAdminController {
@RequestPath("修改用户")
@Operation(summary = "修改用户")
@PostMapping("/update")
@OperateLog(title = "修改用户", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
public Result<Void> update(@RequestBody @Validated(ValidationGroup.edit.class) UserInfoParam userInfoParam) {
userAdminService.update(userInfoParam);
return Res.ok();
@@ -67,8 +69,8 @@ public class UserAdminController {
@RequestPath("重置密码")
@Operation(summary = "重置密码")
@OperateLog(title = "重置密码", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
@PostMapping("/restartPassword")
@OperateLog(title = "重置密码", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
public Result<Void> restartPassword(@RequestBody @Validated RestartPwdParam param) {
userAdminService.restartPassword(param.getUserId(), param.getNewPassword());
return Res.ok();
@@ -76,44 +78,44 @@ public class UserAdminController {
@RequestPath("批量重置密码")
@Operation(summary = "批量重置密码")
@OperateLog(title = "批量重置密码", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
@PostMapping("/restartPasswordBatch")
@OperateLog(title = "批量重置密码", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
public Result<Void> restartPasswordBatch(@RequestBody @Validated RestartPwdBatchParam param) {
userAdminService.restartPasswordBatch(param.getUserIds(), param.getNewPassword());
return Res.ok();
}
@RequestPath("封禁用户")
@OperateLog(title = "封禁用户", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
@Operation(summary = "封禁用户")
@PostMapping("/ban")
public Result<Void> ban(Long userId) {
@OperateLog(title = "封禁用户", businessType = OperateLog.BusinessType.GRANT, saveParam = true)
public Result<Void> ban(@NotNull(message = "用户不可为空") Long userId) {
userAdminService.ban(userId);
return Res.ok();
}
@RequestPath("批量封禁用户")
@OperateLog(title = "批量封禁用户", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
@Operation(summary = "批量封禁用户")
@PostMapping("/banBatch")
@OperateLog(title = "批量封禁用户", businessType = OperateLog.BusinessType.GRANT, saveParam = true)
public Result<Void> banBatch(@RequestBody @NotEmpty(message = "用户集合不可为空") List<Long> userIds) {
userAdminService.banBatch(userIds);
return Res.ok();
}
@RequestPath("解锁用户")
@OperateLog(title = "解锁用户", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
@Operation(summary = "解锁用户")
@PostMapping("/unlock")
@OperateLog(title = "解锁用户", businessType = OperateLog.BusinessType.GRANT, saveParam = true)
public Result<Void> unlock(@NotNull(message = "用户不可为空") Long userId) {
userAdminService.unlock(userId);
return Res.ok();
}
@RequestPath("批量解锁用户")
@OperateLog(title = "批量解锁用户", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
@Operation(summary = "批量解锁用户")
@PostMapping("/unlockBatch")
@OperateLog(title = "批量解锁用户", businessType = OperateLog.BusinessType.GRANT, saveParam = true)
public Result<Void> unlockBatch(@RequestBody @NotEmpty(message = "用户集合不可为空") List<Long> userIds) {
userAdminService.unlockBatch(userIds);
return Res.ok();
@@ -125,5 +127,4 @@ public class UserAdminController {
public Result<PageResult<UserWholeInfoResult>> page(PageParam pageParam, UserInfoQuery query) {
return Res.ok(userAdminService.page(pageParam, query));
}
}

View File

@@ -1,16 +1,19 @@
package cn.bootx.platform.iam.controller.user;
import cn.bootx.platform.core.annotation.IgnoreAuth;
import cn.bootx.platform.core.annotation.OperateLog;
import cn.bootx.platform.core.rest.Res;
import cn.bootx.platform.core.rest.result.Result;
import cn.bootx.platform.iam.param.user.UserBaseInfoParam;
import cn.bootx.platform.iam.result.user.LoginAfterUserInfoResult;
import cn.bootx.platform.iam.result.user.UserBaseInfoResult;
import cn.bootx.platform.iam.service.service.UserInfoService;
import cn.bootx.platform.iam.service.service.UserQueryService;
import cn.bootx.platform.iam.service.user.UserInfoService;
import cn.bootx.platform.iam.service.user.UserQueryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -34,43 +37,50 @@ public class UserInfoController {
@Operation(summary = "账号是否被使用")
@GetMapping("/existsAccount")
public Result<Boolean> existsAccount(String account) {
public Result<Boolean> existsAccount(@NotBlank(message = "账号不能为空") String account) {
return Res.ok(userQueryService.existsAccount(account));
}
@Operation(summary = "账号是否被使用(不包含自己)")
@GetMapping("/existsAccountNotId")
public Result<Boolean> existsAccount(String account, Long id) {
public Result<Boolean> existsAccount(
@NotBlank(message = "账号不能为空") @Parameter(description = "账号") String account,
@NotNull(message = "用户ID不能为空") @Parameter(description = "用户ID") Long id) {
return Res.ok(userQueryService.existsAccount(account, id));
}
@Operation(summary = "手机号是否被使用")
@GetMapping("/existsPhone")
public Result<Boolean> existsPhone(String phone) {
public Result<Boolean> existsPhone(@NotBlank(message = "手机号不能为空") String phone) {
return Res.ok(userQueryService.existsPhone(phone));
}
@Operation(summary = "手机号是否被使用(不包含自己)")
@GetMapping("/existsPhoneNotId")
public Result<Boolean> existsPhone(String phone, Long id) {
public Result<Boolean> existsPhone(
@NotBlank(message = "手机号不能为空") @Parameter(description = "手机号") String phone,
@NotNull(message = "用户ID不能为空") @Parameter(description = "用户ID") Long id) {
return Res.ok(userQueryService.existsPhone(phone, id));
}
@Operation(summary = "邮箱是否被使用")
@GetMapping("/existsEmail")
public Result<Boolean> existsEmail(String email) {
public Result<Boolean> existsEmail(@NotBlank(message = "邮箱不能为空") @Parameter(description = "邮箱") String email) {
return Res.ok(userQueryService.existsEmail(email));
}
@Operation(summary = "邮箱是否被使用(不包含自己)")
@GetMapping("/existsEmailNotId")
public Result<Boolean> existsEmail(String email, Long id) {
public Result<Boolean> existsEmail(
@NotBlank(message = "邮箱不能为空") @Parameter(description = "邮箱") String email,
@NotNull(message = "用户ID不能为空") @Parameter(description = "用户ID") Long id) {
return Res.ok(userQueryService.existsEmail(email, id));
}
@Operation(summary = "修改密码")
@PostMapping("/updatePassword")
@OperateLog(title = "修改密码", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
public Result<Void> updatePassword(@NotBlank(message = "旧密码不能为空") String password, @NotBlank(message = "新密码不能为空") String newPassword) {
userInfoService.updatePassword(password, newPassword);
return Res.ok();
@@ -84,6 +94,7 @@ public class UserInfoController {
@Operation(summary = "修改用户基础信息")
@PostMapping("/updateBaseInfo")
@OperateLog(title = "修改用户基础信息", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
public Result<Void> updateBaseInfo(@RequestBody @Validated UserBaseInfoParam param) {
userInfoService.updateUserBaseInfo(param);
return Res.ok();

View File

@@ -19,7 +19,7 @@ import java.util.List;
public class PermPathManager extends BaseManager<PermPathMapper, PermPath> {
/**
* 根据节点类型查询查询
* 根据节点类型和终端编码查询
*/
public List<PermPath> findAllByLeafAndClient(boolean isLeaf, String clientCode) {
return lambdaQuery()
@@ -27,6 +27,14 @@ public class PermPathManager extends BaseManager<PermPathMapper, PermPath> {
.eq(PermPath::getClientCode, clientCode)
.list();
}
/**
* 根据节点类型查询
*/
public List<PermPath> findAllByLeafAndClient(boolean isLeaf) {
return lambdaQuery()
.eq(PermPath::isLeaf, isLeaf)
.list();
}
/**
* 根据终端类型查询

View File

@@ -0,0 +1,19 @@
package cn.bootx.platform.iam.entity.client;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
*
* @author xxm
* @since 2025/1/31
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@Schema(title = "")
public class System extends MpBaseEntity {
}

View File

@@ -38,7 +38,7 @@ public class InternalRouterCheck implements RouterCheck {
}
// internalPath 不为空
if (Objects.nonNull(internalPath)) {
//
// 判断当前用户是否为超级管理员
if (!SecurityUtil.getUser().isAdmin()){
throw new BizWarnException("内部接口不允许普通用户进行调用!");
}

View File

@@ -2,7 +2,7 @@ package cn.bootx.platform.iam.handler;
import cn.bootx.platform.core.entity.UserDetail;
import cn.bootx.platform.iam.code.UserStatusEnum;
import cn.bootx.platform.iam.service.service.UserAdminService;
import cn.bootx.platform.iam.service.user.UserAdminService;
import cn.bootx.platform.starter.auth.authentication.UserInfoStatusCheck;
import cn.bootx.platform.starter.auth.configuration.AuthProperties;
import cn.bootx.platform.starter.auth.entity.AuthClient;
@@ -45,7 +45,7 @@ public class UserInfoStatusCheckImpl implements UserInfoStatusCheck {
return;
}
// 判断用户是否被禁用
if (Objects.equals(userDetail.getStatus(), UserStatusEnum.BAN.getCode())){
if (Objects.equals(userDetail.getStatus(), UserStatusEnum.BAN)){
throw new LoginFailureException("该用户已被禁用");
}
}

View File

@@ -1,8 +1,8 @@
package cn.bootx.platform.iam.handler;
import cn.bootx.platform.common.config.BootxConfigProperties;
import cn.bootx.platform.common.spring.util.WebServletUtil;
import cn.bootx.platform.core.entity.UserDetail;
import cn.bootx.platform.iam.service.client.ClientCodeService;
import cn.bootx.platform.iam.service.upms.UserRolePremService;
import cn.bootx.platform.starter.auth.service.RouterCheck;
import cn.bootx.platform.starter.auth.util.SecurityUtil;
@@ -25,7 +25,7 @@ public class UserPathRouterCheck implements RouterCheck {
private final UserRolePremService userRoleService;
private final BootxConfigProperties configProperties;
private final ClientCodeService clientCodeService;
private final AntPathMatcher matcher = new AntPathMatcher();
@@ -45,7 +45,7 @@ public class UserPathRouterCheck implements RouterCheck {
}
UserDetail userDetail = UserDetailOpt.get();
// 获取用户拥有的请求路径权限
List<String> paths = userRoleService.findPathByUser(userDetail.getId(), method, configProperties.getClientCode());
List<String> paths = userRoleService.findPathByUser(userDetail.getId(), method, clientCodeService.getClientCode());
return paths.stream().anyMatch(pattern -> matcher.match(pattern, path));
}

View File

@@ -1,8 +1,10 @@
package cn.bootx.platform.iam.param.client;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.ibatis.annotations.Update;
/**
* 认证应用
@@ -15,12 +17,15 @@ import lombok.experimental.Accessors;
@Accessors(chain = true)
public class ClientParam {
@NotNull(message = "主键不可为空", groups = {Update.class})
@Schema(description = "主键")
private Long id;
@NotNull(message = "编码不可为空")
@Schema(description = "编码")
private String code;
@NotNull(message = "名称不可为空")
@Schema(description = "名称")
private String name;

View File

@@ -1,6 +1,7 @@
package cn.bootx.platform.iam.param.permission;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
@@ -17,6 +18,7 @@ import java.util.List;
public class PermCodeAssignParam {
/** 角色ID */
@NotNull(message = "角色ID不可为空")
@Schema(description = "角色ID")
private Long roleId;
/** 菜单ID */

View File

@@ -1,8 +1,10 @@
package cn.bootx.platform.iam.param.permission;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.ibatis.annotations.Update;
/**
* 权限码
@@ -14,15 +16,18 @@ import lombok.experimental.Accessors;
@Schema(title = "权限码")
public class PermCodeParam {
@NotNull(message = "主键不可为空", groups = {Update.class})
@Schema(description = "id")
private Long id;
@Schema(description = "父id")
private Long pid;
@NotNull(message = "编码不可为空")
@Schema(description = "权限码")
private String code;
@NotNull(message = "名称不可为空")
@Schema(description = "名称")
private String name;

View File

@@ -1,6 +1,8 @@
package cn.bootx.platform.iam.param.permission;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
@@ -17,9 +19,11 @@ import java.util.List;
public class PermMenuAssignParam {
/** 角色ID */
@NotNull(message = "角色ID不可为空")
@Schema(description = "角色ID")
private Long roleId;
/** 终端编码 */
@NotBlank(message = "终端编码不可为空")
@Schema(description = "终端编码")
private String clientCode;
/** 菜单ID */

View File

@@ -2,9 +2,8 @@ package cn.bootx.platform.iam.param.permission;
import cn.bootx.platform.core.validation.ValidationGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Null;
import lombok.Data;
import lombok.experimental.Accessors;
@@ -17,18 +16,18 @@ import lombok.experimental.Accessors;
@Schema(title = "菜单权限")
public class PermMenuParam {
@Null(groups = { ValidationGroup.edit.class })
@NotNull(groups = { ValidationGroup.add.class })
@NotNull(groups = { ValidationGroup.edit.class }, message = "主键不可为空")
@Schema(description = "主键")
private Long id;
@Schema(description = "父id")
private Long pid;
@NotEmpty(groups = { ValidationGroup.add.class, ValidationGroup.edit.class })
@NotBlank(message = "关联应用code不可为空")
@Schema(description = "关联应用code")
private String clientCode;
@NotBlank(message = "菜单标题不可为空")
@Schema(description = "菜单标题")
private String title;

View File

@@ -1,6 +1,7 @@
package cn.bootx.platform.iam.param.permission;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
@@ -17,9 +18,11 @@ import java.util.List;
public class PermPathAssignParam {
/** 角色ID */
@NotNull(message = "角色ID不可为空")
@Schema(description = "角色ID")
private Long roleId;
/** 终端编码 */
@NotNull(message = "终端编码不可为空")
@Schema(description = "终端编码")
private String clientCode;
/** 路径ID */

View File

@@ -1,6 +1,9 @@
package cn.bootx.platform.iam.param.role;
import cn.bootx.platform.core.validation.ValidationGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
@@ -13,15 +16,18 @@ import lombok.experimental.Accessors;
@Schema(title = "角色")
public class RoleParam {
@NotNull(groups = { ValidationGroup.edit.class }, message = "主键不可为空")
@Schema(description = "角色id")
private Long id;
@Schema(description = "父级Id")
private Long pid;
@NotBlank(message = "编码不可为空")
@Schema(description = "角色code")
private String code;
@NotBlank(message = "角色名称不可为空")
@Schema(description = "角色名称")
private String name;

View File

@@ -19,7 +19,6 @@ public class UserRoleParam {
private Long userId;
@Schema(description = "角色的ID集合")
@NotNull(message = "roleIds 不能为空")
private List<Long> roleIds;
}

View File

@@ -28,14 +28,14 @@ public class UserInfoParam {
@Schema(description = "登录账号")
private String account;
@NotBlank(groups = ValidationGroup.add.class, message = "密码不可为空")
@Schema(description = "密码")
private String password;
@Schema(description = "手机号")
private String phone;
@Schema(description = "邮箱")
private String email;
@NotBlank(groups = ValidationGroup.add.class, message = "登录账号不可为空")
@Schema(description = "密码")
private String password;
}

View File

@@ -0,0 +1,20 @@
package cn.bootx.platform.iam.service.client;
import cn.bootx.platform.common.headerholder.local.HolderContextHolder;
import cn.bootx.platform.core.code.CommonCode;
/**
* 获取终端编码
* @author xxm
* @since 2025/1/31
*/
public interface ClientCodeService {
/**
* 获取终端编码
*/
default String getClientCode(){
// 从请求头获取当前终端类型
return HolderContextHolder.get(CommonCode.CLIENT);
}
}

Some files were not shown because too many files have changed in this diff Show More