Merge pull request #19 from hiparker/development

v 2.0
pull/33/head
Parker 3 years ago committed by GitHub
commit 786a530b8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Copyright [2020] [OPSLI 快速开发平台 https://www.opsli.com]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,4 +1,4 @@
# OPSLI 快速开发平台 (已开源)
# OPSLI 快速开发平台 (v2.0)
<div align="center">
<img width="500" src="https://gitee.com/hiparker/opsli-ui/raw/master/repository-images/logo.png"/>
<br/> <br/>
@ -31,15 +31,15 @@
> 单机版
| 名称 | 版本号 | | 名称 | 版本号 |
| ---------------- | ------- | ---- | -------------- | -------------- |
| jdk版本 | ^1.8 | | springboot版本 | ^2.3.3.RELEASE |
| mybatis-plus版本 | ^3.4.0 | | pagehelper版本 | ^1.1.0 |
| druid版本 | ^1.1.17 | | dynamic版本 | ^2.5.4 |
| shiro-redis版本 | ^3.3.1 | | jwt版本 | ^3.10.3 |
| ehcache版本 | ^3.9.0 | | easyexcel版本 | ^2.2.6 |
| kaptcha版本 | ^0.0.9 | | guava版本 | ^29.0-jre |
| enjoy版本 | ^4.9.03 | | hutool版本 | ^5.7.14 |
| 名称 | 版本号 | | 名称 | 版本号 |
| ---------------- |---| ---- | -------------- |--------------|
| jdk版本 | 1.8 | | springboot版本 | 2.5.6 |
| mybatis-plus版本 | 3.5.2 | | pagehelper版本 | 1.3.0 |
| druid版本 | 1.1.17 | | dynamic版本 | 2.5.4 |
| fastjson版本 | 1.2.83 | | transmittable版本 | 2.12.5 |
| ehcache版本 | 3.9.0 | | easyexcel版本 | 2.2.6 |
| captcha版本 | 1.6.2 | | guava版本 | 30.0-android |
| enjoy版本 | 4.9.06 | | hutool版本 | 5.7.14 |
## 在线演示
@ -100,8 +100,6 @@
│ │ │ │ │ ├── exception 公共模块 - 异常类
│ │ │ │ │ ├── msg 公共模块 - 信息
│ │ │ │ │ ├── thread 公共模块 - 线程相关
│ │ │ │ │ │ ├── refuse 拒绝策略线程池
│ │ │ │ │ │ └── wait 等待线程池
│ │ │ │ │ └── utils 公共模块 - 工具类
│ │ │ │ │
│ └── opsli-core 基础 - 核心模块
@ -110,27 +108,33 @@
│ │ │ ├── java
│ │ │ │ └── org
│ │ │ │ └── opsli
│ │ │ │ └── core
│ │ │ │ ├── api 核心模块 - API接口相关登录Token缓存
│ │ │ │ ├── autoconfigure 核心模块 - 自动配置
│ │ │ │ │ ├── conf 自动装配
│ │ │ │ │ └── properties 配置文件注入
│ │ │ │ ├── base 核心模块 - 基础类 Entity Service
│ │ │ │ ├── cache 核心模块 - 缓存处理
│ │ │ │ ├── filters 核心模块 - 过滤器
│ │ │ │ │ ├── aspect AOP切面
│ │ │ │ │ └── interceptor Spring拦截器
│ │ │ │ ├── conf 核心模块 - 全局统一自动装配
│ │ │ │ ├── general 核心模块 - 打印信息
│ │ │ │ ├── handler 核心模块 - 异常拦截处理
│ │ │ │ ├── listener 核心模块 - 系统监听器
│ │ │ │ ├── msg 核心模块 - 信息
│ │ │ │ ├── persistence 核心模块 - 查询条件构造器
│ │ │ │ │ └── querybuilder
│ │ │ │ │ └── chain 核心模块 - 查询条件构造器 - 责任链(例: 租户处理)
│ │ │ │ ├── security 核心模块 - 权限验证
│ │ │ │ │ └── shiro Shiro权限校验
│ │ │ │ └── utils 核心模块 - 工具类
│ │ │ │ ├── core 核心
│ │ │ │ │ ├── api 核心模块 - API接口相关登录Token缓存
│ │ │ │ │ ├── autoconfigure 核心模块 - 自动配置
│ │ │ │ │ │ ├── conf 自动装配
│ │ │ │ │ │ └── properties 配置文件注入
│ │ │ │ │ ├── base 核心模块 - 基础类 Entity Service
│ │ │ │ │ ├── cache 核心模块 - 缓存处理
│ │ │ │ │ ├── eventbus 核心模块 - 消息事件
│ │ │ │ │ ├── filters 核心模块 - 过滤器
│ │ │ │ │ │ ├── aspect AOP切面
│ │ │ │ │ │ └── interceptor Spring拦截器
│ │ │ │ │ ├── general 核心模块 - 其他处理器
│ │ │ │ │ ├── handler 核心模块 - 异常拦截处理
│ │ │ │ │ ├── holder 核心模块 - 上下文数据
│ │ │ │ │ ├── listener 核心模块 - 系统监听器
│ │ │ │ │ ├── log 核心模块 - 日志处理
│ │ │ │ │ ├── msg 核心模块 - 信息
│ │ │ │ │ ├── options 核心模块 - 系统参数
│ │ │ │ │ ├── persistence 核心模块 - 查询条件构造器
│ │ │ │ │ │ └── querybuilder
│ │ │ │ │ │ └── chain 核心模块 - 查询条件构造器 - 责任链(例: 租户处理)
│ │ │ │ │ ├── security 核心模块 - 权限验证
│ │ │ │ │ │ ├── filter 拦截器
│ │ │ │ │ │ └── service 获取用户的Service
│ │ │ │ │ └── utils 核心模块 - 工具类
│ │ │ │ └── pligins 插件
│ │ │ │ └── oss 插件模块 - OSS文件存储
│ │ │ │
├── opsli-modulars 业务
│ ├── opsli-modulars-generator 代码生成器
@ -166,6 +170,11 @@
│ │ │ │ │ ├── area 系统模块 - 地域
│ │ │ │ │ ├── dict 系统模块 - 字典
│ │ │ │ │ ├── login 系统模块 - 登录
│ │ │ │ │ │ ├── dto 系统模块 - 登录 - DTO
│ │ │ │ │ │ ├── event 系统模块 - 登录 - 消息事件
│ │ │ │ │ │ ├── handler 系统模块 - 登录 - 前置、成功、失败处理器
│ │ │ │ │ │ ├── vo 系统模块 - 登录 - 返回数据
│ │ │ │ │ │ └──web 系统模块 - 登录 - 接口控制器
│ │ │ │ │ ├── logs 系统模块 - 日志
│ │ │ │ │ ├── menu 系统模块 - 菜单
│ │ │ │ │ ├── monitor 系统模块 - 系统监控
@ -176,11 +185,29 @@
│ │ │ │ │ └── user 系统模块 - 用户
│ │ │ │ │
│ │ │ │ └── tools 工具包
│ │ │ │ ├── searchhis 工具包 - 搜索历史
│ │ │ │ └── email 工具包 - 邮件包
│ │ │ │ ├── api 工具包 - 版本控制API测试类
│ │ │ │ ├── common 工具包 - 公共服务
│ │ │ │ ├── email 工具包 - 邮件包
│ │ │ │ ├── oss 工具包 - 文件存储
│ │ │ │ └── searchhis 工具包 - 搜索历史
│ │ │ │
├── opsli-plugins 插件
│ ├── opsli-plugins-ehcache Ehcache缓存插件 (二级缓存)
├── opsli-plugins 插件
│ ├── opsli-plugins-crypto 加解密插件包
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
│ │ │ │ │ └── org
│ │ │ │ │ └── opsli
│ │ │ │ │ └── plugins
│ │ │ │ │ └── crypto
│ │ │ │ │ ├── enums 加解密插件包 - 枚举
│ │ │ │ │ ├── exception 加解密插件包 - 异常处理类
│ │ │ │ │ ├── model 加解密插件包 - 模型
│ │ │ │ │ ├── msg 加解密插件包 - 异常消息
│ │ │ │ │ ├── spring 加解密插件包 - Spring集成相关内容
│ │ │ │ │ └── strategy 加解密插件包 - 加解密策略 包含 对称、非对称等等
│ │ │ │ │
│ ├── opsli-plugins-ehcache Ehcache缓存插件 (二级缓存)
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
@ -192,7 +219,21 @@
│ │ │ │ │ ├── msg Ehcache缓存插件 - 信息
│ │ │ │ │ └── service Ehcache缓存插件 - 服务
│ │ │ │ │
│ ├── opsli-plugins-excel Excel插件
│ ├── opsli-plugins-email 邮件插件包
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
│ │ │ │ │ └── org
│ │ │ │ │ └── opsli
│ │ │ │ │ └── plugins
│ │ │ │ │ └── email
│ │ │ │ │ ├── conf 邮件插件包 - 配置文件
│ │ │ │ │ ├── exception 邮件插件包 - 异常处理类
│ │ │ │ │ ├── msg 邮件插件包 - 异常消息
│ │ │ │ │ ├── service 邮件插件包 - 处理类
│ │ │ │ │ └── wrapper 邮件插件包 - 包装器
│ │ │ │ │
│ ├── opsli-plugins-excel Excel插件
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
@ -206,7 +247,7 @@
│ │ │ │ │ ├── listener Excel插件 - 监听器
│ │ │ │ │ └── msg Excel插件 - 信息
│ │ │ │ │
│ └── opsli-plugins-redis Redis缓存插件(一级缓存)
│ └── opsli-plugins-redis Redis缓存插件(一级缓存)
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
@ -216,6 +257,7 @@
│ │ │ │ │ └── redis
│ │ │ │ │ ├── conf Redis缓存插件 - 自动装配
│ │ │ │ │ ├── exception Redis缓存插件 - 异常类
│ │ │ │ │ ├── jsonserializer Redis缓存插件 - json特殊处理器
│ │ │ │ │ ├── lock Redis缓存插件 - 分布式锁
│ │ │ │ │ ├── msg Redis缓存插件 - 信息
│ │ │ │ │ ├── pushsub Redis缓存插件 - 消息订阅
@ -223,7 +265,7 @@
│ │ │ │ └── resources
│ │ │ │ │ └── lua Redis缓存插件 - Lua脚本
│ │ │ │ │
│ └── opsli-plugins-redisson Redisson分布式锁
│ └── opsli-plugins-redisson Redisson分布式锁
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
@ -238,7 +280,41 @@
│ │ │ │ │ ├── properties Redisson分布式锁 - 配置类
│ │ │ │ │ └── strategy Redisson分布式锁 - 策略
│ │ │ │ │
│ └── opsli-plugins-waf Waf软防火墙
│ ├── opsli-plugins-security 安全认证插件包
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
│ │ │ │ │ └── org
│ │ │ │ │ └── opsli
│ │ │ │ │ └── plugins
│ │ │ │ │ └── security
│ │ │ │ │ ├── authentication 安全认证插件包 - 识别器
│ │ │ │ │ ├── checker 安全认证插件包 - 检查器
│ │ │ │ │ ├── eventbus 安全认证插件包 - 消息事件
│ │ │ │ │ ├── eventdto 安全认证插件包 - 消息事件DTO
│ │ │ │ │ ├── exception 安全认证插件包 - 异常
│ │ │ │ │ ├── handler 安全认证插件包 - 登陆处理器
│ │ │ │ │ ├── properties 安全认证插件包 - 配置文件
│ │ │ │ │ ├── provider 安全认证插件包 - Security认证器
│ │ │ │ │ ├── service 安全认证插件包 - 加载用户信息抽象Service
│ │ │ │ │ ├── utils 安全认证插件包 - 工具包
│ │ │ │ │ └── vo 安全认证插件包 - VO
│ │ │ │ │
│ ├── opsli-plugins-sms 短信插件包
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
│ │ │ │ │ └── org
│ │ │ │ │ └── opsli
│ │ │ │ │ └── plugins
│ │ │ │ │ └── sms
│ │ │ │ │ ├── enums 短信插件包 - 配置文件
│ │ │ │ │ ├── exception 短信插件包 - 异常处理类
│ │ │ │ │ ├── model 短信插件包 - 模型
│ │ │ │ │ ├── msg 短信插件包 - 异常消息
│ │ │ │ │ └── service 短信插件包 - 服务处理
│ │ │ │ │
│ └── opsli-plugins-waf Waf软防火墙
│ ├── src
│ │ ├── main
│ │ │ ├── java

File diff suppressed because one or more lines are too long

@ -0,0 +1,14 @@
FROM mysql:8.0.19
MAINTAINER opsli.com
LABEL version=V1.3.3
LABEL description=OPSLI-快速开发平台
LABEL qqGroup=724850675
ENV TZ=Asia/Shanghai
# 切换为上海时区
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime \
&& echo $TZ > /etc/timezone
COPY ./opsli-boot.sql /docker-entrypoint-initdb.d

File diff suppressed because one or more lines are too long

@ -2,7 +2,7 @@ version: '3.3'
services:
# 构建 MySQL数据库 这里不指定数据库文件 防止误操作 等隐患问题
opsli-boot-mysql:
build: ./db-file
build: ./db-file/2.0版本
image: opsli-boot-mysql
restart: always
environment:
@ -57,4 +57,4 @@ services:
volumes:
- /www/wwwroot/demo.opsli.bedebug.com/backend/run:/usr/local/opsli/opsli-boot #挂载目录
ports:
- "7000:7000"
- "7000:7000"

@ -10,7 +10,7 @@ import java.io.Serializable;
/**
*
*
* @author
* @author Parker
* @date 2021-01-24 12:48
**/
@Data

@ -0,0 +1,42 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.base.encrypt;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.enums.ValidatorType;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2021-01-24 12:48
**/
@Data
public class EncryptModel implements Serializable {
private static final long serialVersionUID = 1L;
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(2000)
@ApiModelProperty(value = "加密数据")
private String encryptData;
}

@ -1,207 +0,0 @@
package org.opsli.api.base.result;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.http.HttpStatus;
import java.io.Serializable;
/**
* API
* Feign
* @JsonProperty null
*
* @date 202051510:40:54
* @author Parker
*/
@Data
@ApiModel(value="视图层返回Api对象",
description="视图层返回Api对象 success:成功状态 code:编号 msg:信息 timestamp:时间戳 data:数据")
public class ResultVo<T> implements Serializable {
private static final long serialVersionUID = 1L;
/** 默认成功信息 */
public static final String DEF_SUCCESS_MSG = "操作成功!";
/** 默认失败信息 */
public static final String DEF_ERROR_MSG = "操作失败!";
/** 成功状态 */
@ApiModelProperty(value = "成功状态")
@JsonProperty("success")
private boolean success;
/** 消息 */
@ApiModelProperty(value = "消息")
@JsonProperty("msg")
private String msg;
/** 状态码 */
@ApiModelProperty(value = "状态码")
@JsonProperty("code")
private Integer code;
/** 时间戳 */
@ApiModelProperty(value = "时间戳")
@JsonProperty("timestamp")
private Long timestamp;
/** 数据对象 */
@ApiModelProperty(value = "数据")
@JsonProperty("data")
private T data;
public T getData() {
return data;
}
public ResultVo<T> setData(T data) {
this.data = data;
return this;
}
/**
* Json
* @return String
*/
public String toJsonStr(){
return JSONObject.toJSONString(this);
}
// ===========================================
/**
*
*/
public ResultVo() {
// 初始化值
this.success = true;
this.msg = DEF_SUCCESS_MSG;
this.code = HttpStatus.OK.value();
this.timestamp = System.currentTimeMillis();
}
// ================================== 静态方法 ===================================
/**
*
* @return ResultVo<Object>
*/
@JsonIgnore
public static ResultVo<Object> success() {
return new ResultVo<>();
}
/**
*
* @param msg
* @return ResultVo<Object>
*/
@JsonIgnore
public static ResultVo<Object> success(String msg) {
ResultVo<Object> ret = new ResultVo<>();
ret.setMsg(msg);
return ret;
}
/**
*
* @param data
* @param <T>
* @return ResultVo<T>
*/
@JsonIgnore
public static <T> ResultVo<T> success(T data) {
ResultVo<T> ret = new ResultVo<>();
ret.setData(data);
return ret;
}
/**
*
* @param msg
* @param data
* @param <T>
* @return ResultVo<T>
*/
@JsonIgnore
public static <T> ResultVo<T> success(String msg, T data) {
ResultVo<T> ret = new ResultVo<>();
ret.setMsg(msg);
ret.setData(data);
return ret;
}
/**
*
* @param msg
* @param data
* @param <T>
* @return ResultVo<T>
*/
@JsonIgnore
public static <T> ResultVo<T> success(Integer code, String msg, T data) {
ResultVo<T> ret = new ResultVo<>();
ret.setCode(code);
ret.setMsg(msg);
ret.setData(data);
return ret;
}
/**
*
* @return ResultVo<Object>
*/
@JsonIgnore
public static ResultVo<Object> error() {
return ResultVo.error(
HttpStatus.INTERNAL_SERVER_ERROR.value()
, DEF_ERROR_MSG, null);
}
/**
*
* @param msg
* @return ResultVo<Object>
*/
@JsonIgnore
public static ResultVo<Object> error(String msg) {
return ResultVo.error(
HttpStatus.INTERNAL_SERVER_ERROR.value()
, msg, null);
}
/**
*
* @param code
* @param msg
* @return ResultVo<T>
*/
@JsonIgnore
public static ResultVo<Object> error(Integer code, String msg) {
return ResultVo.error(code, msg, null);
}
/**
*
* @param code
* @param data
* @param <T>
* @return ResultVo<T>
*/
@JsonIgnore
public static <T> ResultVo<T> error(Integer code, String msg, T data) {
ResultVo<T> ret = new ResultVo<>();
ret.setMsg(msg);
ret.setCode(code);
ret.setData(data);
ret.setSuccess(false);
return ret;
}
}

@ -0,0 +1,263 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.base.result;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;
import org.opsli.common.base.msg.BaseMsg;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2021123015:31:41
*/
@Data
@Builder
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "基础返回实体",
description="视图层返回Api对象 code:编号 msg:信息 timestamp:时间戳 data:数据")
public class ResultWrapper<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
@ApiModelProperty(name = "msg", dataType = "string", value = "响应信息")
private String msg;
/**
* 0-1
*/
@ApiModelProperty(name = "code", dataType = "int", value = "响应码")
private int code;
/**
*
*/
@ApiModelProperty(name = "data", dataType = "object", value = "数据内容")
private T data;
/**
*
*/
@ApiModelProperty(name = "timestamp", dataType = "long", value = "时间戳")
private long timestamp;
/**
* ,
* {@link StateCodeEnum#SUCCESS}
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getSuccessResultWrapperByMsg(String msg) {
return ResultWrapper.<T>builder()
.code(StateCodeEnum.SUCCESS.getCode())
.msg(msg)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* ,
* {@link StateCodeEnum#SUCCESS}
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getSuccessResultWrapper() {
return getSuccessResultWrapper(null);
}
/**
* ,
* {@link StateCodeEnum#SUCCESS}
* @param data
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getSuccessResultWrapper(T data) {
return ResultWrapper.<T>builder()
.code(StateCodeEnum.SUCCESS.getCode())
.msg(StateCodeEnum.SUCCESS.getMsg())
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
*
* {@link StateCodeEnum#ERROR}
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getErrorResultWrapper() {
return getErrorResultWrapper(null);
}
/**
*
* {@link StateCodeEnum#ERROR}
* @param data
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getErrorResultWrapper(T data) {
return ResultWrapper.<T>builder()
.code(StateCodeEnum.ERROR.getCode())
.msg(StateCodeEnum.ERROR.getMsg())
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* 便
* @param stateCode
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(StateCodeEnum stateCode) {
return getCustomResultWrapper(null, stateCode);
}
/**
* 便
* @param data
* @param stateCode
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(T data, StateCodeEnum stateCode) {
return ResultWrapper.<T>builder()
.code(stateCode.getCode())
.msg(stateCode.getMsg())
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* 便
* @param baseMsg
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(BaseMsg baseMsg) {
return getCustomResultWrapper(null, baseMsg);
}
/**
* 便
* @param data
* @param baseMsg
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(T data, BaseMsg baseMsg) {
return ResultWrapper.<T>builder()
.code(baseMsg.getCode())
.msg(baseMsg.getMessage())
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* 便
* {@link StateCodeEnum#SUCCESS}
* @param data
* @param code
* @param msg
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(T data, int code, String msg) {
return ResultWrapper.<T>builder()
.code(code)
.msg(msg)
.data(data)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* 便
* {@link StateCodeEnum#SUCCESS}
* @param code
* @param msg
* @param <T>
* @return ResultWrapper<T>
*/
public static <T> ResultWrapper<T> getCustomResultWrapper(int code, String msg) {
return ResultWrapper.<T>builder()
.code(code)
.msg(msg)
.data(null)
.timestamp(System.currentTimeMillis())
.build();
}
/**
* ,
* @param resultWrapper
* @param <T>
* @return boolean
*/
public static <T> boolean isSuccess(ResultWrapper<T> resultWrapper) {
if(null == resultWrapper){
return false;
}
return StateCodeEnum.SUCCESS.getCode() == resultWrapper.getCode();
}
/**
*
*
* @author Parker
* @date 2021123015:29:29
*/
@Getter
@AllArgsConstructor
public enum StateCodeEnum {
/** 请求状态枚举 */
SUCCESS(0, "请求成功"),
FAILURE(-1, "操作失败"),
ERROR(-1, "服务器异常");
private final int code;
private final String msg;
}
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.gentest.carinfo;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
@ -25,7 +25,7 @@ import org.opsli.api.wrapper.gentest.carinfo.TestCarModel;
/**
*
* Api
*
* API @GetMapping @PostMapping
* Mapping Controller
@ -33,98 +33,97 @@ import org.opsli.api.wrapper.gentest.carinfo.TestCarModel;
*
*
* @author Parker
* @date 2020-12-20 20:12:57
* @date 2022-08-06 23:53:30
*/
public interface TestCarRestApi {
/** 标题 */
String TITLE = "汽车信息管理";
String TITLE = "测试汽车";
/** 子标题 */
String SUB_TITLE = "汽车信息";
String SUB_TITLE = "测试汽车";
/**
*
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<TestCarModel> get(TestCarModel model);
ResultWrapper<TestCarModel> get(TestCarModel model);
/**
*
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
);
/**
*
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody TestCarModel model);
ResultWrapper<?> insert(@RequestBody TestCarModel model);
/**
*
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody TestCarModel model);
ResultWrapper<?> update(@RequestBody TestCarModel model);
/**
*
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(String ids);
/**
* Excel
*
* Token
*
* 使2
*
* socketJava
* response javascript alert
*
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param response response
* Excel
* @param request request
* @return ResultWrapper
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
@PostMapping("/importExcel")
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
}
}

@ -15,11 +15,8 @@
*/
package org.opsli.api.web.gentest.user;
import org.opsli.api.base.result.ResultVo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -48,20 +45,20 @@ public interface TestUserRestApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<TestUserModel> get(TestUserModel model);
ResultWrapper<TestUserModel> get(TestUserModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -70,56 +67,64 @@ public interface TestUserRestApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody TestUserModel model);
ResultWrapper<?> insert(@RequestBody TestUserModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody TestUserModel model);
ResultWrapper<?> update(@RequestBody TestUserModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.area;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.area.SysAreaModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -48,80 +48,57 @@ public interface SysAreaRestApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<SysAreaModel> get(SysAreaModel model);
ResultWrapper<SysAreaModel> get(SysAreaModel model);
/**
*
* @param parentId ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findTree")
ResultVo<?> findTree(String parentId);
ResultWrapper<?> findTree(String parentId);
/**
*
* @param deep
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findTreeAll")
ResultVo<?> findTreeAll(@RequestParam(name = "deep", defaultValue = "3", required = false) Integer deep);
ResultWrapper<?> findTreeAll(@RequestParam(name = "deep", defaultValue = "3", required = false) Integer deep);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody SysAreaModel model);
ResultWrapper<?> insert(@RequestBody SysAreaModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody SysAreaModel model);
ResultWrapper<?> update(@RequestBody SysAreaModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> delAll(String ids);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.dict;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.dict.DictModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -48,20 +48,20 @@ public interface DictApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<DictModel> get(DictModel model);
ResultWrapper<DictModel> get(DictModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -70,65 +70,42 @@ public interface DictApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody DictModel model);
ResultWrapper<?> insert(@RequestBody DictModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody DictModel model);
ResultWrapper<?> update(@RequestBody DictModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> delAll(String ids);
/**
*
*
* @param typeCode
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getDictListByCode")
ResultVo<?> getDictListByCode(String typeCode);
ResultWrapper<?> getDictListByCode(String typeCode);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.dict;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.dict.DictDetailModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -49,20 +49,20 @@ public interface DictDetailApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<DictDetailModel> get(DictDetailModel model);
ResultWrapper<DictDetailModel> get(DictDetailModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -71,57 +71,34 @@ public interface DictDetailApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody DictDetailModel model);
ResultWrapper<?> insert(@RequestBody DictDetailModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody DictDetailModel model);
ResultWrapper<?> update(@RequestBody DictDetailModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> delAll(String ids);
// ================================
@ -130,9 +107,9 @@ public interface DictDetailApi {
*
*
* @param typeCode
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findListByTypeCode")
ResultVo<List<DictDetailModel>> findListByTypeCode(String typeCode);
ResultWrapper<List<DictDetailModel>> findListByTypeCode(String typeCode);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.logs;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.logs.LogsModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -48,10 +48,10 @@ public interface LoginLogsApi {
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.logs;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.logs.LogsModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -45,20 +45,20 @@ public interface LogsApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<LogsModel> get(LogsModel model);
ResultWrapper<LogsModel> get(LogsModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -68,8 +68,8 @@ public interface LogsApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
ResultVo<?> insert(LogsModel model);
ResultWrapper<?> insert(LogsModel model);
}

@ -0,0 +1,92 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.web.system.logs;
import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.opsli.api.wrapper.system.logs.OperationLogModel;
/**
* Api
*
* API @GetMapping @PostMapping
* Mapping Controller
*
*
*
* @author Parker
* @date 2022-07-26 19:21:57
*/
public interface OperationLogRestApi {
/** 标题 */
String TITLE = "行为日志";
/** 子标题 */
String SUB_TITLE = "行为日志";
/**
*
* @param model
* @return ResultWrapper
*/
@GetMapping("/get")
ResultWrapper<OperationLogModel> get(OperationLogModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
);
/**
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.menu;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.menu.MenuFullModel;
import org.opsli.api.wrapper.system.menu.MenuModel;
import org.springframework.web.bind.annotation.GetMapping;
@ -52,71 +52,71 @@ public interface MenuApi {
*
*
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findMenuTreePage")
ResultVo<?> findMenuTreePage(HttpServletRequest request);
ResultWrapper<?> findMenuTreePage(HttpServletRequest request);
/**
*
*
* @param parentId ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findMenuTreePageByLazy")
ResultVo<?> findMenuTreePageByLazy(String parentId);
ResultWrapper<?> findMenuTreePageByLazy(String parentId);
/**
*
* @param parentId ID
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findMenuTreeByLazy")
ResultVo<?> findMenuTreeByLazy(String parentId, String id);
ResultWrapper<?> findMenuTreeByLazy(String parentId, String id);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/findMenuTree")
ResultVo<?> findMenuTree();
ResultWrapper<?> findMenuTree();
/**
* -
*
* @param label
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getMenuAndPermsTree")
ResultVo<?> getMenuAndPermsTree(String label);
ResultWrapper<?> getMenuAndPermsTree(String label);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findList")
ResultVo<List<MenuModel>> findList();
ResultWrapper<List<MenuModel>> findList();
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<MenuModel> get(MenuModel model);
ResultWrapper<MenuModel> get(MenuModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -125,58 +125,34 @@ public interface MenuApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody MenuModel model);
ResultWrapper<?> insert(@RequestBody MenuModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody MenuModel model);
ResultWrapper<?> update(@RequestBody MenuModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> delAll(String ids);
// ================= 普通
@ -184,14 +160,14 @@ public interface MenuApi {
/**
*
* @param permissions
* @return ResultVo
* @return ResultWrapper
*/
ResultVo<MenuModel> getByPermissions(String permissions);
ResultWrapper<MenuModel> getByPermissions(String permissions);
/**
*
* @param menuFullModel
* @return ResultVo
* @return ResultWrapper
*/
ResultVo<?> saveMenuByFull(@RequestBody MenuFullModel menuFullModel);
ResultWrapper<?> saveMenuByFull(@RequestBody MenuFullModel menuFullModel);
}

@ -17,11 +17,8 @@
package org.opsli.api.web.system.options;
import org.opsli.api.base.result.ResultVo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -55,20 +52,20 @@ public interface OptionsApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<OptionsModel> get(OptionsModel model);
ResultWrapper<OptionsModel> get(OptionsModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -77,108 +74,105 @@ public interface OptionsApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody OptionsModel model);
ResultWrapper<?> insert(@RequestBody OptionsModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody OptionsModel model);
ResultWrapper<?> update(@RequestBody OptionsModel model);
/**
*
* @param params Map
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/updateOptions")
ResultVo<?> updateOptions(@RequestBody Map<String, String> params);
ResultWrapper<?> updateOptions(@RequestBody Map<String, String> params);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(String ids);
/**
* Excel
*
* Token
*
* 使2
*
* socketJava
* response javascript alert
*
* @param request request
* @param response response
* @return ResultVo
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
* @return ResultVo
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
// ==========================
/**
*
* @param optionCode
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getByCode")
ResultVo<OptionsModel> getByCode(String optionCode);
//@GetMapping("/getByCode")
ResultWrapper<OptionsModel> getByCode(String optionCode);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findAllOptions")
ResultVo<Map<String, OptionsModel>> findAllOptions();
ResultWrapper<Map<String, OptionsModel>> findAllOptions();
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findAll")
ResultVo<List<OptionsModel>> findAll();
//@GetMapping("/findAll")
ResultWrapper<List<OptionsModel>> findAll();
/**
*
*
* @param type
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/createCrypto")
ResultVo<?> createCrypto(String type);
ResultWrapper<?> createCrypto(String type);
}

@ -15,11 +15,8 @@
*/
package org.opsli.api.web.system.org;
import org.opsli.api.base.result.ResultVo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.opsli.api.base.result.ResultWrapper;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -50,90 +47,67 @@ public interface SysOrgRestApi {
*
* @param parentId ID
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findTreeLazy")
ResultVo<?> findTreeLazy(String parentId, String id);
ResultWrapper<?> findTreeLazy(String parentId, String id);
/**
*
* @param isGen
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findTreeByDef")
ResultVo<?> findTreeByDef(boolean isGen, String id);
ResultWrapper<?> findTreeByDef(boolean isGen, String id);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findTreeByDefWithUserToLike")
ResultVo<?> findTreeByDefWithUserToLike();
ResultWrapper<?> findTreeByDefWithUserToLike();
// ================
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<SysOrgModel> get(SysOrgModel model);
ResultWrapper<SysOrgModel> get(SysOrgModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody SysOrgModel model);
ResultWrapper<?> insert(@RequestBody SysOrgModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody SysOrgModel model);
ResultWrapper<?> update(@RequestBody SysOrgModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
/**
* Excel
* @param request request
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> delAll(String ids);
}

@ -15,12 +15,9 @@
*/
package org.opsli.api.web.system.role;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.role.RoleModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
@ -48,20 +45,20 @@ public interface RoleApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<RoleModel> get(RoleModel model);
ResultWrapper<RoleModel> get(RoleModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -70,56 +67,63 @@ public interface RoleApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody RoleModel model);
ResultWrapper<?> insert(@RequestBody RoleModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody RoleModel model);
ResultWrapper<?> update(@RequestBody RoleModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(String ids);
/**
* Excel
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.role;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.role.RoleMenuRefModel;
import org.opsli.api.wrapper.system.role.RoleModel;
import org.springframework.web.bind.annotation.GetMapping;
@ -49,18 +49,18 @@ public interface RoleMenuRefApi {
/**
*
* @param model Id
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getPerms")
ResultVo<?> getPerms(RoleMenuRefModel model);
ResultWrapper<?> getPerms(RoleMenuRefModel model);
/**
*
* @param model roleId Id
* @param model permsIds Id
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/setPerms")
ResultVo<?> setPerms(@RequestBody RoleMenuRefModel model);
ResultWrapper<?> setPerms(@RequestBody RoleMenuRefModel model);
}

@ -15,12 +15,9 @@
*/
package org.opsli.api.web.system.tenant;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.tenant.TenantModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
@ -48,20 +45,20 @@ public interface TenantApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<TenantModel> get(TenantModel model);
ResultWrapper<TenantModel> get(TenantModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -70,57 +67,65 @@ public interface TenantApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody TenantModel model);
ResultWrapper<?> insert(@RequestBody TenantModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody TenantModel model);
ResultWrapper<?> update(@RequestBody TenantModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(String ids);
/**
* Excel
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
/**
@ -128,18 +133,18 @@ public interface TenantApi {
*
* @param tenantId ID
* @param enable
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/enableTenant")
ResultVo<?> enableTenant(String tenantId, String enable);
ResultWrapper<?> enableTenant(String tenantId, String enable);
// =========================
/**
*
* @param tenantId
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getTenantByUsable")
ResultVo<TenantModel> getTenantByUsable(String tenantId);
ResultWrapper<TenantModel> getTenantByUsable(String tenantId);
}

@ -15,14 +15,12 @@
*/
package org.opsli.api.web.system.user;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.encrypt.EncryptModel;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.menu.MenuModel;
import org.opsli.api.wrapper.system.role.RoleModel;
import org.opsli.api.wrapper.system.user.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
@ -51,97 +49,123 @@ public interface UserApi {
/**
*
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getInfo")
ResultVo<UserInfo> getInfo(HttpServletRequest request);
ResultWrapper<UserInfo> getInfo(HttpServletRequest request);
/**
*
*
* @param userId ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getInfoById")
ResultVo<UserInfo> getInfoById(String userId);
ResultWrapper<UserInfo> getInfoById(String userId);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getOrg")
ResultVo<?> getOrg();
ResultWrapper<?> getOrg();
/**
*
*
* @param userId ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getOrgByUserId")
ResultVo<?> getOrgByUserId(String userId);
ResultWrapper<?> getOrgByUserId(String userId);
/**
* userId Id
* @param userId Id
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getRoleIdsByUserId")
ResultVo<List<String>> getRoleIdsByUserId(String userId);
ResultWrapper<List<String>> getRoleIdsByUserId(String userId);
/**
* ID
*
* @param encryptModel
* @return ResultVo
*/
@PostMapping("/updatePasswordById")
ResultWrapper<?> updatePasswordById(@RequestBody EncryptModel encryptModel);
/**
*
* @param userPassword
* @return ResultVo
* @param encryptModel
* @return ResultWrapper
*/
@PostMapping("/updatePassword")
ResultVo<?> updatePassword(@RequestBody UserPassword userPassword);
ResultWrapper<?> updatePassword(@RequestBody EncryptModel encryptModel);
/**
* ID
*
* @param userPassword
* @return ResultVo
*
* @param encryptModel
* @return ResultWrapper
*/
@PostMapping("/updatePasswordById")
ResultVo<?> updatePasswordById(@RequestBody ToUserPassword userPassword);
@PostMapping("/updateEmail")
ResultWrapper<?> updateEmail(@RequestBody EncryptModel encryptModel);
/**
*
* @param encryptModel
* @return ResultWrapper
*/
@PostMapping("/updateMobile")
ResultWrapper<?> updateMobile(@RequestBody EncryptModel encryptModel);
/**
* ID
*
* @param userId ID
* @return ResultVo
* @param encryptModel ID
* @return ResultWrapper
*/
@PostMapping("/resetPasswordById")
ResultVo<?> resetPasswordById(String userId);
ResultWrapper<?> resetPasswordById(@RequestBody EncryptModel encryptModel);
/**
*
*
* @param userId ID
* @param enable
* @return ResultVo
* @param encryptModel EnableUserModel
* @return ResultWrapper
*/
@PostMapping("/enableAccount")
ResultVo<?> enableAccount(String userId, String enable);
ResultWrapper<?> enableAccount(@RequestBody EncryptModel encryptModel);
/**
*
*
* @param encryptModel
* @return ResultWrapper
*/
@PostMapping("/updatePasswordByForget")
ResultWrapper<?> updatePasswordByForget(@RequestBody EncryptModel encryptModel);
/**
*
* @param userAvatarModel
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/updateAvatar")
ResultVo<?> updateAvatar(@RequestBody UserAvatarModel userAvatarModel);
ResultWrapper<?> updateAvatar(@RequestBody UserAvatarModel userAvatarModel);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<UserModel> get(UserModel model);
ResultWrapper<UserModel> get(UserModel model);
/**
*
@ -149,10 +173,10 @@ public interface UserApi {
* @param pageSize
* @param orgIdGroup ID
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
@RequestParam(name = "orgIdGroup") String orgIdGroup,
@ -164,10 +188,10 @@ public interface UserApi {
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPageByTenant")
ResultVo<?> findPageByTenant(
ResultWrapper<?> findPageByTenant(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -178,91 +202,114 @@ public interface UserApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody UserModel model);
ResultWrapper<?> insert(@RequestBody UserModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody UserModel model);
ResultWrapper<?> update(@RequestBody UserModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/updateSelf")
ResultVo<?> updateSelf(@RequestBody UserModel model);
ResultWrapper<?> updateSelf(@RequestBody UserModel model);
/**
*
* @param id ID
* @return ResultVo
* @param encryptModel id ID
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(@RequestBody EncryptModel encryptModel);
/**
*
* @param ids ID
* @return ResultVo
* @param encryptModel ids ID
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(@RequestBody EncryptModel encryptModel);
/**
* Excel
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
/**
*
* @param tenantId ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/switchTenant")
ResultVo<?> switchTenant(String tenantId);
ResultWrapper<?> switchTenant(String tenantId);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/switchOneself")
ResultVo<?> switchOneself();
ResultWrapper<?> switchOneself();
/**
* username
* @param username
* @return ResultVo
* @return ResultWrapper
*/
//@GetMapping("/getUserByUsername")
ResultVo<UserModel> getUserByUsername(String username);
ResultWrapper<UserModel> getUserByUsername(String username);
/**
*
* @param mobile
* @return ResultWrapper
*/
ResultWrapper<UserModel> getUserByMobile(String mobile);
/**
*
* @param email
* @return ResultWrapper
*/
ResultWrapper<UserModel> getUserByEmail(String email);

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.user;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.org.SysOrgModel;
import org.opsli.api.wrapper.system.user.UserOrgRefModel;
import org.opsli.api.wrapper.system.user.UserOrgRefWebModel;
@ -47,25 +47,25 @@ public interface UserOrgRefApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/setOrg")
ResultVo<?> setOrg(@RequestBody UserOrgRefWebModel model);
ResultWrapper<?> setOrg(@RequestBody UserOrgRefWebModel model);
/**
* ID
* @param userId ID
* @return List
*/
ResultVo<List<UserOrgRefModel>> findListByUserId(String userId);
ResultWrapper<List<UserOrgRefModel>> findListByUserId(String userId);
/**
* userId
* @param userId Id
* @return ResultVo
* @return ResultWrapper
*/
//@GetMapping("/getRolesByUserId")
ResultVo<UserOrgRefModel> getDefOrgByUserId(String userId);
ResultWrapper<UserOrgRefModel> getDefOrgByUserId(String userId);
}

@ -15,7 +15,7 @@
*/
package org.opsli.api.web.system.user;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.system.menu.MenuModel;
import org.opsli.api.wrapper.system.role.RoleMenuRefModel;
import org.opsli.api.wrapper.system.role.RoleModel;
@ -48,50 +48,50 @@ public interface UserRoleRefApi {
/**
*
* @param userId ID
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/getRoles")
ResultVo<?> getRoles(String userId);
ResultWrapper<?> getRoles(String userId);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/setRoles")
ResultVo<?> setRoles(@RequestBody UserRoleRefModel model);
ResultWrapper<?> setRoles(@RequestBody UserRoleRefModel model);
/**
* userId
* @param userId Id
* @return ResultVo
* @return ResultWrapper
*/
//@GetMapping("/getRolesByUserId")
ResultVo<List<String>> getRolesByUserId(String userId);
ResultWrapper<List<String>> getRolesByUserId(String userId);
/**
* userId
* @param userId Id
* @return ResultVo
* @return ResultWrapper
*/
//@GetMapping("/getRolesByUserId")
ResultVo<RoleModel> getDefRoleByUserId(String userId);
ResultWrapper<RoleModel> getDefRoleByUserId(String userId);
/**
* userId
* @param userId Id
* @return ResultVo
* @return ResultWrapper
*/
//@GetMapping("/queryAllPerms")
ResultVo<List<String>> getAllPerms(String userId);
ResultWrapper<List<String>> getAllPerms(String userId);
/**
* userId
* @param userId Id
* @return ResultVo
* @return ResultWrapper
*/
//@GetMapping("/queryAllPerms")
ResultVo<List<MenuModel>> getMenuListByUserId(String userId);
ResultWrapper<List<MenuModel>> getMenuListByUserId(String userId);
}

@ -1,8 +1,9 @@
package org.opsli.api.web.test;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.test.TestModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest;
@ -28,93 +29,93 @@ public interface TestApi {
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/sendMail")
ResultVo<?> sendMail();
ResultWrapper<?> sendMail();
/**
* Redis
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/sendMsg")
ResultVo<?> sendMsg();
ResultWrapper<?> sendMsg();
/**
* Redis
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/redisTest")
ResultVo<?> redisTest();
ResultWrapper<?> redisTest();
/**
* Redis
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/testLock")
ResultVo<?> testLock();
ResultWrapper<?> testLock();
/**
*
* @param entity entity
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/insert")
ResultVo<TestModel> insert(TestModel entity);
ResultWrapper<TestModel> insert(TestModel entity);
/**
*
* @param entity entity
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/update")
ResultVo<TestModel> update(TestModel entity);
ResultWrapper<TestModel> update(TestModel entity);
/**
*
* @param entity entity
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<TestModel> get(TestModel entity);
ResultWrapper<TestModel> get(TestModel entity);
/**
*
* @param id id
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/delAll")
ResultVo<?> delAll();
ResultWrapper<?> delAll();
/**
*
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findList")
ResultVo<List<TestModel>> findList(HttpServletRequest request);
ResultWrapper<List<TestModel>> findList(HttpServletRequest request);
/**
*
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findAllList")
ResultVo<List<TestModel>> findAllList();
ResultWrapper<List<TestModel>> findAllList();
/**
@ -123,10 +124,10 @@ public interface TestApi {
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -134,29 +135,36 @@ public interface TestApi {
/**
* Excel
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
*
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
*
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
}

@ -15,12 +15,9 @@
*/
package org.opsli.api.web.test;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.wrapper.test.TestModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
@ -48,20 +45,20 @@ public interface TestRestApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/get")
ResultVo<TestModel> get(TestModel model);
ResultWrapper<TestModel> get(TestModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
ResultWrapper<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
@ -70,56 +67,65 @@ public interface TestRestApi {
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/insert")
ResultVo<?> insert(@RequestBody TestModel model);
ResultWrapper<?> insert(@RequestBody TestModel model);
/**
*
* @param model
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/update")
ResultVo<?> update(@RequestBody TestModel model);
ResultWrapper<?> update(@RequestBody TestModel model);
/**
*
* @param id ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/del")
ResultVo<?> del(String id);
ResultWrapper<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String ids);
ResultWrapper<?> delAll(String ids);
/**
* Excel
* Excel
*
* @param type
* @param request request
*/
@GetMapping("/excel/auth/{type}")
ResultWrapper<String> exportExcelAuth(
@PathVariable("type") String type,
HttpServletRequest request);
/**
* Excel
*
* @param certificate
* @param response response
*/
@GetMapping("/exportExcel")
void exportExcel(HttpServletRequest request, HttpServletResponse response);
@GetMapping("/excel/export/{certificate}")
void exportExcel(
@PathVariable("certificate") String certificate,
HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
@PostMapping("/importExcel")
ResultVo<?> importExcel(MultipartHttpServletRequest request);
ResultWrapper<?> importExcel(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
*/
@GetMapping("/importExcel/template")
void importTemplate(HttpServletResponse response);
}

@ -15,6 +15,7 @@
*/
package org.opsli.api.wrapper.gentest.carinfo;
import java.math.BigDecimal;
import java.util.Date;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModelProperty;
@ -23,17 +24,18 @@ import lombok.EqualsAndHashCode;
import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.annotation.validator.ValidatorLenMin;
import org.opsli.common.enums.ValidatorType;
import org.opsli.plugins.excel.annotation.ExcelInfo;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
*
*
* @author Parker
* @date 2020-12-20 20:12:57
*/
* Model
*
* @author Parker
* @date 2022-08-06 23:53:30
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class TestCarModel extends ApiWrapper {
@ -42,7 +44,10 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "汽车名称")
@ExcelProperty(value = "汽车名称", order = 1)
@ExcelInfo
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_GENERAL_WITH_CHINESE})
@Validator({
ValidatorType.IS_GENERAL_WITH_CHINESE,
ValidatorType.IS_NOT_NULL
})
@ValidatorLenMax(20)
private String carName;
@ -50,7 +55,10 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "汽车类型")
@ExcelProperty(value = "汽车类型", order = 2)
@ExcelInfo
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_GENERAL_WITH_CHINESE})
@Validator({
ValidatorType.IS_GENERAL_WITH_CHINESE,
ValidatorType.IS_NOT_NULL
})
@ValidatorLenMax(20)
private String carType;
@ -58,7 +66,9 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "汽车品牌")
@ExcelProperty(value = "汽车品牌", order = 3)
@ExcelInfo
@Validator({ValidatorType.IS_GENERAL_WITH_CHINESE})
@Validator({
ValidatorType.IS_GENERAL_WITH_CHINESE
})
@ValidatorLenMax(50)
private String carBrand;
@ -66,6 +76,9 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "生产日期")
@ExcelProperty(value = "生产日期", order = 4)
@ExcelInfo
@Validator({
ValidatorType.IS_NOT_NULL
})
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date produceData;
@ -74,9 +87,12 @@ public class TestCarModel extends ApiWrapper {
@ApiModelProperty(value = "是否启用")
@ExcelProperty(value = "是否启用", order = 5)
@ExcelInfo( dictType = "no_yes" )
@Validator({
ValidatorType.IS_NOT_NULL
})
@ValidatorLenMax(1)
private String izUsable;
}
}

@ -71,4 +71,10 @@ public class LoginLogsModel extends ApiWrapper {
@ApiModelProperty(value = "用户代理")
private String userAgent;
/**
*
*/
@ApiModelProperty(value = "登陆来源")
private String loginFrom;
}

@ -0,0 +1,132 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.logs;
import java.math.BigDecimal;
import java.util.Date;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.annotation.validator.ValidatorLenMin;
import org.opsli.common.enums.ValidatorType;
import org.opsli.plugins.excel.annotation.ExcelInfo;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* Model
*
* @author Parker
* @date 2022-07-26 19:21:57
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class OperationLogModel extends ApiWrapper {
/** 多租户字段 */
private String tenantId;
/** 日志等级 */
@ApiModelProperty(value = "日志等级")
@ExcelProperty(value = "日志等级", order = 1)
@ExcelInfo( dictType = "log_level" )
@ValidatorLenMax(8)
private String level;
/** 被操作的系统模块 */
@ApiModelProperty(value = "被操作的系统模块")
@ExcelProperty(value = "被操作的系统模块", order = 2)
@ExcelInfo( dictType = "log_model_type" )
@ValidatorLenMax(20)
private String moduleId;
/** 方法名 */
@ApiModelProperty(value = "方法名")
@ExcelProperty(value = "方法名", order = 3)
@ExcelInfo
@ValidatorLenMax(100)
private String method;
/** 参数 */
@ApiModelProperty(value = "参数")
@ExcelProperty(value = "参数", order = 4)
@ExcelInfo
@ValidatorLenMax(20000)
private String args;
/** 操作人id */
@ApiModelProperty(value = "操作人id")
@ExcelProperty(value = "操作人id", order = 5)
@ExcelInfo
@ValidatorLenMax(19)
private String userId;
/** 操作账号 */
@ApiModelProperty(value = "操作账号")
@ExcelProperty(value = "操作账号", order = 6)
@ExcelInfo
@ValidatorLenMax(32)
private String username;
/** 操作人真实名称 */
@ApiModelProperty(value = "操作人真实名称")
@ExcelProperty(value = "操作人真实名称", order = 7)
@ExcelInfo
@ValidatorLenMax(50)
private String realName;
/** 日志描述 */
@ApiModelProperty(value = "日志描述")
@ExcelProperty(value = "日志描述", order = 8)
@ExcelInfo
@ValidatorLenMax(255)
private String description;
/** 操作类型 */
@ApiModelProperty(value = "操作类型")
@ExcelProperty(value = "操作类型", order = 9)
@ExcelInfo( dictType = "log_operation_type" )
@ValidatorLenMax(20)
private String operationType;
/** 方法运行时间 */
@ApiModelProperty(value = "方法运行时间")
@ExcelProperty(value = "方法运行时间", order = 10)
@ExcelInfo
@ValidatorLenMax(19)
private String runTime;
/** 方法返回值 */
@ApiModelProperty(value = "方法返回值")
@ExcelProperty(value = "方法返回值", order = 11)
@ExcelInfo
@ValidatorLenMax(20000)
private String returnValue;
/** 日志请求类型 */
@ApiModelProperty(value = "日志请求类型")
@ExcelProperty(value = "日志请求类型", order = 12)
@ExcelInfo( dictType = "log_type" )
@ValidatorLenMax(8)
private String logType;
}

@ -38,8 +38,8 @@ import org.opsli.plugins.excel.annotation.ExcelInfo;
@EqualsAndHashCode(callSuper = false)
public class OptionsModel extends ApiWrapper {
/** 参数编号 */
@ApiModelProperty(value = "参数编号")
@ExcelProperty(value = "参数编号", order = 1)
@ -57,21 +57,21 @@ public class OptionsModel extends ApiWrapper {
/** 参数值 */
@ApiModelProperty(value = "参数值")
@ExcelProperty(value = "参数值", order = 3)
@ExcelProperty(value = "参数值", order = 4)
@ExcelInfo
@ValidatorLenMax(10000)
private String optionValue;
/** 是否内置数据 0否 1是*/
@ApiModelProperty(value = "是否内置数据 0否 1是")
@ExcelProperty(value = "是否内置数据", order = 4)
@ExcelProperty(value = "是否内置数据", order = 5)
@ExcelInfo(dictType = "no_yes")
@ValidatorLenMax(1)
private String izLock;
/** 备注 */
@ApiModelProperty(value = "备注")
@ExcelProperty(value = "备注", order = 5)
@ExcelProperty(value = "备注", order = 6)
@ExcelInfo
@ValidatorLenMax(255)
private String remark;

@ -0,0 +1,42 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.user;
import lombok.Data;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.enums.ValidatorType;
/**
*
*
* @author Parker
* @date 2022-07-16 8:14 PM
**/
@Data
public class EnableUserModel {
/** 主键 */
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(50)
private String userId;
/** 是否启用 */
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(10)
private String enabled;
}

@ -51,12 +51,6 @@ public class ToUserPassword implements Serializable {
@ValidatorLenMax(50)
private String newPassword;
/** 盐值,密码秘钥 前端不可改*/
@ApiModelProperty(value = "盐值,密码秘钥 前端不可改")
@ExcelIgnore
@ValidatorLenMax(50)
private String salt;
/** 登录密码强度 前端不可改 */
@ApiModelProperty(value = "登录密码强度 前端不可改")
@ExcelIgnore

@ -0,0 +1,46 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.user;
import lombok.Data;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.enums.ValidatorType;
/**
*
*
* @author Parker
* @date 2022-07-16 8:14 PM
**/
@Data
public class UpdateUserEmailModel {
/** 主键 */
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_EMAIL})
@ValidatorLenMax(50)
private String email;
/** 验证码 */
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(20)
private String verificationCode;
/** 凭证 */
@Validator({ValidatorType.IS_NOT_NULL})
private String certificate;
}

@ -0,0 +1,46 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.user;
import lombok.Data;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.enums.ValidatorType;
/**
*
*
* @author Parker
* @date 2022-07-16 8:14 PM
**/
@Data
public class UpdateUserMobileModel {
/** 主键 */
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_MOBILE})
@ValidatorLenMax(50)
private String mobile;
/** 验证码 */
@Validator({ValidatorType.IS_NOT_NULL})
@ValidatorLenMax(20)
private String verificationCode;
/** 凭证 */
@Validator({ValidatorType.IS_NOT_NULL})
private String certificate;
}

