!84 迁移vue版本5.x部分功能更新

Merge pull request !84 from Yjoioooo/2.X
dev
疯狂的狮子Li 3 years ago committed by Gitee
commit d903f34e9f
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F

@ -55,7 +55,7 @@ dubbo:
check: false
scan:
# 接口实现类扫描
base-packages: com.ruoyi.**.dubbo
base-packages: org.dromara.**.dubbo
# 自定义配置
custom:
# 全局请求log
@ -195,11 +195,11 @@ sa-token:
mybatis-plus:
# 不支持多包, 如有需要可在注解配置 或 提升扫包等级
# 例如 com.**.**.mapper
mapperPackage: com.ruoyi.**.mapper
mapperPackage: org.dromara.**.mapper
# 对应的 XML 文件位置
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 实体扫描多个package用逗号或者分号分隔
typeAliasesPackage: com.ruoyi.**.domain
typeAliasesPackage: org.dromara.**.domain
# 启动时是否检查 MyBatis XML 文件的存在,默认不检查
checkConfigLocation: false
configuration:
@ -207,7 +207,7 @@ mybatis-plus:
mapUnderscoreToCamelCase: true
# MyBatis 自动映射策略
# NONE不启用 PARTIAL只对非嵌套 resultMap 自动映射 FULL对所有 resultMap 自动映射
autoMappingBehavior: PARTIAL
autoMappingBehavior: FULL
# MyBatis 自动映射时未知列或未知属性处理策
# NONE不做处理 WARNING打印相关警告 FAILING抛出异常和详细信息
autoMappingUnknownColumnBehavior: NONE
@ -300,3 +300,17 @@ seata:
server-addr: ${spring.cloud.nacos.server-addr}
group: ${spring.cloud.nacos.discovery.group}
namespace: ${spring.profiles.active}
# 多租户配置
tenant:
# 是否开启
enable: true
# 排除表
excludes:
- sys_menu
- sys_tenant
- sys_tenant_package
- sys_role_dept
- sys_role_menu
- sys_user_post
- sys_user_role

@ -26,6 +26,7 @@ security:
- /auth/smsLogin
- /auth/xcxLogin
- /auth/register
- /auth/tenant/list
- /resource/sms/code
- /*/v3/api-docs
- /csrf
@ -54,7 +55,7 @@ spring:
- id: ruoyi-gen
uri: lb://ruoyi-gen
predicates:
- Path=/code/**
- Path=/tool/**
filters:
- StripPrefix=1
# 系统模块
@ -64,6 +65,13 @@ spring:
- Path=/system/**
filters:
- StripPrefix=1
# 监控模块
- id: ruoyi-monitor
uri: lb://ruoyi-system
predicates:
- Path=/monitor/**
filters:
- StripPrefix=1
# 资源服务
- id: ruoyi-resource
uri: lb://ruoyi-resource

@ -31,7 +31,7 @@ gen:
# 作者
author: ruoyi
# 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
packageName: com.ruoyi.system
packageName: org.dromara.system
# 自动去除表前缀默认是false
autoRemovePre: false
# 表前缀(生成类名不会包含表前缀,多个用逗号分隔)

@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-cloud-plus</artifactId>
<version>1.6.0</version>
@ -41,6 +41,9 @@
<elasticsearch.version>7.14.0</elasticsearch.version>
<skywalking-toolkit.version>8.14.0</skywalking-toolkit.version>
<bouncycastle.version>1.72</bouncycastle.version>
<alibaba-ttl.version>2.14.2</alibaba-ttl.version>
<mapstruct-plus.version>1.2.1</mapstruct-plus.version>
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
<!-- 离线IP地址定位库 -->
<ip2region.version>2.7.0</ip2region.version>
@ -101,7 +104,7 @@
<!-- SpringCloud Alibaba 微服务 -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-alibaba-bom</artifactId>
<version>${ruoyi.version}</version>
<type>pom</type>
@ -128,7 +131,7 @@
<!-- common 的依赖配置-->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-bom</artifactId>
<version>${ruoyi.version}</version>
<type>pom</type>
@ -137,7 +140,7 @@
<!-- api 的依赖配置-->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-api-bom</artifactId>
<version>${ruoyi.version}</version>
<type>pom</type>
@ -357,6 +360,20 @@
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>${alibaba-ttl.version}</version>
</dependency>
<dependency>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
<version>${mapstruct-plus.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
@ -401,6 +418,16 @@
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${spring-boot.version}</version>
</path>
<path>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-processor</artifactId>
<version>${mapstruct-plus.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${mapstruct-plus.lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>

@ -2,7 +2,7 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-cloud-plus</artifactId>
<version>1.6.0</version>
</parent>

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-api-bom</artifactId>
<packaging>pom</packaging>
<version>1.6.0</version>
@ -18,14 +18,14 @@
<dependencies>
<!-- 系统接口 -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-api-system</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 资源服务接口 -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-api-resource</artifactId>
<version>${project.version}</version>
</dependency>

@ -3,7 +3,7 @@
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-api</artifactId>
<version>1.6.0</version>
</parent>
@ -19,7 +19,7 @@
<!-- RuoYi Common Core-->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-core</artifactId>
</dependency>

@ -1,7 +1,7 @@
package com.ruoyi.resource.api;
package org.dromara.resource.api;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.resource.api.domain.SysFile;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.resource.api.domain.RemoteFile;
/**
*
@ -16,7 +16,7 @@ public interface RemoteFileService {
* @param file
* @return
*/
SysFile upload(String name, String originalFilename, String contentType, byte[] file) throws ServiceException;
RemoteFile upload(String name, String originalFilename, String contentType, byte[] file) throws ServiceException;
/**
* ossIdurl

@ -1,6 +1,6 @@
package com.ruoyi.resource.api;
package org.dromara.resource.api;
import com.ruoyi.common.core.exception.ServiceException;
import org.dromara.common.core.exception.ServiceException;
import java.io.File;
import java.util.List;

@ -1,8 +1,7 @@
package com.ruoyi.resource.api;
package org.dromara.resource.api;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.resource.api.domain.SysFile;
import com.ruoyi.resource.api.domain.SysSms;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.resource.api.domain.RemoteSms;
import java.util.Map;
@ -20,6 +19,6 @@ public interface RemoteSmsService {
* @param templateId id
* @param param
*/
SysSms send(String phones, String templateId, Map<String, String> param) throws ServiceException;
RemoteSms send(String phones, String templateId, Map<String, String> param) throws ServiceException;
}

