Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/1.6.2-smsLogin
Conflicts: sql/ruoyi-vue-pro.sql yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java yudao-ui-admin/src/api/login.js yudao-ui-admin/src/store/modules/user.js
This commit is contained in:
@@ -18,33 +18,33 @@ public interface UserSessionApi {
|
||||
* @param loginUser 登录用户
|
||||
* @param userIp 用户 IP
|
||||
* @param userAgent 用户 UA
|
||||
* @return Session 编号
|
||||
* @return Token 令牌
|
||||
*/
|
||||
String createUserSession(@NotNull(message = "登录用户不能为空") LoginUser loginUser, String userIp, String userAgent);
|
||||
|
||||
/**
|
||||
* 刷新在线用户 Session 的更新时间
|
||||
*
|
||||
* @param sessionId Session 编号
|
||||
* @param token Token 令牌
|
||||
* @param loginUser 登录用户
|
||||
*/
|
||||
void refreshUserSession(@NotEmpty(message = "Session编号不能为空") String sessionId,
|
||||
void refreshUserSession(@NotEmpty(message = "Token 令牌不能为空") String token,
|
||||
@NotNull(message = "登录用户不能为空") LoginUser loginUser);
|
||||
|
||||
/**
|
||||
* 删除在线用户 Session
|
||||
*
|
||||
* @param sessionId Session 编号
|
||||
* @param token Token 令牌
|
||||
*/
|
||||
void deleteUserSession(String sessionId);
|
||||
void deleteUserSession(String token);
|
||||
|
||||
/**
|
||||
* 获得 Session 编号对应的在线用户
|
||||
* 获得 Token 令牌对应的在线用户
|
||||
*
|
||||
* @param sessionId Session 编号
|
||||
* @param token Token 令牌
|
||||
* @return 在线用户
|
||||
*/
|
||||
LoginUser getLoginUser(String sessionId);
|
||||
LoginUser getLoginUser(String token);
|
||||
|
||||
/**
|
||||
* 获得 Session 超时时间,单位:毫秒
|
||||
|
||||
@@ -37,21 +37,10 @@ public interface SocialUserApi {
|
||||
*/
|
||||
void unbindSocialUser(@Valid SocialUserUnbindReqDTO reqDTO);
|
||||
|
||||
/**
|
||||
* 校验社交用户的认证信息是否正确
|
||||
* 如果校验不通过,则抛出 {@link ServiceException} 业务异常
|
||||
*
|
||||
* @param type 社交平台的类型
|
||||
* @param code 授权码
|
||||
* @param state state
|
||||
*/
|
||||
void checkSocialUser(Integer type, String code, String state);
|
||||
|
||||
/**
|
||||
* 获得社交用户的绑定用户编号
|
||||
* 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号!
|
||||
* 该方法会执行和 {@link #checkSocialUser(Integer, String, String)} 一样的逻辑。
|
||||
* 所以在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常
|
||||
* 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常
|
||||
*
|
||||
* @param userType 用户类型
|
||||
* @param type 社交平台的类型
|
||||
|
||||
@@ -25,18 +25,18 @@ public class UserSessionApiImpl implements UserSessionApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshUserSession(String sessionId, LoginUser loginUser) {
|
||||
userSessionService.refreshUserSession(sessionId, loginUser);
|
||||
public void refreshUserSession(String token, LoginUser loginUser) {
|
||||
userSessionService.refreshUserSession(token, loginUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteUserSession(String sessionId) {
|
||||
userSessionService.deleteUserSession(sessionId);
|
||||
public void deleteUserSession(String token) {
|
||||
userSessionService.deleteUserSession(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginUser getLoginUser(String sessionId) {
|
||||
return userSessionService.getLoginUser(sessionId);
|
||||
public LoginUser getLoginUser(String token) {
|
||||
return userSessionService.getLoginUser(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -36,11 +36,6 @@ public class SocialUserApiImpl implements SocialUserApi {
|
||||
reqDTO.getType(), reqDTO.getUnionId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkSocialUser(Integer type, String code, String state) {
|
||||
socialUserService.authSocialUser(type, code, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getBindUserId(Integer userType, Integer type, String code, String state) {
|
||||
return socialUserService.getBindUserId(userType, type, code, state);
|
||||
|
||||
@@ -36,7 +36,7 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
|
||||
|
||||
@Api(tags = "管理后台 - 认证")
|
||||
@RestController
|
||||
@RequestMapping("/system") // 暂时不跟 /auth 结尾
|
||||
@RequestMapping("/system/auth") // 暂时不跟 /auth 结尾
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class AuthController {
|
||||
@@ -100,7 +100,7 @@ public class AuthController {
|
||||
return success(AuthConvert.INSTANCE.convert(user, roleList, menuList));
|
||||
}
|
||||
|
||||
@GetMapping("list-menus")
|
||||
@GetMapping("/list-menus")
|
||||
@ApiOperation("获得登录用户的菜单列表")
|
||||
public CommonResult<List<AuthMenuRespVO>> getMenus() {
|
||||
// 获得用户拥有的菜单列表
|
||||
@@ -125,36 +125,22 @@ public class AuthController {
|
||||
return CommonResult.success(socialUserService.getAuthorizeUrl(type, redirectUri));
|
||||
}
|
||||
|
||||
@PostMapping("/social-login")
|
||||
@ApiOperation("社交登录,使用 code 授权码")
|
||||
@PostMapping("/social-quick-login")
|
||||
@ApiOperation("社交快捷登录,使用 code 授权码")
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<AuthLoginRespVO> socialLogin(@RequestBody @Valid AuthSocialLoginReqVO reqVO) {
|
||||
public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialQuickLoginReqVO reqVO) {
|
||||
String token = authService.socialLogin(reqVO, getClientIP(), getUserAgent());
|
||||
// 返回结果
|
||||
return success(AuthLoginRespVO.builder().token(token).build());
|
||||
}
|
||||
|
||||
@PostMapping("/social-login2")
|
||||
@ApiOperation("社交登录,使用 code 授权码 + 账号密码")
|
||||
@PostMapping("/social-bind-login")
|
||||
@ApiOperation("社交绑定登录,使用 code 授权码 + 账号密码")
|
||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||
public CommonResult<AuthLoginRespVO> socialLogin2(@RequestBody @Valid AuthSocialLogin2ReqVO reqVO) {
|
||||
String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent());
|
||||
public CommonResult<AuthLoginRespVO> socialBindLogin(@RequestBody @Valid AuthSocialBindLoginReqVO reqVO) {
|
||||
String token = authService.socialBindLogin(reqVO, getClientIP(), getUserAgent());
|
||||
// 返回结果
|
||||
return success(AuthLoginRespVO.builder().token(token).build());
|
||||
}
|
||||
|
||||
@PostMapping("/social-bind")
|
||||
@ApiOperation("社交绑定,使用 code 授权码")
|
||||
public CommonResult<Boolean> socialBind(@RequestBody @Valid AuthSocialBindReqVO reqVO) {
|
||||
authService.socialBind(getLoginUserId(), reqVO);
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/social-unbind")
|
||||
@ApiOperation("取消社交绑定")
|
||||
public CommonResult<Boolean> socialUnbind(@RequestBody AuthSocialUnbindReqVO reqVO) {
|
||||
socialUserService.unbindSocialUser(getLoginUserId(), UserTypeEnum.ADMIN.getValue(), reqVO.getType(), reqVO.getUnionId());
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -69,10 +69,9 @@ public class UserSessionController {
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除 Session")
|
||||
@ApiImplicitParam(name = "id", value = "Session 编号", required = true, dataTypeClass = String.class,
|
||||
example = "fe50b9f6-d177-44b1-8da9-72ea34f63db7")
|
||||
@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") String id) {
|
||||
public CommonResult<Boolean> deleteUserSession(@RequestParam("id") Long id) {
|
||||
userSessionService.deleteUserSession(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@ import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
@ApiModel("管理后台 - 社交登录 Request VO,使用 code 授权码 + 账号密码")
|
||||
@ApiModel("管理后台 - 社交绑定登录 Request VO,使用 code 授权码 + 账号密码")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthSocialLogin2ReqVO {
|
||||
public class AuthSocialBindLoginReqVO {
|
||||
|
||||
@ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 UserSocialTypeEnum 枚举值")
|
||||
@InEnum(SocialTypeEnum.class)
|
||||
@@ -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 AuthSocialLoginReqVO {
|
||||
public class AuthSocialQuickLoginReqVO {
|
||||
|
||||
@ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 UserSocialTypeEnum 枚举值")
|
||||
@InEnum(SocialTypeEnum.class)
|
||||
@@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.socail;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.SocialUserBindReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.SocialUserUnbindReqVO;
|
||||
import cn.iocoder.yudao.module.system.convert.social.SocialUserConvert;
|
||||
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
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.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Api(tags = "管理后台 - 社交用户")
|
||||
@RestController
|
||||
@RequestMapping("/system/social-user")
|
||||
@Validated
|
||||
public class SocialUserController {
|
||||
|
||||
@Resource
|
||||
private SocialUserService socialUserService;
|
||||
|
||||
@PostMapping("/bind")
|
||||
@ApiOperation("社交绑定,使用 code 授权码")
|
||||
public CommonResult<Boolean> socialBind(@RequestBody @Valid SocialUserBindReqVO reqVO) {
|
||||
socialUserService.bindSocialUser(SocialUserConvert.INSTANCE.convert(getLoginUserId(), UserTypeEnum.ADMIN.getValue(), reqVO));
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/unbind")
|
||||
@ApiOperation("取消社交绑定")
|
||||
public CommonResult<Boolean> socialUnbind(@RequestBody SocialUserUnbindReqVO reqVO) {
|
||||
socialUserService.unbindSocialUser(getLoginUserId(), UserTypeEnum.ADMIN.getValue(), reqVO.getType(), reqVO.getOpenid());
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth;
|
||||
package cn.iocoder.yudao.module.system.controller.admin.socail.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
@@ -17,7 +17,7 @@ import javax.validation.constraints.NotNull;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthSocialBindReqVO {
|
||||
public class SocialUserBindReqVO {
|
||||
|
||||
@ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 UserSocialTypeEnum 枚举值")
|
||||
@InEnum(SocialTypeEnum.class)
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth;
|
||||
package cn.iocoder.yudao.module.system.controller.admin.socail.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
|
||||
@@ -12,20 +12,20 @@ import lombok.NoArgsConstructor;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 取消社交绑定 Request VO,使用 code 授权码")
|
||||
@ApiModel("管理后台 - 取消社交绑定 Request VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthSocialUnbindReqVO {
|
||||
public class SocialUserUnbindReqVO {
|
||||
|
||||
@ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 UserSocialTypeEnum 枚举值")
|
||||
@InEnum(SocialTypeEnum.class)
|
||||
@NotNull(message = "社交平台的类型不能为空")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty(value = "社交的全局编号", required = true, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE")
|
||||
@NotEmpty(message = "社交的全局编号不能为空")
|
||||
private String unionId;
|
||||
@ApiModelProperty(value = "社交用户的 openid", required = true, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE")
|
||||
@NotEmpty(message = "社交用户的 openid 不能为空")
|
||||
private String openid;
|
||||
|
||||
}
|
||||
@@ -96,8 +96,8 @@ public class UserProfileRespVO extends UserBaseVO {
|
||||
@ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SocialTypeEnum 枚举类")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty(value = "社交的全局编号", required = true, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE")
|
||||
private String unionId;
|
||||
@ApiModelProperty(value = "社交用户的 openid", required = true, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE")
|
||||
private String openid;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*;
|
||||
@@ -73,9 +74,10 @@ public interface AuthConvert {
|
||||
return CollectionUtils.filterList(treeNodeMap.values(), node -> MenuIdEnum.ROOT.getId().equals(node.getParentId()));
|
||||
}
|
||||
|
||||
SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialBindReqVO reqVO);
|
||||
SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialLogin2ReqVO reqVO);
|
||||
SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialLoginReqVO reqVO);
|
||||
SocialUserUnbindReqDTO convert(Long userId, Integer userType, AuthSocialUnbindReqVO reqVO);
|
||||
SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialBindLoginReqVO reqVO);
|
||||
|
||||
SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialQuickLoginReqVO reqVO);
|
||||
|
||||
SmsCodeSendReqDTO convert(AuthSmsSendReqVO reqVO);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.yudao.module.system.convert.social;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.SocialUserBindReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.SocialUserUnbindReqVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface SocialUserConvert {
|
||||
|
||||
SocialUserConvert INSTANCE = Mappers.getMapper(SocialUserConvert.class);
|
||||
|
||||
SocialUserBindReqDTO convert(Long userId, Integer userType, SocialUserBindReqVO reqVO);
|
||||
|
||||
SocialUserUnbindReqDTO convert(Long userId, Integer userType, SocialUserUnbindReqVO reqVO);
|
||||
|
||||
}
|
||||
@@ -3,9 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.auth;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -21,17 +19,22 @@ import java.util.Date;
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "system_user_session", autoResultMap = true)
|
||||
@TableName(value = "system_user_session")
|
||||
@KeySequence(value = "system_user_session_seq")
|
||||
@Data
|
||||
@Builder
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class UserSessionDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 会话编号, 即 sessionId
|
||||
* 会话编号
|
||||
*/
|
||||
@TableId(type = IdType.INPUT)
|
||||
private String id;
|
||||
private Long id;
|
||||
/**
|
||||
* 令牌
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*
|
||||
|
||||
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.dept;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@@ -15,6 +16,7 @@ import lombok.EqualsAndHashCode;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("system_dept")
|
||||
@KeySequence("system_dept_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DeptDO extends BaseDO {
|
||||
|
||||
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.dept;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@@ -13,6 +14,7 @@ import lombok.EqualsAndHashCode;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@TableName("system_post")
|
||||
@KeySequence("system_post_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PostDO extends BaseDO {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package cn.iocoder.yudao.module.system.dal.dataobject.dept;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 用户和岗位关联
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@TableName("system_user_post")
|
||||
@KeySequence("system_user_post_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class UserPostDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 自增主键
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 用户 ID
|
||||
*
|
||||
* 关联 {@link AdminUserDO#getId()}
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 角色 ID
|
||||
*
|
||||
* 关联 {@link PostDO#getId()}
|
||||
*/
|
||||
private Long postId;
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.dict;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@@ -13,6 +14,7 @@ import lombok.EqualsAndHashCode;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@TableName("system_dict_data")
|
||||
@KeySequence("system_dict_data_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DictDataDO extends BaseDO {
|
||||
|
||||
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.dict;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -13,6 +14,7 @@ import lombok.*;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@TableName("system_dict_type")
|
||||
@KeySequence("system_dict_type_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@@ -33,7 +35,6 @@ public class DictTypeDO extends BaseDO {
|
||||
/**
|
||||
* 字典类型
|
||||
*/
|
||||
@TableField("`type`")
|
||||
private String type;
|
||||
/**
|
||||
* 状态
|
||||
|
||||
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.errorcode;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.system.enums.errorcode.ErrorCodeTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@@ -14,6 +15,7 @@ import lombok.ToString;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "system_error_code")
|
||||
@KeySequence("system_error_code_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
||||
@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -17,6 +18,7 @@ import lombok.ToString;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("system_login_log")
|
||||
@KeySequence("system_login_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
||||
@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -20,6 +21,7 @@ import java.util.Map;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "system_operate_log", autoResultMap = true)
|
||||
@KeySequence("system_operate_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class OperateLogDO extends BaseDO {
|
||||
@@ -70,7 +72,6 @@ public class OperateLogDO extends BaseDO {
|
||||
*
|
||||
* 枚举 {@link OperateTypeEnum}
|
||||
*/
|
||||
@TableField("operate_type")
|
||||
private Integer type;
|
||||
/**
|
||||
* 操作内容,记录整个操作的明细
|
||||
|
||||
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.notice;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.system.enums.notice.NoticeTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -14,6 +14,7 @@ import lombok.EqualsAndHashCode;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@TableName("system_notice")
|
||||
@KeySequence("system_notice_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class NoticeDO extends BaseDO {
|
||||
@@ -31,7 +32,6 @@ public class NoticeDO extends BaseDO {
|
||||
*
|
||||
* 枚举 {@link NoticeTypeEnum}
|
||||
*/
|
||||
@TableField("notice_type")
|
||||
private Integer type;
|
||||
/**
|
||||
* 公告内容
|
||||
|
||||
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.permission;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@@ -15,6 +15,7 @@ import lombok.EqualsAndHashCode;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@TableName("system_menu")
|
||||
@KeySequence("system_menu_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class MenuDO extends BaseDO {
|
||||
@@ -44,7 +45,6 @@ public class MenuDO extends BaseDO {
|
||||
*
|
||||
* 枚举 {@link MenuTypeEnum}
|
||||
*/
|
||||
@TableField("menu_type")
|
||||
private Integer type;
|
||||
/**
|
||||
* 显示顺序
|
||||
|
||||
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
|
||||
import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
|
||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
|
||||
import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -19,6 +20,7 @@ import java.util.Set;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@TableName(value = "system_role", autoResultMap = true)
|
||||
@KeySequence("system_role_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RoleDO extends TenantBaseDO {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.dal.dataobject.permission;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@@ -13,6 +13,7 @@ import lombok.EqualsAndHashCode;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@TableName("system_role_menu")
|
||||
@KeySequence("system_role_menu_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RoleMenuDO extends TenantBaseDO {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.dal.dataobject.permission;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@@ -12,6 +13,7 @@ import lombok.EqualsAndHashCode;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@TableName("system_user_role")
|
||||
@KeySequence("system_user_role_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class UserRoleDO extends BaseDO {
|
||||
|
||||
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.StringLiSTTypeHandler;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -16,6 +17,7 @@ import java.util.List;
|
||||
* @author 永不言败
|
||||
*/
|
||||
@TableName(value = "system_sensitive_word", autoResultMap = true)
|
||||
@KeySequence("system_sensitive_word_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
||||
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.sms;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -15,6 +16,7 @@ import lombok.ToString;
|
||||
* @since 2021-01-25
|
||||
*/
|
||||
@TableName(value = "system_sms_channel", autoResultMap = true)
|
||||
@KeySequence("system_sms_channel_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.dal.dataobject.sms;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
@@ -14,6 +15,7 @@ import java.util.Date;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("system_sms_code")
|
||||
@KeySequence("system_sms_code_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Builder
|
||||
|
||||
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
@@ -20,6 +21,7 @@ import java.util.Map;
|
||||
* @since 2021-01-25
|
||||
*/
|
||||
@TableName(value = "system_sms_log", autoResultMap = true)
|
||||
@KeySequence("system_sms_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
||||
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.sms;
|
||||
import cn.iocoder.yudao.module.system.enums.sms.SmsTemplateTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
@@ -19,6 +20,7 @@ import java.util.List;
|
||||
* @since 2021-01-25
|
||||
*/
|
||||
@TableName(value = "system_sms_template", autoResultMap = true)
|
||||
@KeySequence("system_sms_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
||||
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.social;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
@@ -13,6 +13,7 @@ import lombok.*;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "system_social_user_bind", autoResultMap = true)
|
||||
@KeySequence("system_social_user_bind_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Builder
|
||||
|
||||
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.social;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
@@ -12,6 +13,7 @@ import lombok.*;
|
||||
* @author weir
|
||||
*/
|
||||
@TableName(value = "system_social_user", autoResultMap = true)
|
||||
@KeySequence("system_social_user_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Builder
|
||||
|
||||
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.tenant;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
@@ -14,6 +15,7 @@ import java.util.Date;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "system_tenant", autoResultMap = true)
|
||||
@KeySequence("system_tenant_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
||||
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.tenant;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
@@ -15,6 +16,7 @@ import java.util.Set;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "system_tenant_package", autoResultMap = true)
|
||||
@KeySequence("system_tenant_package_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
||||
@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
|
||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
|
||||
import cn.iocoder.yudao.module.system.enums.common.SexEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -18,7 +19,8 @@ import java.util.Set;
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "system_user", autoResultMap = true)
|
||||
@TableName(value = "system_users", autoResultMap = true) // 由于 SQL Server 的 system_user 是关键字,所以使用 system_users
|
||||
@KeySequence("system_user_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Builder
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package cn.iocoder.yudao.module.system.dal.mysql.auth;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -15,13 +15,23 @@ import java.util.List;
|
||||
public interface UserSessionMapper extends BaseMapperX<UserSessionDO> {
|
||||
|
||||
default PageResult<UserSessionDO> selectPage(UserSessionPageReqVO reqVO, Collection<Long> userIds) {
|
||||
return selectPage(reqVO, new QueryWrapperX<UserSessionDO>()
|
||||
.inIfPresent("user_id", userIds)
|
||||
.likeIfPresent("user_ip", reqVO.getUserIp()));
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<UserSessionDO>()
|
||||
.inIfPresent(UserSessionDO::getUserId, userIds)
|
||||
.likeIfPresent(UserSessionDO::getUserIp, reqVO.getUserIp()));
|
||||
}
|
||||
|
||||
default List<UserSessionDO> selectListBySessionTimoutLt() {
|
||||
return selectList(new QueryWrapperX<UserSessionDO>().lt("session_timeout",new Date()));
|
||||
return selectList(new LambdaQueryWrapperX<UserSessionDO>()
|
||||
.lt(UserSessionDO::getSessionTimeout, new Date()));
|
||||
}
|
||||
|
||||
default void updateByToken(String token, UserSessionDO updateObj) {
|
||||
update(updateObj, new LambdaQueryWrapperX<UserSessionDO>()
|
||||
.eq(UserSessionDO::getToken, token));
|
||||
}
|
||||
|
||||
default void deleteByToken(String token) {
|
||||
delete(new LambdaQueryWrapperX<UserSessionDO>().eq(UserSessionDO::getToken, token));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public interface DeptMapper extends BaseMapperX<DeptDO> {
|
||||
return selectCount(DeptDO::getParentId, parentId);
|
||||
}
|
||||
|
||||
@Select("SELECT id FROM system_dept WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
@Select("SELECT COUNT(*) FROM system_dept WHERE update_time > #{maxUpdateTime}")
|
||||
Long selectCountByUpdateTimeGt(Date maxUpdateTime);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.system.dal.mysql.dept;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface UserPostMapper extends BaseMapperX<UserPostDO> {
|
||||
|
||||
default List<UserPostDO> selectListByUserId(Long userId) {
|
||||
return selectList(new LambdaQueryWrapperX<UserPostDO>()
|
||||
.eq(UserPostDO::getUserId, userId));
|
||||
}
|
||||
|
||||
default void deleteByUserIdAndPostId(Long userId, Collection<Long> postIds) {
|
||||
delete(new LambdaQueryWrapperX<UserPostDO>()
|
||||
.eq(UserPostDO::getUserId, userId)
|
||||
.in(UserPostDO::getPostId, postIds));
|
||||
}
|
||||
|
||||
default List<UserPostDO> selectListByPostIds(Collection<Long> postIds) {
|
||||
return selectList(new LambdaQueryWrapperX<UserPostDO>()
|
||||
.in(UserPostDO::getPostId, postIds));
|
||||
}
|
||||
|
||||
default void deleteByUserId(Long userId){
|
||||
delete(Wrappers.lambdaUpdate(UserPostDO.class).eq(UserPostDO::getUserId, userId));
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ public interface DictDataMapper extends BaseMapperX<DictDataDO> {
|
||||
.eqIfPresent(DictDataDO::getStatus, reqVO.getStatus()));
|
||||
}
|
||||
|
||||
@Select("SELECT id FROM system_dict_data WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
@Select("SELECT COUNT(*) FROM system_dict_data WHERE update_time > #{maxUpdateTime}")
|
||||
Long selectCountByUpdateTimeGt(Date maxUpdateTime);
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.system.dal.mysql.dict;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExportReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO;
|
||||
@@ -14,27 +14,27 @@ import java.util.List;
|
||||
public interface DictTypeMapper extends BaseMapperX<DictTypeDO> {
|
||||
|
||||
default PageResult<DictTypeDO> selectPage(DictTypePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new QueryWrapperX<DictTypeDO>()
|
||||
.likeIfPresent("name", reqVO.getName())
|
||||
.likeIfPresent("`type`", reqVO.getType())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()));
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<DictTypeDO>()
|
||||
.likeIfPresent(DictTypeDO::getName, reqVO.getName())
|
||||
.likeIfPresent(DictTypeDO::getType, reqVO.getType())
|
||||
.eqIfPresent(DictTypeDO::getStatus, reqVO.getStatus())
|
||||
.betweenIfPresent(DictTypeDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()));
|
||||
}
|
||||
|
||||
default List<DictTypeDO> selectList(DictTypeExportReqVO reqVO) {
|
||||
return selectList(new QueryWrapperX<DictTypeDO>()
|
||||
.likeIfPresent("name", reqVO.getName())
|
||||
.likeIfPresent("`type`", reqVO.getType())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()));
|
||||
return selectList(new LambdaQueryWrapperX<DictTypeDO>()
|
||||
.likeIfPresent(DictTypeDO::getName, reqVO.getName())
|
||||
.likeIfPresent(DictTypeDO::getType, reqVO.getType())
|
||||
.eqIfPresent(DictTypeDO::getStatus, reqVO.getStatus())
|
||||
.betweenIfPresent(DictTypeDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()));
|
||||
}
|
||||
|
||||
default DictTypeDO selectByType(String type) {
|
||||
return selectOne(new QueryWrapperX<DictTypeDO>().eq("`type`", type));
|
||||
return selectOne(DictTypeDO::getType, type);
|
||||
}
|
||||
|
||||
default DictTypeDO selectByName(String name) {
|
||||
return selectOne(new QueryWrapperX<DictTypeDO>().eq("name", name));
|
||||
return selectOne(DictTypeDO::getName, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.system.dal.mysql.notice;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@@ -11,9 +11,9 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
public interface NoticeMapper extends BaseMapperX<NoticeDO> {
|
||||
|
||||
default PageResult<NoticeDO> selectPage(NoticePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new QueryWrapperX<NoticeDO>()
|
||||
.likeIfPresent("title", reqVO.getTitle())
|
||||
.eqIfPresent("status", reqVO.getStatus()));
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<NoticeDO>()
|
||||
.likeIfPresent(NoticeDO::getTitle, reqVO.getTitle())
|
||||
.eqIfPresent(NoticeDO::getStatus, reqVO.getStatus()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public interface MenuMapper extends BaseMapperX<MenuDO> {
|
||||
.eqIfPresent(MenuDO::getStatus, reqVO.getStatus()));
|
||||
}
|
||||
|
||||
@Select("SELECT id FROM system_menu WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
MenuDO selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
@Select("SELECT COUNT(*) FROM system_menu WHERE update_time > #{maxUpdateTime}")
|
||||
Long selectCountByUpdateTimeGt(Date maxUpdateTime);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package cn.iocoder.yudao.module.system.dal.mysql.permission;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleExportReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
||||
@@ -19,32 +19,34 @@ import java.util.List;
|
||||
public interface RoleMapper extends BaseMapperX<RoleDO> {
|
||||
|
||||
default PageResult<RoleDO> selectPage(RolePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new QueryWrapperX<RoleDO>().likeIfPresent("name", reqVO.getName())
|
||||
.likeIfPresent("code", reqVO.getCode())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime()));
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<RoleDO>()
|
||||
.likeIfPresent(RoleDO::getName, reqVO.getName())
|
||||
.likeIfPresent(RoleDO::getCode, reqVO.getCode())
|
||||
.eqIfPresent(RoleDO::getStatus, reqVO.getStatus())
|
||||
.betweenIfPresent(BaseDO::getCreateTime, reqVO.getBeginTime(), reqVO.getEndTime()));
|
||||
}
|
||||
|
||||
default List<RoleDO> listRoles(RoleExportReqVO reqVO) {
|
||||
return selectList(new QueryWrapperX<RoleDO>().likeIfPresent("name", reqVO.getName())
|
||||
.likeIfPresent("code", reqVO.getCode())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime()));
|
||||
default List<RoleDO> selectList(RoleExportReqVO reqVO) {
|
||||
return selectList(new LambdaQueryWrapperX<RoleDO>()
|
||||
.likeIfPresent(RoleDO::getName, reqVO.getName())
|
||||
.likeIfPresent(RoleDO::getCode, reqVO.getCode())
|
||||
.eqIfPresent(RoleDO::getStatus, reqVO.getStatus())
|
||||
.betweenIfPresent(BaseDO::getCreateTime, reqVO.getBeginTime(), reqVO.getEndTime()));
|
||||
}
|
||||
|
||||
default RoleDO selectByName(String name) {
|
||||
return selectOne(new QueryWrapperX<RoleDO>().eq("name", name));
|
||||
return selectOne(RoleDO::getName, name);
|
||||
}
|
||||
|
||||
default RoleDO selectByCode(String code) {
|
||||
return selectOne(new QueryWrapperX<RoleDO>().eq("code", code));
|
||||
return selectOne(RoleDO::getCode, code);
|
||||
}
|
||||
|
||||
default List<RoleDO> selectListByStatus(@Nullable Collection<Integer> statuses) {
|
||||
return selectList(new LambdaQueryWrapperX<RoleDO>().inIfPresent(RoleDO::getStatus, statuses));
|
||||
return selectList(RoleDO::getStatus, statuses);
|
||||
}
|
||||
|
||||
@Select("SELECT id FROM system_role WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
RoleDO selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
@Select("SELECT COUNT(*) FROM system_role WHERE update_time > #{maxUpdateTime}")
|
||||
Long selectCountByUpdateTimeGt(Date maxUpdateTime);
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import org.springframework.stereotype.Repository;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mapper
|
||||
public interface RoleMenuMapper extends BaseMapperX<RoleMenuDO> {
|
||||
@@ -37,7 +36,7 @@ public interface RoleMenuMapper extends BaseMapperX<RoleMenuDO> {
|
||||
delete(new QueryWrapper<RoleMenuDO>().eq("role_id", roleId));
|
||||
}
|
||||
|
||||
@Select("SELECT id FROM system_role_menu WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
@Select("SELECT COUNT(*) FROM system_role_menu WHERE update_time > #{maxUpdateTime}")
|
||||
Long selectCountByUpdateTimeGt(Date maxUpdateTime);
|
||||
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ public interface SensitiveWordMapper extends BaseMapperX<SensitiveWordDO> {
|
||||
return selectOne(SensitiveWordDO::getName, name);
|
||||
}
|
||||
|
||||
@Select("SELECT id FROM system_sensitive_word WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
SensitiveWordDO selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
@Select("SELECT COUNT(*) FROM system_sensitive_word WHERE update_time > #{maxUpdateTime}")
|
||||
Long selectCountByUpdateTimeGt(Date maxUpdateTime);
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.system.dal.mysql.sms;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@@ -14,14 +14,14 @@ import java.util.Date;
|
||||
public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> {
|
||||
|
||||
default PageResult<SmsChannelDO> selectPage(SmsChannelPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new QueryWrapperX<SmsChannelDO>()
|
||||
.likeIfPresent("signature", reqVO.getSignature())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("id"));
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<SmsChannelDO>()
|
||||
.likeIfPresent(SmsChannelDO::getSignature, reqVO.getSignature())
|
||||
.eqIfPresent(SmsChannelDO::getStatus, reqVO.getStatus())
|
||||
.betweenIfPresent(SmsChannelDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc(SmsChannelDO::getId));
|
||||
}
|
||||
|
||||
@Select("SELECT id FROM system_sms_channel WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
@Select("SELECT COUNT(*) FROM system_sms_channel WHERE update_time > #{maxUpdateTime}")
|
||||
Long selectCountByUpdateTimeGt(Date maxUpdateTime);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package cn.iocoder.yudao.module.system.dal.mysql.sms;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsCodeDO;
|
||||
@@ -19,8 +18,11 @@ public interface SmsCodeMapper extends BaseMapperX<SmsCodeDO> {
|
||||
*/
|
||||
default SmsCodeDO selectLastByMobile(String mobile, String code, Integer scene) {
|
||||
return selectOne(new QueryWrapperX<SmsCodeDO>()
|
||||
.eq("mobile", mobile).eqIfPresent("scene", scene).eqIfPresent("code", code)
|
||||
.orderByDesc("id").last(SqlConstants.LIMIT1));
|
||||
.eq("mobile", mobile)
|
||||
.eqIfPresent("scene", scene)
|
||||
.eqIfPresent("code", code)
|
||||
.orderByDesc("id")
|
||||
.limit1());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@ import java.util.List;
|
||||
@Mapper
|
||||
public interface SmsTemplateMapper extends BaseMapperX<SmsTemplateDO> {
|
||||
|
||||
@Select("SELECT id FROM system_sms_template WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
@Select("SELECT COUNT(*) FROM system_sms_template WHERE update_time > #{maxUpdateTime}")
|
||||
Long selectCountByUpdateTimeGt(Date maxUpdateTime);
|
||||
|
||||
default SmsTemplateDO selectByCode(String code) {
|
||||
return selectOne(SmsTemplateDO::getCode, code);
|
||||
|
||||
@@ -52,7 +52,7 @@ public interface TenantMapper extends BaseMapperX<TenantDO> {
|
||||
return selectList(TenantDO::getPackageId, packageId);
|
||||
}
|
||||
|
||||
@Select("SELECT id FROM system_tenant WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
@Select("SELECT COUNT(*) FROM system_tenant WHERE update_time > #{maxUpdateTime}")
|
||||
Long selectCountByUpdateTimeGt(Date maxUpdateTime);
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.system.dal.redis;
|
||||
|
||||
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@@ -20,7 +19,7 @@ public interface RedisKeyConstants {
|
||||
STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);
|
||||
|
||||
RedisKeyDefine LOGIN_USER = new RedisKeyDefine("登录用户的缓存",
|
||||
"login_user:%s", // 参数为 sessionId
|
||||
"login_user:%s", // 参数为 token 令牌
|
||||
STRING, LoginUser.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);
|
||||
|
||||
RedisKeyDefine SOCIAL_AUTH_STATE = new RedisKeyDefine("社交登陆的 state", // 注意,它是被 JustAuth 的 justauth.type.prefix 使用到
|
||||
|
||||
@@ -24,24 +24,29 @@ public class LoginUserRedisDAO {
|
||||
@Resource
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
public LoginUser get(String sessionId) {
|
||||
String redisKey = formatKey(sessionId);
|
||||
public LoginUser get(String token) {
|
||||
String redisKey = formatKey(token);
|
||||
return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), LoginUser.class);
|
||||
}
|
||||
|
||||
public void set(String sessionId, LoginUser loginUser) {
|
||||
String redisKey = formatKey(sessionId);
|
||||
public Boolean exists(String token) {
|
||||
String redisKey = formatKey(token);
|
||||
return stringRedisTemplate.hasKey(redisKey);
|
||||
}
|
||||
|
||||
public void set(String token, LoginUser loginUser) {
|
||||
String redisKey = formatKey(token);
|
||||
stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(loginUser),
|
||||
securityProperties.getSessionTimeout());
|
||||
}
|
||||
|
||||
public void delete(String sessionId) {
|
||||
String redisKey = formatKey(sessionId);
|
||||
public void delete(String token) {
|
||||
String redisKey = formatKey(token);
|
||||
stringRedisTemplate.delete(redisKey);
|
||||
}
|
||||
|
||||
private static String formatKey(String sessionId) {
|
||||
return LOGIN_USER.formatKey(sessionId);
|
||||
private static String formatKey(String token) {
|
||||
return LOGIN_USER.formatKey(token);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.framework.errorcode.core.generator;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
@@ -57,7 +58,7 @@ public class ErrorCodeAutoGeneratorImpl implements ErrorCodeAutoGenerator {
|
||||
*
|
||||
* @return 错误码数组
|
||||
*/
|
||||
private List<ErrorCodeAutoGenerateReqDTO> parseErrorCode() {
|
||||
private List<ErrorCodeAutoGenerateReqDTO> parseErrorCode() {
|
||||
// 校验 errorCodeConstantsClass 参数
|
||||
if (CollUtil.isEmpty(constantsClassList)) {
|
||||
log.info("[execute][未配置 yudao.error-code.constants-class-list 配置项,不进行自动写入到 system 服务中]");
|
||||
@@ -67,10 +68,15 @@ public class ErrorCodeAutoGeneratorImpl implements ErrorCodeAutoGenerator {
|
||||
// 解析错误码
|
||||
List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs = new ArrayList<>();
|
||||
constantsClassList.forEach(constantsClass -> {
|
||||
// 解析错误码枚举类
|
||||
Class<?> errorCodeConstantsClazz = ClassUtil.loadClass(constantsClass);
|
||||
// 解析错误码
|
||||
autoGenerateDTOs.addAll(parseErrorCode(errorCodeConstantsClazz));
|
||||
try {
|
||||
// 解析错误码枚举类
|
||||
Class<?> errorCodeConstantsClazz = ClassUtil.loadClass(constantsClass);
|
||||
// 解析错误码
|
||||
autoGenerateDTOs.addAll(parseErrorCode(errorCodeConstantsClazz));
|
||||
} catch (Exception ex) {
|
||||
log.warn("[parseErrorCode][constantsClass({}) 加载失败({})]", constantsClass,
|
||||
ExceptionUtil.getRootCauseMessage(ex));
|
||||
}
|
||||
});
|
||||
return autoGenerateDTOs;
|
||||
}
|
||||
|
||||
@@ -18,18 +18,21 @@ public class SecurityConfiguration {
|
||||
|
||||
@Override
|
||||
public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
|
||||
// 登录的接口,可匿名访问
|
||||
registry.antMatchers(buildAdminApi("/system/login")).anonymous();
|
||||
//手机短信验证码登录
|
||||
registry.antMatchers(buildAdminApi("/system/sms-login")).anonymous();
|
||||
//短信登录验证码接口
|
||||
registry.antMatchers(buildAdminApi("/system/send-login-sms-code")).anonymous();
|
||||
// 登录的接口
|
||||
registry.antMatchers(buildAdminApi("/system/auth/login")).permitAll();
|
||||
// 社交登陆的接口
|
||||
registry.antMatchers(buildAdminApi("/system/auth/social-auth-redirect")).permitAll();
|
||||
registry.antMatchers(buildAdminApi("/system/auth/social-quick-login")).permitAll();
|
||||
registry.antMatchers(buildAdminApi("/system/auth/social-bind-login")).permitAll();
|
||||
// 登录登录的接口
|
||||
registry.antMatchers(buildAdminApi("/system/auth/sms-login")).permitAll();
|
||||
registry.antMatchers(buildAdminApi("/system/auth/send-login-sms-code")).permitAll();
|
||||
// 验证码的接口
|
||||
registry.antMatchers(buildAdminApi("/system/captcha/**")).anonymous();
|
||||
registry.antMatchers(buildAdminApi("/system/captcha/**")).permitAll();
|
||||
// 获得租户编号的接口
|
||||
registry.antMatchers(buildAdminApi("/system/tenant/get-id-by-name")).anonymous();
|
||||
registry.antMatchers(buildAdminApi("/system/tenant/get-id-by-name")).permitAll();
|
||||
// 短信回调 API
|
||||
registry.antMatchers(buildAdminApi("/system/sms/callback/**")).anonymous();
|
||||
registry.antMatchers(buildAdminApi("/system/sms/callback/**")).permitAll();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ public class UserSessionTimeoutJob implements JobHandler {
|
||||
@Override
|
||||
public String execute(String param) throws Exception {
|
||||
// 执行过期
|
||||
Long timeoutCount = userSessionService.clearSessionTimeout();
|
||||
Long timeoutCount = userSessionService.deleteTimeoutSession();
|
||||
// 返回结果,记录每次的超时数量
|
||||
return String.format("移除在线会话数量为 %s 个", timeoutCount);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public interface AdminAuthService extends SecurityAuthFrameworkService {
|
||||
* @param userId
|
||||
* @param reqVO
|
||||
*/
|
||||
public void sendSmsCode(Long userId, AuthSmsSendReqVO reqVO);
|
||||
void sendSmsCode(Long userId, AuthSmsSendReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 短信登录
|
||||
@@ -42,31 +42,23 @@ public interface AdminAuthService extends SecurityAuthFrameworkService {
|
||||
String smsLogin(AuthSmsLoginReqVO reqVO, String userIp, String userAgent) ;
|
||||
|
||||
/**
|
||||
* 社交登录,使用 code 授权码
|
||||
* 社交快捷登录,使用 code 授权码
|
||||
*
|
||||
* @param reqVO 登录信息
|
||||
* @param userIp 用户 IP
|
||||
* @param userAgent 用户 UA
|
||||
* @return 身份令牌,使用 JWT 方式
|
||||
*/
|
||||
String socialLogin(@Valid AuthSocialLoginReqVO reqVO, String userIp, String userAgent);
|
||||
String socialLogin(@Valid AuthSocialQuickLoginReqVO reqVO, String userIp, String userAgent);
|
||||
|
||||
/**
|
||||
* 社交登录,使用 code 授权码 + 账号密码
|
||||
* 社交绑定登录,使用 code 授权码 + 账号密码
|
||||
*
|
||||
* @param reqVO 登录信息
|
||||
* @param userIp 用户 IP
|
||||
* @param userAgent 用户 UA
|
||||
* @return 身份令牌,使用 JWT 方式
|
||||
*/
|
||||
String socialLogin2(@Valid AuthSocialLogin2ReqVO reqVO, String userIp, String userAgent);
|
||||
|
||||
/**
|
||||
* 社交绑定,使用 code 授权码
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param reqVO 绑定信息
|
||||
*/
|
||||
void socialBind(Long userId, @Valid AuthSocialBindReqVO reqVO);
|
||||
String socialBindLogin(@Valid AuthSocialBindLoginReqVO reqVO, String userIp, String userAgent);
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
import cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthLoginReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthSocialBindLoginReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthSocialQuickLoginReqVO;
|
||||
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
|
||||
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*;
|
||||
@@ -22,7 +25,6 @@ import cn.iocoder.yudao.module.system.service.permission.PermissionService;
|
||||
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
|
||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
@@ -78,7 +80,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
@Resource
|
||||
private SmsCodeApi smsCodeApi;
|
||||
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
// 获取 username 对应的 AdminUserDO
|
||||
@@ -87,7 +88,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
throw new UsernameNotFoundException(username);
|
||||
}
|
||||
// 创建 LoginUser 对象
|
||||
return this.buildLoginUser(user);
|
||||
return buildLoginUser(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -97,21 +98,21 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException(String.valueOf(userId));
|
||||
}
|
||||
this.createLoginLog(user.getUsername(), LoginLogTypeEnum.LOGIN_MOCK, LoginResultEnum.SUCCESS);
|
||||
createLoginLog(user.getUsername(), LoginLogTypeEnum.LOGIN_MOCK, LoginResultEnum.SUCCESS);
|
||||
|
||||
// 创建 LoginUser 对象
|
||||
return this.buildLoginUser(user);
|
||||
return buildLoginUser(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String login(AuthLoginReqVO reqVO, String userIp, String userAgent) {
|
||||
// 判断验证码是否正确
|
||||
this.verifyCaptcha(reqVO);
|
||||
verifyCaptcha(reqVO);
|
||||
|
||||
// 使用账号密码,进行登录
|
||||
LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
|
||||
LoginUser loginUser = login0(reqVO.getUsername(), reqVO.getPassword());
|
||||
|
||||
// 缓存登陆用户到 Redis 中,返回 sessionId 编号
|
||||
// 缓存登陆用户到 Redis 中,返回 Token 令牌
|
||||
return createUserSessionAfterLoginSuccess(loginUser, LoginLogTypeEnum.LOGIN_USERNAME, userIp, userAgent);
|
||||
}
|
||||
|
||||
@@ -276,7 +277,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String socialLogin(AuthSocialLoginReqVO reqVO, String userIp, String userAgent) {
|
||||
public String socialLogin(AuthSocialQuickLoginReqVO reqVO, String userIp, String userAgent) {
|
||||
// 使用 code 授权码,进行登录。然后,获得到绑定的用户编号
|
||||
Long userId = socialUserService.getBindUserId(UserTypeEnum.ADMIN.getValue(), reqVO.getType(),
|
||||
reqVO.getCode(), reqVO.getState());
|
||||
@@ -291,43 +292,31 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
}
|
||||
|
||||
// 创建 LoginUser 对象
|
||||
LoginUser loginUser = this.buildLoginUser(user);
|
||||
LoginUser loginUser = buildLoginUser(user);
|
||||
|
||||
// 绑定社交用户(更新)
|
||||
socialUserService.bindSocialUser(AuthConvert.INSTANCE.convert(loginUser.getId(), getUserType().getValue(), reqVO));
|
||||
|
||||
// 缓存登录用户到 Redis 中,返回 sessionId 编号
|
||||
// 缓存登录用户到 Redis 中,返回 Token 令牌
|
||||
return createUserSessionAfterLoginSuccess(loginUser, LoginLogTypeEnum.LOGIN_SOCIAL, userIp, userAgent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String socialLogin2(AuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) {
|
||||
// 使用 code 授权码,进行登录
|
||||
socialUserService.authSocialUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());
|
||||
|
||||
public String socialBindLogin(AuthSocialBindLoginReqVO reqVO, String userIp, String userAgent) {
|
||||
// 使用账号密码,进行登录。
|
||||
LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
|
||||
LoginUser loginUser = login0(reqVO.getUsername(), reqVO.getPassword());
|
||||
|
||||
// 绑定社交用户(新增)
|
||||
// 绑定社交用户
|
||||
socialUserService.bindSocialUser(AuthConvert.INSTANCE.convert(loginUser.getId(), getUserType().getValue(), reqVO));
|
||||
|
||||
// 缓存登录用户到 Redis 中,返回 sessionId 编号
|
||||
// 缓存登录用户到 Redis 中,返回 Token 令牌
|
||||
return createUserSessionAfterLoginSuccess(loginUser, LoginLogTypeEnum.LOGIN_SOCIAL, userIp, userAgent);
|
||||
}
|
||||
|
||||
private String createUserSessionAfterLoginSuccess(LoginUser loginUser, LoginLogTypeEnum logType, String userIp, String userAgent) {
|
||||
// 插入登陆日志
|
||||
createLoginLog(loginUser.getUsername(), logType, LoginResultEnum.SUCCESS);
|
||||
// 缓存登录用户到 Redis 中,返回 sessionId 编号
|
||||
// 缓存登录用户到 Redis 中,返回 Token 令牌
|
||||
return userSessionService.createUserSession(loginUser, userIp, userAgent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void socialBind(Long userId, AuthSocialBindReqVO reqVO) {
|
||||
// 绑定社交用户(新增)
|
||||
socialUserService.bindSocialUser(AuthConvert.INSTANCE.convert(userId, getUserType().getValue(), reqVO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout(String token) {
|
||||
// 查询用户信息
|
||||
@@ -338,7 +327,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
// 删除 session
|
||||
userSessionService.deleteUserSession(token);
|
||||
// 记录登出日志
|
||||
this.createLogoutLog(loginUser.getId(), loginUser.getUsername());
|
||||
createLogoutLog(loginUser.getId(), loginUser.getUsername());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,7 +25,7 @@ public interface UserSessionService {
|
||||
*
|
||||
* @return {@link Long } 移出的超时用户数量
|
||||
**/
|
||||
long clearSessionTimeout();
|
||||
long deleteTimeoutSession();
|
||||
|
||||
/**
|
||||
* 创建在线用户 Session
|
||||
@@ -33,32 +33,39 @@ public interface UserSessionService {
|
||||
* @param loginUser 登录用户
|
||||
* @param userIp 用户 IP
|
||||
* @param userAgent 用户 UA
|
||||
* @return Session 编号
|
||||
* @return Token 令牌
|
||||
*/
|
||||
String createUserSession(LoginUser loginUser, String userIp, String userAgent);
|
||||
|
||||
/**
|
||||
* 刷新在线用户 Session 的更新时间
|
||||
*
|
||||
* @param sessionId Session 编号
|
||||
* @param token 令牌
|
||||
* @param loginUser 登录用户
|
||||
*/
|
||||
void refreshUserSession(String sessionId, LoginUser loginUser);
|
||||
void refreshUserSession(String token, LoginUser loginUser);
|
||||
|
||||
/**
|
||||
* 删除在线用户 Session
|
||||
*
|
||||
* @param sessionId Session 编号
|
||||
* @param token token 令牌
|
||||
*/
|
||||
void deleteUserSession(String sessionId);
|
||||
void deleteUserSession(String token);
|
||||
|
||||
/**
|
||||
* 获得 Session 编号对应的在线用户
|
||||
* 删除在线用户 Session
|
||||
*
|
||||
* @param sessionId Session 编号
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteUserSession(Long id);
|
||||
|
||||
/**
|
||||
* 获得 Token 对应的在线用户
|
||||
*
|
||||
* @param token 令牌
|
||||
* @return 在线用户
|
||||
*/
|
||||
LoginUser getLoginUser(String sessionId);
|
||||
LoginUser getLoginUser(String token);
|
||||
|
||||
/**
|
||||
* 获得 Session 超时时间,单位:毫秒
|
||||
|
||||
@@ -3,28 +3,28 @@ package cn.iocoder.yudao.module.system.service.auth;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
||||
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.auth.UserSessionMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.redis.auth.LoginUserRedisDAO;
|
||||
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
|
||||
import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
|
||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||
import cn.iocoder.yudao.module.system.dal.redis.auth.LoginUserRedisDAO;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;
|
||||
@@ -65,82 +65,99 @@ public class UserSessionServiceImpl implements UserSessionService {
|
||||
return userSessionMapper.selectPage(reqVO, userIds);
|
||||
}
|
||||
|
||||
// TODO @芋艿:优化下该方法
|
||||
@Override
|
||||
public long clearSessionTimeout() {
|
||||
// 获取db里已经超时的用户列表
|
||||
List<UserSessionDO> sessionTimeoutDOS = userSessionMapper.selectListBySessionTimoutLt();
|
||||
Map<String, UserSessionDO> timeoutSessionDOMap = sessionTimeoutDOS
|
||||
.stream()
|
||||
.filter(sessionDO -> loginUserRedisDAO.get(sessionDO.getId()) == null)
|
||||
.collect(Collectors.toMap(UserSessionDO::getId, o -> o));
|
||||
// 确认已经超时,按批次移出在线用户列表
|
||||
if (CollUtil.isNotEmpty(timeoutSessionDOMap)) {
|
||||
Lists.partition(new ArrayList<>(timeoutSessionDOMap.keySet()), 100)
|
||||
.forEach(userSessionMapper::deleteBatchIds);
|
||||
// 记录用户超时退出日志
|
||||
createTimeoutLogoutLog(timeoutSessionDOMap.values());
|
||||
public long deleteTimeoutSession() {
|
||||
// 获取 db 里已经超时的用户列表
|
||||
List<UserSessionDO> timeoutSessions = userSessionMapper.selectListBySessionTimoutLt();
|
||||
if (CollUtil.isEmpty(timeoutSessions)) {
|
||||
return 0L;
|
||||
}
|
||||
return timeoutSessionDOMap.size();
|
||||
|
||||
// 由于过期的用户一般不多,所以顺序遍历,进行清理
|
||||
int count = 0;
|
||||
for (UserSessionDO session : timeoutSessions) {
|
||||
// 基于 Redis 二次判断,同时也保证 Redis Key 的立即过期,避免延迟导致浪费内存空间
|
||||
if (loginUserRedisDAO.exists(session.getToken())) {
|
||||
continue;
|
||||
}
|
||||
userSessionMapper.deleteById(session.getId());
|
||||
// 记录退出日志
|
||||
createLogoutLog(session, LoginLogTypeEnum.LOGOUT_TIMEOUT);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private void createTimeoutLogoutLog(Collection<UserSessionDO> timeoutSessionDOS) {
|
||||
for (UserSessionDO timeoutSessionDO : timeoutSessionDOS) {
|
||||
LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
|
||||
reqDTO.setLogType(LoginLogTypeEnum.LOGOUT_TIMEOUT.getType());
|
||||
reqDTO.setTraceId(TracerUtils.getTraceId());
|
||||
reqDTO.setUserId(timeoutSessionDO.getUserId());
|
||||
reqDTO.setUserType(timeoutSessionDO.getUserType());
|
||||
reqDTO.setUsername(timeoutSessionDO.getUsername());
|
||||
reqDTO.setUserAgent(timeoutSessionDO.getUserAgent());
|
||||
reqDTO.setUserIp(timeoutSessionDO.getUserIp());
|
||||
reqDTO.setResult(LoginResultEnum.SUCCESS.getResult());
|
||||
loginLogService.createLoginLog(reqDTO);
|
||||
}
|
||||
private void createLogoutLog(UserSessionDO session, LoginLogTypeEnum type) {
|
||||
LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
|
||||
reqDTO.setLogType(type.getType());
|
||||
reqDTO.setTraceId(TracerUtils.getTraceId());
|
||||
reqDTO.setUserId(session.getUserId());
|
||||
reqDTO.setUserType(session.getUserType());
|
||||
reqDTO.setUsername(session.getUsername());
|
||||
reqDTO.setUserAgent(session.getUserAgent());
|
||||
reqDTO.setUserIp(session.getUserIp());
|
||||
reqDTO.setResult(LoginResultEnum.SUCCESS.getResult());
|
||||
loginLogService.createLoginLog(reqDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createUserSession(LoginUser loginUser, String userIp, String userAgent) {
|
||||
// 生成 Session 编号
|
||||
String sessionId = generateSessionId();
|
||||
String token = generateToken();
|
||||
// 写入 Redis 缓存
|
||||
loginUser.setUpdateTime(new Date());
|
||||
loginUserRedisDAO.set(sessionId, loginUser);
|
||||
loginUserRedisDAO.set(token, loginUser);
|
||||
// 写入 DB 中
|
||||
UserSessionDO userSession = UserSessionDO.builder().id(sessionId)
|
||||
UserSessionDO userSession = UserSessionDO.builder().token(token)
|
||||
.userId(loginUser.getId()).userType(loginUser.getUserType())
|
||||
.userIp(userIp).userAgent(userAgent).username(loginUser.getUsername())
|
||||
.sessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis())))
|
||||
.build();
|
||||
userSessionMapper.insert(userSession);
|
||||
// 返回 Session 编号
|
||||
return sessionId;
|
||||
// 返回 Token 令牌
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshUserSession(String sessionId, LoginUser loginUser) {
|
||||
public void refreshUserSession(String token, LoginUser loginUser) {
|
||||
// 写入 Redis 缓存
|
||||
loginUser.setUpdateTime(new Date());
|
||||
loginUserRedisDAO.set(sessionId, loginUser);
|
||||
loginUserRedisDAO.set(token, loginUser);
|
||||
// 更新 DB 中
|
||||
UserSessionDO updateObj = UserSessionDO.builder().id(sessionId).build();
|
||||
UserSessionDO updateObj = UserSessionDO.builder().build();
|
||||
updateObj.setUsername(loginUser.getUsername());
|
||||
updateObj.setUpdateTime(new Date());
|
||||
updateObj.setSessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis())));
|
||||
userSessionMapper.updateById(updateObj);
|
||||
userSessionMapper.updateByToken(token, updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteUserSession(String sessionId) {
|
||||
public void deleteUserSession(String token) {
|
||||
// 删除 Redis 缓存
|
||||
loginUserRedisDAO.delete(sessionId);
|
||||
loginUserRedisDAO.delete(token);
|
||||
// 删除 DB 记录
|
||||
userSessionMapper.deleteById(sessionId);
|
||||
userSessionMapper.deleteByToken(token);
|
||||
// 无需记录日志,因为退出那已经记录
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginUser getLoginUser(String sessionId) {
|
||||
return loginUserRedisDAO.get(sessionId);
|
||||
public void deleteUserSession(Long id) {
|
||||
UserSessionDO session = userSessionMapper.selectById(id);
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
// 删除 Redis 缓存
|
||||
loginUserRedisDAO.delete(session.getToken());
|
||||
// 删除 DB 记录
|
||||
userSessionMapper.deleteById(id);
|
||||
// 记录退出日志
|
||||
createLogoutLog(session, LoginLogTypeEnum.LOGOUT_DELETE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginUser getLoginUser(String token) {
|
||||
return loginUserRedisDAO.get(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,11 +166,11 @@ public class UserSessionServiceImpl implements UserSessionService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 Session 编号,目前采用 UUID 算法
|
||||
* 生成 Token 令牌,目前采用 UUID 算法
|
||||
*
|
||||
* @return Session 编号
|
||||
*/
|
||||
private static String generateSessionId() {
|
||||
private static String generateToken() {
|
||||
return IdUtil.fastSimpleUUID();
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ public class DeptServiceImpl implements DeptService {
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadMenuIfUpdate][首次加载全量部门]");
|
||||
} else { // 判断数据库中是否有更新的部门
|
||||
if (deptMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) {
|
||||
if (deptMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadMenuIfUpdate][增量加载全量部门]");
|
||||
|
||||
@@ -115,7 +115,7 @@ public class DictDataServiceImpl implements DictDataService {
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadDictDataIfUpdate][首次加载全量字典数据]");
|
||||
} else { // 判断数据库中是否有更新的字典数据
|
||||
if (dictDataMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) {
|
||||
if (dictDataMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadDictDataIfUpdate][增量加载全量字典数据]");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.system.service.dict;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeCreateReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExportReqVO;
|
||||
@@ -113,6 +114,9 @@ public class DictTypeServiceImpl implements DictTypeService {
|
||||
|
||||
@VisibleForTesting
|
||||
public void checkDictTypeUnique(Long id, String type) {
|
||||
if (StrUtil.isEmpty(type)) {
|
||||
return;
|
||||
}
|
||||
DictTypeDO dictType = dictTypeMapper.selectByType(type);
|
||||
if (dictType == null) {
|
||||
return;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.service.permission;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO;
|
||||
@@ -95,7 +96,9 @@ public class MenuServiceImpl implements MenuService {
|
||||
ImmutableMultimap.Builder<String, MenuDO> permMenuCacheBuilder = ImmutableMultimap.builder();
|
||||
menuList.forEach(menuDO -> {
|
||||
menuCacheBuilder.put(menuDO.getId(), menuDO);
|
||||
permMenuCacheBuilder.put(menuDO.getPermission(), menuDO);
|
||||
if (StrUtil.isNotEmpty(menuDO.getPermission())) { // 会存在 permission 为 null 的情况,导致 put 报 NPE 异常
|
||||
permMenuCacheBuilder.put(menuDO.getPermission(), menuDO);
|
||||
}
|
||||
});
|
||||
menuCache = menuCacheBuilder.build();
|
||||
permissionMenuCache = permMenuCacheBuilder.build();
|
||||
@@ -120,7 +123,7 @@ public class MenuServiceImpl implements MenuService {
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadMenuIfUpdate][首次加载全量菜单]");
|
||||
} else { // 判断数据库中是否有更新的菜单
|
||||
if (menuMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) {
|
||||
if (menuMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadMenuIfUpdate][增量加载全量菜单]");
|
||||
|
||||
@@ -144,7 +144,7 @@ public class PermissionServiceImpl implements PermissionService {
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadRoleMenuIfUpdate][首次加载全量角色与菜单的关联]");
|
||||
} else { // 判断数据库中是否有更新的角色与菜单的关联
|
||||
if (Objects.isNull(roleMenuMapper.selectExistsByUpdateTimeAfter(maxUpdateTime))) {
|
||||
if (roleMenuMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadRoleMenuIfUpdate][增量加载全量角色与菜单的关联]");
|
||||
|
||||
@@ -116,7 +116,7 @@ public class RoleServiceImpl implements RoleService {
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadRoleIfUpdate][首次加载全量角色]");
|
||||
} else { // 判断数据库中是否有更新的角色
|
||||
if (roleMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) {
|
||||
if (roleMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadRoleIfUpdate][增量加载全量角色]");
|
||||
@@ -247,7 +247,7 @@ public class RoleServiceImpl implements RoleService {
|
||||
|
||||
@Override
|
||||
public List<RoleDO> getRoleList(RoleExportReqVO reqVO) {
|
||||
return roleMapper.listRoles(reqVO);
|
||||
return roleMapper.selectList(reqVO);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -139,7 +139,7 @@ public class SensitiveWordServiceImpl implements SensitiveWordService {
|
||||
if (maxUpdateTime == null) {
|
||||
log.info("[loadSensitiveWordIfUpdate][首次加载全量敏感词]");
|
||||
} else { // 判断数据库中是否有更新的敏感词
|
||||
if (sensitiveWordMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) {
|
||||
if (sensitiveWordMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadSensitiveWordIfUpdate][增量加载全量敏感词]");
|
||||
|
||||
@@ -94,7 +94,7 @@ public class SmsChannelServiceImpl implements SmsChannelService {
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadSmsChannelIfUpdate][首次加载全量短信渠道]");
|
||||
} else { // 判断数据库中是否有更新的短信渠道
|
||||
if (smsChannelMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) {
|
||||
if (smsChannelMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadSmsChannelIfUpdate][增量加载全量短信渠道]");
|
||||
|
||||
@@ -105,7 +105,7 @@ public class SmsTemplateServiceImpl implements SmsTemplateService {
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadSmsTemplateIfUpdate][首次加载全量短信模板]");
|
||||
} else { // 判断数据库中是否有更新的短信模板
|
||||
if (smsTemplateMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) {
|
||||
if (smsTemplateMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadSmsTemplateIfUpdate][增量加载全量短信模板]");
|
||||
|
||||
@@ -137,7 +137,7 @@ public class TenantServiceImpl implements TenantService {
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadTenantIfUpdate][首次加载全量租户]");
|
||||
} else { // 判断数据库中是否有更新的租户
|
||||
if (tenantMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) {
|
||||
if (tenantMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadTenantIfUpdate][增量加载全量租户]");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.service.user;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
@@ -13,7 +14,9 @@ import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfi
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*;
|
||||
import cn.iocoder.yudao.module.system.convert.user.UserConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.dept.UserPostMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
|
||||
import cn.iocoder.yudao.module.system.service.dept.DeptService;
|
||||
import cn.iocoder.yudao.module.system.service.dept.PostService;
|
||||
@@ -31,11 +34,12 @@ import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 后台用户 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service("adminUserService")
|
||||
@@ -59,11 +63,14 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
@Resource
|
||||
private TenantService tenantService;
|
||||
|
||||
@Resource
|
||||
private UserPostMapper userPostMapper;
|
||||
|
||||
@Resource
|
||||
private FileApi fileApi;
|
||||
|
||||
@Override
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createUser(UserCreateReqVO reqVO) {
|
||||
// 校验账户配合
|
||||
tenantService.handleTenantInfo(tenant -> {
|
||||
@@ -73,24 +80,49 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
}
|
||||
});
|
||||
// 校验正确性
|
||||
this.checkCreateOrUpdate(null, reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(),
|
||||
reqVO.getDeptId(), reqVO.getPostIds());
|
||||
checkCreateOrUpdate(null, reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(),
|
||||
reqVO.getDeptId(), reqVO.getPostIds());
|
||||
// 插入用户
|
||||
AdminUserDO user = UserConvert.INSTANCE.convert(reqVO);
|
||||
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
|
||||
user.setPassword(passwordEncoder.encode(reqVO.getPassword())); // 加密密码
|
||||
userMapper.insert(user);
|
||||
// 插入关联岗位
|
||||
if (CollectionUtil.isNotEmpty(user.getPostIds())) {
|
||||
userPostMapper.insertBatch(convertList(user.getPostIds(),
|
||||
postId -> new UserPostDO().setUserId(user.getId()).setPostId(postId)));
|
||||
}
|
||||
return user.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateUser(UserUpdateReqVO reqVO) {
|
||||
// 校验正确性
|
||||
this.checkCreateOrUpdate(reqVO.getId(), reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(),
|
||||
reqVO.getDeptId(), reqVO.getPostIds());
|
||||
checkCreateOrUpdate(reqVO.getId(), reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(),
|
||||
reqVO.getDeptId(), reqVO.getPostIds());
|
||||
// 更新用户
|
||||
AdminUserDO updateObj = UserConvert.INSTANCE.convert(reqVO);
|
||||
userMapper.updateById(updateObj);
|
||||
// 更新岗位
|
||||
updateUserPost(reqVO, updateObj);
|
||||
}
|
||||
|
||||
private void updateUserPost(UserUpdateReqVO reqVO, AdminUserDO updateObj) {
|
||||
Long userId = reqVO.getId();
|
||||
Set<Long> dbPostIds = convertSet(userPostMapper.selectListByUserId(userId), UserPostDO::getPostId);
|
||||
// 计算新增和删除的岗位编号
|
||||
Set<Long> postIds = updateObj.getPostIds();
|
||||
Collection<Long> createPostIds = CollUtil.subtract(postIds, dbPostIds);
|
||||
Collection<Long> deletePostIds = CollUtil.subtract(dbPostIds, postIds);
|
||||
// 执行新增和删除。对于已经授权的菜单,不用做任何处理
|
||||
if (!CollectionUtil.isEmpty(createPostIds)) {
|
||||
userPostMapper.insertBatch(convertList(createPostIds,
|
||||
postId -> new UserPostDO().setUserId(userId).setPostId(postId)));
|
||||
}
|
||||
if (!CollectionUtil.isEmpty(deletePostIds)) {
|
||||
userPostMapper.deleteByUserIdAndPostId(userId, deletePostIds);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,9 +133,9 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
@Override
|
||||
public void updateUserProfile(Long id, UserProfileUpdateReqVO reqVO) {
|
||||
// 校验正确性
|
||||
this.checkUserExists(id);
|
||||
this.checkEmailUnique(id, reqVO.getEmail());
|
||||
this.checkMobileUnique(id, reqVO.getMobile());
|
||||
checkUserExists(id);
|
||||
checkEmailUnique(id, reqVO.getEmail());
|
||||
checkMobileUnique(id, reqVO.getMobile());
|
||||
// 执行更新
|
||||
userMapper.updateById(UserConvert.INSTANCE.convert(reqVO).setId(id));
|
||||
}
|
||||
@@ -111,7 +143,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
@Override
|
||||
public void updateUserPassword(Long id, UserProfileUpdatePasswordReqVO reqVO) {
|
||||
// 校验旧密码密码
|
||||
this.checkOldPassword(id, reqVO.getOldPassword());
|
||||
checkOldPassword(id, reqVO.getOldPassword());
|
||||
// 执行更新
|
||||
AdminUserDO updateObj = new AdminUserDO().setId(id);
|
||||
updateObj.setPassword(passwordEncoder.encode(reqVO.getNewPassword())); // 加密密码
|
||||
@@ -120,7 +152,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
|
||||
@Override
|
||||
public String updateUserAvatar(Long id, InputStream avatarFile) throws Exception {
|
||||
this.checkUserExists(id);
|
||||
checkUserExists(id);
|
||||
// 存储文件
|
||||
String avatar = fileApi.createFile(IoUtil.readBytes(avatarFile));
|
||||
// 更新路径
|
||||
@@ -134,7 +166,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
@Override
|
||||
public void updateUserPassword(Long id, String password) {
|
||||
// 校验用户存在
|
||||
this.checkUserExists(id);
|
||||
checkUserExists(id);
|
||||
// 更新密码
|
||||
AdminUserDO updateObj = new AdminUserDO();
|
||||
updateObj.setId(id);
|
||||
@@ -145,7 +177,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
@Override
|
||||
public void updateUserStatus(Long id, Integer status) {
|
||||
// 校验用户存在
|
||||
this.checkUserExists(id);
|
||||
checkUserExists(id);
|
||||
// 更新状态
|
||||
AdminUserDO updateObj = new AdminUserDO();
|
||||
updateObj.setId(id);
|
||||
@@ -154,13 +186,16 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteUser(Long id) {
|
||||
// 校验用户存在
|
||||
this.checkUserExists(id);
|
||||
checkUserExists(id);
|
||||
// 删除用户
|
||||
userMapper.deleteById(id);
|
||||
// 删除用户关联数据
|
||||
permissionService.processUserDeleted(id);
|
||||
// 删除用户岗位
|
||||
userPostMapper.deleteByUserId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -180,7 +215,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
|
||||
@Override
|
||||
public PageResult<AdminUserDO> getUserPage(UserPageReqVO reqVO) {
|
||||
return userMapper.selectPage(reqVO, this.getDeptCondition(reqVO.getDeptId()));
|
||||
return userMapper.selectPage(reqVO, getDeptCondition(reqVO.getDeptId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -201,11 +236,11 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
if (CollUtil.isEmpty(postIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 过滤不符合条件的
|
||||
// TODO 芋艿:暂时只能内存过滤。解决方案:1、新建一个关联表;2、基于 where + 函数;3、json 字段,适合 mysql 8+ 版本
|
||||
List<AdminUserDO> users = userMapper.selectList();
|
||||
users.removeIf(user -> !CollUtil.containsAny(user.getPostIds(), postIds));
|
||||
return users;
|
||||
Set<Long> userIds = convertSet(userPostMapper.selectListByPostIds(postIds), UserPostDO::getUserId);
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return userMapper.selectBatchIds(userIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -238,7 +273,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
|
||||
@Override
|
||||
public List<AdminUserDO> getUsers(UserExportReqVO reqVO) {
|
||||
return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId()));
|
||||
return userMapper.selectList(reqVO, getDeptCondition(reqVO.getDeptId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -253,7 +288,6 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
|
||||
/**
|
||||
* 获得部门条件:查询指定部门的子部门编号们,包括自身
|
||||
*
|
||||
* @param deptId 部门编号
|
||||
* @return 部门编号集合
|
||||
*/
|
||||
@@ -261,8 +295,8 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
if (deptId == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Set<Long> deptIds = CollectionUtils.convertSet(deptService.getDeptsByParentIdFromCache(
|
||||
deptId, true), DeptDO::getId);
|
||||
Set<Long> deptIds = convertSet(deptService.getDeptsByParentIdFromCache(
|
||||
deptId, true), DeptDO::getId);
|
||||
deptIds.add(deptId); // 包括自身
|
||||
return deptIds;
|
||||
}
|
||||
@@ -270,13 +304,13 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
private void checkCreateOrUpdate(Long id, String username, String mobile, String email,
|
||||
Long deptId, Set<Long> postIds) {
|
||||
// 校验用户存在
|
||||
this.checkUserExists(id);
|
||||
checkUserExists(id);
|
||||
// 校验用户名唯一
|
||||
this.checkUsernameUnique(id, username);
|
||||
checkUsernameUnique(id, username);
|
||||
// 校验手机号唯一
|
||||
this.checkMobileUnique(id, mobile);
|
||||
checkMobileUnique(id, mobile);
|
||||
// 校验邮箱唯一
|
||||
this.checkEmailUnique(id, email);
|
||||
checkEmailUnique(id, email);
|
||||
// 校验部门处于开启状态
|
||||
deptService.validDepts(CollectionUtils.singleton(deptId));
|
||||
// 校验岗位处于开启状态
|
||||
@@ -350,7 +384,6 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
|
||||
/**
|
||||
* 校验旧密码
|
||||
*
|
||||
* @param id 用户 id
|
||||
* @param oldPassword 旧密码
|
||||
*/
|
||||
@@ -372,12 +405,12 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
throw exception(USER_IMPORT_LIST_IS_EMPTY);
|
||||
}
|
||||
UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>())
|
||||
.updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build();
|
||||
.updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build();
|
||||
importUsers.forEach(importUser -> {
|
||||
// 校验,判断是否有不符合的原因
|
||||
try {
|
||||
checkCreateOrUpdate(null, null, importUser.getMobile(), importUser.getEmail(),
|
||||
importUser.getDeptId(), null);
|
||||
importUser.getDeptId(), null);
|
||||
} catch (ServiceException ex) {
|
||||
respVO.getFailureUsernames().put(importUser.getUsername(), ex.getMessage());
|
||||
return;
|
||||
@@ -386,7 +419,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername());
|
||||
if (existUser == null) {
|
||||
userMapper.insert(UserConvert.INSTANCE.convert(importUser)
|
||||
.setPassword(passwordEncoder.encode(userInitPassword))); // 设置默认密码
|
||||
.setPassword(passwordEncoder.encode(userInitPassword))); // 设置默认密码
|
||||
respVO.getCreateUsernames().add(importUser.getUsername());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -134,6 +134,7 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
|
||||
AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
|
||||
String userIp = randomString();
|
||||
String userAgent = randomString();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_CAPTCHA_NOT_FOUND);
|
||||
// 校验调用参数
|
||||
@@ -148,10 +149,12 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
|
||||
// 准备参数
|
||||
String userIp = randomString();
|
||||
String userAgent = randomString();
|
||||
String code = randomString();
|
||||
AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
|
||||
|
||||
// mock 验证码不正确
|
||||
String code = randomString();
|
||||
when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(code);
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_CAPTCHA_CODE_ERROR);
|
||||
// 校验调用参数
|
||||
@@ -172,6 +175,7 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
|
||||
// mock 抛出异常
|
||||
when(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(reqVO.getUsername(), reqVO.getPassword())))
|
||||
.thenThrow(new BadCredentialsException("测试账号或密码不正确"));
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_BAD_CREDENTIALS);
|
||||
// 校验调用参数
|
||||
@@ -188,11 +192,13 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
|
||||
String userIp = randomString();
|
||||
String userAgent = randomString();
|
||||
AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
|
||||
|
||||
// mock 验证码正确
|
||||
when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode());
|
||||
// mock 抛出异常
|
||||
when(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(reqVO.getUsername(), reqVO.getPassword())))
|
||||
.thenThrow(new DisabledException("测试用户被禁用"));
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_USER_DISABLED);
|
||||
// 校验调用参数
|
||||
@@ -214,6 +220,7 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
|
||||
// mock 抛出异常
|
||||
when(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(reqVO.getUsername(), reqVO.getPassword())))
|
||||
.thenThrow(new AuthenticationException("测试未知异常") {});
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_FAIL_UNKNOWN);
|
||||
// 校验调用参数
|
||||
@@ -229,27 +236,29 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
|
||||
// 准备参数
|
||||
String userIp = randomString();
|
||||
String userAgent = randomString();
|
||||
AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
|
||||
|
||||
// mock 验证码正确
|
||||
when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode());
|
||||
// mock authentication
|
||||
Long userId = randomLongId();
|
||||
Set<Long> userRoleIds = randomSet(Long.class);
|
||||
String sessionId = randomString();
|
||||
AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
|
||||
LoginUser loginUser = randomPojo(LoginUser.class, o -> {
|
||||
o.setId(userId);
|
||||
o.setRoleIds(userRoleIds);
|
||||
});
|
||||
// mock 验证码正确
|
||||
when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode());
|
||||
// mock authentication
|
||||
when(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(reqVO.getUsername(), reqVO.getPassword())))
|
||||
.thenReturn(authentication);
|
||||
when(authentication.getPrincipal()).thenReturn(loginUser);
|
||||
// mock 获得 User 拥有的角色编号数组
|
||||
when(permissionService.getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus()))).thenReturn(userRoleIds);
|
||||
// mock 缓存登录用户到 Redis
|
||||
when(userSessionService.createUserSession(loginUser, userIp, userAgent)).thenReturn(sessionId);
|
||||
String token = randomString();
|
||||
when(userSessionService.createUserSession(loginUser, userIp, userAgent)).thenReturn(token);
|
||||
|
||||
// 调用, 并断言异常
|
||||
String login = authService.login(reqVO, userIp, userAgent);
|
||||
assertEquals(sessionId, login);
|
||||
assertEquals(token, login);
|
||||
// 校验调用参数
|
||||
verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid());
|
||||
verify(loginLogService, times(1)).createLoginLog(
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
package cn.iocoder.yudao.module.system.service.auth;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.auth.UserSessionMapper;
|
||||
import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
|
||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO;
|
||||
import cn.iocoder.yudao.module.system.dal.redis.auth.LoginUserRedisDAO;
|
||||
import cn.iocoder.yudao.module.system.enums.common.SexEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.auth.UserSessionMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.redis.auth.LoginUserRedisDAO;
|
||||
import cn.iocoder.yudao.module.system.enums.common.SexEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
|
||||
import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
|
||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.Duration;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.Calendar;
|
||||
|
||||
import static cn.hutool.core.util.RandomUtil.randomEle;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;
|
||||
@@ -33,8 +33,9 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
@@ -61,6 +62,11 @@ public class UserSessionServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||
@MockBean
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUserSessionPage_success() {
|
||||
// mock 数据
|
||||
@@ -78,15 +84,9 @@ public class UserSessionServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||
});
|
||||
userSessionMapper.insert(dbSession);
|
||||
// 测试 username 不匹配
|
||||
userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> {
|
||||
o.setId(randomString());
|
||||
o.setUserId(123456L);
|
||||
}));
|
||||
userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> o.setUserId(123456L)));
|
||||
// 测试 userIp 不匹配
|
||||
userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> {
|
||||
o.setId(randomString());
|
||||
o.setUserIp("testUserIp");
|
||||
}));
|
||||
userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> o.setUserIp("testUserIp")));
|
||||
// 准备参数
|
||||
UserSessionPageReqVO reqVO = new UserSessionPageReqVO();
|
||||
reqVO.setUsername(dbUser.getUsername());
|
||||
@@ -100,35 +100,60 @@ public class UserSessionServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||
assertPojoEquals(dbSession, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
// TODO 芋艿:单测写的有问题
|
||||
@Test
|
||||
public void testClearSessionTimeout_none() {
|
||||
// mock db 数据
|
||||
UserSessionDO userSession = randomPojo(UserSessionDO.class, o -> {
|
||||
o.setUserType(randomEle(UserTypeEnum.values()).getValue());
|
||||
o.setSessionTimeout(addTime(Duration.ofDays(1)));
|
||||
});
|
||||
userSessionMapper.insert(userSession);
|
||||
|
||||
// 调用
|
||||
long count = userSessionService.deleteTimeoutSession();
|
||||
// 断言
|
||||
assertEquals(0, count);
|
||||
assertPojoEquals(userSession, userSessionMapper.selectById(userSession.getId())); // 未删除
|
||||
}
|
||||
|
||||
@Test // Redis 还存在的情况
|
||||
public void testClearSessionTimeout_exists() {
|
||||
// mock db 数据
|
||||
UserSessionDO userSession = randomPojo(UserSessionDO.class, o -> {
|
||||
o.setUserType(randomEle(UserTypeEnum.values()).getValue());
|
||||
o.setSessionTimeout(DateUtils.addDate(Calendar.DAY_OF_YEAR, -1));
|
||||
});
|
||||
userSessionMapper.insert(userSession);
|
||||
// mock redis 数据
|
||||
loginUserRedisDAO.set(userSession.getToken(), new LoginUser());
|
||||
|
||||
// 调用
|
||||
long count = userSessionService.deleteTimeoutSession();
|
||||
// 断言
|
||||
assertEquals(0, count);
|
||||
assertPojoEquals(userSession, userSessionMapper.selectById(userSession.getId())); // 未删除
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearSessionTimeout_success() {
|
||||
// 准备超时数据 120 条, 在线用户 1 条
|
||||
int expectedTimeoutCount = 120, expectedTotal = 1;
|
||||
|
||||
// 准备数据
|
||||
List<UserSessionDO> prepareData = Stream
|
||||
.iterate(0, i -> i)
|
||||
.limit(expectedTimeoutCount)
|
||||
.map(i -> randomPojo(UserSessionDO.class, o -> {
|
||||
o.setUserType(randomEle(UserTypeEnum.values()).getValue());
|
||||
o.setSessionTimeout(DateUtil.offsetSecond(new Date(), -1));
|
||||
}))
|
||||
.collect(Collectors.toList());
|
||||
UserSessionDO sessionDO = randomPojo(UserSessionDO.class, o -> {
|
||||
// mock db 数据
|
||||
UserSessionDO userSession = randomPojo(UserSessionDO.class, o -> {
|
||||
o.setUserType(randomEle(UserTypeEnum.values()).getValue());
|
||||
o.setSessionTimeout(DateUtil.offsetMinute(new Date(), 30));
|
||||
o.setSessionTimeout(DateUtils.addDate(Calendar.DAY_OF_YEAR, -1));
|
||||
});
|
||||
prepareData.add(sessionDO);
|
||||
prepareData.forEach(userSessionMapper::insert);
|
||||
userSessionMapper.insert(userSession);
|
||||
|
||||
// 清空超时数据
|
||||
long actualTimeoutCount = userSessionService.clearSessionTimeout();
|
||||
long count = userSessionService.deleteTimeoutSession();
|
||||
// 校验
|
||||
assertEquals(expectedTimeoutCount, actualTimeoutCount);
|
||||
List<UserSessionDO> userSessionDOS = userSessionMapper.selectList();
|
||||
assertEquals(expectedTotal, userSessionDOS.size());
|
||||
assertPojoEquals(sessionDO, userSessionDOS.get(0), "updateTime");
|
||||
assertEquals(1, count);
|
||||
assertNull(userSessionMapper.selectById(userSession.getId())); // 已删除
|
||||
verify(loginLogService).createLoginLog(argThat(loginLog -> {
|
||||
assertPojoEquals(userSession, loginLog);
|
||||
assertEquals(LoginLogTypeEnum.LOGOUT_TIMEOUT.getType(), loginLog.getLogType());
|
||||
assertEquals(LoginResultEnum.SUCCESS.getResult(), loginLog.getResult());
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -140,80 +165,86 @@ public class UserSessionServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||
o.setUserType(randomEle(UserTypeEnum.values()).getValue());
|
||||
o.setTenantId(0L); // 租户设置为 0,因为暂未启用多租户组件
|
||||
});
|
||||
// mock 方法
|
||||
when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1));
|
||||
|
||||
// 调用
|
||||
String sessionId = userSessionService.createUserSession(loginUser, userIp, userAgent);
|
||||
String token = userSessionService.createUserSession(loginUser, userIp, userAgent);
|
||||
// 校验 UserSessionDO 记录
|
||||
UserSessionDO userSessionDO = userSessionMapper.selectById(sessionId);
|
||||
UserSessionDO userSessionDO = userSessionMapper.selectOne(UserSessionDO::getToken, token);
|
||||
assertPojoEquals(loginUser, userSessionDO, "id", "updateTime");
|
||||
assertEquals(sessionId, userSessionDO.getId());
|
||||
assertEquals(token, userSessionDO.getToken());
|
||||
assertEquals(userIp, userSessionDO.getUserIp());
|
||||
assertEquals(userAgent, userSessionDO.getUserAgent());
|
||||
// 校验 LoginUser 缓存
|
||||
LoginUser redisLoginUser = loginUserRedisDAO.get(sessionId);
|
||||
LoginUser redisLoginUser = loginUserRedisDAO.get(token);
|
||||
assertPojoEquals(loginUser, redisLoginUser, "username", "password");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRefreshUserSession_success() {
|
||||
public void testCreateRefreshUserSession() {
|
||||
// 准备参数
|
||||
String sessionId = randomString();
|
||||
String userIp = randomString();
|
||||
String userAgent = randomString();
|
||||
long timeLong = randomLongId();
|
||||
String userName = randomString();
|
||||
Date date = randomDate();
|
||||
String token = randomString();
|
||||
|
||||
// mock redis 数据
|
||||
LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setUserType(randomEle(UserTypeEnum.values()).getValue()));
|
||||
// mock 方法
|
||||
when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1));
|
||||
// mock 数据
|
||||
loginUser.setUpdateTime(date);
|
||||
loginUserRedisDAO.set(sessionId, loginUser);
|
||||
UserSessionDO userSession = UserSessionDO.builder().id(sessionId)
|
||||
.userId(loginUser.getId()).userType(loginUser.getUserType())
|
||||
.userIp(userIp).userAgent(userAgent).username(userName)
|
||||
.sessionTimeout(addTime(Duration.ofMillis(timeLong)))
|
||||
.build();
|
||||
loginUserRedisDAO.set(token, loginUser);
|
||||
// mock db 数据
|
||||
UserSessionDO userSession = randomPojo(UserSessionDO.class, o -> {
|
||||
o.setUserType(randomEle(UserTypeEnum.values()).getValue());
|
||||
o.setToken(token);
|
||||
});
|
||||
userSessionMapper.insert(userSession);
|
||||
|
||||
// 调用
|
||||
userSessionService.refreshUserSession(sessionId, loginUser);
|
||||
userSessionService.refreshUserSession(token, loginUser);
|
||||
// 校验 LoginUser 缓存
|
||||
LoginUser redisLoginUser = loginUserRedisDAO.get(sessionId);
|
||||
assertNotEquals(redisLoginUser.getUpdateTime(), date);
|
||||
LoginUser redisLoginUser = loginUserRedisDAO.get(token);
|
||||
assertPojoEquals(redisLoginUser, loginUser, "username", "password");
|
||||
// 校验 UserSessionDO 记录
|
||||
UserSessionDO updateDO = userSessionMapper.selectById(sessionId);
|
||||
UserSessionDO updateDO = userSessionMapper.selectOne(UserSessionDO::getToken, token);
|
||||
assertEquals(updateDO.getUsername(), loginUser.getUsername());
|
||||
assertNotEquals(updateDO.getUpdateTime(), userSession.getUpdateTime());
|
||||
assertNotEquals(updateDO.getSessionTimeout(), addTime(Duration.ofMillis(timeLong)));
|
||||
assertNotNull(userSession.getUpdateTime());
|
||||
assertNotNull(userSession.getSessionTimeout());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteUserSession_success() {
|
||||
public void testDeleteUserSession_Token() {
|
||||
// 准备参数
|
||||
String sessionId = randomString();
|
||||
String userIp = randomString();
|
||||
String userAgent = randomString();
|
||||
Long timeLong = randomLongId();
|
||||
LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setUserType(randomEle(UserTypeEnum.values()).getValue()));
|
||||
// mock 存入 Redis
|
||||
when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1));
|
||||
// mock 数据
|
||||
loginUserRedisDAO.set(sessionId, loginUser);
|
||||
UserSessionDO userSession = UserSessionDO.builder().id(sessionId)
|
||||
.userId(loginUser.getId()).userType(loginUser.getUserType())
|
||||
.userIp(userIp).userAgent(userAgent).username(loginUser.getUsername())
|
||||
.sessionTimeout(addTime(Duration.ofMillis(timeLong)))
|
||||
.build();
|
||||
String token = randomString();
|
||||
|
||||
// mock redis 数据
|
||||
loginUserRedisDAO.set(token, new LoginUser());
|
||||
// mock db 数据
|
||||
UserSessionDO userSession = randomPojo(UserSessionDO.class, o -> {
|
||||
o.setUserType(randomEle(UserTypeEnum.values()).getValue());
|
||||
o.setToken(token);
|
||||
});
|
||||
userSessionMapper.insert(userSession);
|
||||
|
||||
// 调用
|
||||
userSessionService.deleteUserSession(sessionId);
|
||||
userSessionService.deleteUserSession(token);
|
||||
// 校验数据不存在了
|
||||
assertNull(loginUserRedisDAO.get(sessionId));
|
||||
assertNull(userSessionMapper.selectById(sessionId));
|
||||
assertNull(loginUserRedisDAO.get(token));
|
||||
assertNull(userSessionMapper.selectOne(UserSessionDO::getToken, token));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteUserSession_Id() {
|
||||
// mock db 数据
|
||||
UserSessionDO userSession = randomPojo(UserSessionDO.class, o -> {
|
||||
o.setUserType(randomEle(UserTypeEnum.values()).getValue());
|
||||
});
|
||||
userSessionMapper.insert(userSession);
|
||||
// mock redis 数据
|
||||
loginUserRedisDAO.set(userSession.getToken(), new LoginUser());
|
||||
|
||||
// 准备参数
|
||||
Long id = userSession.getId();
|
||||
|
||||
// 调用
|
||||
userSessionService.deleteUserSession(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(loginUserRedisDAO.get(userSession.getToken()));
|
||||
assertNull(userSessionMapper.selectById(id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,21 +7,23 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*;
|
||||
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.dept.UserPostDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.dept.UserPostMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
|
||||
import cn.iocoder.yudao.module.system.enums.common.SexEnum;
|
||||
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.permission.PermissionService;
|
||||
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
@@ -30,16 +32,19 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static cn.hutool.core.util.RandomUtil.randomBytes;
|
||||
import static cn.hutool.core.util.RandomUtil.randomEle;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||
import static java.util.Collections.singleton;
|
||||
import static org.assertj.core.util.Lists.newArrayList;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
@@ -47,13 +52,15 @@ import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@Import(AdminUserServiceImpl.class)
|
||||
public class UserServiceImplTest extends BaseDbUnitTest {
|
||||
public class AdminUserServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private AdminUserServiceImpl userService;
|
||||
|
||||
@Resource
|
||||
private AdminUserMapper userMapper;
|
||||
@Resource
|
||||
private UserPostMapper userPostMapper;
|
||||
|
||||
@MockBean
|
||||
private DeptService deptService;
|
||||
@@ -74,6 +81,7 @@ public class UserServiceImplTest extends BaseDbUnitTest {
|
||||
UserCreateReqVO reqVO = randomPojo(UserCreateReqVO.class, o -> {
|
||||
o.setSex(RandomUtil.randomEle(SexEnum.values()).getSex());
|
||||
o.setMobile(randomString());
|
||||
o.setPostIds(asSet(1L, 2L));
|
||||
});
|
||||
// mock 账户额度充足
|
||||
TenantDO tenant = randomPojo(TenantDO.class, o -> o.setAccountCount(1));
|
||||
@@ -104,6 +112,10 @@ public class UserServiceImplTest extends BaseDbUnitTest {
|
||||
assertPojoEquals(reqVO, user, "password");
|
||||
assertEquals("yudaoyuanma", user.getPassword());
|
||||
assertEquals(CommonStatusEnum.ENABLE.getStatus(), user.getStatus());
|
||||
// 断言关联岗位
|
||||
List<UserPostDO> userPosts = userPostMapper.selectListByUserId(user.getId());
|
||||
assertEquals(1L, userPosts.get(0).getPostId());
|
||||
assertEquals(2L, userPosts.get(1).getPostId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -124,13 +136,16 @@ public class UserServiceImplTest extends BaseDbUnitTest {
|
||||
@Test
|
||||
public void testUpdateUser_success() {
|
||||
// mock 数据
|
||||
AdminUserDO dbUser = randomAdminUserDO();
|
||||
AdminUserDO dbUser = randomAdminUserDO(o -> o.setPostIds(asSet(1L, 2L)));
|
||||
userMapper.insert(dbUser);
|
||||
userPostMapper.insert(new UserPostDO().setUserId(dbUser.getId()).setPostId(1L));
|
||||
userPostMapper.insert(new UserPostDO().setUserId(dbUser.getId()).setPostId(2L));
|
||||
// 准备参数
|
||||
UserUpdateReqVO reqVO = randomPojo(UserUpdateReqVO.class, o -> {
|
||||
o.setId(dbUser.getId());
|
||||
o.setSex(RandomUtil.randomEle(SexEnum.values()).getSex());
|
||||
o.setMobile(randomString());
|
||||
o.setPostIds(asSet(2L, 3L));
|
||||
});
|
||||
// mock deptService 的方法
|
||||
DeptDO dept = randomPojo(DeptDO.class, o -> {
|
||||
@@ -151,6 +166,10 @@ public class UserServiceImplTest extends BaseDbUnitTest {
|
||||
// 断言
|
||||
AdminUserDO user = userMapper.selectById(reqVO.getId());
|
||||
assertPojoEquals(reqVO, user);
|
||||
// 断言关联岗位
|
||||
List<UserPostDO> userPosts = userPostMapper.selectListByUserId(user.getId());
|
||||
assertEquals(2L, userPosts.get(0).getPostId());
|
||||
assertEquals(3L, userPosts.get(1).getPostId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -552,22 +571,26 @@ public class UserServiceImplTest extends BaseDbUnitTest {
|
||||
verify(passwordEncoder, times(1)).matches(eq(oldPassword), eq(user.getPassword()));
|
||||
}
|
||||
|
||||
// @Test //TODO jason 已经移到userCoreService.getUsersByPostIds
|
||||
// public void testUsersByPostIds() {
|
||||
// // 准备参数
|
||||
// Collection<Long> postIds = asSet(10L, 20L);
|
||||
// // mock 方法
|
||||
// AdminUserDO user1 = randomAdminUserDO(o -> o.setPostIds(asSet(10L, 30L)));
|
||||
// userMapper.insert(user1);
|
||||
// AdminUserDO user2 = randomAdminUserDO(o -> o.setPostIds(singleton(100L)));
|
||||
// userMapper.insert(user2);
|
||||
//
|
||||
// // 调用
|
||||
// List<AdminUserDO> result = userService.getUsersByPostIds(postIds);
|
||||
// // 断言
|
||||
// assertEquals(1, result.size());
|
||||
// assertEquals(user1, result.get(0));
|
||||
// }
|
||||
@Test
|
||||
public void testUsersByPostIds() {
|
||||
// 准备参数
|
||||
Collection<Long> postIds = asSet(10L, 20L);
|
||||
// mock user1 数据
|
||||
AdminUserDO user1 = randomAdminUserDO(o -> o.setPostIds(asSet(10L, 30L)));
|
||||
userMapper.insert(user1);
|
||||
userPostMapper.insert(new UserPostDO().setUserId(user1.getId()).setPostId(10L));
|
||||
userPostMapper.insert(new UserPostDO().setUserId(user1.getId()).setPostId(30L));
|
||||
// mock user2 数据
|
||||
AdminUserDO user2 = randomAdminUserDO(o -> o.setPostIds(singleton(100L)));
|
||||
userMapper.insert(user2);
|
||||
userPostMapper.insert(new UserPostDO().setUserId(user2.getId()).setPostId(100L));
|
||||
|
||||
// 调用
|
||||
List<AdminUserDO> result = userService.getUsersByPostIds(postIds);
|
||||
// 断言
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(user1, result.get(0));
|
||||
}
|
||||
|
||||
// ========== 随机对象 ==========
|
||||
|
||||
@@ -4,12 +4,13 @@ DELETE FROM "system_role";
|
||||
DELETE FROM "system_role_menu";
|
||||
DELETE FROM "system_menu";
|
||||
DELETE FROM "system_user_role";
|
||||
DELETE FROM "system_user_post";
|
||||
DELETE FROM "system_dict_type";
|
||||
DELETE FROM "system_user_session";
|
||||
DELETE FROM "system_post";
|
||||
DELETE FROM "system_login_log";
|
||||
DELETE FROM "system_operate_log";
|
||||
DELETE FROM "system_user";
|
||||
DELETE FROM "system_users";
|
||||
DELETE FROM "system_sms_channel";
|
||||
DELETE FROM "system_sms_template";
|
||||
DELETE FROM "system_sms_log";
|
||||
|
||||
@@ -78,7 +78,7 @@ CREATE TABLE IF NOT EXISTS "system_menu" (
|
||||
"component" varchar(255) DEFAULT NULL,
|
||||
"status" tinyint NOT NULL DEFAULT '0',
|
||||
"visible" bit NOT NULL DEFAULT TRUE,
|
||||
"hidden" bit NOT NULL DEFAULT TRUE,
|
||||
"keep_alive" bit NOT NULL DEFAULT TRUE,
|
||||
"creator" varchar(64) DEFAULT '',
|
||||
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updater" varchar(64) DEFAULT '',
|
||||
@@ -115,7 +115,8 @@ CREATE TABLE IF NOT EXISTS "system_dict_type" (
|
||||
) COMMENT '字典类型表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `system_user_session` (
|
||||
`id` varchar(32) NOT NULL,
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
`token` varchar(32) NOT NULL,
|
||||
`user_id` bigint DEFAULT NULL,
|
||||
"user_type" tinyint NOT NULL,
|
||||
`username` varchar(50) NOT NULL DEFAULT '',
|
||||
@@ -147,11 +148,25 @@ CREATE TABLE IF NOT EXISTS "system_post" (
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '岗位信息表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `system_user_post`(
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"user_id" bigint DEFAULT NULL,
|
||||
"post_id" bigint DEFAULT NULL,
|
||||
"creator" varchar(64) DEFAULT '',
|
||||
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updater" varchar(64) DEFAULT '',
|
||||
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||
"tenant_id" bigint not null default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) COMMENT ='用户岗位表';
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "system_notice" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"title" varchar(50) NOT NULL COMMENT '公告标题',
|
||||
"content" text NOT NULL COMMENT '公告内容',
|
||||
"notice_type" tinyint NOT NULL COMMENT '公告类型(1通知 2公告)',
|
||||
"type" tinyint NOT NULL COMMENT '公告类型(1通知 2公告)',
|
||||
"status" tinyint NOT NULL DEFAULT '0' COMMENT '公告状态(0正常 1关闭)',
|
||||
"creator" varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
@@ -210,7 +225,7 @@ CREATE TABLE IF NOT EXISTS `system_operate_log` (
|
||||
PRIMARY KEY (`id`)
|
||||
) COMMENT ='操作日志记录';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "system_user" (
|
||||
CREATE TABLE IF NOT EXISTS "system_users" (
|
||||
"id" bigint not null GENERATED BY DEFAULT AS IDENTITY,
|
||||
"username" varchar(30) not null,
|
||||
"password" varchar(100) not null default '',
|
||||
|
||||
Reference in New Issue
Block a user