@ -0,0 +1,53 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.api.wrapper.system.user;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.annotation.validator.ValidatorLenMax;
import org.opsli.common.annotation.validator.ValidatorLenMin;
import org.opsli.common.enums.ValidatorType;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2020-09-16 17:33
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ExcelIgnoreUnannotated
public class UpdateUserPasswordByForgetModel implements Serializable {
private static final long serialVersionUID = 1L;
/** 新密码 */
@ApiModelProperty(value = "新密码")
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_SECURITY_PASSWORD})
@ValidatorLenMin(6)
@ValidatorLenMax(50)
private String newPassword;
/** 凭证 */
@Validator({ValidatorType.IS_NOT_NULL})
private String certificate;
}

@ -56,12 +56,12 @@ public class UserInfo extends ApiWrapper {
/** 手机 */
@ApiModelProperty(value = "手机")
@Validator({ValidatorType.IS_MOBILE})
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_MOBILE})
private String mobile;
/** 邮箱 */
@ApiModelProperty(value = "邮箱")
@Validator({ValidatorType.IS_EMAIL})
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_EMAIL})
private String email;
/** 工号 */

@ -60,12 +60,6 @@ public class UserModel extends ApiWrapper {
@ValidatorLenMax(1)
private String passwordLevel;
/** 盐值,密码秘钥 */
@ApiModelProperty(value = "盐值,密码秘钥")
@ExcelIgnore
@ValidatorLenMax(50)
private String secretKey;
/** 是否启用 */
@ApiModelProperty(value = "是否启用")
@ExcelIgnore
@ -84,14 +78,14 @@ public class UserModel extends ApiWrapper {
@ApiModelProperty(value = "手机")
@ExcelProperty(value = "手机", order = 2)
@ExcelInfo
@Validator({ValidatorType.IS_MOBILE})
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_MOBILE})
private String mobile;
/** 邮箱 */
@ApiModelProperty(value = "邮箱")
@ExcelProperty(value = "邮箱", order = 3)
@ExcelInfo
@Validator({ValidatorType.IS_EMAIL})
@Validator({ValidatorType.IS_NOT_NULL, ValidatorType.IS_EMAIL})
@ValidatorLenMax(100)
private String email;