@ -1,4 +1,4 @@
package com.ruoyi.resource.api.domain;
package org.dromara.resource.api.domain;
import lombok.Data;
@ -10,7 +10,7 @@ import java.io.Serializable;
* @author ruoyi
*/
@Data
public class SysFile implements Serializable {
public class RemoteFile implements Serializable {
private static final long serialVersionUID = 1L;

@ -1,4 +1,4 @@
package com.ruoyi.resource.api.domain;
package org.dromara.resource.api.domain;
import lombok.Data;
@ -10,7 +10,7 @@ import java.io.Serializable;
* @author ruoyi
*/
@Data
public class SysSms implements Serializable {
public class RemoteSms implements Serializable {
private static final long serialVersionUID = 1L;

@ -3,7 +3,7 @@
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-api</artifactId>
<version>1.6.0</version>
</parent>
@ -19,12 +19,12 @@
<!-- RuoYi Common Core-->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-core</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-excel</artifactId>
</dependency>

@ -1,102 +0,0 @@
package com.ruoyi.system.api.domain;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.web.domain.BaseEntity;
import com.ruoyi.common.excel.annotation.ExcelDictFormat;
import com.ruoyi.common.excel.convert.ExcelDictConvert;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
/**
* sys_dict_data
*
* @author Lion Li
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@TableName("sys_dict_data")
@ExcelIgnoreUnannotated
public class SysDictData extends BaseEntity {
/**
*
*/
@ExcelProperty(value = "字典编码")
@TableId(value = "dict_code")
private Long dictCode;
/**
*
*/
@ExcelProperty(value = "字典排序")
private Integer dictSort;
/**
*
*/
@ExcelProperty(value = "字典标签")
@NotBlank(message = "字典标签不能为空")
@Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符")
private String dictLabel;
/**
*
*/
@ExcelProperty(value = "字典键值")
@NotBlank(message = "字典键值不能为空")
@Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符")
private String dictValue;
/**
*
*/
@ExcelProperty(value = "字典类型")
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符")
private String dictType;
/**
*
*/
@Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符")
private String cssClass;
/**
*
*/
private String listClass;
/**
* Y N
*/
@ExcelProperty(value = "是否默认", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_yes_no")
private String isDefault;
/**
* 0 1
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_normal_disable")
private String status;
/**
*
*/
private String remark;
public boolean getDefault() {
return UserConstants.YES.equals(this.isDefault);
}
}

@ -1,67 +0,0 @@
package com.ruoyi.system.api.domain;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.web.domain.BaseEntity;
import com.ruoyi.common.excel.annotation.ExcelDictFormat;
import com.ruoyi.common.excel.convert.ExcelDictConvert;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
/**
* sys_dict_type
*
* @author Lion Li
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@TableName("sys_dict_type")
@ExcelIgnoreUnannotated
public class SysDictType extends BaseEntity {
/**
*
*/
@ExcelProperty(value = "字典主键")
@TableId(value = "dict_id")
private Long dictId;
/**
*
*/
@ExcelProperty(value = "字典名称")
@NotBlank(message = "字典名称不能为空")
@Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符")
private String dictName;
/**
*
*/
@ExcelProperty(value = "字典类型")
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
@Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
private String dictType;
/**
* 0 1
*/
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_normal_disable")
private String status;
/**
*
*/
private String remark;
}

@ -1,129 +0,0 @@
package com.ruoyi.system.api.domain;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.web.domain.BaseEntity;
import com.ruoyi.common.excel.annotation.ExcelDictFormat;
import com.ruoyi.common.excel.convert.ExcelDictConvert;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Set;
/**
* sys_role
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@TableName("sys_role")
@ExcelIgnoreUnannotated
public class SysRole extends BaseEntity {
/**
* ID
*/
@ExcelProperty(value = "角色序号")
@TableId(value = "role_id")
private Long roleId;
/**
*
*/
@ExcelProperty(value = "角色名称")
@NotBlank(message = "角色名称不能为空")
@Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符")
private String roleName;
/**
*
*/
@ExcelProperty(value = "角色权限")
@NotBlank(message = "权限字符不能为空")
@Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符")
private String roleKey;
/**
*
*/
@ExcelProperty(value = "角色排序")
@NotNull(message = "显示顺序不能为空")
private Integer roleSort;
/**
* 12345
*/
@ExcelProperty(value = "数据范围", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
private String dataScope;
/**
* 0 1
*/
private Boolean menuCheckStrictly;
/**
* 0 1
*/
private Boolean deptCheckStrictly;
/**
* 0 1
*/
@ExcelProperty(value = "角色状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_normal_disable")
private String status;
/**
* 0 2
*/
@TableLogic
private String delFlag;
/**
*
*/
private String remark;
/**
*
*/
@TableField(exist = false)
private boolean flag = false;
/**
*
*/
@TableField(exist = false)
private Long[] menuIds;
/**
*
*/
@TableField(exist = false)
private Long[] deptIds;
public SysRole(Long roleId) {
this.roleId = roleId;
}
/**
*
*/
public boolean isAdmin() {
return UserConstants.ADMIN_ID.equals(this.roleId);
}
}

@ -1,6 +1,6 @@
package com.ruoyi.system.api;
package org.dromara.system.api;
import com.ruoyi.system.api.domain.SysDictData;
import org.dromara.system.api.domain.vo.RemoteDictDataVo;
import java.util.List;
@ -17,5 +17,5 @@ public interface RemoteDictService {
* @param dictType
* @return
*/
List<SysDictData> selectDictDataByType(String dictType);
List<RemoteDictDataVo> selectDictDataByType(String dictType);
}

@ -1,7 +1,7 @@
package com.ruoyi.system.api;
package org.dromara.system.api;
import com.ruoyi.system.api.domain.SysLogininfor;
import com.ruoyi.system.api.domain.SysOperLog;
import org.dromara.system.api.domain.bo.RemoteLogininforBo;
import org.dromara.system.api.domain.bo.RemoteOperLogBo;
/**
*
@ -16,7 +16,7 @@ public interface RemoteLogService {
* @param sysOperLog
* @return
*/
Boolean saveLog(SysOperLog sysOperLog);
void saveLog(RemoteOperLogBo sysOperLog);
/**
* 访
@ -24,5 +24,5 @@ public interface RemoteLogService {
* @param sysLogininfor 访
* @return
*/
Boolean saveLogininfor(SysLogininfor sysLogininfor);
void saveLogininfor(RemoteLogininforBo sysLogininfor);
}

@ -0,0 +1,26 @@
package org.dromara.system.api;
import org.dromara.system.api.domain.vo.RemoteTenantVo;
import java.util.List;
/**
* @author zhujie
*/
public interface RemoteTenantService {
/**
* id
* @param tenantId id
* @return
*/
RemoteTenantVo queryByTenantId(String tenantId);
/**
*
* @return
*/
List<RemoteTenantVo> queryList();
}

@ -1,9 +1,9 @@
package com.ruoyi.system.api;
package org.dromara.system.api;
import com.ruoyi.common.core.exception.user.UserException;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.api.model.XcxLoginUser;
import org.dromara.common.core.exception.user.UserException;
import org.dromara.system.api.domain.bo.RemoteUserBo;
import org.dromara.system.api.model.LoginUser;
import org.dromara.system.api.model.XcxLoginUser;
/**
*
@ -47,10 +47,10 @@ public interface RemoteUserService {
/**
*
*
* @param sysUser
* @param remoteUserBo
* @return
*/
Boolean registerUserInfo(SysUser sysUser);
Boolean registerUserInfo(RemoteUserBo remoteUserBo);
/**
* userId

@ -1,4 +1,4 @@
package com.ruoyi.system.api.domain;
package org.dromara.system.api.domain;
import lombok.Data;
import lombok.NoArgsConstructor;

@ -0,0 +1,75 @@
package org.dromara.system.api.domain.bo;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 访 sys_logininfor
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
public class RemoteLogininforBo implements Serializable {
/**
* 访ID
*/
private Long infoId;
/**
*
*/
private String tenantId;
/**
*
*/
private String userName;
/**
* IP
*/
private String ipaddr;
/**
*
*/
private String loginLocation;
/**
*
*/
private String browser;
/**
*
*/
private String os;
/**
* 0 1
*/
private String status;
/**
*
*/
private String msg;
/**
* 访
*/
private Date loginTime;
/**
*
*/
private Map<String, Object> params = new HashMap<>();
}

@ -0,0 +1,115 @@
package org.dromara.system.api.domain.bo;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* oper_log
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
public class RemoteOperLogBo implements Serializable {
/**
*
*/
private Long operId;
/**
*
*/
private String tenantId;
/**
*
*/
private String title;
/**
* 0 1 2 3
*/
private Integer businessType;
/**
*
*/
private String method;
/**
*
*/
private String requestMethod;
/**
* 0 1 2
*/
private Integer operatorType;
/**
*
*/
private String operName;
/**
*
*/
private String deptName;
/**
* URL
*/
private String operUrl;
/**
*
*/
private String operIp;
/**
*
*/
private String operLocation;
/**
*
*/
private String operParam;
/**
*
*/
private String jsonResult;
/**
* 0 1
*/
private Integer status;
/**
*
*/
private String errorMsg;
/**
*
*/
private Date operTime;
/**
*
*/
private Long costTime;
/**
*
*/
private Map<String, Object> params = new HashMap<>();
}

@ -0,0 +1,126 @@
package org.dromara.system.api.domain.bo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.dromara.common.core.annotation.Sensitive;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.enums.SensitiveStrategy;
import org.dromara.common.core.web.domain.BaseEntity;
import org.dromara.common.core.xss.Xss;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.util.Date;
/**
* sys_user
*
* @author Michelle.Chung
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class RemoteUserBo extends BaseEntity {
/**
* ID
*/
private Long userId;
/**
* ID
*/
private String tenantId;
/**
* ID
*/
private Long deptId;
/**
*
*/
@Xss(message = "用户账号不能包含脚本字符")
@NotBlank(message = "用户账号不能为空")
@Size(min = 0, max = 30, message = "用户账号长度不能超过{max}个字符")
private String userName;
/**
*
*/
@Xss(message = "用户昵称不能包含脚本字符")
@Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符")
private String nickName;
/**
* sys_user
*/
private String userType;
/**
*
*/
@Sensitive(strategy = SensitiveStrategy.EMAIL)
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符")
private String email;
/**
*
*/
@Sensitive(strategy = SensitiveStrategy.PHONE)
private String phonenumber;
/**
* 0 1 2
*/
private String sex;
/**
*
*/
private Long avatar;
/**
*
*/
private String password;
/**
* 0 1
*/
private String status;
/**
* IP
*/
private String loginIp;
/**
*
*/
private Date loginDate;
/**
*
*/
private String remark;
/**
* ID
*/
private Long roleId;
public RemoteUserBo(Long userId) {
this.userId = userId;
}
public boolean isSuperAdmin() {
return UserConstants.SUPER_ADMIN_ID.equals(this.userId);
}
}

