mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-09-08 14:12:29 +08:00
Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/mail-1.6.1
# Conflicts: # yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java # yudao-module-system/yudao-module-system-biz/pom.xml
This commit is contained in:
@@ -29,13 +29,6 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- 用户信息 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-security</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@@ -1,56 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.api.auth;
|
||||
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 在线用户 Session API 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface UserSessionApi {
|
||||
|
||||
/**
|
||||
* 创建在线用户 Session
|
||||
*
|
||||
* @param loginUser 登录用户
|
||||
* @param userIp 用户 IP
|
||||
* @param userAgent 用户 UA
|
||||
* @return Token 令牌
|
||||
*/
|
||||
String createUserSession(@NotNull(message = "登录用户不能为空") LoginUser loginUser, String userIp, String userAgent);
|
||||
|
||||
/**
|
||||
* 刷新在线用户 Session 的更新时间
|
||||
*
|
||||
* @param token Token 令牌
|
||||
* @param loginUser 登录用户
|
||||
*/
|
||||
void refreshUserSession(@NotEmpty(message = "Token 令牌不能为空") String token,
|
||||
@NotNull(message = "登录用户不能为空") LoginUser loginUser);
|
||||
|
||||
/**
|
||||
* 删除在线用户 Session
|
||||
*
|
||||
* @param token Token 令牌
|
||||
*/
|
||||
void deleteUserSession(String token);
|
||||
|
||||
/**
|
||||
* 获得 Token 令牌对应的在线用户
|
||||
*
|
||||
* @param token Token 令牌
|
||||
* @return 在线用户
|
||||
*/
|
||||
LoginUser getLoginUser(String token);
|
||||
|
||||
/**
|
||||
* 获得 Session 超时时间,单位:毫秒
|
||||
*
|
||||
* @return 超时时间
|
||||
*/
|
||||
Long getSessionTimeoutMillis();
|
||||
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.system.api.dept;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -45,6 +46,9 @@ public interface DeptApi {
|
||||
* @param ids 部门编号数组
|
||||
* @return 部门 Map
|
||||
*/
|
||||
Map<Long, DeptRespDTO> getDeptMap(Set<Long> ids);
|
||||
default Map<Long, DeptRespDTO> getDeptMap(Set<Long> ids) {
|
||||
List<DeptRespDTO> list = getDepts(ids);
|
||||
return CollectionUtils.convertMap(list, DeptRespDTO::getId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.api.dict;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
@@ -19,4 +21,22 @@ public interface DictDataApi {
|
||||
*/
|
||||
void validDictDatas(String dictType, Collection<String> values);
|
||||
|
||||
/**
|
||||
* 获得指定的字典数据,从缓存中
|
||||
*
|
||||
* @param type 字典类型
|
||||
* @param value 字典数据值
|
||||
* @return 字典数据
|
||||
*/
|
||||
DictDataRespDTO getDictData(String type, String value);
|
||||
|
||||
/**
|
||||
* 解析获得指定的字典数据,从缓存中
|
||||
*
|
||||
* @param type 字典类型
|
||||
* @param label 字典数据标签
|
||||
* @return 字典数据
|
||||
*/
|
||||
DictDataRespDTO parseDictData(String type, String label);
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.system.api.dict.dto;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 字典数据 Response DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class DictDataRespDTO {
|
||||
|
||||
/**
|
||||
* 字典标签
|
||||
*/
|
||||
private String label;
|
||||
/**
|
||||
* 字典值
|
||||
*/
|
||||
private String value;
|
||||
/**
|
||||
* 字典类型
|
||||
*/
|
||||
private String dictType;
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
@@ -1,18 +1,18 @@
|
||||
package cn.iocoder.yudao.module.system.framework.errorcode.core.service;
|
||||
package cn.iocoder.yudao.module.system.api.errorcode;
|
||||
|
||||
import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.framework.errorcode.core.dto.ErrorCodeRespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeRespDTO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 错误码 Framework Service 接口
|
||||
* 错误码 Api 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface ErrorCodeFrameworkService {
|
||||
public interface ErrorCodeApi {
|
||||
|
||||
/**
|
||||
* 自动创建错误码
|
||||
@@ -30,6 +30,6 @@ public interface ErrorCodeFrameworkService {
|
||||
* @param minUpdateTime 最小更新时间
|
||||
* @return 错误码数组
|
||||
*/
|
||||
List<ErrorCodeRespDTO> getErrorCodeList(String applicationName, Date minUpdateTime);
|
||||
List<ErrorCodeRespDTO> getErrorCodeList(String applicationName, LocalDateTime minUpdateTime);
|
||||
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.module.system.framework.errorcode.core.dto;
|
||||
package cn.iocoder.yudao.module.system.api.errorcode.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
@@ -1,8 +1,8 @@
|
||||
package cn.iocoder.yudao.module.system.framework.errorcode.core.dto;
|
||||
package cn.iocoder.yudao.module.system.api.errorcode.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 错误码的 Response DTO
|
||||
@@ -23,6 +23,6 @@ public class ErrorCodeRespDTO {
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.system.api.logger;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 操作日志 API 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface OperateLogApi {
|
||||
|
||||
/**
|
||||
* 创建操作日志
|
||||
*
|
||||
* @param createReqDTO 请求
|
||||
*/
|
||||
void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO);
|
||||
|
||||
}
|
@@ -0,0 +1,123 @@
|
||||
package cn.iocoder.yudao.module.system.api.logger.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 操作日志创建 Request DTO
|
||||
*/
|
||||
@Data
|
||||
public class OperateLogCreateReqDTO {
|
||||
|
||||
/**
|
||||
* 链路追踪编号
|
||||
*/
|
||||
private String traceId;
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
@NotNull(message = "用户类型不能为空")
|
||||
private Integer userType;
|
||||
|
||||
/**
|
||||
* 操作模块
|
||||
*/
|
||||
@NotEmpty(message = "操作模块不能为空")
|
||||
private String module;
|
||||
|
||||
/**
|
||||
* 操作名
|
||||
*/
|
||||
@NotEmpty(message = "操作名")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 操作分类
|
||||
*/
|
||||
@NotNull(message = "操作分类不能为空")
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 操作明细
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 拓展字段
|
||||
*/
|
||||
private Map<String, Object> exts;
|
||||
|
||||
/**
|
||||
* 请求方法名
|
||||
*/
|
||||
@NotEmpty(message = "请求方法名不能为空")
|
||||
private String requestMethod;
|
||||
|
||||
/**
|
||||
* 请求地址
|
||||
*/
|
||||
@NotEmpty(message = "请求地址不能为空")
|
||||
private String requestUrl;
|
||||
|
||||
/**
|
||||
* 用户 IP
|
||||
*/
|
||||
@NotEmpty(message = "用户 IP 不能为空")
|
||||
private String userIp;
|
||||
|
||||
/**
|
||||
* 浏览器 UserAgent
|
||||
*/
|
||||
@NotEmpty(message = "浏览器 UserAgent 不能为空")
|
||||
private String userAgent;
|
||||
|
||||
/**
|
||||
* Java 方法名
|
||||
*/
|
||||
@NotEmpty(message = "Java 方法名不能为空")
|
||||
private String javaMethod;
|
||||
|
||||
/**
|
||||
* Java 方法的参数
|
||||
*/
|
||||
private String javaMethodArgs;
|
||||
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
@NotNull(message = "开始时间不能为空")
|
||||
private LocalDateTime startTime;
|
||||
|
||||
/**
|
||||
* 执行时长,单位:毫秒
|
||||
*/
|
||||
@NotNull(message = "执行时长不能为空")
|
||||
private Integer duration;
|
||||
|
||||
/**
|
||||
* 结果码
|
||||
*/
|
||||
@NotNull(message = "结果码不能为空")
|
||||
private Integer resultCode;
|
||||
|
||||
/**
|
||||
* 结果提示
|
||||
*/
|
||||
private String resultMsg;
|
||||
|
||||
/**
|
||||
* 结果数据
|
||||
*/
|
||||
private String resultData;
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
package cn.iocoder.yudao.module.system.api.oauth2;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* OAuth2.0 Token API 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface OAuth2TokenApi {
|
||||
|
||||
/**
|
||||
* 创建访问令牌
|
||||
*
|
||||
* @param reqDTO 访问令牌的创建信息
|
||||
* @return 访问令牌的信息
|
||||
*/
|
||||
OAuth2AccessTokenRespDTO createAccessToken(@Valid OAuth2AccessTokenCreateReqDTO reqDTO);
|
||||
|
||||
/**
|
||||
* 校验访问令牌
|
||||
*
|
||||
* @param accessToken 访问令牌
|
||||
* @return 访问令牌的信息
|
||||
*/
|
||||
OAuth2AccessTokenCheckRespDTO checkAccessToken(String accessToken);
|
||||
|
||||
/**
|
||||
* 移除访问令牌
|
||||
*
|
||||
* @param accessToken 访问令牌
|
||||
* @return 访问令牌的信息
|
||||
*/
|
||||
OAuth2AccessTokenRespDTO removeAccessToken(String accessToken);
|
||||
|
||||
/**
|
||||
* 刷新访问令牌
|
||||
*
|
||||
* @param refreshToken 刷新令牌
|
||||
* @param clientId 客户端编号
|
||||
* @return 访问令牌的信息
|
||||
*/
|
||||
OAuth2AccessTokenRespDTO refreshAccessToken(String refreshToken, String clientId);
|
||||
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.system.api.oauth2.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* OAuth2.0 访问令牌的校验 Response DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class OAuth2AccessTokenCheckRespDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
private Integer userType;
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
private Long tenantId;
|
||||
/**
|
||||
* 授权范围的数组
|
||||
*/
|
||||
private List<String> scopes;
|
||||
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package cn.iocoder.yudao.module.system.api.oauth2.dto;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* OAuth2.0 访问令牌创建 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class OAuth2AccessTokenCreateReqDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
@NotNull(message = "用户类型不能为空")
|
||||
@InEnum(value = UserTypeEnum.class, message = "用户类型必须是 {value}")
|
||||
private Integer userType;
|
||||
/**
|
||||
* 客户端编号
|
||||
*/
|
||||
@NotNull(message = "客户端编号不能为空")
|
||||
private String clientId;
|
||||
/**
|
||||
* 授权范围
|
||||
*/
|
||||
private List<String> scopes;
|
||||
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.system.api.oauth2.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* OAuth2.0 访问令牌的信息 Response DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2AccessTokenRespDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 访问令牌
|
||||
*/
|
||||
private String accessToken;
|
||||
/**
|
||||
* 刷新令牌
|
||||
*/
|
||||
private String refreshToken;
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
private Integer userType;
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private LocalDateTime expiresTime;
|
||||
|
||||
}
|
@@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.api.permission;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -18,4 +20,30 @@ public interface PermissionApi {
|
||||
*/
|
||||
Set<Long> getUserRoleIdListByRoleIds(Collection<Long> roleIds);
|
||||
|
||||
/**
|
||||
* 判断是否有权限,任一一个即可
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param permissions 权限
|
||||
* @return 是否
|
||||
*/
|
||||
boolean hasAnyPermissions(Long userId, String... permissions);
|
||||
|
||||
/**
|
||||
* 判断是否有角色,任一一个即可
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param roles 角色数组
|
||||
* @return 是否
|
||||
*/
|
||||
boolean hasAnyRoles(Long userId, String... roles);
|
||||
|
||||
/**
|
||||
* 获得登陆用户的部门数据权限
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @return 部门数据权限
|
||||
*/
|
||||
DeptDataPermissionRespDTO getDeptDataPermission(Long userId);
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.system.api.permission.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 部门的数据权限 Response DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class DeptDataPermissionRespDTO {
|
||||
|
||||
/**
|
||||
* 是否可查看全部数据
|
||||
*/
|
||||
private Boolean all;
|
||||
/**
|
||||
* 是否可查看自己的数据
|
||||
*/
|
||||
private Boolean self;
|
||||
/**
|
||||
* 可查看的部门编号数组
|
||||
*/
|
||||
private Set<Long> deptIds;
|
||||
|
||||
public DeptDataPermissionRespDTO() {
|
||||
this.all = false;
|
||||
this.self = false;
|
||||
this.deptIds = new HashSet<>();
|
||||
}
|
||||
|
||||
}
|
@@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.validation.Mobile;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@@ -3,7 +3,9 @@ package cn.iocoder.yudao.module.system.api.social.dto;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
@@ -14,6 +16,8 @@ import javax.validation.constraints.NotNull;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SocialUserBindReqDTO {
|
||||
|
||||
/**
|
||||
@@ -42,7 +46,7 @@ public class SocialUserBindReqDTO {
|
||||
/**
|
||||
* state
|
||||
*/
|
||||
@NotEmpty(message = "state 不能为空")
|
||||
@NotNull(message = "state 不能为空")
|
||||
private String state;
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.system.api.tenant;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 多租户的 API 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface TenantApi {
|
||||
|
||||
/**
|
||||
* 获得所有租户
|
||||
*
|
||||
* @return 租户编号数组
|
||||
*/
|
||||
List<Long> getTenantIds();
|
||||
|
||||
/**
|
||||
* 校验租户是否合法
|
||||
*
|
||||
* @param id 租户编号
|
||||
*/
|
||||
void validTenant(Long id);
|
||||
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.system.api.user;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -22,6 +23,14 @@ public interface AdminUserApi {
|
||||
*/
|
||||
AdminUserRespDTO getUser(Long id);
|
||||
|
||||
/**
|
||||
* 通过用户 ID 查询用户们
|
||||
*
|
||||
* @param ids 用户 ID 们
|
||||
* @return 用户对象信息
|
||||
*/
|
||||
List<AdminUserRespDTO> getUsers(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得指定部门的用户数组
|
||||
*
|
||||
@@ -44,7 +53,10 @@ public interface AdminUserApi {
|
||||
* @param ids 用户编号数组
|
||||
* @return 用户 Map
|
||||
*/
|
||||
Map<Long, AdminUserRespDTO> getUserMap(Collection<Long> ids);
|
||||
default Map<Long, AdminUserRespDTO> getUserMap(Collection<Long> ids) {
|
||||
List<AdminUserRespDTO> users = getUsers(ids);
|
||||
return CollectionUtils.convertMap(users, AdminUserRespDTO::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验用户们是否有效。如下情况,视为无效:
|
||||
|
@@ -12,11 +12,10 @@ public interface ErrorCodeConstants {
|
||||
// ========== AUTH 模块 1002000000 ==========
|
||||
ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1002000000, "登录失败,账号密码不正确");
|
||||
ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1002000001, "登录失败,账号被禁用");
|
||||
ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1002000002, "登录失败"); // 登录失败的兜底,未知原因
|
||||
ErrorCode AUTH_LOGIN_CAPTCHA_NOT_FOUND = new ErrorCode(1002000003, "验证码不存在");
|
||||
ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确");
|
||||
ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确,原因:{}");
|
||||
ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1002000005, "未绑定账号,需要进行绑定");
|
||||
ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1002000006, "Token 已经过期");
|
||||
ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1002000007, "手机号不存在");
|
||||
|
||||
// ========== 菜单模块 1002001000 ==========
|
||||
ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1002001000, "已经存在该名字的菜单");
|
||||
@@ -119,10 +118,31 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode SOCIAL_USER_UNBIND_NOT_SELF = new ErrorCode(1002018001, "社交解绑失败,非当前用户绑定");
|
||||
ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1002018002, "社交授权失败,找不到对应的用户");
|
||||
|
||||
// ========== 系统铭感词 1002019000 =========
|
||||
// ========== 系统敏感词 1002019000 =========
|
||||
ErrorCode SENSITIVE_WORD_NOT_EXISTS = new ErrorCode(1002019000, "系统敏感词在所有标签中都不存在");
|
||||
ErrorCode SENSITIVE_WORD_EXISTS = new ErrorCode(1002019001, "系统敏感词已在标签中存在");
|
||||
|
||||
// ========== OAuth2 客户端 1002020000 =========
|
||||
ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1002020000, "OAuth2 客户端不存在");
|
||||
ErrorCode OAUTH2_CLIENT_EXISTS = new ErrorCode(1002020001, "OAuth2 客户端编号已存在");
|
||||
ErrorCode OAUTH2_CLIENT_DISABLE = new ErrorCode(1002020002, "OAuth2 客户端已禁用");
|
||||
ErrorCode OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS = new ErrorCode(1002020003, "不支持该授权类型");
|
||||
ErrorCode OAUTH2_CLIENT_SCOPE_OVER = new ErrorCode(1002020004, "授权范围过大");
|
||||
ErrorCode OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH = new ErrorCode(1002020005, "无效 redirect_uri: {}");
|
||||
ErrorCode OAUTH2_CLIENT_CLIENT_SECRET_ERROR = new ErrorCode(1002020006, "无效 client_secret: {}");
|
||||
|
||||
// ========== OAuth2 授权 1002021000 =========
|
||||
ErrorCode OAUTH2_GRANT_CLIENT_ID_MISMATCH = new ErrorCode(1002021000, "client_id 不匹配");
|
||||
ErrorCode OAUTH2_GRANT_REDIRECT_URI_MISMATCH = new ErrorCode(1002021001, "redirect_uri 不匹配");
|
||||
ErrorCode OAUTH2_GRANT_STATE_MISMATCH = new ErrorCode(1002021002, "state 不匹配");
|
||||
ErrorCode OAUTH2_GRANT_CODE_NOT_EXISTS = new ErrorCode(1002021003, "code 不存在");
|
||||
|
||||
// ========== OAuth2 授权 1002022000 =========
|
||||
ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1002022000, "code 不存在");
|
||||
ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1002022000, "code 已过期");
|
||||
|
||||
// TODO @芋艿:需要重新搞下 mail 错误码
|
||||
|
||||
// ========== 邮箱账号 1002020000 ==========
|
||||
ErrorCode MAIL_ACCOUNT_NOT_EXISTS = new ErrorCode(1002020000, "邮箱账号不存在");
|
||||
ErrorCode MAIL_ACCOUNT_EXISTS = new ErrorCode(1002020001, "邮箱账号存在");
|
||||
|
@@ -12,12 +12,10 @@ public enum LoginLogTypeEnum {
|
||||
|
||||
LOGIN_USERNAME(100), // 使用账号登录
|
||||
LOGIN_SOCIAL(101), // 使用社交登录
|
||||
LOGIN_MOCK(102), // 使用 Mock 登录
|
||||
LOGIN_MOBILE(103), // 使用手机登陆
|
||||
LOGIN_SMS(104), // 使用短信登陆
|
||||
|
||||
LOGOUT_SELF(200), // 自己主动登出
|
||||
LOGOUT_TIMEOUT(201), // 超时登出
|
||||
LOGOUT_DELETE(202), // 强制退出
|
||||
;
|
||||
|
||||
|
@@ -16,7 +16,6 @@ public enum LoginResultEnum {
|
||||
CAPTCHA_NOT_FOUND(30), // 图片验证码不存在
|
||||
CAPTCHA_CODE_ERROR(31), // 图片验证码不正确
|
||||
|
||||
UNKNOWN_ERROR(100), // 未知异常
|
||||
;
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,12 @@
|
||||
package cn.iocoder.yudao.module.system.enums.oauth2;
|
||||
|
||||
/**
|
||||
* OAuth2.0 客户端的通用枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface OAuth2ClientConstants {
|
||||
|
||||
String CLIENT_ID_DEFAULT = "default";
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.system.enums.oauth2;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* OAuth2 授权类型(模式)的枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum OAuth2GrantTypeEnum {
|
||||
|
||||
PASSWORD("password"), // 密码模式
|
||||
AUTHORIZATION_CODE("authorization_code"), // 授权码模式
|
||||
IMPLICIT("implicit"), // 简化模式
|
||||
CLIENT_CREDENTIALS("client_credentials"), // 客户端模式
|
||||
REFRESH_TOKEN("refresh_token"), // 刷新模式
|
||||
;
|
||||
|
||||
private final String grantType;
|
||||
|
||||
public static OAuth2GrantTypeEnum getByGranType(String grantType) {
|
||||
return ArrayUtil.firstMatch(o -> o.getGrantType().equals(grantType), values());
|
||||
}
|
||||
|
||||
}
|
@@ -18,9 +18,9 @@ public enum SmsSceneEnum implements IntArrayValuable {
|
||||
|
||||
MEMBER_LOGIN(1, "user-sms-login", "会员用户 - 手机号登陆"),
|
||||
MEMBER_UPDATE_MOBILE(2, "user-sms-reset-password", "会员用户 - 修改手机"),
|
||||
MEMBER_FORGET_PASSWORD(3, "user-sms-update-mobile", "会员用户 - 忘记密码");
|
||||
MEMBER_FORGET_PASSWORD(3, "user-sms-update-mobile", "会员用户 - 忘记密码"),
|
||||
|
||||
// 如果未来希望管理后台支持手机验证码登陆,可以通过添加 ADMIN_MEMBER_LOGIN 枚举
|
||||
ADMIN_MEMBER_LOGIN(21, "admin-sms-login", "后台用户 - 手机号登录");
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SmsSceneEnum::getScene).toArray();
|
||||
|
||||
|
@@ -6,9 +6,6 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 社交平台的类型枚举
|
||||
@@ -49,7 +46,7 @@ public enum SocialTypeEnum implements IntArrayValuable {
|
||||
* 微信小程序
|
||||
* 文档链接:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
|
||||
*/
|
||||
WECHAT_MINI_PROGRAM(33, "WECHAT_MINI_PROGRAM"),
|
||||
WECHAT_MINI_APP(34, "WECHAT_MINI_APP"),
|
||||
;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SocialTypeEnum::getType).toArray();
|
||||
|
@@ -97,6 +97,10 @@
|
||||
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-captcha</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
@@ -1,47 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.api.auth;
|
||||
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
import cn.iocoder.yudao.module.system.service.auth.UserSessionService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 在线用户 Session API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class UserSessionApiImpl implements UserSessionApi {
|
||||
|
||||
@Resource
|
||||
private UserSessionService userSessionService;
|
||||
|
||||
@Override
|
||||
public String createUserSession(LoginUser loginUser, String userIp, String userAgent) {
|
||||
return userSessionService.createUserSession(loginUser, userIp, userAgent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshUserSession(String token, LoginUser loginUser) {
|
||||
userSessionService.refreshUserSession(token, loginUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteUserSession(String token) {
|
||||
userSessionService.deleteUserSession(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginUser getLoginUser(String token) {
|
||||
return userSessionService.getLoginUser(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getSessionTimeoutMillis() {
|
||||
return userSessionService.getSessionTimeoutMillis();
|
||||
}
|
||||
|
||||
}
|
@@ -9,8 +9,6 @@ import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 部门 API 实现类
|
||||
@@ -40,10 +38,4 @@ public class DeptApiImpl implements DeptApi {
|
||||
deptService.validDepts(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, DeptRespDTO> getDeptMap(Set<Long> ids) {
|
||||
Map<Long, DeptDO> depts = deptService.getDeptMap(ids);
|
||||
return DeptConvert.INSTANCE.convertMap(depts);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,5 +1,8 @@
|
||||
package cn.iocoder.yudao.module.system.api.dict;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
|
||||
import cn.iocoder.yudao.module.system.convert.dict.DictDataConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
|
||||
import cn.iocoder.yudao.module.system.service.dict.DictDataService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -22,4 +25,16 @@ public class DictDataApiImpl implements DictDataApi {
|
||||
dictDataService.validDictDatas(dictType, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DictDataRespDTO getDictData(String dictType, String value) {
|
||||
DictDataDO dictData = dictDataService.getDictData(dictType, value);
|
||||
return DictDataConvert.INSTANCE.convert02(dictData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DictDataRespDTO parseDictData(String dictType, String label) {
|
||||
DictDataDO dictData = dictDataService.parseDictData(dictType, label);
|
||||
return DictDataConvert.INSTANCE.convert02(dictData);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.system.api.errorcode;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeRespDTO;
|
||||
import cn.iocoder.yudao.module.system.service.errorcode.ErrorCodeService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 错误码 Api 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
public class ErrorCodeApiImpl implements ErrorCodeApi {
|
||||
|
||||
@Resource
|
||||
private ErrorCodeService errorCodeService;
|
||||
|
||||
@Override
|
||||
public void autoGenerateErrorCodes(List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs) {
|
||||
errorCodeService.autoGenerateErrorCodes(autoGenerateDTOs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ErrorCodeRespDTO> getErrorCodeList(String applicationName, LocalDateTime minUpdateTime) {
|
||||
return errorCodeService.getErrorCodeList(applicationName, minUpdateTime);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.module.system.api.logger;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.service.logger.OperateLogService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 操作日志 API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class OperateLogApiImpl implements OperateLogApi {
|
||||
|
||||
@Resource
|
||||
private OperateLogService operateLogService;
|
||||
|
||||
@Override
|
||||
public void createOperateLog(OperateLogCreateReqDTO createReqDTO) {
|
||||
operateLogService.createOperateLog(createReqDTO);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
package cn.iocoder.yudao.module.system.api.oauth2;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO;
|
||||
import cn.iocoder.yudao.module.system.convert.auth.OAuth2TokenConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* OAuth2.0 Token API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
public class OAuth2TokenApiImpl implements OAuth2TokenApi {
|
||||
|
||||
@Resource
|
||||
private OAuth2TokenService oauth2TokenService;
|
||||
|
||||
@Override
|
||||
public OAuth2AccessTokenRespDTO createAccessToken(OAuth2AccessTokenCreateReqDTO reqDTO) {
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(
|
||||
reqDTO.getUserId(), reqDTO.getUserType(), reqDTO.getClientId(), reqDTO.getScopes());
|
||||
return OAuth2TokenConvert.INSTANCE.convert2(accessTokenDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2AccessTokenCheckRespDTO checkAccessToken(String accessToken) {
|
||||
return OAuth2TokenConvert.INSTANCE.convert(oauth2TokenService.checkAccessToken(accessToken));
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2AccessTokenRespDTO removeAccessToken(String accessToken) {
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.removeAccessToken(accessToken);
|
||||
return OAuth2TokenConvert.INSTANCE.convert2(accessTokenDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2AccessTokenRespDTO refreshAccessToken(String refreshToken, String clientId) {
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, clientId);
|
||||
return OAuth2TokenConvert.INSTANCE.convert2(accessTokenDO);
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.system.api.permission;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
|
||||
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -23,4 +24,19 @@ public class PermissionApiImpl implements PermissionApi {
|
||||
return permissionService.getUserRoleIdListByRoleIds(roleIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAnyPermissions(Long userId, String... permissions) {
|
||||
return permissionService.hasAnyPermissions(userId, permissions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAnyRoles(Long userId, String... roles) {
|
||||
return permissionService.hasAnyRoles(userId, roles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeptDataPermissionRespDTO getDeptDataPermission(Long userId) {
|
||||
return permissionService.getDeptDataPermission(userId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.system.api.tenant;
|
||||
|
||||
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 多租户的 API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
public class TenantApiImpl implements TenantApi {
|
||||
|
||||
@Resource
|
||||
private TenantService tenantService;
|
||||
|
||||
@Override
|
||||
public List<Long> getTenantIds() {
|
||||
return tenantService.getTenantIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validTenant(Long id) {
|
||||
tenantService.validTenant(id);
|
||||
}
|
||||
|
||||
}
|
@@ -9,7 +9,6 @@ import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -29,6 +28,12 @@ public class AdminUserApiImpl implements AdminUserApi {
|
||||
return UserConvert.INSTANCE.convert4(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AdminUserRespDTO> getUsers(Collection<Long> ids) {
|
||||
List<AdminUserDO> users = userService.getUsers(ids);
|
||||
return UserConvert.INSTANCE.convertList4(users);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AdminUserRespDTO> getUsersByDeptIds(Collection<Long> deptIds) {
|
||||
List<AdminUserDO> users = userService.getUsersByDeptIds(deptIds);
|
||||
@@ -41,12 +46,6 @@ public class AdminUserApiImpl implements AdminUserApi {
|
||||
return UserConvert.INSTANCE.convertList4(users);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, AdminUserRespDTO> getUserMap(Collection<Long> ids) {
|
||||
Map<Long, AdminUserDO> userMap = userService.getUserMap(ids);
|
||||
return UserConvert.INSTANCE.convertMap4(userMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validUsers(Set<Long> ids) {
|
||||
userService.validUsers(ids);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
### 请求 /login 接口 => 成功
|
||||
POST {{baseUrl}}/system/login
|
||||
POST {{baseUrl}}/system/auth/login
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
@@ -11,7 +11,7 @@ tenant-id: {{adminTenentId}}
|
||||
}
|
||||
|
||||
### 请求 /login 接口 => 成功(无验证码)
|
||||
POST {{baseUrl}}/system/login
|
||||
POST {{baseUrl}}/system/auth/login
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
@@ -21,7 +21,7 @@ tenant-id: {{adminTenentId}}
|
||||
}
|
||||
|
||||
### 请求 /get-permission-info 接口 => 成功
|
||||
GET {{baseUrl}}/system/get-permission-info
|
||||
GET {{baseUrl}}/system/auth/get-permission-info
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
|
@@ -1,15 +1,17 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*;
|
||||
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
|
||||
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
|
||||
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
|
||||
@@ -25,18 +27,20 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
|
||||
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserRoleIds;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.obtainAuthorization;
|
||||
import static java.util.Collections.singleton;
|
||||
|
||||
@Api(tags = "管理后台 - 认证")
|
||||
@RestController
|
||||
@RequestMapping("/system/auth") // 暂时不跟 /auth 结尾
|
||||
@RequestMapping("/system/auth")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class AuthController {
|
||||
@@ -51,14 +55,36 @@ public class AuthController {
|
||||
private PermissionService permissionService;
|
||||
@Resource
|
||||
private SocialUserService socialUserService;
|
||||
@Resource
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
@PostMapping("/login")
|
||||
@PermitAll
|
||||
@ApiOperation("使用账号密码登录")
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
|
||||
String token = authService.login(reqVO, getClientIP(), getUserAgent());
|
||||
// 返回结果
|
||||
return success(AuthLoginRespVO.builder().token(token).build());
|
||||
return success(authService.login(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/logout")
|
||||
@PermitAll
|
||||
@ApiOperation("登出系统")
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<Boolean> logout(HttpServletRequest request) {
|
||||
String token = obtainAuthorization(request, securityProperties.getTokenHeader());
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType());
|
||||
}
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PostMapping("/refresh-token")
|
||||
@PermitAll
|
||||
@ApiOperation("刷新令牌")
|
||||
@ApiImplicitParam(name = "refreshToken", value = "刷新令牌", required = true, dataTypeClass = String.class)
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<AuthLoginRespVO> refreshToken(@RequestParam("refreshToken") String refreshToken) {
|
||||
return success(authService.refreshToken(refreshToken));
|
||||
}
|
||||
|
||||
@GetMapping("/get-permission-info")
|
||||
@@ -70,12 +96,12 @@ public class AuthController {
|
||||
return null;
|
||||
}
|
||||
// 获得角色列表
|
||||
List<RoleDO> roleList = roleService.getRolesFromCache(getLoginUserRoleIds());
|
||||
Set<Long> roleIds = permissionService.getUserRoleIdsFromCache(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
|
||||
List<RoleDO> roleList = roleService.getRolesFromCache(roleIds);
|
||||
// 获得菜单列表
|
||||
List<MenuDO> menuList = permissionService.getRoleMenuListFromCache(
|
||||
getLoginUserRoleIds(), // 注意,基于登录的角色,因为后续的权限判断也是基于它
|
||||
List<MenuDO> menuList = permissionService.getRoleMenuListFromCache(roleIds,
|
||||
SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType(), MenuTypeEnum.BUTTON.getType()),
|
||||
SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus()));
|
||||
singleton(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的
|
||||
// 拼接结果返回
|
||||
return success(AuthConvert.INSTANCE.convert(user, roleList, menuList));
|
||||
}
|
||||
@@ -83,44 +109,55 @@ public class AuthController {
|
||||
@GetMapping("/list-menus")
|
||||
@ApiOperation("获得登录用户的菜单列表")
|
||||
public CommonResult<List<AuthMenuRespVO>> getMenus() {
|
||||
// 获得角色列表
|
||||
Set<Long> roleIds = permissionService.getUserRoleIdsFromCache(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
|
||||
// 获得用户拥有的菜单列表
|
||||
List<MenuDO> menuList = permissionService.getRoleMenuListFromCache(
|
||||
getLoginUserRoleIds(), // 注意,基于登录的角色,因为后续的权限判断也是基于它
|
||||
List<MenuDO> menuList = permissionService.getRoleMenuListFromCache(roleIds,
|
||||
SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), // 只要目录和菜单类型
|
||||
SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的
|
||||
singleton(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的
|
||||
// 转换成 Tree 结构返回
|
||||
return success(AuthConvert.INSTANCE.buildMenuTree(menuList));
|
||||
}
|
||||
|
||||
// ========== 短信登录相关 ==========
|
||||
|
||||
@PostMapping("/sms-login")
|
||||
@PermitAll
|
||||
@ApiOperation("使用短信验证码登录")
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<AuthLoginRespVO> smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) {
|
||||
return success(authService.smsLogin(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/send-sms-code")
|
||||
@PermitAll
|
||||
@ApiOperation(value = "发送手机验证码")
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<Boolean> sendLoginSmsCode(@RequestBody @Valid AuthSmsSendReqVO reqVO) {
|
||||
authService.sendSmsCode(reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// ========== 社交登录相关 ==========
|
||||
|
||||
@GetMapping("/social-auth-redirect")
|
||||
@PermitAll
|
||||
@ApiOperation("社交授权的跳转")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "type", value = "社交类型", required = true, dataTypeClass = Integer.class),
|
||||
@ApiImplicitParam(name = "redirectUri", value = "回调路径", dataTypeClass = String.class)
|
||||
})
|
||||
public CommonResult<String> socialAuthRedirect(@RequestParam("type") Integer type,
|
||||
public CommonResult<String> socialLogin(@RequestParam("type") Integer type,
|
||||
@RequestParam("redirectUri") String redirectUri) {
|
||||
return CommonResult.success(socialUserService.getAuthorizeUrl(type, redirectUri));
|
||||
}
|
||||
|
||||
@PostMapping("/social-quick-login")
|
||||
@ApiOperation("社交快捷登录,使用 code 授权码")
|
||||
@PostMapping("/social-login")
|
||||
@PermitAll
|
||||
@ApiOperation(value = "社交快捷登录,使用 code 授权码", notes = "适合未登录的用户,但是社交账号已绑定用户")
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialQuickLoginReqVO reqVO) {
|
||||
String token = authService.socialLogin(reqVO, getClientIP(), getUserAgent());
|
||||
// 返回结果
|
||||
return success(AuthLoginRespVO.builder().token(token).build());
|
||||
}
|
||||
|
||||
@PostMapping("/social-bind-login")
|
||||
@ApiOperation("社交绑定登录,使用 code 授权码 + 账号密码")
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<AuthLoginRespVO> socialBindLogin(@RequestBody @Valid AuthSocialBindLoginReqVO reqVO) {
|
||||
String token = authService.socialBindLogin(reqVO, getClientIP(), getUserAgent());
|
||||
// 返回结果
|
||||
return success(AuthLoginRespVO.builder().token(token).build());
|
||||
public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialLoginReqVO reqVO) {
|
||||
return success(authService.socialLogin(reqVO));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,79 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageItemRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.convert.auth.UserSessionConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
||||
import cn.iocoder.yudao.module.system.service.auth.UserSessionService;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||
import cn.iocoder.yudao.module.system.service.dept.DeptService;
|
||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
@Api(tags = "管理后台 - 用户 Session")
|
||||
@RestController
|
||||
@RequestMapping("/system/user-session")
|
||||
public class UserSessionController {
|
||||
|
||||
@Resource
|
||||
private UserSessionService userSessionService;
|
||||
@Resource
|
||||
private AdminUserService userService;
|
||||
|
||||
@Resource
|
||||
private DeptService deptService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得 Session 分页列表")
|
||||
@PreAuthorize("@ss.hasPermission('system:user-session:page')")
|
||||
public CommonResult<PageResult<UserSessionPageItemRespVO>> getUserSessionPage(@Validated UserSessionPageReqVO reqVO) {
|
||||
// 获得 Session 分页
|
||||
PageResult<UserSessionDO> pageResult = userSessionService.getUserSessionPage(reqVO);
|
||||
|
||||
// 获得拼接需要的数据
|
||||
Map<Long, AdminUserDO> userMap = userService.getUserMap(
|
||||
convertList(pageResult.getList(), UserSessionDO::getUserId));
|
||||
Map<Long, DeptDO> deptMap = deptService.getDeptMap(
|
||||
convertList(userMap.values(), AdminUserDO::getDeptId));
|
||||
// 拼接结果返回
|
||||
List<UserSessionPageItemRespVO> sessionList = new ArrayList<>(pageResult.getList().size());
|
||||
pageResult.getList().forEach(session -> {
|
||||
UserSessionPageItemRespVO respVO = UserSessionConvert.INSTANCE.convert(session);
|
||||
sessionList.add(respVO);
|
||||
// 设置用户账号
|
||||
MapUtils.findAndThen(userMap, session.getUserId(), user -> {
|
||||
respVO.setUsername(user.getUsername());
|
||||
// 设置用户部门
|
||||
MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> respVO.setDeptName(dept.getName()));
|
||||
});
|
||||
});
|
||||
return success(new PageResult<>(sessionList, pageResult.getTotal()));
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除 Session")
|
||||
@ApiImplicitParam(name = "id", value = "Session 编号", required = true, dataTypeClass = Long.class, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('system:user-session:delete')")
|
||||
public CommonResult<Boolean> deleteUserSession(@RequestParam("id") Long id) {
|
||||
userSessionService.deleteUserSession(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.AssertTrue;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
@ApiModel(value = "管理后台 - 账号密码登录 Request VO", description = "如果登录并绑定社交用户,需要传递 social 开头的参数")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthLoginReqVO {
|
||||
|
||||
@ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma")
|
||||
@NotEmpty(message = "登录账号不能为空")
|
||||
@Length(min = 4, max = 16, message = "账号长度为 4-16 位")
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty(value = "密码", required = true, example = "buzhidao")
|
||||
@NotEmpty(message = "密码不能为空")
|
||||
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String password;
|
||||
|
||||
// ========== 图片验证码相关 ==========
|
||||
|
||||
@ApiModelProperty(value = "验证码", required = true,
|
||||
example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==",
|
||||
notes = "验证码开启时,需要传递")
|
||||
@NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
|
||||
private String captchaVerification;
|
||||
|
||||
// ========== 绑定社交登录时,需要传递如下参数 ==========
|
||||
|
||||
@ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值")
|
||||
@InEnum(SocialTypeEnum.class)
|
||||
private Integer socialType;
|
||||
|
||||
@ApiModelProperty(value = "授权码", required = true, example = "1024")
|
||||
private String socialCode;
|
||||
|
||||
@ApiModelProperty(value = "state", required = true, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
|
||||
private String socialState;
|
||||
|
||||
/**
|
||||
* 开启验证码的 Group
|
||||
*/
|
||||
public interface CodeEnableGroup {}
|
||||
|
||||
@AssertTrue(message = "授权码不能为空")
|
||||
public boolean isSocialCodeValid() {
|
||||
return socialType == null || StrUtil.isNotEmpty(socialCode);
|
||||
}
|
||||
|
||||
@AssertTrue(message = "授权 state 不能为空")
|
||||
public boolean isSocialState() {
|
||||
return socialType == null || StrUtil.isNotEmpty(socialState);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("管理后台 - 登录 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthLoginRespVO {
|
||||
|
||||
@ApiModelProperty(value = "用户编号", required = true, example = "1024")
|
||||
private Long userId;
|
||||
|
||||
@ApiModelProperty(value = "访问令牌", required = true, example = "happy")
|
||||
private String accessToken;
|
||||
|
||||
@ApiModelProperty(value = "刷新令牌", required = true, example = "nice")
|
||||
private String refreshToken;
|
||||
|
||||
@ApiModelProperty(value = "过期时间", required = true)
|
||||
private LocalDateTime expiresTime;
|
||||
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth;
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth;
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.Mobile;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@ApiModel("管理后台 - 短信验证码的登录 Request VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthSmsLoginReqVO {
|
||||
|
||||
@ApiModelProperty(value = "手机号", required = true, example = "yudaoyuanma")
|
||||
@NotEmpty(message = "手机号不能为空")
|
||||
@Mobile
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "短信验证码", required = true, example = "1024")
|
||||
@NotEmpty(message = "验证码不能为空")
|
||||
private String code;
|
||||
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.Mobile;
|
||||
import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 发送手机验证码 Request VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthSmsSendReqVO {
|
||||
|
||||
@ApiModelProperty(value = "手机号", required = true, example = "yudaoyuanma")
|
||||
@NotEmpty(message = "手机号不能为空")
|
||||
@Mobile
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "短信场景", required = true, example = "1")
|
||||
@NotNull(message = "发送场景不能为空")
|
||||
@InEnum(SmsSceneEnum.class)
|
||||
private Integer scene;
|
||||
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth;
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -12,12 +12,12 @@ import lombok.NoArgsConstructor;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 社交快捷登录 Request VO,使用 code 授权码")
|
||||
@ApiModel("管理后台 - 社交绑定登录 Request VO,使用 code 授权码 + 账号密码")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthSocialQuickLoginReqVO {
|
||||
public class AuthSocialLoginReqVO {
|
||||
|
||||
@ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 UserSocialTypeEnum 枚举值")
|
||||
@InEnum(SocialTypeEnum.class)
|
@@ -1,45 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
@ApiModel("管理后台 - 账号密码登录 Request VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthLoginReqVO {
|
||||
|
||||
@ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma")
|
||||
@NotEmpty(message = "登录账号不能为空")
|
||||
@Length(min = 4, max = 16, message = "账号长度为 4-16 位")
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty(value = "密码", required = true, example = "buzhidao")
|
||||
@NotEmpty(message = "密码不能为空")
|
||||
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String password;
|
||||
|
||||
@ApiModelProperty(value = "验证码", required = true, example = "1024", notes = "验证码开启时,需要传递")
|
||||
@NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty(value = "验证码的唯一标识", required = true, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62", notes = "验证码开启时,需要传递")
|
||||
@NotEmpty(message = "唯一标识不能为空", groups = CodeEnableGroup.class)
|
||||
private String uuid;
|
||||
|
||||
/**
|
||||
* 开启验证码的 Group
|
||||
*/
|
||||
public interface CodeEnableGroup {}
|
||||
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@ApiModel("管理后台 - 账号密码登录 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthLoginRespVO {
|
||||
|
||||
@ApiModelProperty(value = "token", required = true, example = "yudaoyuanma")
|
||||
private String token;
|
||||
|
||||
}
|
@@ -1,48 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
@ApiModel("管理后台 - 社交绑定登录 Request VO,使用 code 授权码 + 账号密码")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthSocialBindLoginReqVO {
|
||||
|
||||
@ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 UserSocialTypeEnum 枚举值")
|
||||
@InEnum(SocialTypeEnum.class)
|
||||
@NotNull(message = "社交平台的类型不能为空")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty(value = "授权码", required = true, example = "1024")
|
||||
@NotEmpty(message = "授权码不能为空")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty(value = "state", required = true, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
|
||||
@NotEmpty(message = "state 不能为空")
|
||||
private String state;
|
||||
|
||||
@ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma")
|
||||
@NotEmpty(message = "登录账号不能为空")
|
||||
@Length(min = 4, max = 16, message = "账号长度为 4-16 位")
|
||||
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty(value = "密码", required = true, example = "buzhidao")
|
||||
@NotEmpty(message = "密码不能为空")
|
||||
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String password;
|
||||
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo.session;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel(value = "管理后台 - 用户在线 Session Response VO", description = "相比用户基本信息来说,会多部门、用户账号等信息")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class UserSessionPageItemRespVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "Session 编号", required = true, example = "fe50b9f6-d177-44b1-8da9-72ea34f63db7")
|
||||
private String id;
|
||||
|
||||
@ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1")
|
||||
private String userIp;
|
||||
|
||||
@ApiModelProperty(value = "浏览器 UserAgent", required = true, example = "Mozilla/5.0")
|
||||
private String userAgent;
|
||||
|
||||
@ApiModelProperty(value = "登录时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
@ApiModelProperty(value = "用户账号", required = true, example = "yudao")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty(value = "部门名称", example = "研发部")
|
||||
private String deptName;
|
||||
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo.session;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@ApiModel("管理后台 - 在线用户 Session 分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class UserSessionPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "用户 IP", example = "127.0.0.1", notes = "模糊匹配")
|
||||
private String userIp;
|
||||
|
||||
@ApiModelProperty(value = "用户账号", example = "yudao", notes = "模糊匹配")
|
||||
private String username;
|
||||
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.captcha;
|
||||
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import com.anji.captcha.model.common.ResponseModel;
|
||||
import com.anji.captcha.model.vo.CaptchaVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*
|
||||
* 问题:为什么不直接使用 anji 提供的 CaptchaController,而要另外继承?
|
||||
* 回答:管理使用 /admin-api/* 作为前缀,所以需要继承!
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Api(tags = "管理后台 - 验证码")
|
||||
@RestController("adminCaptchaController")
|
||||
@RequestMapping("/system/captcha")
|
||||
public class CaptchaController extends com.anji.captcha.controller.CaptchaController {
|
||||
|
||||
@PostMapping({"/get"})
|
||||
@ApiOperation("获得验证码")
|
||||
@PermitAll
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
@Override
|
||||
public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {
|
||||
return super.get(data, request);
|
||||
}
|
||||
|
||||
@PostMapping("/check")
|
||||
@ApiOperation("校验验证码")
|
||||
@PermitAll
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
@Override
|
||||
public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {
|
||||
return super.check(data, request);
|
||||
}
|
||||
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
### 请求 /captcha/get-image 接口 => 成功
|
||||
GET {{baseUrl}}/system/captcha/get-image
|
||||
tenant-id: {{adminTenentId}}
|
@@ -1,30 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.common;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.common.vo.CaptchaImageRespVO;
|
||||
import cn.iocoder.yudao.module.system.service.common.CaptchaService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - 验证码")
|
||||
@RestController
|
||||
@RequestMapping("/system/captcha")
|
||||
public class CaptchaController {
|
||||
|
||||
@Resource
|
||||
private CaptchaService captchaService;
|
||||
|
||||
@GetMapping("/get-image")
|
||||
@ApiOperation("生成图片验证码")
|
||||
public CommonResult<CaptchaImageRespVO> getCaptchaImage() {
|
||||
return success(captchaService.getCaptchaImage());
|
||||
}
|
||||
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.common.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@ApiModel("管理后台 - 验证码图片 Response VO")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CaptchaImageRespVO {
|
||||
|
||||
@ApiModelProperty(value = "是否开启", required = true, example = "true", notes = "如果为 false,则关闭验证码功能")
|
||||
private Boolean enable;
|
||||
|
||||
@ApiModelProperty(value = "uuid", example = "1b3b7d00-83a8-4638-9e37-d67011855968",
|
||||
notes = "enable = true 时,非空!通过该 uuid 作为该验证码的标识")
|
||||
private String uuid;
|
||||
|
||||
@ApiModelProperty(value = "图片", notes = "enable = true 时,非空!验证码的图片内容,使用 Base64 编码")
|
||||
private String img;
|
||||
|
||||
}
|
@@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("管理后台 - 部门信息 Response VO")
|
||||
@Data
|
||||
@@ -19,6 +19,6 @@ public class DeptRespVO extends DeptBaseVO {
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("管理后台 - 岗位信息 Response VO")
|
||||
@Data
|
||||
@@ -16,6 +16,6 @@ public class PostRespVO extends PostBaseVO {
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("管理后台 - 字典数据信息 Response VO")
|
||||
@Data
|
||||
@@ -20,6 +20,6 @@ public class DictDataRespVO extends DictDataBaseVO {
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@@ -23,11 +23,7 @@ public class DictTypeExportReqVO {
|
||||
private Integer status;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始创建时间")
|
||||
private Date beginCreateTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "结束创建时间")
|
||||
private Date endCreateTime;
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@@ -28,11 +28,7 @@ public class DictTypePageReqVO extends PageParam {
|
||||
private Integer status;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始创建时间")
|
||||
private Date beginCreateTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "结束创建时间")
|
||||
private Date endCreateTime;
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("管理后台 - 字典类型信息 Response VO")
|
||||
@Data
|
||||
@@ -23,6 +23,6 @@ public class DictTypeRespVO extends DictTypeBaseVO {
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@@ -2,11 +2,10 @@ package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||
//import cn.iocoder.yudao.adminserver.modules.infra.enums.InfDictTypeConstants;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 错误码 Excel VO
|
||||
@@ -36,6 +35,6 @@ public class ErrorCodeExcelVO {
|
||||
private String memo;
|
||||
|
||||
@ExcelProperty("创建时间")
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@@ -26,11 +26,7 @@ public class ErrorCodeExportReqVO {
|
||||
private String message;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始创建时间")
|
||||
private Date beginCreateTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "结束创建时间")
|
||||
private Date endCreateTime;
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@@ -31,11 +31,7 @@ public class ErrorCodePageReqVO extends PageParam {
|
||||
private String message;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始创建时间")
|
||||
private Date beginCreateTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "结束创建时间")
|
||||
private Date endCreateTime;
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("管理后台 - 错误码 Response VO")
|
||||
@Data
|
||||
@@ -21,6 +21,6 @@ public class ErrorCodeRespVO extends ErrorCodeBaseVO {
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ public class LoginLogBaseVO {
|
||||
@NotNull(message = "日志类型不能为空")
|
||||
private Integer logType;
|
||||
|
||||
@ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab")
|
||||
@ApiModelProperty(value = "链路追踪编号", example = "89aca178-a370-411c-ae02-3f0d672be4ab")
|
||||
@NotEmpty(message = "链路追踪编号不能为空")
|
||||
private String traceId;
|
||||
|
||||
@@ -36,8 +36,7 @@ public class LoginLogBaseVO {
|
||||
@NotEmpty(message = "用户 IP 不能为空")
|
||||
private String userIp;
|
||||
|
||||
@ApiModelProperty(value = "浏览器 UserAgent", required = true, example = "Mozilla/5.0")
|
||||
@NotEmpty(message = "浏览器 UserAgent 不能为空")
|
||||
@ApiModelProperty(value = "浏览器 UserAgent", example = "Mozilla/5.0")
|
||||
private String userAgent;
|
||||
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 登录日志 Excel 导出响应 VO
|
||||
@@ -35,6 +35,6 @@ public class LoginLogExcelVO {
|
||||
private String userAgent;
|
||||
|
||||
@ExcelProperty("登录时间")
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@@ -22,12 +22,8 @@ public class LoginLogExportReqVO {
|
||||
@ApiModelProperty(value = "操作状态", example = "true")
|
||||
private Boolean status;
|
||||
|
||||
@ApiModelProperty(value = "开始时间", example = "2020-10-24")
|
||||
@ApiModelProperty(value = "登录时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date beginTime;
|
||||
|
||||
@ApiModelProperty(value = "结束时间", example = "2020-10-24")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date endTime;
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@@ -25,12 +25,8 @@ public class LoginLogPageReqVO extends PageParam {
|
||||
@ApiModelProperty(value = "操作状态", example = "true")
|
||||
private Boolean status;
|
||||
|
||||
@ApiModelProperty(value = "开始时间", example = "2020-10-24")
|
||||
@ApiModelProperty(value = "登录时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date beginTime;
|
||||
|
||||
@ApiModelProperty(value = "结束时间", example = "2020-10-24")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date endTime;
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("管理后台 - 登录日志 Response VO")
|
||||
@Data
|
||||
@@ -18,8 +18,7 @@ public class LoginLogRespVO extends LoginLogBaseVO {
|
||||
@ApiModelProperty(value = "日志编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "用户编号", required = true, example = "666")
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
@ApiModelProperty(value = "用户编号", example = "666")
|
||||
private Long userId;
|
||||
|
||||
@ApiModelProperty(value = "用户类型", required = true, example = "2", notes = "参见 UserTypeEnum 枚举")
|
||||
@@ -27,6 +26,6 @@ public class LoginLogRespVO extends LoginLogBaseVO {
|
||||
private Integer userType;
|
||||
|
||||
@ApiModelProperty(value = "登录时间", required = true)
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -66,7 +66,7 @@ public class OperateLogBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "开始时间", required = true)
|
||||
@NotNull(message = "开始时间不能为空")
|
||||
private Date startTime;
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@ApiModelProperty(value = "执行时长,单位:毫秒", required = true)
|
||||
@NotNull(message = "执行时长不能为空")
|
||||
|
@@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 操作日志 Excel 导出响应 VO
|
||||
@@ -34,7 +34,7 @@ public class OperateLogExcelVO {
|
||||
private String successStr;
|
||||
|
||||
@ExcelProperty("操作日志")
|
||||
private Date startTime;
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@ExcelProperty("执行时长")
|
||||
private Integer duration;
|
||||
|
@@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@@ -25,12 +25,8 @@ public class OperateLogExportReqVO {
|
||||
@ApiModelProperty(value = "操作状态", example = "true")
|
||||
private Boolean success;
|
||||
|
||||
@ApiModelProperty(value = "开始时间", example = "2020-10-24")
|
||||
@ApiModelProperty(value = "开始时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date beginTime;
|
||||
|
||||
@ApiModelProperty(value = "结束时间", example = "2020-10-24")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date endTime;
|
||||
private LocalDateTime[] startTime;
|
||||
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@@ -26,12 +26,8 @@ public class OperateLogPageReqVO extends PageParam {
|
||||
@ApiModelProperty(value = "操作状态", example = "true")
|
||||
private Boolean success;
|
||||
|
||||
@ApiModelProperty(value = "开始时间", example = "2020-10-24")
|
||||
@ApiModelProperty(value = "开始时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date beginTime;
|
||||
|
||||
@ApiModelProperty(value = "结束时间", example = "2020-10-24")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date endTime;
|
||||
private LocalDateTime[] startTime;
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("管理后台 - 通知公告信息 Response VO")
|
||||
@Data
|
||||
@@ -16,6 +16,6 @@ public class NoticeRespVO extends NoticeBaseVO {
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,23 @@
|
||||
### 请求 /login 接口 => 成功
|
||||
POST {{baseUrl}}/system/oauth2-client/create
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"id": "1",
|
||||
"secret": "admin123",
|
||||
"name": "芋道源码",
|
||||
"logo": "https://www.iocoder.cn/images/favicon.ico",
|
||||
"description": "我是描述",
|
||||
"status": 0,
|
||||
"accessTokenValiditySeconds": 180,
|
||||
"refreshTokenValiditySeconds": 8640,
|
||||
"redirectUris": ["https://www.iocoder.cn"],
|
||||
"autoApprove": true,
|
||||
"authorizedGrantTypes": ["password"],
|
||||
"scopes": ["user_info"],
|
||||
"authorities": ["system:user:query"],
|
||||
"resource_ids": ["1024"],
|
||||
"additionalInformation": "{}"
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientCreateReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.system.convert.auth.OAuth2ClientConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
|
||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - OAuth2 客户端")
|
||||
@RestController
|
||||
@RequestMapping("/system/oauth2-client")
|
||||
@Validated
|
||||
public class OAuth2ClientController {
|
||||
|
||||
@Resource
|
||||
private OAuth2ClientService oAuth2ClientService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("创建 OAuth2 客户端")
|
||||
@PreAuthorize("@ss.hasPermission('system:oauth2-client:create')")
|
||||
public CommonResult<Long> createOAuth2Client(@Valid @RequestBody OAuth2ClientCreateReqVO createReqVO) {
|
||||
return success(oAuth2ClientService.createOAuth2Client(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("更新 OAuth2 客户端")
|
||||
@PreAuthorize("@ss.hasPermission('system:oauth2-client:update')")
|
||||
public CommonResult<Boolean> updateOAuth2Client(@Valid @RequestBody OAuth2ClientUpdateReqVO updateReqVO) {
|
||||
oAuth2ClientService.updateOAuth2Client(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除 OAuth2 客户端")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('system:oauth2-client:delete')")
|
||||
public CommonResult<Boolean> deleteOAuth2Client(@RequestParam("id") Long id) {
|
||||
oAuth2ClientService.deleteOAuth2Client(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得 OAuth2 客户端")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('system:oauth2-client:query')")
|
||||
public CommonResult<OAuth2ClientRespVO> getOAuth2Client(@RequestParam("id") Long id) {
|
||||
OAuth2ClientDO oAuth2Client = oAuth2ClientService.getOAuth2Client(id);
|
||||
return success(OAuth2ClientConvert.INSTANCE.convert(oAuth2Client));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得OAuth2 客户端分页")
|
||||
@PreAuthorize("@ss.hasPermission('system:oauth2-client:query')")
|
||||
public CommonResult<PageResult<OAuth2ClientRespVO>> getOAuth2ClientPage(@Valid OAuth2ClientPageReqVO pageVO) {
|
||||
PageResult<OAuth2ClientDO> pageResult = oAuth2ClientService.getOAuth2ClientPage(pageVO);
|
||||
return success(OAuth2ClientConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
### 请求 /system/oauth2/authorize 接口 => 成功
|
||||
GET {{baseUrl}}/system/oauth2/authorize?clientId=default
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
### 请求 /system/oauth2/authorize + token 接口 => 成功
|
||||
POST {{baseUrl}}/system/oauth2/authorize
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
response_type=token&client_id=default&scope={"user.read": true}&redirect_uri=https://www.iocoder.cn&auto_approve=true
|
||||
|
||||
### 请求 /system/oauth2/authorize + code 接口 => 成功
|
||||
POST {{baseUrl}}/system/oauth2/authorize
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
response_type=code&client_id=default&scope={"user.read": true}&redirect_uri=https://www.iocoder.cn&auto_approve=false
|
||||
|
||||
### 请求 /system/oauth2/token + code 接口 => 成功
|
||||
POST {{baseUrl}}/system/oauth2/token
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw==
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
grant_type=authorization_code&redirect_uri=https://www.iocoder.cn&code=189956c07a174588a97157eabef2f93a
|
||||
|
||||
### 请求 /system/oauth2/token + password 接口 => 成功
|
||||
POST {{baseUrl}}/system/oauth2/token
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw==
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
grant_type=password&username=admin&password=admin123&scope=user.read
|
||||
|
||||
### 请求 /system/oauth2/token + refresh_token 接口 => 成功
|
||||
POST {{baseUrl}}/system/oauth2/token
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw==
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
grant_type=refresh_token&refresh_token=00895465d6994f72a9d926ceeed0f588
|
||||
|
||||
### 请求 /system/oauth2/token + DELETE 接口 => 成功
|
||||
DELETE {{baseUrl}}/system/oauth2/token?token=ca8a188f464441d6949c51493a2b7596
|
||||
Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw==
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
### 请求 /system/oauth2/check-token 接口 => 成功
|
||||
POST {{baseUrl}}/system/oauth2/check-token?token=620d307c5b4148df8a98dd6c6c547106
|
||||
Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw==
|
||||
tenant-id: {{adminTenentId}}
|
@@ -0,0 +1,302 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAuthorizeInfoRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO;
|
||||
import cn.iocoder.yudao.module.system.convert.oauth2.OAuth2OpenConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ApproveDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
|
||||
import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2GrantTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ApproveService;
|
||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService;
|
||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2GrantService;
|
||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
|
||||
import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
/**
|
||||
* 提供给外部应用调用为主
|
||||
*
|
||||
* 一般来说,管理后台的 /system-api/* 是不直接提供给外部应用使用,主要是外部应用能够访问的数据与接口是有限的,而管理后台的 RBAC 无法很好的控制。
|
||||
* 参考大量的开放平台,都是独立的一套 OpenAPI,对应到【本系统】就是在 Controller 下新建 open 包,实现 /open-api/* 接口,然后通过 scope 进行控制。
|
||||
* 另外,一个公司如果有多个管理后台,它们 client_id 产生的 access token 相互之间是无法互通的,即无法访问它们系统的 API 接口,直到两个 client_id 产生信任授权。
|
||||
*
|
||||
* 考虑到【本系统】暂时不想做的过于复杂,默认只有获取到 access token 之后,可以访问【本系统】管理后台的 /system-api/* 所有接口,除非手动添加 scope 控制。
|
||||
* scope 的使用示例,可见 {@link OAuth2UserController} 类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Api(tags = "管理后台 - OAuth2.0 授权")
|
||||
@RestController
|
||||
@RequestMapping("/system/oauth2")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class OAuth2OpenController {
|
||||
|
||||
@Resource
|
||||
private OAuth2GrantService oauth2GrantService;
|
||||
@Resource
|
||||
private OAuth2ClientService oauth2ClientService;
|
||||
@Resource
|
||||
private OAuth2ApproveService oauth2ApproveService;
|
||||
@Resource
|
||||
private OAuth2TokenService oauth2TokenService;
|
||||
|
||||
/**
|
||||
* 对应 Spring Security OAuth 的 TokenEndpoint 类的 postAccessToken 方法
|
||||
*
|
||||
* 授权码 authorization_code 模式时:code + redirectUri + state 参数
|
||||
* 密码 password 模式时:username + password + scope 参数
|
||||
* 刷新 refresh_token 模式时:refreshToken 参数
|
||||
* 客户端 client_credentials 模式:scope 参数
|
||||
* 简化 implicit 模式时:不支持
|
||||
*
|
||||
* 注意,默认需要传递 client_id + client_secret 参数
|
||||
*/
|
||||
@PostMapping("/token")
|
||||
@PermitAll
|
||||
@ApiOperation(value = "获得访问令牌", notes = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【获取】调用")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "grant_type", required = true, value = "授权类型", example = "code", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "code", value = "授权范围", example = "userinfo.read", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "redirect_uri", value = "重定向 URI", example = "https://www.iocoder.cn", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "state", value = "状态", example = "1", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "username", example = "tudou", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "password", example = "cai", dataTypeClass = String.class), // 多个使用空格分隔
|
||||
@ApiImplicitParam(name = "scope", example = "user_info", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "refresh_token", example = "123424233", dataTypeClass = String.class),
|
||||
})
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<OAuth2OpenAccessTokenRespVO> postAccessToken(HttpServletRequest request,
|
||||
@RequestParam("grant_type") String grantType,
|
||||
@RequestParam(value = "code", required = false) String code, // 授权码模式
|
||||
@RequestParam(value = "redirect_uri", required = false) String redirectUri, // 授权码模式
|
||||
@RequestParam(value = "state", required = false) String state, // 授权码模式
|
||||
@RequestParam(value = "username", required = false) String username, // 密码模式
|
||||
@RequestParam(value = "password", required = false) String password, // 密码模式
|
||||
@RequestParam(value = "scope", required = false) String scope, // 密码模式
|
||||
@RequestParam(value = "refresh_token", required = false) String refreshToken) { // 刷新模式
|
||||
List<String> scopes = OAuth2Utils.buildScopes(scope);
|
||||
// 1.1 校验授权类型
|
||||
OAuth2GrantTypeEnum grantTypeEnum = OAuth2GrantTypeEnum.getByGranType(grantType);
|
||||
if (grantTypeEnum == null) {
|
||||
throw exception0(BAD_REQUEST.getCode(), StrUtil.format("未知授权类型({})", grantType));
|
||||
}
|
||||
if (grantTypeEnum == OAuth2GrantTypeEnum.IMPLICIT) {
|
||||
throw exception0(BAD_REQUEST.getCode(), "Token 接口不支持 implicit 授权模式");
|
||||
}
|
||||
|
||||
// 1.2 校验客户端
|
||||
String[] clientIdAndSecret = obtainBasicAuthorization(request);
|
||||
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientIdAndSecret[0], clientIdAndSecret[1],
|
||||
grantType, scopes, redirectUri);
|
||||
|
||||
// 2. 根据授权模式,获取访问令牌
|
||||
OAuth2AccessTokenDO accessTokenDO;
|
||||
switch (grantTypeEnum) {
|
||||
case AUTHORIZATION_CODE:
|
||||
accessTokenDO = oauth2GrantService.grantAuthorizationCodeForAccessToken(client.getClientId(), code, redirectUri, state);
|
||||
break;
|
||||
case PASSWORD:
|
||||
accessTokenDO = oauth2GrantService.grantPassword(username, password, client.getClientId(), scopes);
|
||||
break;
|
||||
case CLIENT_CREDENTIALS:
|
||||
accessTokenDO = oauth2GrantService.grantClientCredentials(client.getClientId(), scopes);
|
||||
break;
|
||||
case REFRESH_TOKEN:
|
||||
accessTokenDO = oauth2GrantService.grantRefreshToken(refreshToken, client.getClientId());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("未知授权类型:" + grantType);
|
||||
}
|
||||
Assert.notNull(accessTokenDO, "访问令牌不能为空"); // 防御性检查
|
||||
return success(OAuth2OpenConvert.INSTANCE.convert(accessTokenDO));
|
||||
}
|
||||
|
||||
@DeleteMapping("/token")
|
||||
@PermitAll
|
||||
@ApiOperation(value = "删除访问令牌")
|
||||
@ApiImplicitParam(name = "token", required = true, value = "访问令牌", example = "biu", dataTypeClass = String.class)
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<Boolean> revokeToken(HttpServletRequest request,
|
||||
@RequestParam("token") String token) {
|
||||
// 校验客户端
|
||||
String[] clientIdAndSecret = obtainBasicAuthorization(request);
|
||||
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientIdAndSecret[0], clientIdAndSecret[1],
|
||||
null, null, null);
|
||||
|
||||
// 删除访问令牌
|
||||
return success(oauth2GrantService.revokeToken(client.getClientId(), token));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对应 Spring Security OAuth 的 CheckTokenEndpoint 类的 checkToken 方法
|
||||
*/
|
||||
@PostMapping("/check-token")
|
||||
@PermitAll
|
||||
@ApiOperation(value = "校验访问令牌")
|
||||
@ApiImplicitParam(name = "token", required = true, value = "访问令牌", example = "biu", dataTypeClass = String.class)
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<OAuth2OpenCheckTokenRespVO> checkToken(HttpServletRequest request,
|
||||
@RequestParam("token") String token) {
|
||||
// 校验客户端
|
||||
String[] clientIdAndSecret = obtainBasicAuthorization(request);
|
||||
oauth2ClientService.validOAuthClientFromCache(clientIdAndSecret[0], clientIdAndSecret[1],
|
||||
null, null, null);
|
||||
|
||||
// 校验令牌
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.checkAccessToken(token);
|
||||
Assert.notNull(accessTokenDO, "访问令牌不能为空"); // 防御性检查
|
||||
return success(OAuth2OpenConvert.INSTANCE.convert2(accessTokenDO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对应 Spring Security OAuth 的 AuthorizationEndpoint 类的 authorize 方法
|
||||
*/
|
||||
@GetMapping("/authorize")
|
||||
@ApiOperation(value = "获得授权信息", notes = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【获取】调用")
|
||||
@ApiImplicitParam(name = "clientId", required = true, value = "客户端编号", example = "tudou", dataTypeClass = String.class)
|
||||
public CommonResult<OAuth2OpenAuthorizeInfoRespVO> authorize(@RequestParam("clientId") String clientId) {
|
||||
// 0. 校验用户已经登录。通过 Spring Security 实现
|
||||
|
||||
// 1. 获得 Client 客户端的信息
|
||||
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientId);
|
||||
// 2. 获得用户已经授权的信息
|
||||
List<OAuth2ApproveDO> approves = oauth2ApproveService.getApproveList(getLoginUserId(), getUserType(), clientId);
|
||||
// 拼接返回
|
||||
return success(OAuth2OpenConvert.INSTANCE.convert(client, approves));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对应 Spring Security OAuth 的 AuthorizationEndpoint 类的 approveOrDeny 方法
|
||||
*
|
||||
* 场景一:【自动授权 autoApprove = true】
|
||||
* 刚进入 sso.vue 界面,调用该接口,用户历史已经给该应用做过对应的授权,或者 OAuth2Client 支持该 scope 的自动授权
|
||||
* 场景二:【手动授权 autoApprove = false】
|
||||
* 在 sso.vue 界面,用户选择好 scope 授权范围,调用该接口,进行授权。此时,approved 为 true 或者 false
|
||||
*
|
||||
* 因为前后端分离,Axios 无法很好的处理 302 重定向,所以和 Spring Security OAuth 略有不同,返回结果是重定向的 URL,剩余交给前端处理
|
||||
*/
|
||||
@PostMapping("/authorize")
|
||||
@ApiOperation(value = "申请授权", notes = "适合 code 授权码模式,或者 implicit 简化模式;在 sso.vue 单点登录界面被【提交】调用")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "response_type", required = true, value = "响应类型", example = "code", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "client_id", required = true, value = "客户端编号", example = "tudou", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "scope", value = "授权范围", example = "userinfo.read", dataTypeClass = String.class), // 使用 Map<String, Boolean> 格式,Spring MVC 暂时不支持这么接收参数
|
||||
@ApiImplicitParam(name = "redirect_uri", required = true, value = "重定向 URI", example = "https://www.iocoder.cn", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "auto_approve", required = true, value = "用户是否接受", example = "true", dataTypeClass = Boolean.class),
|
||||
@ApiImplicitParam(name = "state", example = "1", dataTypeClass = String.class)
|
||||
})
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<String> approveOrDeny(@RequestParam("response_type") String responseType,
|
||||
@RequestParam("client_id") String clientId,
|
||||
@RequestParam(value = "scope", required = false) String scope,
|
||||
@RequestParam("redirect_uri") String redirectUri,
|
||||
@RequestParam(value = "auto_approve") Boolean autoApprove,
|
||||
@RequestParam(value = "state", required = false) String state) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Boolean> scopes = JsonUtils.parseObject(scope, Map.class);
|
||||
scopes = ObjectUtil.defaultIfNull(scopes, Collections.emptyMap());
|
||||
// 0. 校验用户已经登录。通过 Spring Security 实现
|
||||
|
||||
// 1.1 校验 responseType 是否满足 code 或者 token 值
|
||||
OAuth2GrantTypeEnum grantTypeEnum = getGrantTypeEnum(responseType);
|
||||
// 1.2 校验 redirectUri 重定向域名是否合法 + 校验 scope 是否在 Client 授权范围内
|
||||
OAuth2ClientDO client = oauth2ClientService.validOAuthClientFromCache(clientId, null,
|
||||
grantTypeEnum.getGrantType(), scopes.keySet(), redirectUri);
|
||||
|
||||
// 2.1 假设 approved 为 null,说明是场景一
|
||||
if (Boolean.TRUE.equals(autoApprove)) {
|
||||
// 如果无法自动授权通过,则返回空 url,前端不进行跳转
|
||||
if (!oauth2ApproveService.checkForPreApproval(getLoginUserId(), getUserType(), clientId, scopes.keySet())) {
|
||||
return success(null);
|
||||
}
|
||||
} else { // 2.2 假设 approved 非 null,说明是场景二
|
||||
// 如果计算后不通过,则跳转一个错误链接
|
||||
if (!oauth2ApproveService.updateAfterApproval(getLoginUserId(), getUserType(), clientId, scopes)) {
|
||||
return success(OAuth2Utils.buildUnsuccessfulRedirect(redirectUri, responseType, state,
|
||||
"access_denied", "User denied access"));
|
||||
}
|
||||
}
|
||||
|
||||
// 3.1 如果是 code 授权码模式,则发放 code 授权码,并重定向
|
||||
List<String> approveScopes = convertList(scopes.entrySet(), Map.Entry::getKey, Map.Entry::getValue);
|
||||
if (grantTypeEnum == OAuth2GrantTypeEnum.AUTHORIZATION_CODE) {
|
||||
return success(getAuthorizationCodeRedirect(getLoginUserId(), client, approveScopes, redirectUri, state));
|
||||
}
|
||||
// 3.2 如果是 token 则是 implicit 简化模式,则发送 accessToken 访问令牌,并重定向
|
||||
return success(getImplicitGrantRedirect(getLoginUserId(), client, approveScopes, redirectUri, state));
|
||||
}
|
||||
|
||||
private static OAuth2GrantTypeEnum getGrantTypeEnum(String responseType) {
|
||||
if (StrUtil.equals(responseType, "code")) {
|
||||
return OAuth2GrantTypeEnum.AUTHORIZATION_CODE;
|
||||
}
|
||||
if (StrUtil.equalsAny(responseType, "token")) {
|
||||
return OAuth2GrantTypeEnum.IMPLICIT;
|
||||
}
|
||||
throw exception0(BAD_REQUEST.getCode(), "response_type 参数值只允许 code 和 token");
|
||||
}
|
||||
|
||||
private String getImplicitGrantRedirect(Long userId, OAuth2ClientDO client,
|
||||
List<String> scopes, String redirectUri, String state) {
|
||||
// 1. 创建 access token 访问令牌
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2GrantService.grantImplicit(userId, getUserType(), client.getClientId(), scopes);
|
||||
Assert.notNull(accessTokenDO, "访问令牌不能为空"); // 防御性检查
|
||||
// 2. 拼接重定向的 URL
|
||||
// noinspection unchecked
|
||||
return OAuth2Utils.buildImplicitRedirectUri(redirectUri, accessTokenDO.getAccessToken(), state, accessTokenDO.getExpiresTime(),
|
||||
scopes, JsonUtils.parseObject(client.getAdditionalInformation(), Map.class));
|
||||
}
|
||||
|
||||
private String getAuthorizationCodeRedirect(Long userId, OAuth2ClientDO client,
|
||||
List<String> scopes, String redirectUri, String state) {
|
||||
// 1. 创建 code 授权码
|
||||
String authorizationCode = oauth2GrantService.grantAuthorizationCodeForCode(userId, getUserType(), client.getClientId(), scopes,
|
||||
redirectUri, state);
|
||||
// 2. 拼接重定向的 URL
|
||||
return OAuth2Utils.buildAuthorizationCodeRedirectUri(redirectUri, authorizationCode, state);
|
||||
}
|
||||
|
||||
private Integer getUserType() {
|
||||
return UserTypeEnum.ADMIN.getValue();
|
||||
}
|
||||
|
||||
private String[] obtainBasicAuthorization(HttpServletRequest request) {
|
||||
String[] clientIdAndSecret = HttpUtils.obtainBasicAuthorization(request);
|
||||
if (ArrayUtil.isEmpty(clientIdAndSecret) || clientIdAndSecret.length != 2) {
|
||||
throw exception0(BAD_REQUEST.getCode(), "client_id 或 client_secret 未正确传递");
|
||||
}
|
||||
return clientIdAndSecret;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenRespVO;
|
||||
import cn.iocoder.yudao.module.system.convert.auth.OAuth2TokenConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
|
||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - OAuth2.0 令牌")
|
||||
@RestController
|
||||
@RequestMapping("/system/oauth2-token")
|
||||
public class OAuth2TokenController {
|
||||
|
||||
@Resource
|
||||
private OAuth2TokenService oauth2TokenService;
|
||||
@Resource
|
||||
private AdminAuthService authService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation(value = "获得访问令牌分页", notes = "只返回有效期内的")
|
||||
@PreAuthorize("@ss.hasPermission('system:oauth2-token:page')")
|
||||
public CommonResult<PageResult<OAuth2AccessTokenRespVO>> getAccessTokenPage(@Valid OAuth2AccessTokenPageReqVO reqVO) {
|
||||
PageResult<OAuth2AccessTokenDO> pageResult = oauth2TokenService.getAccessTokenPage(reqVO);
|
||||
return success(OAuth2TokenConvert.INSTANCE.convert(pageResult));
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除访问令牌")
|
||||
@ApiImplicitParam(name = "accessToken", value = "访问令牌", required = true, dataTypeClass = String.class, example = "tudou")
|
||||
@PreAuthorize("@ss.hasPermission('system:oauth2-token:delete')")
|
||||
public CommonResult<Boolean> deleteAccessToken(@RequestParam("accessToken") String accessToken) {
|
||||
authService.logout(accessToken, LoginLogTypeEnum.LOGOUT_DELETE.getType());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
### 请求 /system/oauth2/user/get 接口 => 成功
|
||||
GET {{baseUrl}}/system/oauth2/user/get
|
||||
Authorization: Bearer 47f9c74ec11041f193b777ebb95c3b0d
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
### 请求 /system/oauth2/user/update 接口 => 成功
|
||||
PUT {{baseUrl}}/system/oauth2/user/update
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer 47f9c74ec11041f193b777ebb95c3b0d
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"nickname": "芋道源码"
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserInfoRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.system.convert.oauth2.OAuth2UserConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.service.dept.DeptService;
|
||||
import cn.iocoder.yudao.module.system.service.dept.PostService;
|
||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
/**
|
||||
* 提供给外部应用调用为主
|
||||
*
|
||||
* 1. 在 getUserInfo 方法上,添加 @PreAuthorize("@ss.hasScope('user.read')") 注解,声明需要满足 scope = user.read
|
||||
* 2. 在 updateUserInfo 方法上,添加 @PreAuthorize("@ss.hasScope('user.write')") 注解,声明需要满足 scope = user.write
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Api(tags = "管理后台 - OAuth2.0 用户")
|
||||
@RestController
|
||||
@RequestMapping("/system/oauth2/user")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class OAuth2UserController {
|
||||
|
||||
@Resource
|
||||
private AdminUserService userService;
|
||||
@Resource
|
||||
private DeptService deptService;
|
||||
@Resource
|
||||
private PostService postService;
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得用户基本信息")
|
||||
@PreAuthorize("@ss.hasScope('user.read')") //
|
||||
public CommonResult<OAuth2UserInfoRespVO> getUserInfo() {
|
||||
// 获得用户基本信息
|
||||
AdminUserDO user = userService.getUser(getLoginUserId());
|
||||
OAuth2UserInfoRespVO resp = OAuth2UserConvert.INSTANCE.convert(user);
|
||||
// 获得部门信息
|
||||
if (user.getDeptId() != null) {
|
||||
DeptDO dept = deptService.getDept(user.getDeptId());
|
||||
resp.setDept(OAuth2UserConvert.INSTANCE.convert(dept));
|
||||
}
|
||||
// 获得岗位信息
|
||||
if (CollUtil.isNotEmpty(user.getPostIds())) {
|
||||
List<PostDO> posts = postService.getPosts(user.getPostIds());
|
||||
resp.setPosts(OAuth2UserConvert.INSTANCE.convertList(posts));
|
||||
}
|
||||
return success(resp);
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("更新用户基本信息")
|
||||
@PreAuthorize("@ss.hasScope('user.write')")
|
||||
public CommonResult<Boolean> updateUserInfo(@Valid @RequestBody OAuth2UserUpdateReqVO reqVO) {
|
||||
// 这里将 UserProfileUpdateReqVO =》UserProfileUpdateReqVO 对象,实现接口的复用。
|
||||
// 主要是,AdminUserService 没有自己的 BO 对象,所以复用只能这么做
|
||||
userService.updateUserProfile(getLoginUserId(), OAuth2UserConvert.INSTANCE.convert(reqVO));
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
|
||||
import javax.validation.constraints.AssertTrue;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* OAuth2 客户端 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||
*/
|
||||
@Data
|
||||
public class OAuth2ClientBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "客户端编号", required = true, example = "tudou")
|
||||
@NotNull(message = "客户端编号不能为空")
|
||||
private String clientId;
|
||||
|
||||
@ApiModelProperty(value = "客户端密钥", required = true, example = "fan")
|
||||
@NotNull(message = "客户端密钥不能为空")
|
||||
private String secret;
|
||||
|
||||
@ApiModelProperty(value = "应用名", required = true, example = "土豆")
|
||||
@NotNull(message = "应用名不能为空")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "应用图标", required = true, example = "https://www.iocoder.cn/xx.png")
|
||||
@NotNull(message = "应用图标不能为空")
|
||||
@URL(message = "应用图标的地址不正确")
|
||||
private String logo;
|
||||
|
||||
@ApiModelProperty(value = "应用描述", example = "我是一个应用")
|
||||
private String description;
|
||||
|
||||
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
|
||||
@NotNull(message = "状态不能为空")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty(value = "访问令牌的有效期", required = true, example = "8640")
|
||||
@NotNull(message = "访问令牌的有效期不能为空")
|
||||
private Integer accessTokenValiditySeconds;
|
||||
|
||||
@ApiModelProperty(value = "刷新令牌的有效期", required = true, example = "8640000")
|
||||
@NotNull(message = "刷新令牌的有效期不能为空")
|
||||
private Integer refreshTokenValiditySeconds;
|
||||
|
||||
@ApiModelProperty(value = "可重定向的 URI 地址", required = true, example = "https://www.iocoder.cn")
|
||||
@NotNull(message = "可重定向的 URI 地址不能为空")
|
||||
private List<@NotEmpty(message = "重定向的 URI 不能为空")
|
||||
@URL(message = "重定向的 URI 格式不正确") String> redirectUris;
|
||||
|
||||
@ApiModelProperty(value = "授权类型", required = true, example = "password", notes = "参见 OAuth2GrantTypeEnum 枚举")
|
||||
@NotNull(message = "授权类型不能为空")
|
||||
private List<String> authorizedGrantTypes;
|
||||
|
||||
@ApiModelProperty(value = "授权范围", example = "user_info")
|
||||
private List<String> scopes;
|
||||
|
||||
@ApiModelProperty(value = "自动通过的授权范围", example = "user_info")
|
||||
private List<String> autoApproveScopes;
|
||||
|
||||
@ApiModelProperty(value = "权限", example = "system:user:query")
|
||||
private List<String> authorities;
|
||||
|
||||
@ApiModelProperty(value = "资源", example = "1024")
|
||||
private List<String> resourceIds;
|
||||
|
||||
@ApiModelProperty(value = "附加信息", example = "{yunai: true}")
|
||||
private String additionalInformation;
|
||||
|
||||
@AssertTrue(message = "附加信息必须是 JSON 格式")
|
||||
public boolean isAdditionalInformationJson() {
|
||||
return StrUtil.isEmpty(additionalInformation) || JsonUtils.isJson(additionalInformation);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client;
|
||||
|
||||
import lombok.*;
|
||||
import io.swagger.annotations.*;
|
||||
|
||||
@ApiModel("管理后台 - OAuth2 客户端创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class OAuth2ClientCreateReqVO extends OAuth2ClientBaseVO {
|
||||
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client;
|
||||
|
||||
import lombok.*;
|
||||
import io.swagger.annotations.*;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
|
||||
@ApiModel("管理后台 - OAuth2 客户端分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class OAuth2ClientPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "应用名", example = "土豆", notes = "模糊匹配")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "状态", example = "1", notes = "参见 CommonStatusEnum 枚举")
|
||||
private Integer status;
|
||||
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("管理后台 - OAuth2 客户端 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class OAuth2ClientRespVO extends OAuth2ClientBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - OAuth2 客户端更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class OAuth2ClientUpdateReqVO extends OAuth2ClientBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@ApiModel("管理后台 - 【开放接口】访问令牌 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OAuth2OpenAccessTokenRespVO {
|
||||
|
||||
@ApiModelProperty(value = "访问令牌", required = true, example = "tudou")
|
||||
@JsonProperty("access_token")
|
||||
private String accessToken;
|
||||
|
||||
@ApiModelProperty(value = "刷新令牌", required = true, example = "nice")
|
||||
@JsonProperty("refresh_token")
|
||||
private String refreshToken;
|
||||
|
||||
@ApiModelProperty(value = "令牌类型", required = true, example = "bearer")
|
||||
@JsonProperty("token_type")
|
||||
private String tokenType;
|
||||
|
||||
@ApiModelProperty(value = "过期时间", required = true, example = "42430", notes = "单位:秒")
|
||||
@JsonProperty("expires_in")
|
||||
private Long expiresIn;
|
||||
|
||||
@ApiModelProperty(value = "授权范围", example = "user_info", notes = "如果多个授权范围,使用空格分隔")
|
||||
private String scope;
|
||||
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("管理后台 - 授权页的信息 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OAuth2OpenAuthorizeInfoRespVO {
|
||||
|
||||
/**
|
||||
* 客户端
|
||||
*/
|
||||
private Client client;
|
||||
|
||||
@ApiModelProperty(value = "scope 的选中信息", required = true, notes = "使用 List 保证有序性,Key 是 scope,Value 为是否选中")
|
||||
private List<KeyValue<String, Boolean>> scopes;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Client {
|
||||
|
||||
@ApiModelProperty(value = "应用名", required = true, example = "土豆")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "应用图标", required = true, example = "https://www.iocoder.cn/xx.png")
|
||||
private String logo;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("管理后台 - 【开放接口】校验令牌 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OAuth2OpenCheckTokenRespVO {
|
||||
|
||||
@ApiModelProperty(value = "用户编号", required = true, example = "666")
|
||||
@JsonProperty("user_id")
|
||||
private Long userId;
|
||||
@ApiModelProperty(value = "用户类型", required = true, example = "2", notes = "参见 UserTypeEnum 枚举")
|
||||
@JsonProperty("user_type")
|
||||
private Integer userType;
|
||||
@ApiModelProperty(value = "租户编号", required = true, example = "1024")
|
||||
@JsonProperty("tenant_id")
|
||||
private Long tenantId;
|
||||
|
||||
@ApiModelProperty(value = "客户端编号", required = true, example = "car")
|
||||
@JsonProperty("client_id")
|
||||
private String clientId;
|
||||
@ApiModelProperty(value = "授权范围", required = true, example = "user_info")
|
||||
private List<String> scopes;
|
||||
|
||||
@ApiModelProperty(value = "访问令牌", required = true, example = "tudou")
|
||||
@JsonProperty("access_token")
|
||||
private String accessToken;
|
||||
|
||||
@ApiModelProperty(value = "过期时间", required = true, example = "1593092157", notes = "时间戳 / 1000,即单位:秒")
|
||||
private Long exp;
|
||||
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@ApiModel("管理后台 - 访问令牌分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class OAuth2AccessTokenPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "用户编号", required = true, example = "666")
|
||||
private Long userId;
|
||||
|
||||
@ApiModelProperty(value = "用户类型", required = true, example = "2", notes = "参见 UserTypeEnum 枚举")
|
||||
private Integer userType;
|
||||
|
||||
@ApiModelProperty(value = "客户端编号", required = true, example = "2")
|
||||
private String clientId;
|
||||
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("管理后台 - 访问令牌 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OAuth2AccessTokenRespVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "访问令牌", required = true, example = "tudou")
|
||||
private String accessToken;
|
||||
|
||||
@ApiModelProperty(value = "刷新令牌", required = true, example = "nice")
|
||||
private String refreshToken;
|
||||
|
||||
@ApiModelProperty(value = "用户编号", required = true, example = "666")
|
||||
private Long userId;
|
||||
|
||||
@ApiModelProperty(value = "用户类型", required = true, example = "2", notes = "参见 UserTypeEnum 枚举")
|
||||
private Integer userType;
|
||||
|
||||
@ApiModelProperty(value = "客户端编号", required = true, example = "2")
|
||||
private String clientId;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@ApiModelProperty(value = "过期时间", required = true)
|
||||
private LocalDateTime expiresTime;
|
||||
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("管理后台 - OAuth2 获得用户基本信息 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OAuth2UserInfoRespVO {
|
||||
|
||||
@ApiModelProperty(value = "用户编号", required = true, example = "1")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "用户账号", required = true, example = "芋艿")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty(value = "用户昵称", required = true, example = "芋道")
|
||||
private String nickname;
|
||||
|
||||
@ApiModelProperty(value = "用户邮箱", example = "yudao@iocoder.cn")
|
||||
private String email;
|
||||
@ApiModelProperty(value = "手机号码", example = "15601691300")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SexEnum 枚举类")
|
||||
private Integer sex;
|
||||
|
||||
@ApiModelProperty(value = "用户头像", example = "https://www.iocoder.cn/xxx.png")
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 所在部门
|
||||
*/
|
||||
private Dept dept;
|
||||
|
||||
/**
|
||||
* 所属岗位数组
|
||||
*/
|
||||
private List<Post> posts;
|
||||
|
||||
@ApiModel("部门")
|
||||
@Data
|
||||
public static class Dept {
|
||||
|
||||
@ApiModelProperty(value = "部门编号", required = true, example = "1")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "部门名称", required = true, example = "研发部")
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
@ApiModel("岗位")
|
||||
@Data
|
||||
public static class Post {
|
||||
|
||||
@ApiModelProperty(value = "岗位编号", required = true, example = "1")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "岗位名称", required = true, example = "开发")
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
@ApiModel("管理后台 - OAuth2 更新用户基本信息 Request VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OAuth2UserUpdateReqVO {
|
||||
|
||||
@ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
|
||||
@Size(max = 30, message = "用户昵称长度不能超过 30 个字符")
|
||||
private String nickname;
|
||||
|
||||
@ApiModelProperty(value = "用户邮箱", example = "yudao@iocoder.cn")
|
||||
@Email(message = "邮箱格式不正确")
|
||||
@Size(max = 50, message = "邮箱长度不能超过 50 个字符")
|
||||
private String email;
|
||||
|
||||
@ApiModelProperty(value = "手机号码", example = "15601691300")
|
||||
@Length(min = 11, max = 11, message = "手机号长度必须 11 位")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SexEnum 枚举类")
|
||||
private Integer sex;
|
||||
|
||||
}
|
@@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.*;
|
||||
import cn.iocoder.yudao.module.system.convert.permission.MenuConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
|
||||
import cn.iocoder.yudao.module.system.service.permission.MenuService;
|
||||
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@@ -29,8 +28,6 @@ public class MenuController {
|
||||
|
||||
@Resource
|
||||
private MenuService menuService;
|
||||
@Resource
|
||||
private TenantService tenantService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("创建菜单")
|
||||
|
@@ -7,7 +7,7 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("管理后台 - 菜单信息 Response VO")
|
||||
@Data
|
||||
@@ -23,6 +23,6 @@ public class MenuRespVO extends MenuBaseVO {
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
|
||||
private Date createTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@@ -12,8 +12,8 @@ import java.util.Set;
|
||||
@Data
|
||||
public class PermissionAssignUserRoleReqVO {
|
||||
|
||||
@ApiModelProperty(value = "角色编号", required = true, example = "1")
|
||||
@NotNull(message = "角色编号不能为空")
|
||||
@ApiModelProperty(value = "用户编号", required = true, example = "1")
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Long userId;
|
||||
|
||||
@ApiModelProperty(value = "角色编号列表", example = "1,3,5")
|
||||
|
@@ -5,7 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@@ -22,12 +22,8 @@ public class RoleExportReqVO {
|
||||
@ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty(value = "开始时间", example = "2020-10-24")
|
||||
@ApiModelProperty(value = "开始时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date beginTime;
|
||||
|
||||
@ApiModelProperty(value = "结束时间", example = "2020-10-24")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date endTime;
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@@ -25,12 +25,8 @@ public class RolePageReqVO extends PageParam {
|
||||
@ApiModelProperty(value = "展示状态", example = "1", notes = "参见 CommonStatusEnum 枚举类")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty(value = "开始时间", example = "2020-10-24")
|
||||
@ApiModelProperty(value = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date beginTime;
|
||||
|
||||
@ApiModelProperty(value = "结束时间", example = "2020-10-24")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date endTime;
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user