@ -58,12 +58,6 @@ public class UserPassword implements Serializable {
@ValidatorLenMax(50)
private String newPassword;
/** 盐值,密码秘钥 前端不可改*/
@ApiModelProperty(value = "盐值,密码秘钥 前端不可改")
@ExcelIgnore
@ValidatorLenMax(50)
private String salt;
/** 登录密码强度 前端不可改 */
@ApiModelProperty(value = "登录密码强度 前端不可改")
@ExcelIgnore

@ -64,12 +64,6 @@ public class UserWebModel extends ApiWrapper {
@ValidatorLenMax(1)
private String passwordLevel;
/** 盐值,密码秘钥 */
@ApiModelProperty(value = "盐值,密码秘钥")
@ExcelIgnore
@ValidatorLenMax(50)
private String secretKey;
/** 启用状态 */
@ApiModelProperty(value = "启用状态")
@ExcelIgnore

@ -22,4 +22,4 @@
</dependencies>
</project>
</project>

@ -70,13 +70,20 @@ public class ResultVoMap extends HashMap<String,Object> implements Serializable
// -------------------------------------------
@JsonIgnore//返回对象时忽略此属性
/**
*
*/
@JsonIgnore
public static ResultVoMap success(String msg) {
ResultVoMap j = new ResultVoMap();
j.setMsg(msg);
return j;
}
@JsonIgnore//返回对象时忽略此属性
/**
*
*/
@JsonIgnore//
public static ResultVoMap error(String msg) {
ResultVoMap j = new ResultVoMap();
j.setSuccess(false);
@ -84,14 +91,20 @@ public class ResultVoMap extends HashMap<String,Object> implements Serializable
return j;
}
@JsonIgnore//返回对象时忽略此属性
/**
*
*/
@JsonIgnore
public static ResultVoMap success(Map<String, Object> map) {
ResultVoMap restResponse = new ResultVoMap();
restResponse.putAll(map);
return restResponse;
}
@JsonIgnore//返回对象时忽略此属性
/**
*
*/
@JsonIgnore
public static ResultVoMap success() {
return new ResultVoMap();
}

@ -3,7 +3,7 @@ package org.opsli.common.constants;
/**
* Redis
* {}
* @author
* @author Parker
* @date 2021/12/10 19:52
*/
public final class RedisConstants {
@ -47,9 +47,12 @@ public final class RedisConstants {
/** 用户ID 和 菜单 */
public static final String PREFIX_USER_ID_MENUS = "kv#{}:user_id:menus:";
/** 用户名 */
public static final String PREFIX_USERNAME = "kv#{}:username:";
/** 用户名 + 用户ID */
public static final String PREFIX_USER_USERNAME = "kv#{}:user:username_id:";
/** 手机号 + 用户ID */
public static final String PREFIX_USER_MOBILE = "kv#{}:user:mobile_id:";
/** 邮箱 + 用户ID */
public static final String PREFIX_USER_EMAIL = "kv#{}:user:email_id:";
/** 票据 */
@ -61,8 +64,21 @@ public final class RedisConstants {
/** 账号失败锁定KEY */
public static final String PREFIX_ACCOUNT_SLIP_LOCK = "kv#{}:account:slip:lock:";
/** 临时邮箱验证码 */
public static final String PREFIX_TMP_EMAIL_CODE_NAME = "kv#{}:verification:email:code:";
/** 临时手机验证码 */
public static final String PREFIX_TMP_MOBILE_CODE_NAME = "kv#{}:verification:mobile:code:";
/** 验证码凭证 用于验证码二次校验(唯一流水号 increment) */
public static final String PREFIX_TMP_VERIFICATION_CERTIFICATE_NUM_NAME = "kv#{}:verification:certificate-num";
/** 验证码凭证 用于验证码二次校验 */
public static final String PREFIX_TMP_VERIFICATION_CERTIFICATE_NAME = "kv#{}:verification:certificate:";
/** Excel 导出(唯一流水号 increment) */
public static final String PREFIX_TMP_EXCEL_EXPORT_NUM_NAME = "kv#{}:excel-export-num";
/** Excel 导出 凭证 */
public static final String PREFIX_TMP_EXCEL_EXPORT_NAME = "kv#{}:excel-export:";
private RedisConstants(){}
}

@ -17,6 +17,9 @@ public final class SignConstants {
/** 租户ID */
public static final String TENANT_ID = "tenantId";
/** 登陆来源 */
public static final String LOGIN_FROM = "loginFrom";
/** 时间戳 */
public static final String TIMESTAMP = "timestamp";

@ -19,7 +19,7 @@ package org.opsli.common.enums;
/**
*
*
* @author :
* @author : Parker
* @date : 2020-09-17 23:40
*/
public enum DictType {

@ -0,0 +1,77 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.enums;
import cn.hutool.core.bean.BeanUtil;
import java.util.Arrays;
/**
*
*
* @author
* @date 2020-09-17 23:40
*/
public enum LoginFromEnum {
/** 账号 */
PC("0"),
/** APP - 安卓 */
APP_ANDROID("1"),
/** APP - 苹果 */
APP_IOS("2"),
/** 微信小程序 */
WX_APPLET("3"),
/** h5 */
H5("4"),
/** 未知 */
UNKNOWN("-1"),
;
private final static String FILED_NAME = "loginFrom";
/***/
private final String type;
LoginFromEnum(String type){
this.type = type;
}
public String getType() {
return this.type;
}
public static LoginFromEnum getByCode(String code){
return Arrays.stream(LoginFromEnum.values())
.filter(value -> value.getType().equals(code))
.findFirst().orElse(LoginFromEnum.UNKNOWN);
}
public static LoginFromEnum getByBean(Object bean){
if(null == bean || !BeanUtil.isBean(bean.getClass())){
return LoginFromEnum.UNKNOWN;
}
Object fieldValue = BeanUtil.getFieldValue(bean, FILED_NAME);
if(null == fieldValue){
return LoginFromEnum.UNKNOWN;
}
return getByCode((String) fieldValue);
}
}

@ -0,0 +1,61 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.enums;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
/**
*
*
* @author Parker
* @date 2022-07-21 2:07 PM
**/
public enum LoginModelType {
/** 未知 */
UNKNOWN,
/** 账号 */
ACCOUNT,
/** 手机 */
MOBILE,
/** 邮箱 */
EMAIL
;
public static LoginModelType getTypeByStr(String principal){
if(StrUtil.isBlank(principal)){
return UNKNOWN;
}
// 手机号
if(Validator.isMobile(principal)){
return MOBILE;
}
// 邮箱
else if(Validator.isEmail(principal)){
return EMAIL;
}
// 默认账号
return ACCOUNT;
}
}

@ -0,0 +1,53 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Optional;
/**
*
*
* @author
* @date 2022-08-01 12:49 PM
**/
@AllArgsConstructor
@Getter
public enum VerificationTypeEnum {
/** 类型 */
LOGIN("0"),
AUTH("1")
;
/** 类型 */
private final String type;
public static Optional<VerificationTypeEnum> getEnumByType(String type){
VerificationTypeEnum[] types = values();
for (VerificationTypeEnum typeEnum : types) {
if(typeEnum.type.equals(type)){
return Optional.of(typeEnum);
}
}
return Optional.empty();
}
}

@ -32,7 +32,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* 线线
* 202111214:07:54 线
*
* @author
* @author Parker
* @date 2020-12-10 10:36
*/
@Slf4j

@ -31,7 +31,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* 线
* 线线
*
* @author
* @author Parker
* @date 2020-12-10 10:36
*/
@Slf4j

@ -1,3 +1,18 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.thread;
import cn.hutool.core.util.StrUtil;
@ -14,7 +29,7 @@ import java.util.function.Function;
/**
* 线 - 线
*
* @author
* @author Parker
* @date 2020-10-08 10:24
*/
@Slf4j

@ -1,3 +1,18 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.thread;
import cn.hutool.core.thread.ThreadUtil;
@ -11,7 +26,7 @@ import java.util.concurrent.ExecutorService;
/**
* 线
*
* @author
* @author Parker
* @date 2021/8/27 17:00
*/
@Slf4j

@ -0,0 +1,388 @@
package org.opsli.common.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Hashids designed for Generating short hashes from numbers (like YouTube and Bitly), obfuscate
* database IDs, use them as forgotten password hashes, invitation codes, store shard numbers.
* <p>
* This is implementation of http://hashids.org v1.0.0 version.
*
* This implementation is immutable, thread-safe, no lock is necessary.
*
* @author <a href="mailto:fanweixiao@gmail.com">fanweixiao</a>
* @author <a href="mailto:terciofilho@gmail.com">Tercio Gaudencio Filho</a>
* @since 0.3.3
*/
public class HashIdsUtil {
/**
* Max number that can be encoded with Hashids.
*/
public static final long MAX_NUMBER = 9007199254740992L;
private static final String DEFAULT_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
private static final String DEFAULT_SEPS = "cfhistuCFHISTU";
private static final String DEFAULT_SALT = "";
private static final int DEFAULT_MIN_HASH_LENGTH = 0;
private static final int MIN_ALPHABET_LENGTH = 16;
private static final double SEP_DIV = 3.5;
private static final int GUARD_DIV = 12;
private final String salt;
private final int minHashLength;
private final String alphabet;
private final String seps;
private final String guards;
public HashIdsUtil() {
this(DEFAULT_SALT);
}
public HashIdsUtil(String salt) {
this(salt, 0);
}
public HashIdsUtil(String salt, int minHashLength) {
this(salt, minHashLength, DEFAULT_ALPHABET);
}
public HashIdsUtil(String salt, int minHashLength, String alphabet) {
this.salt = salt != null ? salt : DEFAULT_SALT;
this.minHashLength = minHashLength > 0 ? minHashLength : DEFAULT_MIN_HASH_LENGTH;
final StringBuilder uniqueAlphabet = new StringBuilder();
for (int i = 0; i < alphabet.length(); i++) {
if (uniqueAlphabet.indexOf(String.valueOf(alphabet.charAt(i))) == -1) {
uniqueAlphabet.append(alphabet.charAt(i));
}
}
alphabet = uniqueAlphabet.toString();
if (alphabet.length() < MIN_ALPHABET_LENGTH) {
throw new IllegalArgumentException(
"alphabet must contain at least " + MIN_ALPHABET_LENGTH + " unique characters");
}
if (alphabet.contains(" ")) {
throw new IllegalArgumentException("alphabet cannot contains spaces");
}
// seps should contain only characters present in alphabet;
// alphabet should not contains seps
String seps = DEFAULT_SEPS;
for (int i = 0; i < seps.length(); i++) {
final int j = alphabet.indexOf(seps.charAt(i));
if (j == -1) {
seps = seps.substring(0, i) + " " + seps.substring(i + 1);
} else {
alphabet = alphabet.substring(0, j) + " " + alphabet.substring(j + 1);
}
}
alphabet = alphabet.replaceAll("\\s+", "");
seps = seps.replaceAll("\\s+", "");
seps = HashIdsUtil.consistentShuffle(seps, this.salt);
if ((seps.isEmpty()) || (((float) alphabet.length() / seps.length()) > SEP_DIV)) {
int seps_len = (int) Math.ceil(alphabet.length() / SEP_DIV);
if (seps_len == 1) {
seps_len++;
}
if (seps_len > seps.length()) {
final int diff = seps_len - seps.length();
seps += alphabet.substring(0, diff);
alphabet = alphabet.substring(diff);
} else {
seps = seps.substring(0, seps_len);
}
}
alphabet = HashIdsUtil.consistentShuffle(alphabet, this.salt);
// use double to round up
final int guardCount = (int) Math.ceil((double) alphabet.length() / GUARD_DIV);
String guards;
if (alphabet.length() < 3) {
guards = seps.substring(0, guardCount);
seps = seps.substring(guardCount);
} else {
guards = alphabet.substring(0, guardCount);
alphabet = alphabet.substring(guardCount);
}
this.guards = guards;
this.alphabet = alphabet;
this.seps = seps;
}
/**
* Encrypt numbers to string
*
* @param numbers
* the numbers to encrypt
* @return the encrypt string
*/
public String encode(long... numbers) {
if (numbers.length == 0) {
return "";
}
for (final long number : numbers) {
if (number < 0) {
return "";
}
if (number > MAX_NUMBER) {
throw new IllegalArgumentException("number can not be greater than " + MAX_NUMBER + "L");
}
}
return this._encode(numbers);
}
/**
* Decrypt string to numbers
*
* @param hash
* the encrypt string
* @return decryped numbers
*/
public long[] decode(String hash) {
if (hash.isEmpty()) {
return new long[0];
}
String validChars = this.alphabet + this.guards + this.seps;
for (int i = 0; i < hash.length(); i++) {
if(validChars.indexOf(hash.charAt(i)) == -1) {
return new long[0];
}
}
return this._decode(hash, this.alphabet);
}
/**
* Encrypt hexa to string
*
* @param hexa
* the hexa to encrypt
* @return the encrypt string
*/
public String encodeHex(String hexa) {
if (!hexa.matches("^[0-9a-fA-F]+$")) {
return "";
}
final List<Long> matched = new ArrayList<Long>();
final Matcher matcher = Pattern.compile("[\\w\\W]{1,12}").matcher(hexa);
while (matcher.find()) {
matched.add(Long.parseLong("1" + matcher.group(), 16));
}
// conversion
final long[] result = new long[matched.size()];
for (int i = 0; i < matched.size(); i++) {
result[i] = matched.get(i);
}
return this.encode(result);
}
/**
* Decrypt string to numbers
*
* @param hash
* the encrypt string
* @return decryped numbers
*/
public String decodeHex(String hash) {
final StringBuilder result = new StringBuilder();
final long[] numbers = this.decode(hash);
for (final long number : numbers) {
result.append(Long.toHexString(number).substring(1));
}
return result.toString();
}
public static int checkedCast(long value) {
final int result = (int) value;
if (result != value) {
// don't use checkArgument here, to avoid boxing
throw new IllegalArgumentException("Out of range: " + value);
}
return result;
}
/* Private methods */
private String _encode(long... numbers) {
long numberHashInt = 0;
for (int i = 0; i < numbers.length; i++) {
numberHashInt += (numbers[i] % (i + 100));
}
String alphabet = this.alphabet;
final char ret = alphabet.charAt((int) (numberHashInt % alphabet.length()));
long num;
long sepsIndex, guardIndex;
String buffer;
final StringBuilder ret_strB = new StringBuilder(this.minHashLength);
ret_strB.append(ret);
char guard;
for (int i = 0; i < numbers.length; i++) {
num = numbers[i];
buffer = ret + this.salt + alphabet;
alphabet = HashIdsUtil.consistentShuffle(alphabet, buffer.substring(0, alphabet.length()));
final String last = HashIdsUtil.hash(num, alphabet);
ret_strB.append(last);
if (i + 1 < numbers.length) {
if (last.length() > 0) {
num %= (last.charAt(0) + i);
sepsIndex = (int) (num % this.seps.length());
} else {
sepsIndex = 0;
}
ret_strB.append(this.seps.charAt((int) sepsIndex));
}
}
String ret_str = ret_strB.toString();
if (ret_str.length() < this.minHashLength) {
guardIndex = (numberHashInt + (ret_str.charAt(0))) % this.guards.length();
guard = this.guards.charAt((int) guardIndex);
ret_str = guard + ret_str;
if (ret_str.length() < this.minHashLength) {
guardIndex = (numberHashInt + (ret_str.charAt(2))) % this.guards.length();
guard = this.guards.charAt((int) guardIndex);
ret_str += guard;
}
}
final int halfLen = alphabet.length() / 2;
while (ret_str.length() < this.minHashLength) {
alphabet = HashIdsUtil.consistentShuffle(alphabet, alphabet);
ret_str = alphabet.substring(halfLen) + ret_str + alphabet.substring(0, halfLen);
final int excess = ret_str.length() - this.minHashLength;
if (excess > 0) {
final int start_pos = excess / 2;
ret_str = ret_str.substring(start_pos, start_pos + this.minHashLength);
}
}
return ret_str;
}
private long[] _decode(String hash, String alphabet) {
final ArrayList<Long> ret = new ArrayList<Long>();
int i = 0;
final String regexp = "[" + this.guards + "]";
String hashBreakdown = hash.replaceAll(regexp, " ");
String[] hashArray = hashBreakdown.split(" ");
if (hashArray.length == 3 || hashArray.length == 2) {
i = 1;
}
if (hashArray.length > 0) {
hashBreakdown = hashArray[i];
if (!hashBreakdown.isEmpty()) {
final char lottery = hashBreakdown.charAt(0);
hashBreakdown = hashBreakdown.substring(1);
hashBreakdown = hashBreakdown.replaceAll("[" + this.seps + "]", " ");
hashArray = hashBreakdown.split(" ");
String subHash, buffer;
for (final String aHashArray : hashArray) {
subHash = aHashArray;
buffer = lottery + this.salt + alphabet;
alphabet = HashIdsUtil.consistentShuffle(alphabet, buffer.substring(0, alphabet.length()));
ret.add(HashIdsUtil.unhash(subHash, alphabet));
}
}
}
// transform from List<Long> to long[]
long[] arr = new long[ret.size()];
for (int k = 0; k < arr.length; k++) {
arr[k] = ret.get(k);
}
if (!this.encode(arr).equals(hash)) {
arr = new long[0];
}
return arr;
}
private static String consistentShuffle(String alphabet, String salt) {
if (salt.length() <= 0) {
return alphabet;
}
int asc_val, j;
final char[] tmpArr = alphabet.toCharArray();
for (int i = tmpArr.length - 1, v = 0, p = 0; i > 0; i--, v++) {
v %= salt.length();
asc_val = salt.charAt(v);
p += asc_val;
j = (asc_val + v + p) % i;
final char tmp = tmpArr[j];
tmpArr[j] = tmpArr[i];
tmpArr[i] = tmp;
}
return new String(tmpArr);
}
private static String hash(long input, String alphabet) {
String hash = "";
final int alphabetLen = alphabet.length();
do {
final int index = (int) (input % alphabetLen);
if (index >= 0 && index < alphabet.length()) {
hash = alphabet.charAt(index) + hash;
}
input /= alphabetLen;
} while (input > 0);
return hash;
}
private static Long unhash(String input, String alphabet) {
long number = 0, pos;
for (int i = 0; i < input.length(); i++) {
pos = alphabet.indexOf(input.charAt(i));
number = number * alphabet.length() + pos;
}
return number;
}
/**
* Get Hashid algorithm version.
*
* @return Hashids algorithm version implemented.
*/
public String getVersion() {
return "1.0.0";
}
}

@ -15,6 +15,8 @@
*/
package org.opsli.common.utils;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Maps;
@ -25,7 +27,6 @@ import org.opsli.common.thread.AsyncProcessExecutor;
import org.opsli.common.thread.AsyncProcessExecutorFactory;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@ -39,6 +40,8 @@ import java.util.concurrent.TimeUnit;
@Slf4j
public final class RateLimiterUtil {
/** 默认IP */
public static final String DEFAULT_IP = "unknown";
/** 默认QPS */
public static final double DEFAULT_QPS = 10d;
/** 默认缓存个数 超出后流量自动清理 */
@ -46,7 +49,7 @@ public final class RateLimiterUtil {
/** 默认缓存时效 超出后自动清理 */
private static final int DEFAULT_CACHE_TIME = 5;
/** 默认等待时长 */
private static final int DEFAULT_WAIT = 5000;
private static final int DEFAULT_WAIT = 500;
/** 限流器单机缓存 */
private static final Cache<String, Map<String, RateLimiterUtil.RateLimiterInner> > LFU_CACHE;
@ -108,6 +111,11 @@ public final class RateLimiterUtil {
*/
@SuppressWarnings("UnstableApiUsage")
public static boolean enter(String clientIpAddress, String resource, Double dfQps) {
// IP 为空补偿器
if(StrUtil.isBlank(clientIpAddress)){
clientIpAddress = DEFAULT_IP;
}
// 计时器
long t1 = System.currentTimeMillis();
@ -152,7 +160,7 @@ public final class RateLimiterUtil {
RateLimiter rateLimiter = rateLimiterObj.getRateLimiter();
//非阻塞
if (!rateLimiter.tryAcquire(Duration.ofMillis(DEFAULT_WAIT))) {
if (!rateLimiter.tryAcquire(DEFAULT_WAIT, TimeUnit.MILLISECONDS)) {
//限速中,提示用户
log.error("限流器 - 访问频繁 耗时: "+ (System.currentTimeMillis() - t1) + "ms, IP地址: " + clientIpAddress + ", URI: " + resource);
return false;
@ -183,18 +191,40 @@ public final class RateLimiterUtil {
public static void main(String[] args) {
int count = 500;
RateLimiterUtil.removeIp("127.0.0.1");
AsyncProcessExecutor normalExecutor = AsyncProcessExecutorFactory.createNormalExecutor();
for (int i = 0; i < count; i++) {
normalExecutor.put(()->{
boolean enter = RateLimiterUtil.enter("127.0.0.1","/api/v1", 2d);
System.out.println(enter);
});
// int count = 500;
// RateLimiterUtil.removeIp("127.0.0.1");
// AsyncProcessExecutor normalExecutor = AsyncProcessExecutorFactory.createNormalExecutor();
// for (int i = 0; i < count; i++) {
// normalExecutor.put(()->{
// RateLimiter rateLimiter = RateLimiter.create(1);
//
//
// boolean enter = RateLimiterUtil.enter("127.0.0.1","/api/v1", 2d);
// System.out.println(enter);
// });
// }
// normalExecutor.execute();
int count = 3;
RateLimiter rateLimiter = RateLimiter.create(count);
AsyncProcessExecutor normalExecutor = AsyncProcessExecutorFactory.createWaitExecutor();
int num = 0;
while (true){
System.out.println("------------"+ (++num) +"------------");
for (int i = 0; i < count+1; i++) {
normalExecutor.put(()->{
boolean tryAcquire = rateLimiter.tryAcquire(500, TimeUnit.MILLISECONDS);
System.out.println(tryAcquire);
});
}
normalExecutor.execute();
ThreadUtil.sleep(1100);
}
normalExecutor.execute();
}
}

@ -0,0 +1,48 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.utils;
import cn.hutool.core.util.RandomUtil;
/**
*
* <a href="https://huzb.me/2018/03/23/%E7%AE%80%E5%8D%95%E7%9A%84%E5%AF%86%E7%A0%81%E5%AD%A6%E7%94%9F%E6%88%90%E5%94%AF%E4%B8%80%E9%82%80%E8%AF%B7%E7%A0%81">...</a>
*
* @author Parker
* @date 20220711 14:07
*/
public final class UniqueStrGeneratorUtils {
private static final String BEGIN_SALT = "opsli_2022_begin";
private static final String END_SALT = "opsli_2022_end";
private static final String CONTENT_SALT = "opsli_2022";
private static final HashIdsUtil DISTURB_HASH_ID_BEGIN = new HashIdsUtil(BEGIN_SALT, 2);
private static final HashIdsUtil DISTURB_HASH_ID_END = new HashIdsUtil(END_SALT, 3);
private static final HashIdsUtil CONTENT_HASH_ID = new HashIdsUtil(CONTENT_SALT, 7);
/** 生成 */
public static String generator(long i) {
int begin = RandomUtil.randomInt(0, 10);
int end = RandomUtil.randomInt(10, 100);
String disturbHashIdBeginStr = DISTURB_HASH_ID_BEGIN.encode(begin);
String disturbHashIdEndStr = DISTURB_HASH_ID_END.encode(end);
String contentHashIdStr = CONTENT_HASH_ID.encode(i);
return disturbHashIdBeginStr + contentHashIdStr + disturbHashIdEndStr;
}
}

@ -48,6 +48,13 @@
<version>${plugins.version}</version>
</dependency>
<!-- 引入短信插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-sms</artifactId>
<version>${plugins.version}</version>
</dependency>
<!-- 引入Redis插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
@ -55,6 +62,13 @@
<version>${plugins.version}</version>
</dependency>
<!-- 引入Security插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-security</artifactId>
<version>${plugins.version}</version>
</dependency>
<!-- 引入Redisson插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
@ -78,12 +92,6 @@
<!-- ———————————————————— 集成Shiro鉴权安全认证 - 开始 ———————————————————— -->
<!-- ShiroRedis包 -->
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis-spring-boot-starter</artifactId>
</dependency>
<!-- captcha 验证码 -->
<dependency>
<groupId>com.github.whvcse</groupId>
@ -96,6 +104,11 @@
<artifactId>java-jwt</artifactId>
</dependency>
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>enjoy</artifactId>
</dependency>
<!-- ———————————————————— 集成Shiro鉴权安全认证 - 结束 ———————————————————— -->
<!-- ———————————————————— 集成数据库相关配置 - 开始 ———————————————————— -->
@ -127,7 +140,20 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
<exclusions>
<!-- 修复 CVE-2021-22569 -->
<exclusion>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 修复 CVE-2021-22569 -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
<!-- sqlserver-->
@ -149,6 +175,7 @@
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
<version>${postgresql.version}</version>
</dependency>
<!-- ———————————————————— 集成数据库相关配置 - 结束 ———————————————————— -->

@ -0,0 +1,46 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.conf;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Cors
*
* @author Parker
* @date 2022071412:57:33
**/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
/**
*
*
* @param registry registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(7200);
}
}

@ -15,7 +15,8 @@
*/
package org.opsli.core.autoconfigure.conf;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.opsli.core.filters.interceptor.MybatisAutoFillInterceptor;
@ -35,13 +36,20 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
public class MyBatisPlusConfig {
/***
*
* @return
/**
*
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
// 乐观锁
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
// 防止全表更新与删除插件
//mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return mybatisPlusInterceptor;
}
/**

@ -0,0 +1,141 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.conf;
import cn.hutool.extra.spring.SpringUtil;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import org.opsli.core.security.filter.JwtAuthenticationTokenFilter;
import org.opsli.core.security.service.UidUserDetailDetailServiceImpl;
import org.opsli.plugins.security.exception.handler.AccessDeniedHandlerImpl;
import org.opsli.plugins.security.exception.handler.AuthenticationEntryPointImpl;
import org.opsli.plugins.security.properties.AuthProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import java.util.List;
import java.util.Map;
/**
* Security
*
* @author Parker
* @date 2022071412:57:33
**/
@AllArgsConstructor
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final AuthProperties authProperties;
private final AccessDeniedHandlerImpl accessDeniedHandler;
private final AuthenticationEntryPointImpl authenticationEntryPoint;
private final UidUserDetailDetailServiceImpl uidUserDetailDetailService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
// 默认关闭 Security 的 xss防护与系统本身的 xss防护冲突
.xssProtection().disable()
// 允许Iframe加载
.frameOptions().disable()
.and()
// 关闭csrf token认证不需要csrf防护
.csrf().disable();
// 初始化 initAuthorizeRequests
this.initAuthorizeRequests(http);
}
/**
* URL
* @param http http
*/
private void initAuthorizeRequests(HttpSecurity http) throws Exception {
// 设置URL 未登陆前可访问URL
List<String> anonymousList = authProperties.getUrlExclusion().getAnonymous();
if(null != anonymousList){
String[] urlExclusionArray = anonymousList.toArray(new String[0]);
http.authorizeRequests()
// URL 未登陆前可访问
.antMatchers(urlExclusionArray).anonymous();
}
// 设置URL白名单
List<String> permitAll = authProperties.getUrlExclusion().getPermitAll();
if(null != permitAll){
String[] urlExclusionArray = permitAll.toArray(new String[0]);
http.authorizeRequests()
// URL 白名单
.antMatchers(urlExclusionArray).permitAll();
}
// 除上面外的所有请求全部需要鉴权认证
http.authorizeRequests()
.anyRequest().authenticated();
// 添加过滤器
// 注意 自定义 Filter 不要交给 Spring管理
http.addFilterBefore(new JwtAuthenticationTokenFilter(uidUserDetailDetailService),
UsernamePasswordAuthenticationFilter.class);
// 异常处理
http.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint);
}
/**
*
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected AuthenticationManager authenticationManager() {
// 设置 多Provider
Map<String, AuthenticationProvider> providerMap =
SpringUtil.getBeansOfType(AuthenticationProvider.class);
List<AuthenticationProvider> authenticationProviderList =
Lists.newArrayListWithCapacity(providerMap.size());
for (Map.Entry<String, AuthenticationProvider> providerEntry : providerMap.entrySet()) {
authenticationProviderList.add(providerEntry.getValue());
}
ProviderManager authenticationManager = new ProviderManager(authenticationProviderList);
//不擦除认证密码擦除会导致TokenBasedRememberMeServices因为找不到Credentials再调用UserDetailsService而抛出UsernameNotFoundException
authenticationManager.setEraseCredentialsAfterAuthentication(false);
return authenticationManager;
}
}

@ -1,198 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.conf;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ClassUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.opsli.core.autoconfigure.properties.ApiPathProperties;
import org.opsli.core.autoconfigure.properties.GlobalProperties;
import org.opsli.core.security.shiro.authenticator.CustomModularRealmAuthenticator;
import org.opsli.core.security.shiro.filter.CustomShiroFilter;
import org.opsli.core.security.shiro.realm.FlagRealm;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.servlet.Filter;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Shiro
*
* token -
*
* @author Parker
* @date 2017-04-20 18:33
*/
@Configuration
public class ShiroConfig {
/**
* filer
* @param securityManager
* @return ShiroFilterFactoryBean
*/
@Bean("shiroFilter")
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager,
GlobalProperties globalProperties, ApiPathProperties apiPathProperties) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
//oauth过滤
Map<String, Filter> filters = Maps.newHashMapWithExpectedSize(1);
filters.put("last_filter", new CustomShiroFilter());
shiroFilter.setFilters(filters);
Map<String, String> filterMap = Maps.newLinkedHashMap();
// 加载排除URL
if(globalProperties.getAuth() != null &&
globalProperties.getAuth().getToken() != null){
Set<String> urlExclusion = globalProperties.getAuth().getToken().getUrlExclusion();
if(CollUtil.isNotEmpty(urlExclusion)){
for (String excUrl : urlExclusion) {
filterMap.put(excUrl, "anon");
}
}
}
// 登录接口拦截
filterMap.put("/system/login", "anon");
filterMap.put("/system/publicKey", "anon");
filterMap.put("/system/slipCount", "anon");
filterMap.put("/captcha*", "anon");
// 导出Excel\模版 不做自动拦截 手动拦截
filterMap.put(apiPathProperties.getGlobalPrefix() + "/**/exportExcel", "anon");
filterMap.put(apiPathProperties.getGlobalPrefix() + "/**/importExcel/template", "anon");
filterMap.put("/webjars/**", "anon");
filterMap.put("/druid/**", "anon");
filterMap.put("/app/**", "anon");
filterMap.put("/swagger/**", "anon");
filterMap.put("/v2/api-docs", "anon");
filterMap.put("/doc.html", "anon");
filterMap.put("/swagger-ui.html", "anon");
filterMap.put("/swagger-resources/**", "anon");
filterMap.put("/**", "last_filter");
shiroFilter.setFilterChainDefinitionMap(filterMap);
return shiroFilter;
}
@Bean("sessionManager")
public SessionManager sessionManager(){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setSessionIdCookieEnabled(true);
return sessionManager;
}
@Bean("securityManager")
public DefaultWebSecurityManager securityManager(SessionManager sessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setSessionManager(sessionManager);
// 设置验证器为自定义验证器
securityManager.setAuthenticator(modularRealmAuthenticator());
List<Realm> realms = Lists.newArrayList();
// 拿到state包下 实现了 FlagRealm 接口的,所有子类
Set<Class<?>> clazzSet = ClassUtil.scanPackageBySuper(
FlagRealm.class.getPackage().getName(),
FlagRealm.class
);
for (Class<?> aClass : clazzSet) {
// 位运算 去除抽象类
if((aClass.getModifiers() & Modifier.ABSTRACT) != 0){
continue;
}
try {
realms.add((Realm) aClass.newInstance());
} catch (Exception ignored){ }
}
if(CollUtil.isNotEmpty(realms)){
// 追加 Realms
securityManager.setRealms(realms);
}
return securityManager;
}
/**
* Realm使
*/
@Bean("modularRealmAuthenticator")
public ModularRealmAuthenticator modularRealmAuthenticator(){
CustomModularRealmAuthenticator authenticator = new CustomModularRealmAuthenticator();
authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return authenticator;
}
// ===================== 固定三板斧 =====================
// 其实 没有 Spring Security 配置起来简单
//
@Bean("lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean("defaultAdvisorAutoProxyCreator")
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
proxyCreator.setProxyTargetClass(true);
proxyCreator.setUsePrefix(true);
proxyCreator.setAdvisorBeanNamePrefix("_no_advisor");
return proxyCreator;
}
/**
* shiro
* @param securityManager
* @return AuthorizationAttributeSourceAdvisor
*/
@Bean("authorizationAttributeSourceAdvisor")
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}

@ -26,6 +26,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ -67,23 +68,18 @@ public class SpringWebMvcConfig implements WebMvcConfigurer, WebMvcRegistrations
/**
*
* @return CorsFilter
*
* @param registry registry
*/
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
/* 是否允许请求带有验证信息 */
corsConfiguration.setAllowCredentials(true);
/* 允许访问的客户端域名 */
corsConfiguration.addAllowedOrigin("*");
/* 允许服务端访问的客户端请求头 */
corsConfiguration.addAllowedHeader("*");
/* 允许访问的方法名,GET POST等 */
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
// @Override
// public void addCorsMappings(CorsRegistry registry) {
// registry.addMapping("/**")
// .allowedOriginPatterns("*")
// .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
// .allowedHeaders("*")
// .allowCredentials(true)
// .maxAge(7200);
// }
@Override
public void addInterceptors(InterceptorRegistry registry) {

@ -18,6 +18,7 @@ package org.opsli.core.autoconfigure.properties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
@ -26,7 +27,7 @@ import org.springframework.stereotype.Component;
* @author Parker
* @date 2020-09-15
*/
@Component
@Configuration
@ConfigurationProperties(prefix = ApiPathProperties.PROP_PREFIX)
@Data
@EqualsAndHashCode(callSuper = false)

@ -18,6 +18,7 @@ package org.opsli.core.autoconfigure.properties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
@ -26,7 +27,7 @@ import org.springframework.stereotype.Component;
* @author Parker
* @date 2020-09-15
*/
@Component
@Configuration
@ConfigurationProperties(prefix = CacheProperties.PROP_PREFIX)
@Data
@EqualsAndHashCode(callSuper = false)

@ -0,0 +1,25 @@
package org.opsli.core.autoconfigure.properties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
*
*
* @author Parker
* @date 2022-08-07
*/
@Configuration
@ConfigurationProperties(prefix = EncryptProperties.PROP_PREFIX)
@Data
@EqualsAndHashCode(callSuper = false)
public class EncryptProperties {
public static final String PROP_PREFIX = "opsli.data-encrypt";
/** 秘钥 */
private String key;
}

@ -90,9 +90,6 @@ public class GlobalProperties {
/** 有效时间 (分钟)*/
private Integer effectiveTime;
/** 排除URL*/
private Set<String> urlExclusion;
}
/**

@ -0,0 +1,44 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.properties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
* Token
*
* @author Parker
* @date 2020-09-15
*/
@Configuration
@ConfigurationProperties(prefix = TokenProperties.PROP_PREFIX)
@Data
@EqualsAndHashCode(callSuper = false)
public class TokenProperties {
public static final String PROP_PREFIX = "opsli.auth.token";
/** 盐 */
private String secret;
/** 有效时间 */
private int effectiveTime;
}

@ -16,7 +16,6 @@
package org.opsli.core.base.controller;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
@ -24,36 +23,42 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.annotation.RequiresPermissionsCus;
import org.opsli.common.annotation.hotdata.EnableHotData;
import org.opsli.common.constants.RedisConstants;
import org.opsli.common.constants.TreeConstants;
import org.opsli.common.enums.ExcelOperate;
import org.opsli.common.exception.ServiceException;
import org.opsli.common.exception.TokenException;
import org.opsli.common.utils.OutputStreamUtil;
import org.opsli.common.utils.UniqueStrGeneratorUtils;
import org.opsli.common.utils.WrapperUtil;
import org.opsli.core.autoconfigure.properties.GlobalProperties;
import org.opsli.core.base.entity.BaseEntity;
import org.opsli.core.base.entity.HasChildren;
import org.opsli.core.base.service.interfaces.CrudServiceInterface;
import org.opsli.core.cache.CacheUtil;
import org.opsli.core.msg.CoreMsg;
import org.opsli.core.msg.TokenMsg;
import org.opsli.core.security.shiro.realm.JwtRealm;
import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.persistence.querybuilder.WebQueryBuilder;
import org.opsli.core.utils.ExcelUtil;
import org.opsli.core.utils.UserUtil;
import org.opsli.plugins.excel.exception.ExcelPluginException;
import org.opsli.plugins.excel.listener.BatchExcelListener;
import org.opsli.plugins.redis.RedisPlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestParam;
@ -61,10 +66,11 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
/**
@ -77,14 +83,8 @@ import java.util.function.Function;
@RestController
public abstract class BaseRestController <T extends BaseEntity, E extends ApiWrapper, S extends CrudServiceInterface<T,E>>{
/** 开启热点数据状态 */
protected boolean hotDataFlag = false;
/** Entity Clazz 类 */
protected Class<T> entityClazz;
/** Model Clazz 类 */
protected Class<E> modelClazz;
/** 凭证 10分钟失效 */
private static final int CERTIFICATE_EXPIRED_MINUTE = 10;
/** 配置类 */
@Autowired
@ -94,6 +94,10 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
@Autowired(required = false)
protected S IService;
/** Redis 类 */
@Autowired
private RedisPlugin redisPlugin;
/**
*
* id
@ -103,15 +107,18 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
*/
@ModelAttribute
public E get(@RequestParam(required=false) String id) {
if(StrUtil.isEmpty(id)){
return null;
}
return IService.get(id);
}
/**
* Excel
* @param request request
* @return ResultVo
* @return ResultWrapper
*/
protected ResultVo<?> importExcel(MultipartHttpServletRequest request){
protected ResultWrapper<?> importExcel(MultipartHttpServletRequest request){
// 计时器
TimeInterval timer = DateUtil.timer();
Iterator<String> itr = request.getFileNames();
@ -119,21 +126,20 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
List<MultipartFile> files = request.getFiles(uploadedFile);
if (CollectionUtils.isEmpty(files)) {
// 请选择文件
return ResultVo.error(CoreMsg.EXCEL_FILE_NULL.getCode(),
CoreMsg.EXCEL_FILE_NULL.getMessage());
return ResultWrapper.getCustomResultWrapper(CoreMsg.EXCEL_FILE_NULL);
}
ResultVo<?> resultVo ;
ResultWrapper<?> resultVo ;
String msgInfo;
try {
UserModel user = UserUtil.getUser();
Date currDate = DateUtil.date();
// 导入优化为 监听器 模式 超过一定阈值直接释放资源 防止导入数据导致系统 OOM
ExcelUtil.getInstance().readExcelByListener(files.get(0), modelClazz, new BatchExcelListener<E>() {
ExcelUtil.getInstance().readExcelByListener(files.get(0), IService.getModelClass(), new BatchExcelListener<E>() {
@Override
public void saveData(List<E> dataList) {
// 处理字典数据
List<E> disposeData = ExcelUtil.getInstance().handleDatas(dataList, modelClazz, ExcelOperate.READ);
List<E> disposeData = ExcelUtil.getInstance().handleDatas(dataList, IService.getModelClass(), ExcelOperate.READ);
// 手动赋值 必要数据 防止频繁开启Redis网络IO
for (E model : disposeData) {
model.setIzManual(true);
@ -152,7 +158,7 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
// 提示信息
msgInfo = StrUtil.format(CoreMsg.EXCEL_IMPORT_SUCCESS.getMessage(), DateUtil.formatBetween(timerCount));
// 导出成功
resultVo = ResultVo.success(msgInfo);
resultVo = ResultWrapper.getSuccessResultWrapper(msgInfo);
resultVo.setCode(CoreMsg.EXCEL_IMPORT_SUCCESS.getCode());
} catch (ExcelPluginException e) {
@ -162,7 +168,8 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
msgInfo = StrUtil.format(CoreMsg.EXCEL_IMPORT_ERROR.getMessage(), DateUtil.formatBetween(timerCount),
e.getMessage());
// 导入失败
resultVo = ResultVo.error(CoreMsg.EXCEL_IMPORT_ERROR.getCode(), msgInfo);
resultVo = ResultWrapper.getCustomResultWrapper(
CoreMsg.EXCEL_IMPORT_ERROR.getCode(), msgInfo);
}
// 记录导出日志
log.info(msgInfo);
@ -170,108 +177,113 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
}
/**
*
* @param fileName
* @param response response
* Excel
*
* @param type ExcelExcel
* @param subName
* @param request request
* @return Optional<String>
*/
protected void importTemplate(String fileName, HttpServletResponse response, Method method){
this.excelExport(fileName + " 模版 ",null, response, method);
protected Optional<String> excelExportAuth(String type, String subName, HttpServletRequest request){
// 封装缓存数据
ExcelExportCache exportCache;
if(ExcelExportCache.EXCEL_EXPORT.equals(type)){
// 异常检测
QueryBuilder<T> queryBuilder = new WebQueryBuilder<>(IService.getEntityClass(), request.getParameterMap());
QueryWrapper<T> queryWrapper = queryBuilder.build();
// 导出数量限制 -1 为无限制
Integer exportMaxCount = globalProperties.getExcel().getExportMaxCount();
if(exportMaxCount != null && exportMaxCount > -1){
// 获得数量 大于 阈值 禁止导出, 防止OOM
long count = IService.count(queryWrapper);
if(count > exportMaxCount){
String maxError = StrUtil.format(CoreMsg.EXCEL_HANDLE_MAX.getMessage(), count,
exportMaxCount);
// 超出最大导出数量
throw new ExcelPluginException(CoreMsg.EXCEL_HANDLE_MAX.getCode(), maxError);
}
}
// 封装缓存数据
exportCache = ExcelExportCache.builder()
.subName(subName)
.parameterMapStr(JSONUtil.toJsonStr(request.getParameterMap()))
.type(type)
.build();
}else if(ExcelExportCache.EXCEL_IMPORT_TEMPLATE_EXPORT.equals(type)){
// 封装缓存数据
exportCache = ExcelExportCache.builder()
.subName(subName+ " 模版 ")
.parameterMapStr(JSONUtil.toJsonStr(request.getParameterMap()))
.type(type)
.build();
}else {
return Optional.empty();
}
// 缓存Key
Long increment = redisPlugin
.increment(CacheUtil.formatKey(RedisConstants.PREFIX_TMP_EXCEL_EXPORT_NUM_NAME));
String certificate = UniqueStrGeneratorUtils.generator(increment);
// 缓存Key
String certificateCacheKeyTmp = CacheUtil.formatKey(
RedisConstants.PREFIX_TMP_EXCEL_EXPORT_NAME + certificate);
redisPlugin.put(certificateCacheKeyTmp, exportCache, CERTIFICATE_EXPIRED_MINUTE, TimeUnit.MINUTES);
return Optional.of(certificate);
}
/**
*
* Excel
*
* Token
*
* 使2
*
* socketJava
* response javascript alert
*
* @param fileName
* @param queryWrapper
* @param response response
*/
protected void excelExport(String fileName, QueryWrapper<T> queryWrapper, HttpServletResponse response,
Method method){
// 权限认证
try {
if(method == null){
// 无权访问该方法
throw new TokenException(TokenMsg.EXCEPTION_NOT_AUTH);
protected void excelExport(String certificate, HttpServletResponse response){
// 缓存Key
String certificateCacheKeyTmp = CacheUtil.formatKey(
RedisConstants.PREFIX_TMP_EXCEL_EXPORT_NAME + certificate);
Object cacheObj = redisPlugin.get(certificateCacheKeyTmp);
ExcelExportCache cache = Convert.convert(ExcelExportCache.class, cacheObj);
if(cache == null){
return;
}
}
// 主题名称
String subName = cache.getSubName();
// Token 认证
JwtRealm.authToken();
List<E> modelList = null;
RequiresPermissionsCus permissionsCus = method.getAnnotation(RequiresPermissionsCus.class);
if(permissionsCus != null){
// 方法权限认证
JwtRealm.authPerms(permissionsCus.value());
}
}catch (TokenException e){
// 推送错误信息
OutputStreamUtil.exceptionResponse(e.getMessage(), response);
return;
}
// 如果导出Excel 需要查询数据
if(ExcelExportCache.EXCEL_EXPORT.equals(cache.getType())){
// 参数Map
Map<String, String[]> parameterMap = new HashMap<>();
JSONObject jsonObject = JSONUtil.parseObj(cache.getParameterMapStr());
jsonObject.forEach((k, v) -> {
JSONArray values = (JSONArray) v;
String[] parameters = (String[]) values.toArray(String.class);
parameterMap.put(k, parameters);
});
// 计时器
TimeInterval timer = DateUtil.timer();
String msgInfo;
ResultVo<?> resultVo;
List<E> modelList = Lists.newArrayList();
try {
if(queryWrapper != null){
// 导出数量限制 -1 为无限制
Integer exportMaxCount = globalProperties.getExcel().getExportMaxCount();
if(exportMaxCount != null && exportMaxCount > -1){
// 获得数量 大于 阈值 禁止导出, 防止OOM
int count = IService.count(queryWrapper);
if(count > exportMaxCount){
String maxError = StrUtil.format(CoreMsg.EXCEL_HANDLE_MAX.getMessage(), count,
exportMaxCount);
// 超出最大导出数量
throw new ExcelPluginException(CoreMsg.EXCEL_HANDLE_MAX.getCode(), maxError);
}
}
QueryBuilder<T> queryBuilder = new WebQueryBuilder<>(IService.getEntityClass(), parameterMap);
QueryWrapper<T> queryWrapper = queryBuilder.build();
List<T> entityList = IService.findList(queryWrapper);
// 转化类型
modelList = WrapperUtil.transformInstance(entityList, IService.getModelClass());
List<T> entityList = IService.findList(queryWrapper);
// 转化类型
modelList = WrapperUtil.transformInstance(entityList, modelClazz);
}
// 导出Excel
ExcelUtil.getInstance().writeExcel(response, modelList ,fileName,"sheet", modelClazz ,ExcelTypeEnum.XLSX);
// 花费毫秒数
long timerCount = timer.interval();
// 提示信息
msgInfo = StrUtil.format(CoreMsg.EXCEL_EXPORT_SUCCESS.getMessage(), modelList.size(),
DateUtil.formatBetween(timerCount));
// 导出成功
resultVo = ResultVo.success(msgInfo);
resultVo.setCode(CoreMsg.EXCEL_EXPORT_SUCCESS.getCode());
} catch (ExcelPluginException e) {
// 花费毫秒数
long timerCount = timer.interval();
// 提示信息
msgInfo = StrUtil.format(CoreMsg.EXCEL_EXPORT_ERROR.getMessage(), DateUtil.formatBetween(timerCount), e.getMessage());
// 导出失败
resultVo = ResultVo.error(CoreMsg.EXCEL_EXPORT_ERROR.getCode(), msgInfo);
}finally {
// 清空list
modelList.clear();
}
// 记录导出日志
log.info(msgInfo);
// 导出异常
if(!resultVo.isSuccess()){
// 无权访问该方法
OutputStreamUtil.exceptionResponse(resultVo.getMsg(), response);
}
// 导出Excel
ExcelUtil.getInstance().writeExcel(
response, modelList, subName,"sheet", IService.getModelClass() ,ExcelTypeEnum.XLSX);
// 删除凭证
redisPlugin.del(certificateCacheKeyTmp);
}
/**
*
*/
@ -347,34 +359,28 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
// =================================================
@PostConstruct
public void init(){
try {
this.modelClazz = IService.getModelClazz();
this.entityClazz = IService.getEntityClazz();
if(IService != null){
// 判断Service 是否包含 热数据注解
this.hotDataFlag = AnnotationUtil.hasAnnotation(IService.getServiceClazz(),
EnableHotData.class);
}
}catch (Exception e){
log.error(e.getMessage(),e);
}
}
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public static class ExcelExportCache implements Serializable {
/**
*
* @return E
*/
private E createModel() {
try {
Class<E> modelClazz = this.modelClazz;
return modelClazz.newInstance();
} catch (Exception e) {
log.error(e.getMessage(),e);
}
return null;
}
private static final long serialVersionUID = 1L;
public final static String EXCEL_IMPORT_TEMPLATE_EXPORT = "import-template-export";
public final static String EXCEL_EXPORT = "export";
/** 主题名 */
private String subName;
/** 类型 */
private String type;
/** 请求参数Map */
private String parameterMapStr;
}
}

@ -0,0 +1,62 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.base.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2021122216:22:37
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LoginUserDto implements Serializable {
private static final long serialVersionUID = 1L;
/** 用户ID */
private String uid;
/** 用户名 */
private String username;
/** 用户昵称 */
private String nickname;
/** 租户ID */
private String tenantId;
/** 手机 */
private String mobile;
/** 邮箱 */
private String email;
/** 登录来源: 0:PC端1:APP-安卓 2:APP-IOS 3:小程序 */
private String loginFrom;
/** 登录ip */
private String loginIp;
}

@ -16,10 +16,14 @@
package org.opsli.core.base.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.TypeUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.reflect.SpringReflectionHelper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
@ -35,6 +39,7 @@ import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.persistence.querybuilder.chain.QueryDataPermsHandler;
import org.opsli.core.persistence.querybuilder.chain.QueryTenantHandler;
import org.opsli.core.persistence.querybuilder.conf.WebQueryConf;
import org.springframework.core.GenericTypeResolver;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
@ -64,12 +69,8 @@ import java.util.Map;
public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEntity, E extends ApiWrapper>
extends BaseService<M, T> implements CrudServiceInterface<T,E> {
/** JSON tmp */
private static final String JSON_TMP = "{\"id\":\"1\"}";
/** Entity Clazz 类 */
protected Class<T> entityClazz;
/** Model Clazz 类 */
protected Class<E> modelClazz;
protected Class<E> modelClazz = getInnerModelClazz();
@Override
public E get(String id) {
@ -213,7 +214,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
@Override
public List<T> findList(QueryWrapper<T> queryWrapper) {
// 数据处理责任链
QueryWrapper<T> qWrapper = this.addHandler(entityClazz, queryWrapper);
QueryWrapper<T> qWrapper = this.addHandler(this.getEntityClass(), queryWrapper);
return super.list(qWrapper);
}
@ -221,7 +222,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
@Override
public List<T> findAllList() {
// 数据处理责任链
QueryWrapper<T> qWrapper = this.addHandler(entityClazz);
QueryWrapper<T> qWrapper = this.addHandler(this.getEntityClass());
return super.list(qWrapper);
}
@ -229,7 +230,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
@Override
public Page<T,E> findPage(Page<T,E> page) {
// 数据处理责任链
QueryWrapper<T> qWrapper = this.addHandler(entityClazz, page.getQueryWrapper());
QueryWrapper<T> qWrapper = this.addHandler(this.getEntityClass(), page.getQueryWrapper());
page.pageHelperBegin();
try{
List<T> list = super.list(qWrapper);
@ -245,7 +246,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
@Override
public Page<T,E> findPageNotCount(Page<T,E> page) {
// 数据处理责任链
QueryWrapper<T> qWrapper = this.addHandler(entityClazz, page.getQueryWrapper());
QueryWrapper<T> qWrapper = this.addHandler(this.getEntityClass(), page.getQueryWrapper());
page.pageHelperBegin(false);
try{
List<T> list = super.list(qWrapper);
@ -286,7 +287,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
* @return T
*/
protected T transformM2T(E model){
return WrapperUtil.transformInstance(model, entityClazz);
return WrapperUtil.transformInstance(model, this.getEntityClass());
}
/**
@ -296,7 +297,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
* @return List<T>
*/
protected List<T> transformMs2Ts(List<E> models){
return WrapperUtil.transformInstance(models, entityClazz);
return WrapperUtil.transformInstance(models, this.getEntityClass());
}
/**
@ -342,26 +343,8 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
// ======================== 初始化 ========================
/**
*
*/
@PostConstruct
public void init(){
try {
this.modelClazz = this.getInnerModelClazz();
this.entityClazz = this.getInnerEntityClazz();
}catch (Exception e){
log.error(e.getMessage(),e);
}
}
@Override
public Class<T> getEntityClazz() {
return entityClazz;
}
@Override
public Class<E> getModelClazz() {
public Class<E> getModelClass() {
return modelClazz;
}
@ -371,56 +354,8 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseEnt
*/
@SuppressWarnings("unchecked")
public Class<E> getInnerModelClazz(){
String typeName = "E";
Class<E> tClass = null;
Map<Type, Type> typeMap = TypeUtil.getTypeMap(this.getClass());
for (Map.Entry<Type, Type> typeTypeEntry : typeMap.entrySet()) {
Type entryKey = typeTypeEntry.getKey();
Type entryValue = typeTypeEntry.getValue();
// 如果等于当前类型名称则进入
if(entryKey != null && entryValue != null){
if(StringUtils.equals(typeName, entryKey.getTypeName())){
// 小技巧 json 转换 obj 然后 转换成 type对象
Object convert = Convert.convert(entryValue, JSONObject.parse(JSON_TMP));
if(convert instanceof ApiWrapper) {
tClass = (Class<E>) entryValue;
break;
}
}
}
}
return tClass;
}
/**
* Entity Clazz
* @return Class<T>
*/
@SuppressWarnings("unchecked")
private Class<T> getInnerEntityClazz(){
String typeName = "T";
Class<T> tClass = null;
Map<Type, Type> typeMap = TypeUtil.getTypeMap(this.getClass());
for (Map.Entry<Type, Type> typeTypeEntry : typeMap.entrySet()) {
Type entryKey = typeTypeEntry.getKey();
Type entryValue = typeTypeEntry.getValue();
// 如果等于当前类型名称则进入
if(entryKey != null && entryValue != null){
if(StringUtils.equals(typeName, entryKey.getTypeName())){
// 小技巧 json 转换 obj 然后 转换成 type对象
Object convert = Convert.convert(entryValue, JSONObject.parse(JSON_TMP));
if(convert instanceof ApiWrapper) {
tClass = (Class<T>) entryValue;
break;
}
}
}
}
return tClass;
Class<?>[] typeArguments = GenericTypeResolver.resolveTypeArguments(this.getClass(), CrudServiceImpl.class);
return null == typeArguments ? null : (Class<E>) typeArguments[2];
}
}

@ -44,6 +44,13 @@ import java.util.List;
public interface CrudServiceInterface<T extends BaseEntity, E extends ApiWrapper> extends BaseServiceInterface<T> {
/**
* Model Class
* @return Class<E>
*/
Class<E> getModelClass();
/**
*
*
@ -201,19 +208,7 @@ public interface CrudServiceInterface<T extends BaseEntity, E extends ApiWrapper
* @return Page<T>
*/
Page<T,E> findPageNotCount(Page<T,E> page);
/**
* Model Clazz
* @return Class
*/
Class<E> getModelClazz();
/**
* Entity Clazz
* @return Class
*/
Class<T> getEntityClazz();
}

@ -25,7 +25,9 @@ import com.google.common.util.concurrent.Striped;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
@ -37,6 +39,8 @@ import java.util.function.Function;
* 使
*
* Redis String Hash
*
* RedisTemplate LRU cache 穿 N
*
* @author Parker
* @date 2021/12/10 12:39
@ -95,6 +99,11 @@ public final class SecurityCache {
throw new RuntimeException("入参[redisTemplate,key,callbackSource]必填");
}
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 缓存 Object 对象
Object cache = getCacheObject(redisTemplate, key);
// 如果缓存不为空 则直接返回
@ -109,6 +118,11 @@ public final class SecurityCache {
try {
// 尝试获得锁
if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 梅开二度 如果查到后 直接返回
cache = getCacheObject(redisTemplate, key);
// 如果缓存不为空 则直接返回
@ -135,6 +149,68 @@ public final class SecurityCache {
return cache;
}
/**
* TTL
* @param redisTemplate redisTemplate
* @param key
* @param callbackSource
* @return Object
*/
public static Object getByTtl(
final RedisTemplate<String, Object> redisTemplate,
final String key, final Function<String, Object> callbackSource, final int ttl){
if(null == redisTemplate || null == key || null == callbackSource){
throw new RuntimeException("入参[redisTemplate,key,callbackSource]必填");
}
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 缓存 Object 对象
Object cache = getCacheObject(redisTemplate, key);
// 如果缓存不为空 则直接返回
if(null != cache){
return cache;
}
// 如果还没查到缓存 则需要 穿透到 源数据查询
// 开启本地锁
@SuppressWarnings("UnstableApiUsage")
Lock lock = STRIPED.get(key);
try {
// 尝试获得锁
if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 梅开二度 如果查到后 直接返回
cache = getCacheObject(redisTemplate, key);
// 如果缓存不为空 则直接返回
if(null != cache){
return cache;
}
// 如果这时候还没有 则查询源数据
cache = callbackSource.apply(key);
if(null == cache){
// 存储缓存状态
LFU_NULL_CACHE.put(key, CacheStatus.NOT_EXIST);
return null;
}
// 存入 Redis缓存
put(redisTemplate, key, cache, ttl);
}
}catch (Exception e){
log.error(e.getMessage(), e);
}finally {
lock.unlock();
}
return cache;
}
/**
*
* @param redisTemplate redisTemplate
@ -189,7 +265,33 @@ public final class SecurityCache {
LFU_NULL_CACHE.invalidate(key);
}
/**
*
* @param redisTemplate redisTemplate
* @param key
* @param val
* @param seconds
*/
public static void put(
final RedisTemplate<String, Object> redisTemplate,
final String key, final Object val, final Integer seconds) {
if (null == redisTemplate || null == key || null == val) {
throw new RuntimeException("入参[redisTemplate,key,val]必填");
}
String cacheKey = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV);
redisTemplate.opsForValue()
.set(
cacheKey,
val,
seconds,
TimeUnit.SECONDS
);
// 清除本地记录
LFU_NULL_CACHE.invalidate(key);
}
/**
* Hash
@ -208,6 +310,10 @@ public final class SecurityCache {
final String tempKey = key + "_" + field;
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(tempKey)){
return null;
}
// 缓存 Object 对象
Object cache = getHashCacheObject(redisTemplate, key, field);
// 如果缓存不为空 则直接返回
@ -222,6 +328,11 @@ public final class SecurityCache {
try {
// 尝试获得锁
if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(tempKey)){
return null;
}
// 梅开二度 如果查到后 直接返回
cache = getHashCacheObject(redisTemplate, key, field);
// 如果缓存不为空 则直接返回
@ -266,6 +377,10 @@ public final class SecurityCache {
throw new RuntimeException("入参[redisTemplate,key,callbackSource]必填");
}
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 缓存 Object 对象
Map<String, Object> cache = getAllHashCacheObject(redisTemplate, key, null);
// 如果缓存不为空 则直接返回
@ -280,6 +395,11 @@ public final class SecurityCache {
try {
// 尝试获得锁
if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 梅开二度 如果查到后 直接返回
cache = getAllHashCacheObject(redisTemplate, key, null);
// 如果缓存不为空 则直接返回
@ -324,6 +444,10 @@ public final class SecurityCache {
throw new RuntimeException("入参[redisTemplate,key,callbackSourceCount,callbackSource]必填");
}
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 缓存 Object 对象
Map<String, Object> cache = getAllHashCacheObject(redisTemplate, key, callbackSourceCount);
// 如果缓存不为空 则直接返回
@ -338,6 +462,11 @@ public final class SecurityCache {
try {
// 尝试获得锁
if(lock.tryLock(DEFAULT_LOCK_TIME, TimeUnit.SECONDS)){
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
if(isNonExist(key)){
return null;
}
// 梅开二度 如果查到后 直接返回
cache = getAllHashCacheObject(redisTemplate, key, callbackSourceCount);
// 如果缓存不为空 则直接返回
@ -472,48 +601,28 @@ public final class SecurityCache {
/**
*
*
* @param redisTemplate redisTemplate
* @param keys
*/
public static boolean removeMore(
public static boolean remove(
final RedisTemplate<String, Object> redisTemplate,
final String... keys) {
if (null == redisTemplate || null == keys) {
throw new RuntimeException("入参[redisTemplate,keys]必填");
throw new RuntimeException("入参[redisTemplate,key]必填");
}
int count = keys.length;
List<String> removeKeyList = new ArrayList<>();
for (String key : keys) {
boolean isRemove = remove(redisTemplate, key);
if(isRemove){
count--;
}
}
return 0 == count;
}
// 清除本地记录
LFU_NULL_CACHE.invalidate(key);
/**
*
* @param redisTemplate redisTemplate
* @param key
*/
public static boolean remove(
final RedisTemplate<String, Object> redisTemplate,
final String key) {
if (null == redisTemplate || null == key) {
throw new RuntimeException("入参[redisTemplate,key]必填");
removeKeyList.add(StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV));
removeKeyList.add(StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH));
}
// 清除本地记录
LFU_NULL_CACHE.invalidate(key);
String cacheKeyByKv = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV);
String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH);
// 清除缓存
redisTemplate.delete(cacheKeyByKv);
redisTemplate.delete(cacheKeyByHash);
redisTemplate.delete(removeKeyList);
return true;
}
@ -529,13 +638,6 @@ public final class SecurityCache {
private static Object getCacheObject(RedisTemplate<String, Object> redisTemplate, String key) {
Object cache = null;
try {
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
CacheStatus cacheStatus = LFU_NULL_CACHE.get(key, () -> CacheStatus.EXIST);
// 如果不存在 则直接返回空
if(CacheStatus.NOT_EXIST.equals(cacheStatus)){
return null;
}
String cacheKey = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV);
// 从 缓存回调查询数据
@ -555,15 +657,6 @@ public final class SecurityCache {
private static Object getHashCacheObject(RedisTemplate<String, Object> redisTemplate, String key, String field) {
Object cache = null;
try {
final String tempKey = key + "_" + field;
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
CacheStatus cacheStatus = LFU_NULL_CACHE.get(tempKey, () -> CacheStatus.EXIST);
// 如果不存在 则直接返回空
if(CacheStatus.NOT_EXIST.equals(cacheStatus)){
return null;
}
String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH);
// 从 缓存回调查询数据
@ -586,13 +679,6 @@ public final class SecurityCache {
final Function<String, Integer> callbackSourceCount) {
Map<String, Object> cache = null;
try {
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
CacheStatus cacheStatus = LFU_NULL_CACHE.get(key, () -> CacheStatus.EXIST);
// 如果不存在 则直接返回空
if(CacheStatus.NOT_EXIST.equals(cacheStatus)){
return null;
}
String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH);
// 从 缓存回调查询数据
@ -619,6 +705,23 @@ public final class SecurityCache {
return cache;
}
/**
*
* @param key key
* @return boolean
*/
private static boolean isNonExist(String key){
try {
// 先判断本地缓存是否存在 默认为存在(类似于伪布隆过滤)
CacheStatus cacheStatus = LFU_NULL_CACHE.get(key, () -> CacheStatus.EXIST);
// 如果不存在 则直接返回空
return CacheStatus.NOT_EXIST.equals(cacheStatus);
}catch (Exception e){
log.error(e.getMessage(), e);
}
return false;
}
/**
*
*/

@ -0,0 +1,43 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.eventbus;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* EventBus Spring
*
* @author Parker
* @date 202112710:39:16
*/
public abstract class AbstractSpringEventBus implements IEventBus, ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
this.scanConsumer(null);
}
@Override
public void scanConsumer(String packageName) {
context.getBeansOfType(IEventConsumer.class).forEach((k,v)->{
this.addConsumer(v);
});
}
}

@ -0,0 +1,48 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.eventbus;
/**
* EventBus
*
* @author Parker
* @date 202112710:38:24
*/
public interface IEventBus {
/**
*
* @param event
*/
void post(Object event);
/**
*
* @param obj classkey
*/
void addConsumer(Object obj);
/**
*
* @param obj classkey
*/
void removeConsumer(Object obj);
/**
*
* @param packageName
*/
void scanConsumer(String packageName);
}

@ -1,5 +1,5 @@
/**
* Copyright 2018 http://www.renren.io
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@ -13,22 +13,20 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.security.shiro.utils;
package org.opsli.core.eventbus;
/**
* RedisKeys
* EventBus
*
* @author Mark sunlightcs@gmail.com
* @since 3.0.0 2017-07-18
* @author Parker
* @date 2020/9/25 12:19
*/
public class RedisKeys {
public interface IEventConsumer<T> {
public static String getSysConfigKey(String key){
return "system:config:" + key;
}
/**
*
* @param event
*/
void consumer(T event);
public static String getShiroSessionKey(String key){
return "sessionid:" + key;
}
}

@ -43,7 +43,7 @@ import static org.opsli.common.constants.OrderConstants.LIMITER_AOP_SORT;
/**
*
*
* @author
* @author Parker
* @date 2020-09-16
*/
@Slf4j

@ -1,75 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.filters.aspect;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.opsli.core.utils.LogUtil;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import static org.opsli.common.constants.OrderConstants.TOKEN_AOP_SORT;
/**
*
*
* @author parker
* @date 2020-09-16
*/
@Slf4j
@Order(TOKEN_AOP_SORT)
@Aspect
@Component
public class LogAop {
@Pointcut("execution(public * org.opsli..*.*Controller*.*(..))")
public void requestMapping() {
}
/**
* post
* @param point point
*/
@Around("requestMapping()")
public Object tokenAop(ProceedingJoinPoint point) throws Throwable {
// 计时器
TimeInterval timer = DateUtil.timer();
// 执行
Exception exception = null;
// 防止线程抛异常 线程变量不回收 导致oom
Object returnValue;
try {
// 执行正常操作
returnValue = point.proceed();
}catch (Exception e){
exception = e;
throw e;
} finally {
// 花费毫秒数
long timerCount = timer.interval();
//保存日志
LogUtil.saveLog(point, exception, timerCount);
}
return returnValue;
}
}

@ -1,190 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.filters.aspect;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.TypeUtil;
import lombok.extern.slf4j.Slf4j;
import opsli.plugins.crypto.CryptoPlugin;
import opsli.plugins.crypto.enums.CryptoSymmetricType;
import opsli.plugins.crypto.model.CryptoAsymmetric;
import opsli.plugins.crypto.model.CryptoSymmetric;
import opsli.plugins.crypto.strategy.CryptoAsymmetricService;
import opsli.plugins.crypto.strategy.CryptoSymmetricService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.opsli.api.base.encrypt.BaseEncrypt;
import org.opsli.api.base.result.ResultVo;
import org.opsli.common.annotation.LoginCrypto;
import org.opsli.common.exception.ServiceException;
import org.opsli.core.msg.CoreMsg;
import org.opsli.core.options.CryptoConfigFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map;
import static org.opsli.common.constants.OrderConstants.ENCRYPT_ADN_DECRYPT_AOP_SORT;
/**
*
*
* @author parker
* @date 2021-01-23
*/
@Slf4j
@Order(ENCRYPT_ADN_DECRYPT_AOP_SORT)
@Aspect
@Component
public class LoginCryptoAop {
@Pointcut("@annotation(org.opsli.common.annotation.LoginCrypto)")
public void encryptAndDecrypt() {
}
/**
* post
* @param point point
*/
@Around("encryptAndDecrypt()")
public Object encryptAndDecryptHandle(ProceedingJoinPoint point) throws Throwable {
// 获得请求参数
Object[] args = point.getArgs();
// 返回结果
Object returnValue;
MethodSignature signature = (MethodSignature) point.getSignature();
// 获得 方法
Method method = signature.getMethod();
// 获得方法注解
LoginCrypto annotation =
method.getAnnotation(LoginCrypto.class);
// 获得非对称加解密 执行器
CryptoAsymmetricService asymmetric = null;
// 非对称加解密模型
CryptoAsymmetric cryptoAsymmetric = null;
if(annotation != null && annotation.enable()){
asymmetric = CryptoPlugin.getAsymmetric();
cryptoAsymmetric = CryptoConfigFactory.INSTANCE.getCryptoAsymmetric();
}
// 1. 请求解密
if(annotation != null && annotation.enable()){
if(cryptoAsymmetric != null){
enterDecrypt(args, method, asymmetric, cryptoAsymmetric);
}
}
// 2. 执行方法
returnValue = point.proceed(args);
// 3. 返回加密 返回加密为对称加密
if(annotation != null && annotation.enable()){
if(cryptoAsymmetric != null){
CryptoSymmetricService symmetric = CryptoPlugin.getSymmetric();
CryptoSymmetric symmetricModel = symmetric.createNilModel();
symmetricModel.setCryptoType(CryptoSymmetricType.DES);
symmetricModel.setPrivateKey(cryptoAsymmetric.getPublicKey());
// 执行加密操作
returnValue = resultEncrypt(returnValue, symmetric, symmetricModel);
}
}
return returnValue;
}
/**
*
* @param args
* @param method
* @param asymmetric
* @param cryptoModel
*/
private void enterDecrypt(Object[] args, Method method, CryptoAsymmetricService asymmetric, CryptoAsymmetric cryptoModel) {
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
// 参数校验
if(arg instanceof BaseEncrypt){
// 获得加密数据
BaseEncrypt baseEncrypt = (BaseEncrypt) arg;
String encryptData = baseEncrypt.getEncryptData();
// 解密对象
Object dataToObj = asymmetric.decryptToObj(cryptoModel, encryptData);
// 根据方法类型转化对象
Type type = TypeUtil.getParamType(method, i);
Object obj = Convert.convert(type, dataToObj);
// 修改缓存中设备数据 空值不覆盖
Map<String, Object> modelBeanMap = BeanUtil.beanToMap(obj);
modelBeanMap.entrySet().removeIf(entry -> entry.getValue() == null);
// 反射赋值
Field[] fields = ReflectUtil.getFields(arg.getClass());
for (Field f : fields) {
Object val = modelBeanMap.get(f.getName());
if(val == null){
continue;
}
//根据需要,将相关属性赋上默认值
BeanUtil.setProperty(arg, f.getName(), val);
}
}
}
}
/**
*
* @param returnValue
* @param symmetric
* @param cryptoModel
* @return Object
*/
@SuppressWarnings("unchecked")
private Object resultEncrypt(Object returnValue, CryptoSymmetricService symmetric, CryptoSymmetric cryptoModel) {
if(returnValue != null){
try {
// 执行加密过程
if(returnValue instanceof ResultVo){
// 重新赋值 data
ResultVo<Object> ret = (ResultVo<Object>) returnValue;
ret.setData(
symmetric.encrypt(cryptoModel, ret.getData())
);
}else {
returnValue = symmetric.encrypt(cryptoModel, returnValue);
}
}catch (Exception e){
// 非对称加密失败
throw new ServiceException(CoreMsg.OTHER_EXCEPTION_CRYPTO_EN);
}
}
return returnValue;
}
}

@ -38,7 +38,7 @@ import static org.opsli.common.constants.OrderConstants.SEARCH_HIS_AOP_SORT;
/**
* AOP
*
* @author
* @author Parker
* @date 2020-09-16
*/
@Slf4j

@ -0,0 +1,336 @@
package org.opsli.core.filters.interceptor;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import opsli.plugins.crypto.spring.annotation.CryptoMapperField;
import opsli.plugins.crypto.spring.crypto.ICrypto;
import opsli.plugins.crypto.spring.enums.CryptoType;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.opsli.core.autoconfigure.properties.EncryptProperties;
import org.springframework.stereotype.Component;
import java.lang.reflect.*;
import java.time.chrono.ChronoLocalDate;
import java.util.*;
/**
* Mybatis
* <p>
* Signature:
* Signature.type: ExecutorParameterHandlerStatementHandlerResultSetHandler
* Signature.method:
* Signature.args:JAVA
*
* @author Parker
* @date 2022-08-07
*/
@Slf4j
@AllArgsConstructor
@Component
@Intercepts(
{
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
}
)
public class MybatisCryptoInterceptor implements Interceptor {
private final EncryptProperties encryptProperties;
/**
* @param invocation
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
Method method = invocation.getMethod();
switch (method.getName()) {
case "update":
return updateHandle(invocation);
case "query":
return selectHandle(invocation);
default:
return invocation.proceed();
}
}
/**
*
*
* @param invocation
* @return
* @throws Throwable
*/
private Object selectHandle(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
Object parameter = args[1];
RowBounds rowBounds = (RowBounds) args[2];
ResultHandler<Object> resultHandler = (ResultHandler) args[3];
Executor executor = (Executor) invocation.getTarget();
CacheKey cacheKey;
BoundSql boundSql;
//处理参数作为条件查询需要加密
handleParameterOrResult(parameter, CryptoType.ENCRYPT);
//由于逻辑关系,只会进入一次
if (args.length == 4) {
//4 个参数时
boundSql = ms.getBoundSql(parameter);
cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);
} else {
//6 个参数时
cacheKey = (CacheKey) args[4];
boundSql = (BoundSql) args[5];
}
List<Object> resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
for (Object o : resultList) {
handleParameterOrResult(o, CryptoType.DECRYPT);
}
return resultList;
}
/**
*
*
* @param invocation
* @return
* @throws Throwable
*/
private Object updateHandle(Invocation invocation) throws Throwable {
//处理参数
handleParameterOrResult(invocation.getArgs()[1], CryptoType.ENCRYPT);
return invocation.proceed();
}
/**
*
*
* @param object
* @param cryptoType
* @throws IllegalAccessException
*/
private void handleParameterOrResult(Object object, CryptoType cryptoType) throws IllegalAccessException {
HashMap<Field, Object> fieldObjectHashMap = new HashMap<>();
//多个参数
if (object instanceof Map) {
Map paramMap = (Map) object;
Set keySet = paramMap.keySet();
for (Object key : keySet) {
Object o = paramMap.get(key);
if (o != null) {
handleObject(o, o.getClass(), fieldObjectHashMap);
}
}
} else {
if (object != null) {
handleObject(object, object.getClass(), fieldObjectHashMap);
}
}
//统一修改加密解密值
fieldObjectHashMap.keySet().forEach(key -> {
try {
handleString(key, fieldObjectHashMap.get(key), cryptoType);
} catch (Exception e) {
e.printStackTrace();
}
});
}
/**
*
*
* @param type
* @return
*/
private boolean isBase(Type type) {
return boolean.class.equals(type) ||
char.class.equals(type) ||
long.class.equals(type) ||
int.class.equals(type) ||
byte.class.equals(type) ||
short.class.equals(type) ||
double.class.equals(type) ||
float.class.equals(type);
}
/**
*
*
* @param object
* @return
*/
private boolean isFilter(Object object) {
return object == null || object instanceof CharSequence || object instanceof Number || object instanceof Collection || object instanceof Date || object instanceof ChronoLocalDate;
}
/**
*
*
* @param oClass
* @param fields
* @return
*/
private List<Field> mergeField(Class<?> oClass, List<Field> fields) {
if (fields == null) {
fields = new ArrayList<>();
}
Class<?> superclass = oClass.getSuperclass();
if (superclass != null && !superclass.equals(Object.class) && superclass.getDeclaredFields().length > 0) {
mergeField(superclass, fields);
}
for (Field declaredField : oClass.getDeclaredFields()) {
int modifiers = declaredField.getModifiers();
if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers) || Modifier.isVolatile(modifiers) || Modifier.isSynchronized(modifiers)) {
continue;
}
fields.add(declaredField);
}
return fields;
}
/**
* Object
*
* @param obj
* @param oClass
* @throws IllegalAccessException
*/
private void handleObject(Object obj, Class<?> oClass, HashMap<Field, Object> fieldObjectHashMap) throws IllegalAccessException {
//过滤
if (isFilter(obj)) {
return;
}
List<Field> fields = mergeField(oClass, null);
for (Field declaredField : fields) {
//静态属性直接跳过
if (Modifier.isStatic(declaredField.getModifiers())) {
continue;
}
boolean accessible = declaredField.isAccessible();
declaredField.setAccessible(true);
Object value = declaredField.get(obj);
declaredField.setAccessible(accessible);
if (value == null) {
// TODO
continue;
} else if (value instanceof Number) {
// TODO
continue;
} else if (value instanceof String) {
CryptoMapperField annotation = declaredField.getAnnotation(CryptoMapperField.class);
if (annotation != null) {
fieldObjectHashMap.put(declaredField, obj);
}
} else if (value instanceof Collection) {
Collection coll = (Collection) value;
for (Object o : coll) {
if (isFilter(o)) {
//默认集合内类型一致
break;
}
handleObject(o, o.getClass(), fieldObjectHashMap);
}
} else {
handleObject(value, value.getClass(), fieldObjectHashMap);
}
}
}
/**
*
*
* @param field
* @param object
* @param cryptoType
* @throws IllegalAccessException
* @throws InstantiationException
* @throws NoSuchMethodException
* @throws InvocationTargetException
*/
private void handleString(Field field, Object object, CryptoType cryptoType) throws Exception {
boolean accessible = field.isAccessible();
field.setAccessible(true);
Object value = field.get(object);
CryptoMapperField annotation = field.getAnnotation(CryptoMapperField.class);
if (annotation != null) {
String key;
//全局配置的key
String propertiesKey = encryptProperties.getKey();
log.debug("全局key是" + propertiesKey);
//属性上的key
String annotationKey = annotation.key();
log.debug("注解key是" + annotationKey);
if (StrUtil.isNotBlank(annotationKey)) {
key = annotationKey;
} else {
key = propertiesKey;
}
Class<? extends ICrypto> iCryptoImpl = annotation.iCrypto();
ICrypto iCrypto = iCryptoImpl.newInstance();
//解密后的值
String valueResult;
if (cryptoType.equals(CryptoType.DECRYPT)) {
valueResult = iCrypto.decrypt(String.valueOf(value), key);
} else {
valueResult = iCrypto.encrypt(String.valueOf(value), key);
}
log.debug("原值:" + value);
log.debug("现在:" + valueResult);
field.set(object, String.valueOf(valueResult));
field.setAccessible(accessible);
}
}
/**
*
*
* @param target
* @return
*/
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}

@ -27,7 +27,7 @@ import javax.servlet.http.HttpServletResponse;
/**
* , jwt token
*
* @author
* @author Parker
* @date 2021122216:35:20
*/
@Slf4j

@ -20,6 +20,7 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.core.autoconfigure.properties.GlobalProperties;
@ -98,7 +99,8 @@ public class StartPrint {
* @return String
*/
public String getBasePath(){
return NetUtil.getLocalhostStr() + ":" + serverPort + serverContextPath;
return NetUtil.getLocalhostStr() + ":" + serverPort
+ StrUtil.addPrefixIfNot(serverContextPath, "/");
}
/**
@ -107,7 +109,8 @@ public class StartPrint {
*/
public String getRunTime(){
//Level.MINUTE表示精确到分
return DateUtil.formatBetween(DateUtil.parseDateTime(starterDate), DateUtil.date(), BetweenFormatter.Level.MINUTE);
return DateUtil.formatBetween(DateUtil.parseDateTime(starterDate),
DateUtil.date(), BetweenFormatter.Level.MINUTE);
}
// ======================

@ -18,14 +18,9 @@ package org.opsli.core.handler;
import cn.hutool.core.text.StrFormatter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.authz.AuthorizationException;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.base.result.ResultWrapper;
import org.opsli.common.exception.*;
import org.opsli.core.msg.CoreMsg;
import org.opsli.core.msg.TokenMsg;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@ -86,9 +81,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(ServiceException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> businessException(ServiceException e) {
public ResultWrapper<?> businessException(ServiceException e) {
log.warn("业务异常 - 异常编号:{} - 异常信息:{}",e.getCode(),e.getMessage());
return ResultVo.error(e.getCode(), e.getMessage());
return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
}
/**
@ -97,8 +92,8 @@ public class GlobalExceptionHandler {
@ExceptionHandler(EmptyException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> emptyException(EmptyException e) {
return ResultVo.error(e.getCode(), e.getMessage());
public ResultWrapper<?> emptyException(EmptyException e) {
return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
}
/**
@ -107,68 +102,19 @@ public class GlobalExceptionHandler {
@ExceptionHandler(JwtException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> jwtException(JwtException e) {
return ResultVo.error(e.getCode(), e.getMessage());
public ResultWrapper<?> jwtException(JwtException e) {
return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
}
/**
* Shiro
*/
@ExceptionHandler(IncorrectCredentialsException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ResponseBody
public ResultVo<?> incorrectCredentialsException(IncorrectCredentialsException e) {
// token失效请重新登录
return ResultVo.error(e.getMessage());
}
/**
* Shiro
*/
@ExceptionHandler(LockedAccountException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> lockedAccountException(LockedAccountException e) {
// 账号已被锁定,请联系管理员
return ResultVo.error(e.getMessage());
}
/**
* Shiro
*/
@ExceptionHandler(AuthorizationException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> authorizationException(AuthorizationException e) {
// 无权访问该方法
return ResultVo.error(TokenMsg.EXCEPTION_NOT_AUTH.getCode(),
TokenMsg.EXCEPTION_NOT_AUTH.getMessage()
);
}
/**
* Shiro
*/
@ExceptionHandler(UnsupportedTokenException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> unsupportedTokenException(UnsupportedTokenException e) {
// 找不到认证授权器
return ResultVo.error(TokenMsg.EXCEPTION_NOT_REALM.getCode(),
TokenMsg.EXCEPTION_NOT_REALM.getMessage()
);
}
/**
* Token
*/
@ExceptionHandler(TokenException.class)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ResultVo<?> tokenException(TokenException e) {
public ResultWrapper<?> tokenException(TokenException e) {
// Token 异常
return ResultVo.error(e.getCode(), e.getMessage());
return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
}
/**
@ -177,8 +123,8 @@ public class GlobalExceptionHandler {
@ExceptionHandler(WafException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ResultVo<?> wafException(WafException e) {
return ResultVo.error(e.getCode(), e.getMessage());
public ResultWrapper<?> wafException(WafException e) {
return ResultWrapper.getCustomResultWrapper(e.getCode(), e.getMessage());
}
// ============================
@ -189,9 +135,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(NullPointerException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo<?> nullPointerException(NullPointerException e) {
public ResultWrapper<?> nullPointerException(NullPointerException e) {
log.error("空指针异常:{}",e.getMessage(),e);
return ResultVo.error(e.getMessage());
return ResultWrapper.getErrorResultWrapper();
}
@ -201,9 +147,9 @@ public class GlobalExceptionHandler {
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo<?> sqlIntegrityConstraintViolationException(EmptyException e) {
public ResultWrapper<?> sqlIntegrityConstraintViolationException(EmptyException e) {
log.error("数据异常:{}",e.getMessage(),e);
return ResultVo.error(e.getCode(), CoreMsg.SQL_EXCEPTION_INTEGRITY_CONSTRAINT_VIOLATION.getMessage());
return ResultWrapper.getCustomResultWrapper(e.getCode(), CoreMsg.SQL_EXCEPTION_INTEGRITY_CONSTRAINT_VIOLATION.getMessage());
}
/**
@ -212,17 +158,17 @@ public class GlobalExceptionHandler {
@ExceptionHandler(SQLException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo<?> sqlException(SQLException e) {
public ResultWrapper<?> sqlException(SQLException e) {
//log.error("数据异常:{}",e.getMessage(),e);
// 默认值异常
if(StringUtils.contains(e.getMessage(),SQL_EXCEPTION)){
String field = e.getMessage().replaceAll("Field '","")
.replaceAll("' doesn't have a default value","");
String msg = StrFormatter.format(CoreMsg.SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE.getMessage(), field);
return ResultVo.error(CoreMsg.SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE.getCode(), msg);
return ResultWrapper.getCustomResultWrapper(CoreMsg.SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE.getCode(), msg);
}
String msg = StrFormatter.format(CoreMsg.SQL_EXCEPTION_UNKNOWN.getMessage(), e.getMessage());
return ResultVo.error(CoreMsg.SQL_EXCEPTION_UNKNOWN.getCode(), msg);
return ResultWrapper.getCustomResultWrapper(CoreMsg.SQL_EXCEPTION_UNKNOWN.getCode(), msg);
}
}

@ -28,7 +28,7 @@ import java.util.Optional;
/**
*
*
* @author
* @author Parker
* @date 2021122216:22:59
*/
public final class UserContextHolder {

@ -0,0 +1,84 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.annotation;
import org.opsli.core.log.enums.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
*
* @author Parker
* @date 202171520:28:24
*/
@Target({ElementType.METHOD}) //注解作用于方法级别
@Retention(RetentionPolicy.RUNTIME) //运行时起作用
public @interface OperateLogger {
/**
*
*/
boolean loggable() default true;
/**
*
* 使: ${tel}
*/
String description() default "";
/**
*
*/
ModuleEnum module() default ModuleEnum.MODULE_COMMON;
/**
* (enum): select,insert,update,delete
*/
OperationTypeEnum operationType() default OperationTypeEnum.UNKNOWN;
/**
*
*/
LogTypeEnum type() default LogTypeEnum.BACKEND;
/**
*
*/
LogLevelEnum level() default LogLevelEnum.INFO;
/**
* ,
* ALL-, BEFORE-, AFTER-
*/
LogScopeEnum scope() default LogScopeEnum.ALL;
/**
*
*/
boolean db() default false;
/**
*
*/
boolean console() default true;
}

@ -0,0 +1,220 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.aspect;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.opsli.common.utils.MessUtil;
import org.opsli.core.base.dto.LoginUserDto;
import org.opsli.core.holder.UserContextHolder;
import org.opsli.core.log.annotation.OperateLogger;
import org.opsli.core.log.bean.OperationLog;
import org.opsli.core.log.bus.OperationLogEventBus;
import org.opsli.core.log.enums.LogLevelEnum;
import org.opsli.core.log.enums.LogScopeEnum;
import org.opsli.core.utils.UserTokenUtil;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
/**
*
*
* @author Parker
* @date 202171520:28:24
*/
@Slf4j
@Aspect
@Component
@Order(50)
public class OperateLogAspect {
/** 替换条件 */
private static final String RE = "\\$\\{([\\w\\.\\-\\/\\+\\$\\#\\@\\!\\^\\&\\(\\)]+)\\}";
@Resource
private OperationLogEventBus operationLogEventBus;
@Pointcut("@annotation(org.opsli.core.log.annotation.OperateLogger)")
public void operationLog(){}
/**
* MethodInterceptor
*/
@Around("operationLog()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
long time = System.currentTimeMillis();
try {
result = joinPoint.proceed();
return result;
} finally {
time = System.currentTimeMillis() - time;
try {
// 方法执行完成后增加日志
addOperationLog(joinPoint, result, time);
}catch (Exception e){
log.error("LogAspect 操作失败:{}" + e.getMessage());
e.printStackTrace();
}
}
}
/**
*
* @param joinPoint point
* @param result
* @param time
*/
private void addOperationLog(JoinPoint joinPoint, Object result, long time){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
OperateLogger annotation = signature.getMethod()
.getAnnotation(OperateLogger.class);
if(annotation == null || !annotation.loggable()){
return;
}
OperationLog operationLog = new OperationLog();
// 参数
String argsStr = null;
try {
argsStr = JSONUtil.toJsonStr(joinPoint.getArgs());
}catch (Exception ignored){}
// 结果
String resultStr = null;
try {
resultStr = JSONUtil.toJsonStr(result);
}catch (Exception ignored){}
if(LogScopeEnum.REQUEST.equals(annotation.scope())){
operationLog.setArgs(argsStr);
} else if(LogScopeEnum.RESPONSE.equals(annotation.scope())){
operationLog.setReturnValue(resultStr);
} else if(LogScopeEnum.ALL.equals(annotation.scope())){
operationLog.setArgs(argsStr);
operationLog.setReturnValue(resultStr);
}
operationLog.setId(UUID.randomUUID().toString());
operationLog.setRunTime(time);
operationLog.setCreateTime(System.currentTimeMillis());
operationLog.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());
operationLog.setLevel(annotation.level().getValue());
operationLog.setDescription(
// 对当前登录用户和占位符处理
getDetail(
((MethodSignature) joinPoint.getSignature()).getParameterNames(),
joinPoint.getArgs(),
annotation)
);
operationLog.setOperationType(annotation.operationType().getValue());
operationLog.setLogType(annotation.type().getValue());
operationLog.setModuleId(annotation.module().getId());
// 当前Token
Optional<String> tokenOptional = UserContextHolder.getToken();
if(tokenOptional.isPresent()){
LoginUserDto loginUserDto = UserTokenUtil.getLoginUserDto(tokenOptional.get()).orElse(null);
if(null != loginUserDto){
operationLog.setUserId(String.valueOf(loginUserDto.getUid()));
operationLog.setUsername(loginUserDto.getUsername());
operationLog.setRealName(loginUserDto.getNickname());
operationLog.setTenantId(loginUserDto.getTenantId());
}
}
// 输出控制台
if(annotation.console()){
printToConsole(annotation.level(), operationLog);
}
// 存入数据库
if(annotation.db()){
operationLogEventBus.post(operationLog);
}
}
/**
*
* @param level
* @param operationLog
*/
private void printToConsole(LogLevelEnum level, OperationLog operationLog){
switch (level){
case INFO:
log.info("记录日志:{}" , operationLog);
break;
case DEBUG:
log.debug("记录日志:{}" , operationLog);
break;
case WARN:
log.warn("记录日志:{}" , operationLog);
break;
case ERROR:
log.error("记录日志:{}" , operationLog);
break;
case TRACE:
log.trace("记录日志:{}" , operationLog);
break;
default:
break;
}
}
/**
*
* @param argNames
* @param args
* @param annotation
* @return
*/
private String getDetail(String[] argNames, Object[] args, OperateLogger annotation){
Map<String, Object> map = Maps.newHashMap();
for(int i = 0;i < argNames.length;i++){
map.put(argNames[i], args[i]);
}
String description = annotation.description();
try {
// 当前用户信息
Optional<String> tokenOptional = UserContextHolder.getToken();
if(tokenOptional.isPresent()){
LoginUserDto loginUserDto = UserTokenUtil.getLoginUserDto(tokenOptional.get()).orElse(null);
if(null != loginUserDto){
description = "'" + loginUserDto.getNickname() + "'=> " + annotation.description();
}
}
description = MessUtil.getMes(description, RE, "${", "}", map);
}catch (Exception e){
e.printStackTrace();
}
return description;
}
}

@ -0,0 +1,82 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.bean;
import lombok.Data;
import lombok.ToString;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 202171520:28:24
*/
@Data
@ToString
public class OperationLog implements Serializable {
private static final long serialVersionUID = 1L;
/** 日志ID */
private String id;
/** 创建时间 */
private long createTime;
/** 日志等级 */
private String level;
/** 被操作的系统模块 */
private String moduleId;
/** 方法名 */
private String method;
/** 参数 */
private String args;
/** 操作人id */
private String userId;
/** 操作人用户名 */
private String username;
/** 真实姓名 */
private String realName;
/** 日志描述 */
private String description;
/** 操作类型 */
private String operationType;
/** 方法运行时间 */
private Long runTime;
/** 方法返回值 */
private String returnValue;
/** 租户ID */
private String tenantId;
/**
*
*/
private String logType;
}

@ -0,0 +1,72 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.bus;
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.SubscriberExceptionContext;
import com.google.common.eventbus.SubscriberExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.opsli.common.thread.ThreadPoolFactory;
import org.opsli.core.eventbus.AbstractSpringEventBus;
import org.springframework.stereotype.Component;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 线
* @author
* @date 202112710:42:39
*/
@Component
@Slf4j
public class OperationLogEventBus extends AbstractSpringEventBus implements SubscriberExceptionHandler {
private final EventBus eventBus;
public OperationLogEventBus() {
// 异步事件配置线程池
eventBus = new AsyncEventBus(
ThreadPoolFactory.createInitThreadPool(5, 10, 60, TimeUnit.SECONDS,
1024, "Operation-Log-Event-Bus",
new ThreadPoolExecutor.CallerRunsPolicy()
)
, this
);
}
@Override
public void post(Object event) {
eventBus.post(event);
}
@Override
public void addConsumer(Object obj) {
eventBus.register(obj);
}
@Override
public void removeConsumer(Object obj) {
eventBus.unregister(obj);
}
@Override
public void handleException(Throwable exception, SubscriberExceptionContext context) {
log.error("user event handler exception", exception);
}
}

@ -13,23 +13,29 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.annotation;
package org.opsli.core.log.enums;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
*
*
*
* @author Parker
* @date 2020-09-22 17:07
* @date 202171520:28:24
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPermissionsCus {
@Getter
@AllArgsConstructor
public enum LogLevelEnum {
String[] value();
/**
*
*/
DEBUG("-1"),
INFO("0"),
WARN("1"),
ERROR("2"),
TRACE("3");
private final String value;
}

@ -13,25 +13,31 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.annotation;
import java.lang.annotation.*;
package org.opsli.core.log.enums;
/**
*
*
*
*
*
* @author Parker
* @date 202151814:46:02
* @date 202171520:28:24
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoginCrypto {
public enum LogScopeEnum {
/**
*
*/
ALL(0),
REQUEST(1),
RESPONSE(2)
;
private final int value;
/** 加密启用状态 */
boolean enable() default true;
public int getValue() {
return value;
}
LogScopeEnum(int value) {
this.value = value;
}
}

@ -13,25 +13,36 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
package org.opsli.core.log.enums;
/**
*
* @author parker
* @date 2020-09-12
*
*
* @author Parker
* @date 202171520:28:24
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnableLog {
public enum LogTypeEnum {
/** WEB */
WEB("0"),
/** 客户端 */
CLIENT("1"),
/** 后端 */
BACKEND("2"),
/** 程序自动 */
AUTO("3")
;
private final String value;
/** 标题 */
String title() default "";
public String getValue() {
return value;
}
LogTypeEnum(String value) {
this.value = value;
}
}

@ -0,0 +1,66 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.enums;
/**
*
*
* @author Parker
* @date 202171520:19:27
*/
public enum ModuleEnum {
/** 模块 */
MODULE_UNKNOWN("-1", "未知(请配置模块)"),
MODULE_COMMON("00", "公共模块"),
MODULE_USER("01", "用户模块"),
MODULE_ROLE("02", "角色模块"),
MODULE_MENU("03", "菜单模块"),
MODULE_ORG("04", "组织模块"),
MODULE_DICT("05", "字典模块"),
MODULE_TENANT("06", "租户模块"),
MODULE_AREA("07", "地区模块"),
MODULE_MONITOR("08", "监控模块"),
MODULE_GENERATOR("09", "代码生成器"),
MODULE_OPERATION("11", "行为日志"),
MODULE_TEST("100", "测试模块"),
MODULE_TEST_USER("101", "测试用户模块"),
MODULE_TEST_CAR("102", "测试汽车模块"),
;
private final String id;
private final String name;
ModuleEnum(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}

@ -0,0 +1,48 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.log.enums;
/**
*
*
* @author Parker
* @date 202171520:27:27
*/
public enum OperationTypeEnum {
/**
*
*/
UNKNOWN("unknown"),
DELETE("delete"),
SELECT("select"),
UPDATE("update"),
INSERT("insert");
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
OperationTypeEnum(String s) {
this.value = s;
}
}

@ -30,14 +30,20 @@ public enum TokenMsg implements BaseMsg {
*/
EXCEPTION_TOKEN_CREATE_ERROR(12000,"生成Token失败"),
EXCEPTION_TOKEN_CREATE_LIMIT_ERROR(12001,"您的账号已在其他设备登录"),
EXCEPTION_TOKEN_LOSE_EFFICACY(401,"Token失效请重新登录"),
EXCEPTION_TOKEN_LOSE_EFFICACY(401,"凭证已过期,请重新登陆"),
AUTH_CREDENTIALS_INVALID(100208, "凭证已过期,请重新登陆"),
AUTH_AUTH_INVALID(100209, "认证失败,请重新登陆"),
/**
*
*/
EXCEPTION_CAPTCHA_CERTIFICATE_ERROR(12097, "凭证验证失败,请刷新重试"),
EXCEPTION_CAPTCHA_ARGS_NULL(12098, "参数异常"),
EXCEPTION_CAPTCHA_OFTEN(12099, "已获取验证码,请勿频繁获取"),
EXCEPTION_CAPTCHA_ERROR(12100,"验证码不正确!"),
EXCEPTION_CAPTCHA_NULL(12201, "验证码已失效"),
EXCEPTION_CAPTCHA_NULL(12201, "验证码已失效, 请重新生成"),
EXCEPTION_CAPTCHA_UUID_NULL(12202, "验证码UUID为空"),
EXCEPTION_CAPTCHA_CODE_NULL(12203, "验证码为空"),
EXCEPTION_LOGIN_ACCOUNT_NO(12101,"账号或密码不正确!"),

@ -0,0 +1,81 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.options;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.opsli.common.annotation.OptionDict;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.enums.ValidatorType;
import org.opsli.core.utils.OptionsUtil;
import org.opsli.core.utils.ValidatorUtil;
import java.io.Serializable;
/**
* -
*
* @author Parker
* @date 2020-09-19 20:03
*/
public enum SmsAliYunCaptchaConfigFactory {
/** 实例对象 */
INSTANCE;
/**
*
* @return LocalConfig
*/
public SmsAliYunCaptchaConfigOption getConfig() {
SmsAliYunCaptchaConfigOption option = new SmsAliYunCaptchaConfigOption();
// 获得缓存参数配置
OptionsUtil.getOptionByBean(option);
// 验证配置
ValidatorUtil.verify(option);
// 转化对象
return option;
}
// =======================
/**
*
*
* @author Parker
*/
@Data
public static class SmsAliYunCaptchaConfigOption implements Serializable {
private static final long serialVersionUID = 1L;
/** 模版编码 */
@ApiModelProperty(value = "模版编码")
@Validator({ValidatorType.IS_NOT_NULL})
@OptionDict("sms_aliyun_captcha_template_code")
private String templateCode;
/** 签名 */
@ApiModelProperty(value = "签名")
@Validator({ValidatorType.IS_NOT_NULL})
@OptionDict("sms_aliyun_captcha_sign")
private String sign;
}
}

@ -0,0 +1,81 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.options;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.opsli.common.annotation.OptionDict;
import org.opsli.common.annotation.validator.Validator;
import org.opsli.common.enums.ValidatorType;
import org.opsli.core.utils.OptionsUtil;
import org.opsli.core.utils.ValidatorUtil;
import java.io.Serializable;
/**
*
*
* @author Parker
* @date 2020-09-19 20:03
*/
public enum SmsAliYunConfigFactory {
/** 实例对象 */
INSTANCE;
/**
*
* @return LocalConfig
*/
public SmsAliYunConfigOption getConfig() {
SmsAliYunConfigOption option = new SmsAliYunConfigOption();
// 获得缓存参数配置
OptionsUtil.getOptionByBean(option);
// 验证配置
ValidatorUtil.verify(option);
// 转化对象
return option;
}
// =======================
/**
*
*
* @author Parker
*/
@Data
public static class SmsAliYunConfigOption implements Serializable {
private static final long serialVersionUID = 1L;
/** access_key */
@ApiModelProperty(value = "阿里云AccessKey")
@Validator({ValidatorType.IS_NOT_NULL})
@OptionDict("sms_aliyun_access_key")
private String accessKey;
/** access_key_secret */
@ApiModelProperty(value = "阿里云AccessKeySecret")
@Validator({ValidatorType.IS_NOT_NULL})
@OptionDict("sms_aliyun_access_key_secret")
private String accessKeySecret;
}
}

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

Loading…
Cancel
Save