@ -0,0 +1,74 @@
package org.dromara.system.api.domain.vo;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* sys_dict_data
*
* @author Michelle.Chung
*/
@Data
public class RemoteDictDataVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
private Long dictCode;
/**
*
*/
private Integer dictSort;
/**
*
*/
private String dictLabel;
/**
*
*/
private String dictValue;
/**
*
*/
private String dictType;
/**
*
*/
private String cssClass;
/**
*
*/
private String listClass;
/**
* Y N
*/
private String isDefault;
/**
* 0 1
*/
private String status;
/**
*
*/
private String remark;
/**
*
*/
private Date createTime;
}

@ -0,0 +1,89 @@
package org.dromara.system.api.domain.vo;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
*
*
* @author zhujie
*/
@Data
public class RemoteTenantVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
private Long id;
/**
*
*/
private String tenantId;
/**
*
*/
private String contactUserName;
/**
*
*/
private String contactPhone;
/**
*
*/
private String companyName;
/**
*
*/
private String licenseNumber;
/**
*
*/
private String address;
/**
*
*/
private String domain;
/**
*
*/
private String intro;
/**
*
*/
private String remark;
/**
*
*/
private Long packageId;
/**
*
*/
private Date expireTime;
/**
* -1
*/
private Long accountCount;
/**
* 0 1
*/
private String status;
}

@ -1,7 +1,7 @@
package com.ruoyi.system.api.model;
package org.dromara.system.api.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ruoyi.common.core.constant.CacheConstants;
import org.dromara.common.core.constant.CacheConstants;
import lombok.Data;
import lombok.NoArgsConstructor;
@ -19,6 +19,11 @@ import java.util.Set;
public class LoginUser implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private String tenantId;
/**
* ID
*/

@ -1,4 +1,4 @@
package com.ruoyi.system.api.model;
package org.dromara.system.api.model;
import lombok.Data;
import lombok.NoArgsConstructor;

@ -1,4 +1,4 @@
package com.ruoyi.system.api.model;
package org.dromara.system.api.model;
import lombok.Data;
import lombok.EqualsAndHashCode;

@ -2,7 +2,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-cloud-plus</artifactId>
<version>1.6.0</version>
</parent>
@ -29,63 +29,73 @@
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-sentinel</artifactId>
</dependency>
<!-- RuoYi Common Security-->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-security</artifactId>
</dependency>
<!-- RuoYi Common Log -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-log</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-doc</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-web</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-dubbo</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-seata</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-tenant</artifactId>
<exclusions>
<exclusion>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-mybatis</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 自定义负载均衡(多团队开发使用) -->
<!-- <dependency>-->
<!-- <groupId>com.ruoyi</groupId>-->
<!-- <groupId>org.dromara</groupId>-->
<!-- <artifactId>ruoyi-common-loadbalancer</artifactId>-->
<!-- </dependency>-->
<!-- ELK 日志收集 -->
<!-- <dependency>-->
<!-- <groupId>com.ruoyi</groupId>-->
<!-- <groupId>org.dromara</groupId>-->
<!-- <artifactId>ruoyi-common-logstash</artifactId>-->
<!-- </dependency>-->
<!-- skywalking 日志收集 -->
<!-- <dependency>-->
<!-- <groupId>com.ruoyi</groupId>-->
<!-- <groupId>org.dromara</groupId>-->
<!-- <artifactId>ruoyi-common-skylog</artifactId>-->
<!-- </dependency>-->
<!-- prometheus 监控 -->
<!-- <dependency>-->
<!-- <groupId>com.ruoyi</groupId>-->
<!-- <groupId>org.dromara</groupId>-->
<!-- <artifactId>ruoyi-common-prometheus</artifactId>-->
<!-- </dependency>-->

@ -1,111 +0,0 @@
package com.ruoyi.auth.controller;
import com.ruoyi.auth.form.EmailLoginBody;
import com.ruoyi.auth.form.LoginBody;
import com.ruoyi.auth.form.RegisterBody;
import com.ruoyi.auth.form.SmsLoginBody;
import com.ruoyi.auth.service.SysLoginService;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.domain.R;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotBlank;
import java.util.HashMap;
import java.util.Map;
/**
* token
*
* @author Lion Li
*/
@Validated
@RequiredArgsConstructor
@RestController
public class TokenController {
private final SysLoginService sysLoginService;
/**
*
*/
@PostMapping("login")
public R<Map<String, Object>> login(@Validated @RequestBody LoginBody form) {
// 用户登录
String accessToken = sysLoginService.login(form.getUsername(), form.getPassword());
// 接口返回信息
Map<String, Object> rspMap = new HashMap<>();
rspMap.put(Constants.ACCESS_TOKEN, accessToken);
return R.ok(rspMap);
}
/**
*
*
* @param smsLoginBody
* @return
*/
@PostMapping("/smsLogin")
public R<Map<String, Object>> smsLogin(@Validated @RequestBody SmsLoginBody smsLoginBody) {
Map<String, Object> ajax = new HashMap<>();
// 生成令牌
String token = sysLoginService.smsLogin(smsLoginBody.getPhonenumber(), smsLoginBody.getSmsCode());
ajax.put(Constants.ACCESS_TOKEN, token);
return R.ok(ajax);
}
/**
*
*
* @param body
* @return
*/
@PostMapping("/emailLogin")
public R<Map<String, Object>> emailLogin(@Validated @RequestBody EmailLoginBody body) {
Map<String, Object> ajax = new HashMap<>();
// 生成令牌
String token = sysLoginService.emailLogin(body.getEmail(), body.getEmailCode());
ajax.put(Constants.ACCESS_TOKEN, token);
return R.ok(ajax);
}
/**
* ()
*
* @param xcxCode code
* @return
*/
@PostMapping("/xcxLogin")
public R<Map<String, Object>> xcxLogin(@NotBlank(message = "{xcx.code.not.blank}") String xcxCode) {
Map<String, Object> ajax = new HashMap<>();
// 生成令牌
String token = sysLoginService.xcxLogin(xcxCode);
ajax.put(Constants.ACCESS_TOKEN, token);
return R.ok(ajax);
}
/**
*
*/
@DeleteMapping("logout")
public R<Void> logout() {
sysLoginService.logout();
return R.ok();
}
/**
*
*/
@PostMapping("register")
public R<Void> register(@RequestBody RegisterBody registerBody) {
// 用户注册
sysLoginService.register(registerBody);
return R.ok();
}
}

@ -1,233 +0,0 @@
package com.ruoyi.auth.service;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.ruoyi.auth.form.RegisterBody;
import com.ruoyi.auth.properties.UserPasswordProperties;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.enums.DeviceType;
import com.ruoyi.common.core.enums.LoginType;
import com.ruoyi.common.core.enums.UserType;
import com.ruoyi.common.core.exception.user.CaptchaExpireException;
import com.ruoyi.common.core.exception.user.UserException;
import com.ruoyi.common.core.utils.MessageUtils;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.ip.AddressUtils;
import com.ruoyi.common.log.event.LogininforEvent;
import com.ruoyi.common.redis.utils.RedisUtils;
import com.ruoyi.common.satoken.utils.LoginHelper;
import com.ruoyi.system.api.RemoteLogService;
import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.api.model.XcxLoginUser;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.function.Supplier;
/**
*
*
* @author ruoyi
*/
@Service
public class SysLoginService {
@DubboReference
private RemoteLogService remoteLogService;
@DubboReference
private RemoteUserService remoteUserService;
@Autowired
private UserPasswordProperties userPasswordProperties;
/**
*
*/
public String login(String username, String password) {
LoginUser userInfo = remoteUserService.getUserInfo(username);
checkLogin(LoginType.PASSWORD, username, () -> !BCrypt.checkpw(password, userInfo.getPassword()));
// 获取登录token
LoginHelper.loginByDevice(userInfo, DeviceType.PC);
recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
return StpUtil.getTokenValue();
}
public String smsLogin(String phonenumber, String smsCode) {
// 通过手机号查找用户
LoginUser userInfo = remoteUserService.getUserInfoByPhonenumber(phonenumber);
checkLogin(LoginType.SMS, userInfo.getUsername(), () -> !validateSmsCode(phonenumber, smsCode));
// 生成token
LoginHelper.loginByDevice(userInfo, DeviceType.APP);
recordLogininfor(userInfo.getUsername(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
return StpUtil.getTokenValue();
}
public String emailLogin(String email, String emailCode) {
// 通过邮箱查找用户
LoginUser userInfo = remoteUserService.getUserInfoByEmail(email);
checkLogin(LoginType.EMAIL, userInfo.getUsername(), () -> !validateEmailCode(email, emailCode));
// 生成token
LoginHelper.loginByDevice(userInfo, DeviceType.APP);
recordLogininfor(userInfo.getUsername(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
return StpUtil.getTokenValue();
}
public String xcxLogin(String xcxCode) {
// xcxCode 为 小程序调用 wx.login 授权后获取
// todo 自行实现 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
String openid = "";
XcxLoginUser userInfo = remoteUserService.getUserInfoByOpenid(openid);
// 生成token
LoginHelper.loginByDevice(userInfo, DeviceType.XCX);
recordLogininfor(userInfo.getUsername(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
return StpUtil.getTokenValue();
}
/**
* 退
*/
public void logout() {
try {
LoginUser loginUser = LoginHelper.getLoginUser();
StpUtil.logout();
recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
} catch (NotLoginException ignored) {
}
}
/**
*
*/
public void register(RegisterBody registerBody) {
String username = registerBody.getUsername();
String password = registerBody.getPassword();
// 校验用户类型是否存在
String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
// 注册用户信息
SysUser sysUser = new SysUser();
sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setPassword(BCrypt.hashpw(password));
sysUser.setUserType(userType);
boolean regFlag = remoteUserService.registerUserInfo(sysUser);
if (!regFlag) {
throw new UserException("user.register.error");
}
recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"));
}
/**
*
*
* @param username
* @param status
* @param message
* @return
*/
public void recordLogininfor(String username, String status, String message) {
HttpServletRequest request = ServletUtils.getRequest();
final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
final String ip = ServletUtils.getClientIP(request);
String address = AddressUtils.getRealAddressByIP(ip);
// 获取客户端操作系统
String os = userAgent.getOs().getName();
// 获取客户端浏览器
String browser = userAgent.getBrowser().getName();
// 封装对象
LogininforEvent logininfor = new LogininforEvent();
logininfor.setUserName(username);
logininfor.setIpaddr(ip);
logininfor.setLoginLocation(address);
logininfor.setBrowser(browser);
logininfor.setOs(os);
logininfor.setMsg(message);
// 日志状态
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS);
} else if (Constants.LOGIN_FAIL.equals(status)) {
logininfor.setStatus(Constants.LOGIN_FAIL_STATUS);
}
SpringUtils.context().publishEvent(logininfor);
}
/**
*
*/
private boolean validateSmsCode(String phonenumber, String smsCode) {
String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phonenumber);
if (StringUtils.isBlank(code)) {
recordLogininfor(phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
throw new CaptchaExpireException();
}
return code.equals(smsCode);
}
/**
*
*/
private boolean validateEmailCode(String email, String emailCode) {
String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + email);
if (StringUtils.isBlank(code)) {
recordLogininfor(email, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
throw new CaptchaExpireException();
}
return code.equals(emailCode);
}
/**
*
*/
private void checkLogin(LoginType loginType, String username, Supplier<Boolean> supplier) {
String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username;
String loginFail = Constants.LOGIN_FAIL;
Integer maxRetryCount = userPasswordProperties.getMaxRetryCount();
Integer lockTime = userPasswordProperties.getLockTime();
// 获取用户登录错误次数(可自定义限制策略 例如: key + username + ip)
Integer errorNumber = RedisUtils.getCacheObject(errorKey);
// 锁定时间内登录 则踢出
if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) {
recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
}
if (supplier.get()) {
// 是否第一次
errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
// 达到规定错误次数 则锁定登录
if (errorNumber.equals(maxRetryCount)) {
RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
} else {
// 未达到规定错误次数 则递增
RedisUtils.setCacheObject(errorKey, errorNumber);
recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
throw new UserException(loginType.getRetryLimitCount(), errorNumber);
}
}
// 登录成功 清空错误次数
RedisUtils.deleteObject(errorKey);
}
}

@ -1,4 +1,4 @@
package com.ruoyi.auth;
package org.dromara.auth;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;

@ -0,0 +1,146 @@
package org.dromara.auth.controller;
import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.auth.domain.convert.TenantVoConvert;
import org.dromara.auth.domain.vo.LoginTenantVo;
import org.dromara.auth.domain.vo.LoginVo;
import org.dromara.auth.domain.vo.TenantListVo;
import org.dromara.auth.form.EmailLoginBody;
import org.dromara.auth.form.LoginBody;
import org.dromara.auth.form.RegisterBody;
import org.dromara.auth.form.SmsLoginBody;
import org.dromara.auth.service.SysLoginService;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.system.api.RemoteTenantService;
import org.dromara.system.api.domain.vo.RemoteTenantVo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotBlank;
import java.net.URL;
import java.util.List;
/**
* token
*
* @author Lion Li
*/
@Validated
@RequiredArgsConstructor
@RestController
public class TokenController {
private final SysLoginService sysLoginService;
@DubboReference
private final RemoteTenantService remoteTenantService;
/**
*
*/
@PostMapping("login")
public R<LoginVo> login(@Validated @RequestBody LoginBody body) {
LoginVo loginVo = new LoginVo();
// 生成令牌
String token = sysLoginService.login(
body.getTenantId(),
body.getUsername(),
body.getPassword());
loginVo.setToken(token);
return R.ok(loginVo);
}
/**
*
*
* @param smsLoginBody
* @return
*/
@PostMapping("/smsLogin")
public R<LoginVo> smsLogin(@Validated @RequestBody SmsLoginBody smsLoginBody) {
LoginVo loginVo = new LoginVo();
// 生成令牌
String token = sysLoginService.smsLogin(smsLoginBody.getTenantId(),smsLoginBody.getPhonenumber(), smsLoginBody.getSmsCode());
loginVo.setToken(token);
return R.ok(loginVo);
}
/**
*
*
* @param body
* @return
*/
@PostMapping("/emailLogin")
public R<LoginVo> emailLogin(@Validated @RequestBody EmailLoginBody body) {
LoginVo loginVo = new LoginVo();
// 生成令牌
String token = sysLoginService.emailLogin(body.getTenantId(), body.getEmail(), body.getEmailCode());
loginVo.setToken(token);
return R.ok(loginVo);
}
/**
* ()
*
* @param xcxCode code
* @return
*/
@PostMapping("/xcxLogin")
public R<LoginVo> xcxLogin(@NotBlank(message = "{xcx.code.not.blank}") String xcxCode) {
LoginVo loginVo = new LoginVo();
// 生成令牌
String token = sysLoginService.xcxLogin(xcxCode);
loginVo.setToken(token);
return R.ok(loginVo);
}
/**
*
*/
@PostMapping("logout")
public R<Void> logout() {
sysLoginService.logout();
return R.ok();
}
/**
*
*/
@PostMapping("register")
public R<Void> register(@RequestBody RegisterBody registerBody) {
// 用户注册
sysLoginService.register(registerBody);
return R.ok();
}
/**
*
*
* @return
*/
@GetMapping("/tenant/list")
public R<LoginTenantVo> tenantList(HttpServletRequest request) throws Exception {
List<RemoteTenantVo> tenantList = remoteTenantService.queryList();
List<TenantListVo> voList = TenantVoConvert.INSTANCE.convertList(tenantList);
// 获取域名
String host = new URL(request.getRequestURL().toString()).getHost();
// 根据域名进行筛选
List<TenantListVo> list = StreamUtils.filter(voList, vo -> StringUtils.equals(vo.getDomain(), host));
// 返回对象
LoginTenantVo vo = new LoginTenantVo();
vo.setVoList(CollUtil.isNotEmpty(list) ? list : voList);
vo.setTenantEnabled(TenantHelper.isEnable());
return R.ok(vo);
}
}

@ -0,0 +1,35 @@
package org.dromara.auth.domain.convert;
import org.dromara.auth.domain.vo.TenantListVo;
import org.dromara.system.api.domain.vo.RemoteTenantVo;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* vo
* @author zhujie
*/
@Mapper
public interface TenantVoConvert {
TenantVoConvert INSTANCE = Mappers.getMapper(TenantVoConvert.class);
/**
* RemoteTenantVoToTenantListVo
* @param remoteTenantVo
* @return
*/
TenantListVo convert(RemoteTenantVo remoteTenantVo);
/**
* RemoteTenantVoToTenantListVo
* @param remoteTenantVo
* @return
*/
List<TenantListVo> convertList(List<RemoteTenantVo> remoteTenantVo);
}

@ -0,0 +1,25 @@
package org.dromara.auth.domain.vo;
import lombok.Data;
import java.util.List;
/**
*
*
* @author Michelle.Chung
*/
@Data
public class LoginTenantVo {
/**
*
*/
private Boolean tenantEnabled;
/**
*
*/
private List<TenantListVo> voList;
}

@ -0,0 +1,15 @@
package org.dromara.auth.domain.vo;
import lombok.Data;
/**
*
*
* @author Michelle.Chung
*/
@Data
public class LoginVo {
private String token;
}

@ -0,0 +1,19 @@
package org.dromara.auth.domain.vo;
import lombok.Data;
/**
*
*
* @author zhujie
*/
@Data
public class TenantListVo {
private String tenantId;
private String companyName;
private String domain;
}

@ -1,4 +1,4 @@
package com.ruoyi.auth.form;
package org.dromara.auth.form;
import lombok.Data;
@ -14,6 +14,12 @@ import javax.validation.constraints.NotBlank;
@Data
public class EmailLoginBody {
/**
* ID
*/
@NotBlank(message = "{tenant.number.not.blank}")
private String tenantId;
/**
*
*/

@ -1,6 +1,6 @@
package com.ruoyi.auth.form;
package org.dromara.auth.form;
import com.ruoyi.common.core.constant.UserConstants;
import org.dromara.common.core.constant.UserConstants;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
@ -16,6 +16,12 @@ import javax.validation.constraints.NotBlank;
@NoArgsConstructor
public class LoginBody {
/**
* ID
*/
@NotBlank(message = "{tenant.number.not.blank}")
private String tenantId;
/**
*
*/

@ -1,4 +1,4 @@
package com.ruoyi.auth.form;
package org.dromara.auth.form;
import lombok.Data;
import lombok.EqualsAndHashCode;

@ -1,4 +1,4 @@
package com.ruoyi.auth.form;
package org.dromara.auth.form;
import lombok.Data;
@ -13,6 +13,11 @@ import javax.validation.constraints.NotBlank;
@Data
public class SmsLoginBody {
/**
* ID
*/
private String tenantId;
/**
*
*/

@ -1,4 +1,4 @@
package com.ruoyi.auth.listener;
package org.dromara.auth.listener;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.listener.SaTokenListener;
@ -6,14 +6,14 @@ import cn.dev33.satoken.stp.SaLoginModel;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.enums.UserType;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.ip.AddressUtils;
import com.ruoyi.common.redis.utils.RedisUtils;
import com.ruoyi.common.satoken.utils.LoginHelper;
import com.ruoyi.system.api.domain.SysUserOnline;
import com.ruoyi.system.api.model.LoginUser;
import org.dromara.common.core.constant.CacheConstants;
import org.dromara.common.core.enums.UserType;
import org.dromara.common.core.utils.ServletUtils;
import org.dromara.common.core.utils.ip.AddressUtils;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.api.domain.SysUserOnline;
import org.dromara.system.api.model.LoginUser;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@ -1,4 +1,4 @@
package com.ruoyi.auth.properties;
package org.dromara.auth.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ -0,0 +1,256 @@
package org.dromara.auth.service;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.auth.form.RegisterBody;
import org.dromara.auth.properties.UserPasswordProperties;
import org.dromara.common.core.constant.CacheConstants;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.constant.TenantConstants;
import org.dromara.common.core.enums.DeviceType;
import org.dromara.common.core.enums.LoginType;
import org.dromara.common.core.enums.TenantStatus;
import org.dromara.common.core.enums.UserType;
import org.dromara.common.core.exception.user.CaptchaExpireException;
import org.dromara.common.core.exception.user.UserException;
import org.dromara.common.core.utils.MessageUtils;
import org.dromara.common.core.utils.ServletUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.log.event.LogininforEvent;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.tenant.exception.TenantException;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.system.api.RemoteTenantService;
import org.dromara.system.api.RemoteUserService;
import org.dromara.system.api.domain.bo.RemoteUserBo;
import org.dromara.system.api.domain.vo.RemoteTenantVo;
import org.dromara.system.api.model.LoginUser;
import org.dromara.system.api.model.XcxLoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.Date;
import java.util.function.Supplier;
/**
*
*
* @author ruoyi
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class SysLoginService {
@DubboReference
private RemoteUserService remoteUserService;
@DubboReference
private RemoteTenantService remoteTenantService;
@Autowired
private UserPasswordProperties userPasswordProperties;
/**
*
*/
public String login(String tenantId, String username, String password) {
// 校验租户
checkTenant(tenantId);
LoginUser userInfo = remoteUserService.getUserInfo(username);
checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, userInfo.getPassword()));
// 获取登录token
LoginHelper.loginByDevice(userInfo, DeviceType.PC);
recordLogininfor(tenantId, username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
return StpUtil.getTokenValue();
}
public String smsLogin(String tenantId, String phonenumber, String smsCode) {
// 校验租户
checkTenant(tenantId);
// 通过手机号查找用户
LoginUser userInfo = remoteUserService.getUserInfoByPhonenumber(phonenumber);
checkLogin(LoginType.SMS, tenantId, userInfo.getUsername(), () -> !validateSmsCode(tenantId, phonenumber, smsCode));
// 生成token
LoginHelper.loginByDevice(userInfo, DeviceType.APP);
recordLogininfor(tenantId, userInfo.getUsername(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
return StpUtil.getTokenValue();
}
public String emailLogin(String tenantId, String email, String emailCode) {
// 校验租户
checkTenant(tenantId);
// 通过邮箱查找用户
LoginUser userInfo = remoteUserService.getUserInfoByEmail(email);
checkLogin(LoginType.EMAIL,tenantId, userInfo.getUsername(), () -> !validateEmailCode(tenantId, email, emailCode));
// 生成token
LoginHelper.loginByDevice(userInfo, DeviceType.APP);
recordLogininfor(tenantId, userInfo.getUsername(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
return StpUtil.getTokenValue();
}
public String xcxLogin(String xcxCode) {
// xcxCode 为 小程序调用 wx.login 授权后获取
// todo 自行实现 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
String openid = "";
XcxLoginUser userInfo = remoteUserService.getUserInfoByOpenid(openid);
// 校验租户
checkTenant(userInfo.getTenantId());
// 生成token
LoginHelper.loginByDevice(userInfo, DeviceType.XCX);
recordLogininfor(userInfo.getTenantId(), userInfo.getUsername(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
return StpUtil.getTokenValue();
}
/**
* 退
*/
public void logout() {
try {
LoginUser loginUser = LoginHelper.getLoginUser();
if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) {
// 超级管理员 登出清除动态租户
TenantHelper.clearDynamic();
}
StpUtil.logout();
recordLogininfor(loginUser.getTenantId(), loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
} catch (NotLoginException ignored) {
}
}
/**
*
*/
public void register(RegisterBody registerBody) {
String tenantId = registerBody.getTenantId();
String username = registerBody.getUsername();
String password = registerBody.getPassword();
// 校验用户类型是否存在
String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
// 注册用户信息
RemoteUserBo remoteUserBo = new RemoteUserBo();
remoteUserBo.setUserName(username);
remoteUserBo.setNickName(username);
remoteUserBo.setPassword(BCrypt.hashpw(password));
remoteUserBo.setUserType(userType);
boolean regFlag = remoteUserService.registerUserInfo(remoteUserBo);
if (!regFlag) {
throw new UserException("user.register.error");
}
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
}
/**
*
*
* @param username
* @param status
* @param message
* @return
*/
public void recordLogininfor(String tenantId, String username, String status, String message) {
// 封装对象
LogininforEvent logininforEvent = new LogininforEvent();
logininforEvent.setTenantId(tenantId);
logininforEvent.setUsername(username);
logininforEvent.setStatus(status);
logininforEvent.setMessage(message);
logininforEvent.setRequest(ServletUtils.getRequest());
SpringUtils.context().publishEvent(logininforEvent);
}
/**
*
*/
private boolean validateSmsCode(String tenantId, String phonenumber, String smsCode) {
String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phonenumber);
if (StringUtils.isBlank(code)) {
recordLogininfor(tenantId, phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
throw new CaptchaExpireException();
}
return code.equals(smsCode);
}
/**
*
*/
private boolean validateEmailCode(String tenantId, String email, String emailCode) {
String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + email);
if (StringUtils.isBlank(code)) {
recordLogininfor(tenantId, email, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
throw new CaptchaExpireException();
}
return code.equals(emailCode);
}
/**
*
*/
private void checkLogin(LoginType loginType, String tenantId, String username, Supplier<Boolean> supplier) {
String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username;
String loginFail = Constants.LOGIN_FAIL;
Integer maxRetryCount = userPasswordProperties.getMaxRetryCount();
Integer lockTime = userPasswordProperties.getLockTime();
// 获取用户登录错误次数(可自定义限制策略 例如: key + username + ip)
Integer errorNumber = RedisUtils.getCacheObject(errorKey);
// 锁定时间内登录 则踢出
if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) {
recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
}
if (supplier.get()) {
// 是否第一次
errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
// 达到规定错误次数 则锁定登录
if (errorNumber.equals(maxRetryCount)) {
RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
} else {
// 未达到规定错误次数 则递增
RedisUtils.setCacheObject(errorKey, errorNumber);
recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
throw new UserException(loginType.getRetryLimitCount(), errorNumber);
}
}
// 登录成功 清空错误次数
RedisUtils.deleteObject(errorKey);
}
private void checkTenant(String tenantId) {
if (!TenantHelper.isEnable()) {
return;
}
if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) {
return;
}
RemoteTenantVo tenant = remoteTenantService.queryByTenantId(tenantId);
if (ObjectUtil.isNull(tenant)) {
log.info("登录租户:{} 不存在.", tenantId);
throw new TenantException("tenant.not.exists");
} else if (TenantStatus.DISABLE.getCode().equals(tenant.getStatus())) {
log.info("登录租户:{} 已被停用.", tenantId);
throw new TenantException("tenant.blocked");
} else if (ObjectUtil.isNotNull(tenant.getExpireTime())
&& new Date().after(tenant.getExpireTime())) {
log.info("登录租户:{} 已超过有效期.", tenantId);
throw new TenantException("tenant.expired");
}
}
}

@ -2,7 +2,7 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-cloud-plus</artifactId>
<version>1.6.0</version>
</parent>
@ -36,6 +36,7 @@
<module>ruoyi-common-prometheus</module>
<module>ruoyi-common-translation</module>
<module>ruoyi-common-encrypt</module>
<module>ruoyi-common-tenant</module>
</modules>
<artifactId>ruoyi-common</artifactId>

@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-alibaba-bom</artifactId>
<version>1.6.0</version>
<packaging>pom</packaging>

@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-bom</artifactId>
<version>1.6.0</version>
<packaging>pom</packaging>
@ -17,163 +17,170 @@
<dependencies>
<!-- 核心模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-core</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 接口模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-doc</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 安全模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-security</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-satoken</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 日志记录 -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-log</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 字典 -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-dict</artifactId>
<version>${project.version}</version>
</dependency>
<!-- excel -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-excel</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 缓存服务 -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-redis</artifactId>
<version>${project.version}</version>
</dependency>
<!-- web服务 -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-web</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 数据库服务 -->
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-mybatis</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-job</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-dubbo</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-seata</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-loadbalancer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-oss</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-idempotent</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-mail</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-sms</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-logstash</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-elasticsearch</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-sentinel</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-skylog</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-prometheus</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-translation</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-encrypt</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 租户模块 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-tenant</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

@ -3,7 +3,7 @@
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common</artifactId>
<version>1.6.0</version>
</parent>
@ -110,6 +110,11 @@
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

@ -1,9 +1,9 @@
package com.ruoyi.common.core.annotation;
package org.dromara.common.core.annotation;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.ruoyi.common.core.enums.SensitiveStrategy;
import com.ruoyi.common.core.jackson.SensitiveJsonSerializer;
import org.dromara.common.core.enums.SensitiveStrategy;
import org.dromara.common.core.jackson.SensitiveJsonSerializer;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.config;
package org.dromara.common.core.config;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@ -1,8 +1,8 @@
package com.ruoyi.common.core.config;
package org.dromara.common.core.config;
import cn.hutool.core.util.ArrayUtil;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.SpringUtils;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;

@ -1,10 +1,10 @@
package com.ruoyi.common.core.config;
package org.dromara.common.core.config;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.ruoyi.common.core.jackson.BigNumberSerializer;
import org.dromara.common.core.jackson.BigNumberSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.config;
package org.dromara.common.core.config;
import org.hibernate.validator.HibernateValidator;
import org.springframework.beans.factory.annotation.Autowired;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.constant;
package org.dromara.common.core.constant;
/**
*
@ -30,6 +30,11 @@ public interface CacheNames {
*/
String SYS_DICT = "sys_dict";
/**
*
*/
String SYS_TENANT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_tenant#30d";
/**
*
*/

@ -1,11 +1,12 @@
package com.ruoyi.common.core.constant;
package org.dromara.common.core.constant;
/**
*
*
* @author Lion Li
* @author ruoyi
*/
public interface Constants {
/**
* UTF-8
*/
@ -32,24 +33,14 @@ public interface Constants {
String HTTPS = "https://";
/**
*
*
*/
Integer SUCCESS = 200;
String SUCCESS = "0";
/**
*
*
*/
Integer FAIL = 500;
/**
*
*/
String LOGIN_SUCCESS_STATUS = "0";
/**
*
*/
String LOGIN_FAIL_STATUS = "1";
String FAIL = "1";
/**
*
@ -74,13 +65,17 @@ public interface Constants {
/**
*
*/
long CAPTCHA_EXPIRATION = 2;
Integer CAPTCHA_EXPIRATION = 2;
/**
* redis key
*
*/
String REPEAT_SUBMIT_KEY = "repeat_submit:";
String TOKEN = "token";
String ACCESS_TOKEN = "access_token";
/**
* id
*/
Long TOP_PARENT_ID = 0L;
}

@ -0,0 +1,39 @@
package org.dromara.common.core.constant;
/**
* key (key)
*
* @author Lion Li
*/
public interface GlobalConstants {
/**
* redis key (key)
*/
String GLOBAL_REDIS_KEY = "global:";
/**
* redis key
*/
String LOGIN_TOKEN_KEY = GLOBAL_REDIS_KEY + "Authorization:login:token:";
/**
* redis key
*/
String CAPTCHA_CODE_KEY = GLOBAL_REDIS_KEY + "captcha_codes:";
/**
* redis key
*/
String REPEAT_SUBMIT_KEY = GLOBAL_REDIS_KEY + "repeat_submit:";
/**
* redis key
*/
String RATE_LIMIT_KEY = GLOBAL_REDIS_KEY + "rate_limit:";
/**
* redis key
*/
String PWD_ERR_CNT_KEY = GLOBAL_REDIS_KEY + "pwd_err_cnt:";
}

@ -0,0 +1,45 @@
package org.dromara.common.core.constant;
/**
*
*
* @author Lion Li
*/
public interface TenantConstants {
/**
*
*/
String NORMAL = "0";
/**
*
*/
String DISABLE = "1";
/**
* ID
*/
Long SUPER_ADMIN_ID = 1L;
/**
* roleKey
*/
String SUPER_ADMIN_ROLE_KEY = "superadmin";
/**
* roleKey
*/
String TENANT_ADMIN_ROLE_KEY = "admin";
/**
*
*/
String TENANT_ADMIN_ROLE_NAME = "管理员";
/**
* ID
*/
String DEFAULT_TENANT_ID = "000000";
}

@ -1,4 +1,4 @@
package com.ruoyi.common.core.constant;
package org.dromara.common.core.constant;
/**
*
@ -128,5 +128,5 @@ public interface UserConstants {
/**
* ID
*/
Long ADMIN_ID = 1L;
Long SUPER_ADMIN_ID = 1L;
}

@ -1,9 +1,8 @@
package com.ruoyi.common.core.domain;
package org.dromara.common.core.domain;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.HttpStatus;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.dromara.common.core.constant.HttpStatus;
import java.io.Serializable;
@ -20,12 +19,12 @@ public class R<T> implements Serializable {
/**
*
*/
public static final int SUCCESS = Constants.SUCCESS;
public static final int SUCCESS = 200;
/**
*
*/
public static final int FAIL = Constants.FAIL;
public static final int FAIL = 500;
/**
*

@ -1,4 +1,4 @@
package com.ruoyi.common.core.enums;
package org.dromara.common.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.enums;
package org.dromara.common.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.enums;
package org.dromara.common.core.enums;
import cn.hutool.core.util.DesensitizedUtil;
import lombok.AllArgsConstructor;

@ -0,0 +1,30 @@
package org.dromara.common.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
*
*
* @author LionLi
*/
@Getter
@AllArgsConstructor
public enum TenantStatus {
/**
*
*/
OK("0", "正常"),
/**
*
*/
DISABLE("1", "停用"),
/**
*
*/
DELETED("2", "删除");
private final String code;
private final String info;
}

@ -1,19 +1,19 @@
package com.ruoyi.common.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
*
*
* @author ruoyi
*/
@Getter
@AllArgsConstructor
public enum UserStatus {
OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
private final String code;
private final String info;
}
package org.dromara.common.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
*
*
* @author ruoyi
*/
@Getter
@AllArgsConstructor
public enum UserStatus {
OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
private final String code;
private final String info;
}

@ -1,6 +1,6 @@
package com.ruoyi.common.core.enums;
package org.dromara.common.core.enums;
import com.ruoyi.common.core.utils.StringUtils;
import org.dromara.common.core.utils.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;

@ -1,6 +1,6 @@
package com.ruoyi.common.core.exception;
package org.dromara.common.core.exception;
import com.ruoyi.common.core.exception.user.UserException;
import org.dromara.common.core.exception.user.UserException;
/**
*

@ -1,26 +1,26 @@
package com.ruoyi.common.core.exception;
/**
*
*
* @author ruoyi
*/
public class CheckedException extends RuntimeException {
private static final long serialVersionUID = 1L;
public CheckedException(String message) {
super(message);
}
public CheckedException(Throwable cause) {
super(cause);
}
public CheckedException(String message, Throwable cause) {
super(message, cause);
}
public CheckedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
package org.dromara.common.core.exception;
/**
*
*
* @author ruoyi
*/
public class CheckedException extends RuntimeException {
private static final long serialVersionUID = 1L;
public CheckedException(String message) {
super(message);
}
public CheckedException(Throwable cause) {
super(cause);
}
public CheckedException(String message, Throwable cause) {
super(message, cause);
}
public CheckedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

@ -1,13 +1,13 @@
package com.ruoyi.common.core.exception;
/**
*
*
* @author ruoyi
*/
public class DemoModeException extends RuntimeException {
private static final long serialVersionUID = 1L;
public DemoModeException() {
}
}
package org.dromara.common.core.exception;
/**
*
*
* @author ruoyi
*/
public class DemoModeException extends RuntimeException {
private static final long serialVersionUID = 1L;
public DemoModeException() {
}
}

@ -1,22 +1,22 @@
package com.ruoyi.common.core.exception;
/**
*
*
* @author ruoyi
*/
public class UtilException extends RuntimeException {
private static final long serialVersionUID = 8247610319171014183L;
public UtilException(Throwable e) {
super(e.getMessage(), e);
}
public UtilException(String message) {
super(message);
}
public UtilException(String message, Throwable throwable) {
super(message, throwable);
}
}
package org.dromara.common.core.exception;
/**
*
*
* @author ruoyi
*/
public class UtilException extends RuntimeException {
private static final long serialVersionUID = 8247610319171014183L;
public UtilException(Throwable e) {
super(e.getMessage(), e);
}
public UtilException(String message) {
super(message);
}
public UtilException(String message, Throwable throwable) {
super(message, throwable);
}
}

@ -1,7 +1,7 @@
package com.ruoyi.common.core.exception.base;
package org.dromara.common.core.exception.base;
import com.ruoyi.common.core.utils.MessageUtils;
import com.ruoyi.common.core.utils.StringUtils;
import org.dromara.common.core.utils.MessageUtils;
import org.dromara.common.core.utils.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;

@ -1,17 +1,17 @@
package com.ruoyi.common.core.exception.file;
import com.ruoyi.common.core.exception.base.BaseException;
/**
*
*
* @author ruoyi
*/
public class FileException extends BaseException {
private static final long serialVersionUID = 1L;
public FileException(String code, Object[] args) {
super("file", code, args, null);
}
}
package org.dromara.common.core.exception.file;
import org.dromara.common.core.exception.base.BaseException;
/**
*
*
* @author ruoyi
*/
public class FileException extends BaseException {
private static final long serialVersionUID = 1L;
public FileException(String code, Object[] args) {
super("file", code, args, null);
}
}

@ -1,14 +1,14 @@
package com.ruoyi.common.core.exception.file;
/**
*
*
* @author ruoyi
*/
public class FileNameLengthLimitExceededException extends FileException {
private static final long serialVersionUID = 1L;
public FileNameLengthLimitExceededException(int defaultFileNameLength) {
super("upload.filename.exceed.length", new Object[]{defaultFileNameLength});
}
}
package org.dromara.common.core.exception.file;
/**
*
*
* @author ruoyi
*/
public class FileNameLengthLimitExceededException extends FileException {
private static final long serialVersionUID = 1L;
public FileNameLengthLimitExceededException(int defaultFileNameLength) {
super("upload.filename.exceed.length", new Object[]{defaultFileNameLength});
}
}

@ -1,14 +1,14 @@
package com.ruoyi.common.core.exception.file;
/**
*
*
* @author ruoyi
*/
public class FileSizeLimitExceededException extends FileException {
private static final long serialVersionUID = 1L;
public FileSizeLimitExceededException(long defaultMaxSize) {
super("upload.exceed.maxSize", new Object[]{defaultMaxSize});
}
}
package org.dromara.common.core.exception.file;
/**
*
*
* @author ruoyi
*/
public class FileSizeLimitExceededException extends FileException {
private static final long serialVersionUID = 1L;
public FileSizeLimitExceededException(long defaultMaxSize) {
super("upload.exceed.maxSize", new Object[]{defaultMaxSize});
}
}

@ -1,6 +1,6 @@
package com.ruoyi.common.core.exception.user;
package org.dromara.common.core.exception.user;
import com.ruoyi.common.core.exception.base.BaseException;
import org.dromara.common.core.exception.base.BaseException;
/**
*

@ -1,4 +1,4 @@
package com.ruoyi.common.core.jackson;
package org.dromara.common.core.jackson;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.jackson;
package org.dromara.common.core.jackson;
import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.JsonGenerator;
@ -7,10 +7,10 @@ import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.ruoyi.common.core.annotation.Sensitive;
import com.ruoyi.common.core.enums.SensitiveStrategy;
import com.ruoyi.common.core.service.SensitiveService;
import com.ruoyi.common.core.utils.SpringUtils;
import org.dromara.common.core.annotation.Sensitive;
import org.dromara.common.core.enums.SensitiveStrategy;
import org.dromara.common.core.service.SensitiveService;
import org.dromara.common.core.utils.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;

@ -1,6 +1,6 @@
package com.ruoyi.common.core.service;
package org.dromara.common.core.service;
import com.ruoyi.common.core.utils.StringUtils;
import org.dromara.common.core.utils.StringUtils;
/**
*

@ -1,4 +1,4 @@
package com.ruoyi.common.core.utils;
package org.dromara.common.core.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.SimpleCache;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.utils;
package org.dromara.common.core.utils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.utils;
package org.dromara.common.core.utils;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ArrayUtil;

@ -0,0 +1,92 @@
package org.dromara.common.core.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import io.github.linpeilie.Converter;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
/**
* Mapstruct
* <p><a href="https://mapstruct.plus/guide/quick-start">mapstruct-plus</a></p>
*
* @author Michelle.Chung
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MapstructUtils {
private final static Converter CONVERTER = SpringUtils.getBean(Converter.class);
/**
* T desc
*
* @param source
* @param desc
* @return desc
*/
public static <T, V> V convert(T source, Class<V> desc) {
if (ObjectUtil.isNull(source)) {
return null;
}
if (ObjectUtil.isNull(desc)) {
return null;
}
return CONVERTER.convert(source, desc);
}
/**
* T desc desc
*
* @param source
* @param desc
* @return desc
*/
public static <T, V> V convert(T source, V desc) {
if (ObjectUtil.isNull(source)) {
return null;
}
if (ObjectUtil.isNull(desc)) {
return null;
}
return CONVERTER.convert(source, desc);
}
/**
* T desc
*
* @param sourceList
* @param desc
* @return desc
*/
public static <T, V> List<V> convert(List<T> sourceList, Class<V> desc) {
if (ObjectUtil.isNull(sourceList)) {
return null;
}
if (CollUtil.isEmpty(sourceList)) {
return CollUtil.newArrayList();
}
return CONVERTER.convert(sourceList, desc);
}
/**
* Map beanClass
*
* @param map
* @param beanClass bean
* @return bean
*/
public static <T> T convert(Map<String, Object> map, Class<T> beanClass) {
if (MapUtil.isEmpty(map)) {
return null;
}
if (ObjectUtil.isNull(beanClass)) {
return null;
}
return CONVERTER.convert(map, beanClass);
}
}

@ -1,4 +1,4 @@
package com.ruoyi.common.core.utils;
package org.dromara.common.core.utils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@ -1,148 +1,148 @@
package com.ruoyi.common.core.utils;
import cn.hutool.core.convert.Convert;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ReUtil {
public final static Pattern GROUP_VAR = Pattern.compile("\\$(\\d+)");
/**
*
*/
public final static Set<Character> RE_KEYS = new HashSet<>(
Arrays.asList('$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|'));
;
/**
* <br>
* replacementTemplate$11
*
* <p>
* 12341234(1234)
*
* <pre>
* ReUtil.replaceAll("中文1234", "(\\d+)", "($1)"))
*
* (1234)
* </pre>
*
* @param content
* @param regex
* @param replacementTemplate 使$1
* @return
*/
public static String replaceAll(CharSequence content, String regex, String replacementTemplate) {
final Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
return replaceAll(content, pattern, replacementTemplate);
}
/**
* <br>
* replacementTemplate$11
*
* @param content
* @param pattern {@link Pattern}
* @param replacementTemplate 使$1
* @return
* @since 3.0.4
*/
public static String replaceAll(CharSequence content, Pattern pattern, String replacementTemplate) {
if (StringUtils.isEmpty(content)) {
return StringUtils.EMPTY;
}
final Matcher matcher = pattern.matcher(content);
boolean result = matcher.find();
if (result) {
final Set<String> varNums = findAll(GROUP_VAR, replacementTemplate, 1, new HashSet<>());
final StringBuffer sb = new StringBuffer();
do {
String replacement = replacementTemplate;
for (String var : varNums) {
int group = Integer.parseInt(var);
replacement = replacement.replace("$" + var, matcher.group(group));
}
matcher.appendReplacement(sb, escape(replacement));
result = matcher.find();
}
while (result);
matcher.appendTail(sb);
return sb.toString();
}
return Convert.toStr(content);
}
/**
*
*
* @param <T>
* @param pattern
* @param content
* @param group
* @param collection
* @return
*/
public static <T extends Collection<String>> T findAll(Pattern pattern, CharSequence content, int group,
T collection) {
if (null == pattern || null == content) {
return null;
}
if (null == collection) {
throw new NullPointerException("Null collection param provided!");
}
final Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
collection.add(matcher.group(group));
}
return collection;
}
/**
*
*
* @param c
* @return
*/
public static String escape(char c) {
final StringBuilder builder = new StringBuilder();
if (RE_KEYS.contains(c)) {
builder.append('\\');
}
builder.append(c);
return builder.toString();
}
/**
*
*
* @param content
* @return
*/
public static String escape(CharSequence content) {
if (StringUtils.isBlank(content)) {
return StringUtils.EMPTY;
}
final StringBuilder builder = new StringBuilder();
int len = content.length();
char current;
for (int i = 0; i < len; i++) {
current = content.charAt(i);
if (RE_KEYS.contains(current)) {
builder.append('\\');
}
builder.append(current);
}
return builder.toString();
}
}
package org.dromara.common.core.utils;
import cn.hutool.core.convert.Convert;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ReUtil {
public final static Pattern GROUP_VAR = Pattern.compile("\\$(\\d+)");
/**
*
*/
public final static Set<Character> RE_KEYS = new HashSet<>(
Arrays.asList('$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|'));
;
/**
* <br>
* replacementTemplate$11
*
* <p>
* 12341234(1234)
*
* <pre>
* ReUtil.replaceAll("中文1234", "(\\d+)", "($1)"))
*
* (1234)
* </pre>
*
* @param content
* @param regex
* @param replacementTemplate 使$1
* @return
*/
public static String replaceAll(CharSequence content, String regex, String replacementTemplate) {
final Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
return replaceAll(content, pattern, replacementTemplate);
}
/**
* <br>
* replacementTemplate$11
*
* @param content
* @param pattern {@link Pattern}
* @param replacementTemplate 使$1
* @return
* @since 3.0.4
*/
public static String replaceAll(CharSequence content, Pattern pattern, String replacementTemplate) {
if (StringUtils.isEmpty(content)) {
return StringUtils.EMPTY;
}
final Matcher matcher = pattern.matcher(content);
boolean result = matcher.find();
if (result) {
final Set<String> varNums = findAll(GROUP_VAR, replacementTemplate, 1, new HashSet<>());
final StringBuffer sb = new StringBuffer();
do {
String replacement = replacementTemplate;
for (String var : varNums) {
int group = Integer.parseInt(var);
replacement = replacement.replace("$" + var, matcher.group(group));
}
matcher.appendReplacement(sb, escape(replacement));
result = matcher.find();
}
while (result);
matcher.appendTail(sb);
return sb.toString();
}
return Convert.toStr(content);
}
/**
*
*
* @param <T>
* @param pattern
* @param content
* @param group
* @param collection
* @return
*/
public static <T extends Collection<String>> T findAll(Pattern pattern, CharSequence content, int group,
T collection) {
if (null == pattern || null == content) {
return null;
}
if (null == collection) {
throw new NullPointerException("Null collection param provided!");
}
final Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
collection.add(matcher.group(group));
}
return collection;
}
/**
*
*
* @param c
* @return
*/
public static String escape(char c) {
final StringBuilder builder = new StringBuilder();
if (RE_KEYS.contains(c)) {
builder.append('\\');
}
builder.append(c);
return builder.toString();
}
/**
*
*
* @param content
* @return
*/
public static String escape(CharSequence content) {
if (StringUtils.isBlank(content)) {
return StringUtils.EMPTY;
}
final StringBuilder builder = new StringBuilder();
int len = content.length();
char current;
for (int i = 0; i < len; i++) {
current = content.charAt(i);
if (RE_KEYS.contains(current)) {
builder.append('\\');
}
builder.append(current);
}
return builder.toString();
}
}

@ -1,9 +1,9 @@
package com.ruoyi.common.core.utils;
package org.dromara.common.core.utils;
import cn.hutool.core.convert.Convert;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpStatus;
import com.ruoyi.common.core.constant.Constants;
import org.dromara.common.core.constant.Constants;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.http.MediaType;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.utils;
package org.dromara.common.core.utils;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.aop.framework.AopContext;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.utils;
package org.dromara.common.core.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.utils;
package org.dromara.common.core.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;

@ -1,11 +1,11 @@
package com.ruoyi.common.core.utils;
package org.dromara.common.core.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.lang.tree.parser.NodeParser;
import com.ruoyi.common.core.utils.reflect.ReflectUtils;
import org.dromara.common.core.utils.reflect.ReflectUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.utils;
package org.dromara.common.core.utils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@ -1,4 +1,4 @@
package com.ruoyi.common.core.utils.file;
package org.dromara.common.core.utils.file;
import cn.hutool.core.io.FileUtil;
import lombok.AccessLevel;

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

Loading…
Cancel
Save