Commit 5b723d02b23f7be2dd78760892af19228ad85e01

Authored by YunaiV
1 parent e999cc31

增加 yudao-core-service 模块,提供共享逻辑

Showing 50 changed files with 761 additions and 408 deletions
@@ -12,6 +12,7 @@ @@ -12,6 +12,7 @@
12 <module>yudao-framework</module> 12 <module>yudao-framework</module>
13 <module>yudao-admin-server</module> 13 <module>yudao-admin-server</module>
14 <module>yudao-user-server</module> 14 <module>yudao-user-server</module>
  15 + <module>yudao-core-service</module>
15 </modules> 16 </modules>
16 17
17 <name>${artifactId}</name> 18 <name>${artifactId}</name>
yudao-admin-server/pom.xml
@@ -20,6 +20,11 @@ @@ -20,6 +20,11 @@
20 <!-- 业务组件 --> 20 <!-- 业务组件 -->
21 <dependency> 21 <dependency>
22 <groupId>cn.iocoder.boot</groupId> 22 <groupId>cn.iocoder.boot</groupId>
  23 + <artifactId>yudao-core-service</artifactId>
  24 + </dependency>
  25 +
  26 + <dependency>
  27 + <groupId>cn.iocoder.boot</groupId>
23 <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId> 28 <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
24 </dependency> 29 </dependency>
25 <dependency> 30 <dependency>
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/AdminServerApplication.java
@@ -3,7 +3,8 @@ package cn.iocoder.yudao.adminserver; @@ -3,7 +3,8 @@ package cn.iocoder.yudao.adminserver;
3 import org.springframework.boot.SpringApplication; 3 import org.springframework.boot.SpringApplication;
4 import org.springframework.boot.autoconfigure.SpringBootApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
5 5
6 -@SpringBootApplication 6 +@SuppressWarnings("SpringComponentScan") // 忽略 IDEA 无法识别 ${yudao.info.base-package} 和 ${yudao.core-service.base-package}
  7 +@SpringBootApplication(scanBasePackages = {"${yudao.info.base-package}", "${yudao.core-service.base-package}"})
7 public class AdminServerApplication { 8 public class AdminServerApplication {
8 9
9 public static void main(String[] args) { 10 public static void main(String[] args) {
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysUserSessionController.java
1 package cn.iocoder.yudao.adminserver.modules.system.controller.auth; 1 package cn.iocoder.yudao.adminserver.modules.system.controller.auth;
2 2
  3 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO;
  4 +import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageItemRespVO; 7 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageItemRespVO;
6 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; 8 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
7 import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysUserSessionConvert; 9 import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysUserSessionConvert;
8 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.auth.SysUserSessionDO;  
9 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; 10 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
10 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; 11 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;
11 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; 12 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;
@@ -35,6 +36,8 @@ public class SysUserSessionController { @@ -35,6 +36,8 @@ public class SysUserSessionController {
35 @Resource 36 @Resource
36 private SysUserSessionService userSessionService; 37 private SysUserSessionService userSessionService;
37 @Resource 38 @Resource
  39 + private SysUserSessionCoreService userSessionCoreService;
  40 + @Resource
38 private SysUserService userService; 41 private SysUserService userService;
39 @Resource 42 @Resource
40 private SysDeptService deptService; 43 private SysDeptService deptService;
@@ -72,7 +75,7 @@ public class SysUserSessionController { @@ -72,7 +75,7 @@ public class SysUserSessionController {
72 example = "fe50b9f6-d177-44b1-8da9-72ea34f63db7") 75 example = "fe50b9f6-d177-44b1-8da9-72ea34f63db7")
73 @PreAuthorize("@ss.hasPermission('system:user-session:delete')") 76 @PreAuthorize("@ss.hasPermission('system:user-session:delete')")
74 public CommonResult<Boolean> deleteUserSession(@RequestParam("id") String id) { 77 public CommonResult<Boolean> deleteUserSession(@RequestParam("id") String id) {
75 - userSessionService.deleteUserSession(id); 78 + userSessionCoreService.deleteUserSession(id);
76 return success(true); 79 return success(true);
77 } 80 }
78 81
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysAuthConvert.java
@@ -10,6 +10,7 @@ import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.Sys @@ -10,6 +10,7 @@ import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.Sys
10 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; 10 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
11 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; 11 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;
12 import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuIdEnum; 12 import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuIdEnum;
  13 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
13 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 14 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
14 import cn.iocoder.yudao.framework.security.core.LoginUser; 15 import cn.iocoder.yudao.framework.security.core.LoginUser;
15 import me.zhyd.oauth.model.AuthCallback; 16 import me.zhyd.oauth.model.AuthCallback;
@@ -27,7 +28,12 @@ public interface SysAuthConvert { @@ -27,7 +28,12 @@ public interface SysAuthConvert {
27 28
28 @Mapping(source = "updateTime", target = "updateTime", ignore = true) 29 @Mapping(source = "updateTime", target = "updateTime", ignore = true)
29 // 字段相同,但是含义不同,忽略 30 // 字段相同,但是含义不同,忽略
30 - LoginUser convert(SysUserDO bean); 31 + LoginUser convert0(SysUserDO bean);
  32 +
  33 + default LoginUser convert(SysUserDO bean) {
  34 + // 目的,为了设置 UserTypeEnum.ADMIN.getValue()
  35 + return convert0(bean).setUserType(UserTypeEnum.ADMIN.getValue());
  36 + }
31 37
32 default SysAuthPermissionInfoRespVO convert(SysUserDO user, List<SysRoleDO> roleList, List<SysMenuDO> menuList) { 38 default SysAuthPermissionInfoRespVO convert(SysUserDO user, List<SysRoleDO> roleList, List<SysMenuDO> menuList) {
33 return SysAuthPermissionInfoRespVO.builder() 39 return SysAuthPermissionInfoRespVO.builder()
@@ -39,10 +45,6 @@ public interface SysAuthConvert { @@ -39,10 +45,6 @@ public interface SysAuthConvert {
39 45
40 SysAuthMenuRespVO convertTreeNode(SysMenuDO menu); 46 SysAuthMenuRespVO convertTreeNode(SysMenuDO menu);
41 47
42 - LoginUser convert(SysUserProfileUpdateReqVO reqVO);  
43 -  
44 - LoginUser convert(SysUserProfileUpdatePasswordReqVO reqVO);  
45 -  
46 /** 48 /**
47 * 将菜单列表,构建成菜单树 49 * 将菜单列表,构建成菜单树
48 * 50 *
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysUserSessionConvert.java
1 package cn.iocoder.yudao.adminserver.modules.system.convert.auth; 1 package cn.iocoder.yudao.adminserver.modules.system.convert.auth;
2 2
3 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageItemRespVO; 3 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageItemRespVO;
4 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.auth.SysUserSessionDO; 4 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO;
5 import org.mapstruct.Mapper; 5 import org.mapstruct.Mapper;
6 import org.mapstruct.factory.Mappers; 6 import org.mapstruct.factory.Mappers;
7 7
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/auth/SysUserSessionMapper.java
1 package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.auth; 1 package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.auth;
2 2
  3 +import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
  4 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; 7 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
6 -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;  
7 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.auth.SysUserSessionDO;  
8 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
9 9
10 import java.util.Collection; 10 import java.util.Collection;
@@ -23,4 +23,5 @@ public interface SysUserSessionMapper extends BaseMapperX&lt;SysUserSessionDO&gt; { @@ -23,4 +23,5 @@ public interface SysUserSessionMapper extends BaseMapperX&lt;SysUserSessionDO&gt; {
23 default List<SysUserSessionDO> selectListBySessionTimoutLt() { 23 default List<SysUserSessionDO> selectListBySessionTimoutLt() {
24 return selectList(new QueryWrapperX<SysUserSessionDO>().lt("session_timeout",new Date())); 24 return selectList(new QueryWrapperX<SysUserSessionDO>().lt("session_timeout",new Date()));
25 } 25 }
  26 +
26 } 27 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/RedisKeyConstants.java deleted
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/SysRedisKeyConstants.java
@@ -15,10 +15,6 @@ import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.S @@ -15,10 +15,6 @@ import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.S
15 */ 15 */
16 public interface SysRedisKeyConstants { 16 public interface SysRedisKeyConstants {
17 17
18 - RedisKeyDefine LOGIN_USER = new RedisKeyDefine("登录用户的缓存",  
19 - "login_user:%s", // 参数为 sessionId  
20 - STRING, LoginUser.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);  
21 -  
22 RedisKeyDefine CAPTCHA_CODE = new RedisKeyDefine("验证码的缓存", 18 RedisKeyDefine CAPTCHA_CODE = new RedisKeyDefine("验证码的缓存",
23 "captcha_code:%s", // 参数为 uuid 19 "captcha_code:%s", // 参数为 uuid
24 STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); 20 STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionService.java
1 package cn.iocoder.yudao.adminserver.modules.system.service.auth; 1 package cn.iocoder.yudao.adminserver.modules.system.service.auth;
2 2
3 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
4 -import cn.iocoder.yudao.framework.security.core.LoginUser;  
5 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; 3 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
6 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.auth.SysUserSessionDO; 4 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 6
8 /** 7 /**
9 * 在线用户 Session Service 接口 8 * 在线用户 Session Service 接口
@@ -13,46 +12,6 @@ import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.auth.SysUserSe @@ -13,46 +12,6 @@ import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.auth.SysUserSe
13 public interface SysUserSessionService { 12 public interface SysUserSessionService {
14 13
15 /** 14 /**
16 - * 创建在线用户 Session  
17 - *  
18 - * @param loginUser 登录用户  
19 - * @param userIp 用户 IP  
20 - * @param userAgent 用户 UA  
21 - * @return Session 编号  
22 - */  
23 - String createUserSession(LoginUser loginUser, String userIp, String userAgent);  
24 -  
25 - /**  
26 - * 刷新在线用户 Session 的更新时间  
27 - *  
28 - * @param sessionId Session 编号  
29 - * @param loginUser 登录用户  
30 - */  
31 - void refreshUserSession(String sessionId, LoginUser loginUser);  
32 -  
33 - /**  
34 - * 删除在线用户 Session  
35 - *  
36 - * @param sessionId Session 编号  
37 - */  
38 - void deleteUserSession(String sessionId);  
39 -  
40 - /**  
41 - * 获得 Session 编号对应的在线用户  
42 - *  
43 - * @param sessionId Session 编号  
44 - * @return 在线用户  
45 - */  
46 - LoginUser getLoginUser(String sessionId);  
47 -  
48 - /**  
49 - * 获得 Session 超时时间,单位:毫秒  
50 - *  
51 - * @return 超时时间  
52 - */  
53 - Long getSessionTimeoutMillis();  
54 -  
55 - /**  
56 * 获得在线用户分页列表 15 * 获得在线用户分页列表
57 * 16 *
58 * @param reqVO 分页条件 17 * @param reqVO 分页条件
@@ -66,4 +25,5 @@ public interface SysUserSessionService { @@ -66,4 +25,5 @@ public interface SysUserSessionService {
66 * @return {@link Long } 移出的超时用户数量 25 * @return {@link Long } 移出的超时用户数量
67 **/ 26 **/
68 long clearSessionTimeout(); 27 long clearSessionTimeout();
  28 +
69 } 29 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
@@ -11,13 +11,13 @@ import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO @@ -11,13 +11,13 @@ import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO
11 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum; 11 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum;
12 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum; 12 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
13 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService; 13 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
14 -import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;  
15 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService; 14 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService;
16 import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService; 15 import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
17 import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO; 16 import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
18 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; 17 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
19 import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService; 18 import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;
20 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; 19 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
  20 +import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
21 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 21 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
22 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; 22 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
23 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; 23 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
@@ -67,7 +67,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -67,7 +67,7 @@ public class SysAuthServiceImpl implements SysAuthService {
67 @Resource 67 @Resource
68 private SysLoginLogService loginLogService; 68 private SysLoginLogService loginLogService;
69 @Resource 69 @Resource
70 - private SysUserSessionService userSessionService; 70 + private SysUserSessionCoreService userSessionCoreService;
71 @Resource 71 @Resource
72 private SysSocialService socialService; 72 private SysSocialService socialService;
73 73
@@ -107,7 +107,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -107,7 +107,7 @@ public class SysAuthServiceImpl implements SysAuthService {
107 loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表 107 loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
108 108
109 // 缓存登录用户到 Redis 中,返回 sessionId 编号 109 // 缓存登录用户到 Redis 中,返回 sessionId 编号
110 - return userSessionService.createUserSession(loginUser, userIp, userAgent); 110 + return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
111 } 111 }
112 112
113 private void verifyCaptcha(String username, String captchaUUID, String captchaCode) { 113 private void verifyCaptcha(String username, String captchaUUID, String captchaCode) {
@@ -214,7 +214,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -214,7 +214,7 @@ public class SysAuthServiceImpl implements SysAuthService {
214 socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser); 214 socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser);
215 215
216 // 缓存登录用户到 Redis 中,返回 sessionId 编号 216 // 缓存登录用户到 Redis 中,返回 sessionId 编号
217 - return userSessionService.createUserSession(loginUser, userIp, userAgent); 217 + return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
218 } 218 }
219 219
220 @Override 220 @Override
@@ -231,7 +231,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -231,7 +231,7 @@ public class SysAuthServiceImpl implements SysAuthService {
231 socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser); 231 socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser);
232 232
233 // 缓存登录用户到 Redis 中,返回 sessionId 编号 233 // 缓存登录用户到 Redis 中,返回 sessionId 编号
234 - return userSessionService.createUserSession(loginUser, userIp, userAgent); 234 + return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
235 } 235 }
236 236
237 @Override 237 @Override
@@ -247,12 +247,12 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -247,12 +247,12 @@ public class SysAuthServiceImpl implements SysAuthService {
247 @Override 247 @Override
248 public void logout(String token) { 248 public void logout(String token) {
249 // 查询用户信息 249 // 查询用户信息
250 - LoginUser loginUser = userSessionService.getLoginUser(token); 250 + LoginUser loginUser = userSessionCoreService.getLoginUser(token);
251 if (loginUser == null) { 251 if (loginUser == null) {
252 return; 252 return;
253 } 253 }
254 // 删除 session 254 // 删除 session
255 - userSessionService.deleteUserSession(token); 255 + userSessionCoreService.deleteUserSession(token);
256 // 记录登出日子和 256 // 记录登出日子和
257 this.createLogoutLog(loginUser.getUsername()); 257 this.createLogoutLog(loginUser.getUsername());
258 } 258 }
@@ -271,7 +271,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -271,7 +271,7 @@ public class SysAuthServiceImpl implements SysAuthService {
271 @Override 271 @Override
272 public LoginUser verifyTokenAndRefresh(String token) { 272 public LoginUser verifyTokenAndRefresh(String token) {
273 // 获得 LoginUser 273 // 获得 LoginUser
274 - LoginUser loginUser = userSessionService.getLoginUser(token); 274 + LoginUser loginUser = userSessionCoreService.getLoginUser(token);
275 if (loginUser == null) { 275 if (loginUser == null) {
276 return null; 276 return null;
277 } 277 }
@@ -283,7 +283,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -283,7 +283,7 @@ public class SysAuthServiceImpl implements SysAuthService {
283 private void refreshLoginUserCache(String token, LoginUser loginUser) { 283 private void refreshLoginUserCache(String token, LoginUser loginUser) {
284 // 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存 284 // 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存
285 if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() < 285 if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() <
286 - userSessionService.getSessionTimeoutMillis() / 3) { 286 + userSessionCoreService.getSessionTimeoutMillis() / 3) {
287 return; 287 return;
288 } 288 }
289 289
@@ -296,7 +296,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -296,7 +296,7 @@ public class SysAuthServiceImpl implements SysAuthService {
296 // 刷新 LoginUser 缓存 296 // 刷新 LoginUser 缓存
297 loginUser.setDeptId(user.getDeptId()); 297 loginUser.setDeptId(user.getDeptId());
298 loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); 298 loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId()));
299 - userSessionService.refreshUserSession(token, loginUser); 299 + userSessionCoreService.refreshUserSession(token, loginUser);
300 } 300 }
301 301
302 } 302 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysUserSessionServiceImpl.java
1 package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl; 1 package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.util.IdUtil;  
5 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
6 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; 5 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
7 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.auth.SysUserSessionDO;  
8 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; 6 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;
9 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.auth.SysUserSessionMapper; 7 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.auth.SysUserSessionMapper;
10 -import cn.iocoder.yudao.adminserver.modules.system.dal.redis.auth.SysLoginUserRedisDAO;  
11 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum; 8 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum;
12 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum; 9 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
13 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; 10 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;
14 import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService; 11 import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
15 import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO; 12 import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
16 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; 13 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
17 -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 14 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO;
  15 +import cn.iocoder.yudao.coreservice.modules.system.dal.redis.auth.SysLoginUserCoreRedisDAO;
18 import cn.iocoder.yudao.framework.common.pojo.PageResult; 16 import cn.iocoder.yudao.framework.common.pojo.PageResult;
19 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; 17 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
20 -import cn.iocoder.yudao.framework.security.config.SecurityProperties;  
21 -import cn.iocoder.yudao.framework.security.core.LoginUser;  
22 import com.google.common.collect.Lists; 18 import com.google.common.collect.Lists;
23 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
24 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
25 21
26 import javax.annotation.Resource; 22 import javax.annotation.Resource;
27 -import java.time.Duration;  
28 -import java.util.*; 23 +import java.util.ArrayList;
  24 +import java.util.Collection;
  25 +import java.util.List;
  26 +import java.util.Map;
29 import java.util.stream.Collectors; 27 import java.util.stream.Collectors;
30 28
31 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 29 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
32 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;  
33 30
34 /** 31 /**
35 * 在线用户 Session Service 实现类 32 * 在线用户 Session Service 实现类
@@ -41,64 +38,14 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime; @@ -41,64 +38,14 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;
41 public class SysUserSessionServiceImpl implements SysUserSessionService { 38 public class SysUserSessionServiceImpl implements SysUserSessionService {
42 39
43 @Resource 40 @Resource
44 - private SecurityProperties securityProperties;  
45 - @Resource  
46 - private SysLoginUserRedisDAO loginUserRedisDAO;  
47 - @Resource  
48 private SysUserSessionMapper userSessionMapper; 41 private SysUserSessionMapper userSessionMapper;
49 @Resource 42 @Resource
50 private SysUserService userService; 43 private SysUserService userService;
51 @Resource 44 @Resource
52 private SysLoginLogService loginLogService; 45 private SysLoginLogService loginLogService;
53 46
54 - @Override  
55 - public String createUserSession(LoginUser loginUser, String userIp, String userAgent) {  
56 - // 生成 Session 编号  
57 - String sessionId = generateSessionId();  
58 - // 写入 Redis 缓存  
59 - loginUser.setUpdateTime(new Date());  
60 - loginUserRedisDAO.set(sessionId, loginUser);  
61 - // 写入 DB 中  
62 - SysUserSessionDO userSession = SysUserSessionDO.builder().id(sessionId)  
63 - .userId(loginUser.getId()).userType(UserTypeEnum.ADMIN.getValue())  
64 - .userIp(userIp).userAgent(userAgent).username(loginUser.getUsername())  
65 - .sessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis())))  
66 - .build();  
67 - userSessionMapper.insert(userSession);  
68 - // 返回 Session 编号  
69 - return sessionId;  
70 - }  
71 -  
72 - @Override  
73 - public void refreshUserSession(String sessionId, LoginUser loginUser) {  
74 - // 写入 Redis 缓存  
75 - loginUser.setUpdateTime(new Date());  
76 - loginUserRedisDAO.set(sessionId, loginUser);  
77 - // 更新 DB 中  
78 - SysUserSessionDO updateObj = SysUserSessionDO.builder().id(sessionId).build();  
79 - updateObj.setUsername(loginUser.getUsername());  
80 - updateObj.setUpdateTime(new Date());  
81 - updateObj.setSessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis())));  
82 - userSessionMapper.updateById(updateObj);  
83 - }  
84 -  
85 - @Override  
86 - public void deleteUserSession(String sessionId) {  
87 - // 删除 Redis 缓存  
88 - loginUserRedisDAO.delete(sessionId);  
89 - // 删除 DB 记录  
90 - userSessionMapper.deleteById(sessionId);  
91 - }  
92 -  
93 - @Override  
94 - public LoginUser getLoginUser(String sessionId) {  
95 - return loginUserRedisDAO.get(sessionId);  
96 - }  
97 -  
98 - @Override  
99 - public Long getSessionTimeoutMillis() {  
100 - return securityProperties.getSessionTimeout().toMillis();  
101 - } 47 + @Resource
  48 + private SysLoginUserCoreRedisDAO loginUserCoreRedisDAO;
102 49
103 @Override 50 @Override
104 public PageResult<SysUserSessionDO> getUserSessionPage(SysUserSessionPageReqVO reqVO) { 51 public PageResult<SysUserSessionDO> getUserSessionPage(SysUserSessionPageReqVO reqVO) {
@@ -113,18 +60,20 @@ public class SysUserSessionServiceImpl implements SysUserSessionService { @@ -113,18 +60,20 @@ public class SysUserSessionServiceImpl implements SysUserSessionService {
113 return userSessionMapper.selectPage(reqVO, userIds); 60 return userSessionMapper.selectPage(reqVO, userIds);
114 } 61 }
115 62
  63 + // TODO @芋艿:优化下该方法
116 @Override 64 @Override
117 public long clearSessionTimeout() { 65 public long clearSessionTimeout() {
118 // 获取db里已经超时的用户列表 66 // 获取db里已经超时的用户列表
119 List<SysUserSessionDO> sessionTimeoutDOS = userSessionMapper.selectListBySessionTimoutLt(); 67 List<SysUserSessionDO> sessionTimeoutDOS = userSessionMapper.selectListBySessionTimoutLt();
120 Map<String, SysUserSessionDO> timeoutSessionDOMap = sessionTimeoutDOS 68 Map<String, SysUserSessionDO> timeoutSessionDOMap = sessionTimeoutDOS
121 .stream() 69 .stream()
122 - .filter(sessionDO -> loginUserRedisDAO.get(sessionDO.getId()) == null) 70 + .filter(sessionDO -> loginUserCoreRedisDAO.get(sessionDO.getId()) == null)
123 .collect(Collectors.toMap(SysUserSessionDO::getId, o -> o)); 71 .collect(Collectors.toMap(SysUserSessionDO::getId, o -> o));
124 // 确认已经超时,按批次移出在线用户列表 72 // 确认已经超时,按批次移出在线用户列表
125 if (CollUtil.isNotEmpty(timeoutSessionDOMap)) { 73 if (CollUtil.isNotEmpty(timeoutSessionDOMap)) {
126 - Lists.partition(new ArrayList<>(timeoutSessionDOMap.keySet()), 100).forEach(userSessionMapper::deleteBatchIds);  
127 - //记录用户超时退出日志 74 + Lists.partition(new ArrayList<>(timeoutSessionDOMap.keySet()), 100)
  75 + .forEach(userSessionMapper::deleteBatchIds);
  76 + // 记录用户超时退出日志
128 createTimeoutLogoutLog(timeoutSessionDOMap.values()); 77 createTimeoutLogoutLog(timeoutSessionDOMap.values());
129 } 78 }
130 return timeoutSessionDOMap.size(); 79 return timeoutSessionDOMap.size();
@@ -143,13 +92,4 @@ public class SysUserSessionServiceImpl implements SysUserSessionService { @@ -143,13 +92,4 @@ public class SysUserSessionServiceImpl implements SysUserSessionService {
143 } 92 }
144 } 93 }
145 94
146 - /**  
147 - * 生成 Session 编号,目前采用 UUID 算法  
148 - *  
149 - * @return Session 编号  
150 - */  
151 - private static String generateSessionId() {  
152 - return IdUtil.fastSimpleUUID();  
153 - }  
154 -  
155 } 95 }
yudao-admin-server/src/main/resources/application.yaml
@@ -31,7 +31,7 @@ mybatis-plus: @@ -31,7 +31,7 @@ mybatis-plus:
31 logic-delete-value: 1 # 逻辑已删除值(默认为 1) 31 logic-delete-value: 1 # 逻辑已删除值(默认为 1)
32 logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) 32 logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
33 mapper-locations: classpath*:mapper/*.xml 33 mapper-locations: classpath*:mapper/*.xml
34 - type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject 34 + type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject, ${yudao.core-service.base-package}.modules.*.dal.dataobject
35 35
36 --- #################### 芋道相关配置 #################### 36 --- #################### 芋道相关配置 ####################
37 37
@@ -39,6 +39,8 @@ yudao: @@ -39,6 +39,8 @@ yudao:
39 info: 39 info:
40 version: 1.0.0 40 version: 1.0.0
41 base-package: cn.iocoder.yudao.adminserver 41 base-package: cn.iocoder.yudao.adminserver
  42 + core-service:
  43 + base-package: cn.iocoder.yudao.coreservice
42 web: 44 web:
43 api-prefix: /api 45 api-prefix: /api
44 controller-package: ${yudao.info.base-package} 46 controller-package: ${yudao.info.base-package}
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/BaseRedisUnitTest.java
@@ -24,7 +24,7 @@ public class BaseRedisUnitTest { @@ -24,7 +24,7 @@ public class BaseRedisUnitTest {
24 // Redis 配置类 24 // Redis 配置类
25 RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer 25 RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer
26 RedisAutoConfiguration.class, // Spring Redis 自动配置类 26 RedisAutoConfiguration.class, // Spring Redis 自动配置类
27 - YudaoTracerAutoConfiguration.class, // 自己的 Redis 配置类 27 + YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
28 RedissonAutoConfiguration.class, // Redisson 自动高配置类 28 RedissonAutoConfiguration.class, // Redisson 自动高配置类
29 }) 29 })
30 public static class Application { 30 public static class Application {
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/InfFileServiceTest.java
@@ -10,6 +10,7 @@ import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.file.InfFileMapper; @@ -10,6 +10,7 @@ import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.file.InfFileMapper;
10 import cn.iocoder.yudao.adminserver.modules.infra.service.file.impl.InfFileServiceImpl; 10 import cn.iocoder.yudao.adminserver.modules.infra.service.file.impl.InfFileServiceImpl;
11 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 11 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
12 import org.junit.jupiter.api.Test; 12 import org.junit.jupiter.api.Test;
  13 +import org.springframework.boot.test.mock.mockito.MockBean;
13 import org.springframework.context.annotation.Import; 14 import org.springframework.context.annotation.Import;
14 15
15 import javax.annotation.Resource; 16 import javax.annotation.Resource;
@@ -29,8 +30,9 @@ public class InfFileServiceTest extends BaseDbUnitTest { @@ -29,8 +30,9 @@ public class InfFileServiceTest extends BaseDbUnitTest {
29 @Resource 30 @Resource
30 private InfFileServiceImpl fileService; 31 private InfFileServiceImpl fileService;
31 32
32 - @Resource 33 + @MockBean
33 private FileProperties fileProperties; 34 private FileProperties fileProperties;
  35 +
34 @Resource 36 @Resource
35 private InfFileMapper fileMapper; 37 private InfFileMapper fileMapper;
36 38
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthServiceImplTest.java
1 package cn.iocoder.yudao.adminserver.modules.system.service.auth; 1 package cn.iocoder.yudao.adminserver.modules.system.service.auth;
2 2
3 import cn.iocoder.yudao.adminserver.BaseDbUnitTest; 3 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
  4 +import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;
  5 +import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.framework.security.core.LoginUser; 7 import cn.iocoder.yudao.framework.security.core.LoginUser;
6 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; 8 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
@@ -59,7 +61,9 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { @@ -59,7 +61,9 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
59 @MockBean 61 @MockBean
60 private SysLoginLogService loginLogService; 62 private SysLoginLogService loginLogService;
61 @MockBean 63 @MockBean
62 - private SysUserSessionService userSessionService; 64 + private SysUserSessionCoreService userSessionCoreService;
  65 + @MockBean
  66 + private SysSocialService socialService;
63 67
64 @Test 68 @Test
65 public void testLoadUserByUsername_success() { 69 public void testLoadUserByUsername_success() {
@@ -237,7 +241,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { @@ -237,7 +241,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
237 // mock 获得 User 拥有的角色编号数组 241 // mock 获得 User 拥有的角色编号数组
238 when(permissionService.getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus()))).thenReturn(userRoleIds); 242 when(permissionService.getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus()))).thenReturn(userRoleIds);
239 // mock 缓存登录用户到 Redis 243 // mock 缓存登录用户到 Redis
240 - when(userSessionService.createUserSession(loginUser, userIp, userAgent)).thenReturn(sessionId); 244 + when(userSessionCoreService.createUserSession(loginUser, userIp, userAgent)).thenReturn(sessionId);
241 // 调用, 并断言异常 245 // 调用, 并断言异常
242 String login = authService.login(reqVO, userIp, userAgent); 246 String login = authService.login(reqVO, userIp, userAgent);
243 assertEquals(sessionId, login); 247 assertEquals(sessionId, login);
@@ -255,11 +259,11 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest { @@ -255,11 +259,11 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
255 String token = randomString(); 259 String token = randomString();
256 LoginUser loginUser = randomPojo(LoginUser.class); 260 LoginUser loginUser = randomPojo(LoginUser.class);
257 // mock 261 // mock
258 - when(userSessionService.getLoginUser(token)).thenReturn(loginUser); 262 + when(userSessionCoreService.getLoginUser(token)).thenReturn(loginUser);
259 // 调用 263 // 调用
260 authService.logout(token); 264 authService.logout(token);
261 // 校验调用参数 265 // 校验调用参数
262 - verify(userSessionService, times(1)).deleteUserSession(token); 266 + verify(userSessionCoreService, times(1)).deleteUserSession(token);
263 verify(loginLogService, times(1)).createLoginLog( 267 verify(loginLogService, times(1)).createLoginLog(
264 argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGOUT_SELF.getType()) 268 argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGOUT_SELF.getType())
265 && o.getResult().equals(SysLoginResultEnum.SUCCESS.getResult())) 269 && o.getResult().equals(SysLoginResultEnum.SUCCESS.getResult()))
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionServiceImplTest.java
1 package cn.iocoder.yudao.adminserver.modules.system.service.auth; 1 package cn.iocoder.yudao.adminserver.modules.system.service.auth;
2 2
3 -import static cn.hutool.core.util.RandomUtil.randomEle;  
4 -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;  
5 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomDate;  
6 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;  
7 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;  
8 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;  
9 -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;  
10 -import static org.junit.jupiter.api.Assertions.assertEquals;  
11 -import static org.junit.jupiter.api.Assertions.assertNotEquals;  
12 -import static org.junit.jupiter.api.Assertions.assertNotNull;  
13 -import static org.junit.jupiter.api.Assertions.assertNull;  
14 -import static org.mockito.Mockito.when;  
15 -  
16 -import java.time.Duration;  
17 -import java.util.Date;  
18 -import java.util.List;  
19 -import java.util.stream.Collectors;  
20 -import java.util.stream.Stream;  
21 -  
22 -import javax.annotation.Resource;  
23 -  
24 -import org.junit.jupiter.api.Test;  
25 -import org.springframework.boot.test.mock.mockito.MockBean;  
26 -import org.springframework.context.annotation.Import;  
27 -  
28 import cn.hutool.core.date.DateUtil; 3 import cn.hutool.core.date.DateUtil;
29 import cn.iocoder.yudao.adminserver.BaseDbAndRedisUnitTest; 4 import cn.iocoder.yudao.adminserver.BaseDbAndRedisUnitTest;
30 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
31 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
32 -import cn.iocoder.yudao.framework.security.config.SecurityProperties;  
33 -import cn.iocoder.yudao.framework.security.core.LoginUser;  
34 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; 5 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
35 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.auth.SysUserSessionDO;  
36 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; 6 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;
37 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.auth.SysUserSessionMapper; 7 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.auth.SysUserSessionMapper;
38 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.user.SysUserMapper; 8 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.user.SysUserMapper;
39 -import cn.iocoder.yudao.adminserver.modules.system.dal.redis.auth.SysLoginUserRedisDAO;  
40 import cn.iocoder.yudao.adminserver.modules.system.enums.common.SysSexEnum; 9 import cn.iocoder.yudao.adminserver.modules.system.enums.common.SysSexEnum;
41 import cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysUserSessionServiceImpl; 10 import cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysUserSessionServiceImpl;
42 -import cn.iocoder.yudao.adminserver.modules.system.service.dept.impl.SysDeptServiceImpl;  
43 -import cn.iocoder.yudao.adminserver.modules.system.service.logger.impl.SysLoginLogServiceImpl;  
44 -import cn.iocoder.yudao.adminserver.modules.system.service.user.impl.SysUserServiceImpl;  
45 -import cn.iocoder.yudao.framework.test.core.util.AssertUtils;  
46 -import cn.iocoder.yudao.framework.test.core.util.RandomUtils; 11 +import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
  12 +import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
  13 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO;
  14 +import cn.iocoder.yudao.coreservice.modules.system.dal.redis.auth.SysLoginUserCoreRedisDAO;
  15 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  16 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  17 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
47 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 18 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  19 +import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
  20 +import org.junit.jupiter.api.Test;
  21 +import org.springframework.boot.test.mock.mockito.MockBean;
  22 +import org.springframework.context.annotation.Import;
  23 +
  24 +import javax.annotation.Resource;
  25 +import java.util.Arrays;
  26 +import java.util.Collections;
  27 +import java.util.Date;
  28 +import java.util.List;
  29 +import java.util.stream.Collectors;
  30 +import java.util.stream.Stream;
  31 +
  32 +import static cn.hutool.core.util.RandomUtil.randomEle;
  33 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
  34 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  35 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
  36 +import static java.util.Collections.singletonList;
  37 +import static org.junit.jupiter.api.Assertions.assertEquals;
  38 +import static org.mockito.ArgumentMatchers.eq;
  39 +import static org.mockito.Mockito.when;
48 40
49 /** 41 /**
50 - * SysUserSessionServiceImpl Tester. 42 + * {@link SysUserSessionServiceImpl} 的单元测试
51 * 43 *
52 * @author Lyon 44 * @author Lyon
53 - * @version 1.0  
54 - * @since <pre>3月 8, 2021</pre>  
55 */ 45 */
56 -@Import({SysUserSessionServiceImpl.class, SysLoginUserRedisDAO.class}) 46 +@Import({SysUserSessionServiceImpl.class})
57 public class SysUserSessionServiceImplTest extends BaseDbAndRedisUnitTest { 47 public class SysUserSessionServiceImplTest extends BaseDbAndRedisUnitTest {
58 48
59 @Resource 49 @Resource
60 - private SysUserSessionServiceImpl sysUserSessionService;  
61 - @Resource  
62 - private SysUserSessionMapper sysUserSessionMapper;  
63 - @Resource  
64 - private SysLoginUserRedisDAO sysLoginUserRedisDAO; 50 + private SysUserSessionServiceImpl userSessionService;
  51 +
65 @Resource 52 @Resource
66 - private SysUserMapper sysUserMapper; 53 + private SysUserSessionMapper userSessionMapper;
67 54
68 @MockBean 55 @MockBean
69 - private SecurityProperties securityProperties; 56 + private SysUserService userService;
70 @MockBean 57 @MockBean
71 - private SysDeptServiceImpl sysDeptService; 58 + private SysLoginLogService loginLogService;
72 @MockBean 59 @MockBean
73 - private SysUserServiceImpl sysUserService;  
74 - @MockBean  
75 - private SysLoginLogServiceImpl sysLoginLogService;  
76 -  
77 - @Test  
78 - public void testCreateUserSession_success() {  
79 - // 准备参数  
80 - String userIp = randomString();  
81 - String userAgent = randomString();  
82 - LoginUser loginUser = randomPojo(LoginUser.class);  
83 - // mock  
84 - when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1));  
85 - // 调用  
86 - String sessionId = sysUserSessionService.createUserSession(loginUser, userIp, userAgent);  
87 - // 校验记录的属性是否正确  
88 - SysUserSessionDO sysUserSessionDO = sysUserSessionMapper.selectById(sessionId);  
89 - assertEquals(sysUserSessionDO.getId(), sessionId);  
90 - assertEquals(sysUserSessionDO.getUserId(), loginUser.getId());  
91 - assertEquals(sysUserSessionDO.getUserIp(), userIp);  
92 - assertEquals(sysUserSessionDO.getUserAgent(), userAgent);  
93 - assertEquals(sysUserSessionDO.getUsername(), loginUser.getUsername());  
94 - LoginUser redisLoginUser = sysLoginUserRedisDAO.get(sessionId);  
95 - AssertUtils.assertPojoEquals(redisLoginUser, loginUser, "username","password");  
96 - }  
97 -  
98 - @Test  
99 - public void testCreateRefreshUserSession_success() {  
100 - // 准备参数  
101 - String sessionId = randomString();  
102 - String userIp = randomString();  
103 - String userAgent = randomString();  
104 - Long timeLong = randomLongId();  
105 - String userName = randomString();  
106 - Date date = randomDate();  
107 - LoginUser loginUser = randomPojo(LoginUser.class);  
108 - // mock  
109 - when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1));  
110 - loginUser.setUpdateTime(date);  
111 - sysLoginUserRedisDAO.set(sessionId, loginUser);  
112 - SysUserSessionDO userSession = SysUserSessionDO.builder().id(sessionId)  
113 - .userId(loginUser.getId()).userIp(userIp).userAgent(userAgent).username(userName)  
114 - .sessionTimeout(addTime(Duration.ofMillis(timeLong)))  
115 - .build();  
116 - sysUserSessionMapper.insert(userSession);  
117 - SysUserSessionDO insertDO = sysUserSessionMapper.selectById(sessionId);  
118 - // 调用  
119 - sysUserSessionService.refreshUserSession(sessionId, loginUser);  
120 - // 校验记录 redis  
121 - LoginUser redisLoginUser = sysLoginUserRedisDAO.get(sessionId);  
122 - assertNotEquals(redisLoginUser.getUpdateTime(), date);  
123 - // 校验记录 SysUserSessionDO  
124 - SysUserSessionDO updateDO = sysUserSessionMapper.selectById(sessionId);  
125 - assertEquals(updateDO.getUsername(), loginUser.getUsername());  
126 - assertNotEquals(updateDO.getUpdateTime(), insertDO.getUpdateTime());  
127 - assertNotEquals(updateDO.getSessionTimeout(), addTime(Duration.ofMillis(timeLong)));  
128 - }  
129 -  
130 - @Test  
131 - public void testDeleteUserSession_success() {  
132 - // 准备参数  
133 - String sessionId = randomString();  
134 - String userIp = randomString();  
135 - String userAgent = randomString();  
136 - Long timeLong = randomLongId();  
137 - LoginUser loginUser = randomPojo(LoginUser.class);  
138 - // mock 存入 Redis  
139 - when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1));  
140 - sysLoginUserRedisDAO.set(sessionId, loginUser);  
141 - // mock 存入 db  
142 - SysUserSessionDO userSession = SysUserSessionDO.builder().id(sessionId)  
143 - .userId(loginUser.getId()).userIp(userIp).userAgent(userAgent).username(loginUser.getUsername())  
144 - .sessionTimeout(addTime(Duration.ofMillis(timeLong)))  
145 - .build();  
146 - sysUserSessionMapper.insert(userSession);  
147 - // 校验数据存在  
148 - assertNotNull(sysLoginUserRedisDAO.get(sessionId));  
149 - assertNotNull(sysUserSessionMapper.selectById(sessionId));  
150 - // 调用  
151 - sysUserSessionService.deleteUserSession(sessionId);  
152 - // 校验数据不存在了  
153 - assertNull(sysLoginUserRedisDAO.get(sessionId));  
154 - assertNull(sysUserSessionMapper.selectById(sessionId));  
155 - } 60 + private SysLoginUserCoreRedisDAO loginUserCoreRedisDAO;
156 61
157 @Test 62 @Test
158 public void testGetUserSessionPage_success() { 63 public void testGetUserSessionPage_success() {
159 // mock 数据 64 // mock 数据
160 - String userIp = randomString();  
161 - SysUserDO dbUser1 = randomPojo(SysUserDO.class, o -> {  
162 - o.setUsername("testUsername1");  
163 - o.setSex(randomEle(SysSexEnum.values()).getSex());  
164 - o.setStatus(CommonStatusEnum.ENABLE.getStatus());  
165 - });  
166 - SysUserDO dbUser2 = randomPojo(SysUserDO.class, o -> {  
167 - o.setUsername("testUsername2"); 65 + SysUserDO dbUser = randomPojo(SysUserDO.class, o -> {
168 o.setSex(randomEle(SysSexEnum.values()).getSex()); 66 o.setSex(randomEle(SysSexEnum.values()).getSex());
169 o.setStatus(CommonStatusEnum.ENABLE.getStatus()); 67 o.setStatus(CommonStatusEnum.ENABLE.getStatus());
170 }); 68 });
  69 + when(userService.getUsersByUsername(eq(dbUser.getUsername()))).thenReturn(singletonList(dbUser));
  70 + // 插入可被查询到的数据
  71 + String userIp = randomString();
171 SysUserSessionDO dbSession = randomPojo(SysUserSessionDO.class, o -> { 72 SysUserSessionDO dbSession = randomPojo(SysUserSessionDO.class, o -> {
172 - o.setUserId(dbUser1.getId()); 73 + o.setUserId(dbUser.getId());
  74 + o.setUserType(randomEle(UserTypeEnum.values()).getValue());
173 o.setUserIp(userIp); 75 o.setUserIp(userIp);
174 }); 76 });
175 - sysUserMapper.insert(dbUser1);  
176 - sysUserMapper.insert(dbUser2);  
177 - sysUserSessionMapper.insert(dbSession);  
178 - sysUserSessionMapper.insert(ObjectUtils.clone(dbSession, o -> { 77 + userSessionMapper.insert(dbSession);
  78 + // 测试 username 不匹配
  79 + userSessionMapper.insert(ObjectUtils.clone(dbSession, o -> {
179 o.setId(randomString()); 80 o.setId(randomString());
180 - o.setUserId(dbUser2.getId());  
181 - }));  
182 - // 测试 userId 不匹配  
183 - sysUserSessionMapper.insert(ObjectUtils.clone(dbSession, o -> {  
184 - o.setId(randomString());  
185 - o.setUserId(123456l); 81 + o.setUserId(123456L);
186 })); 82 }));
187 // 测试 userIp 不匹配 83 // 测试 userIp 不匹配
188 - sysUserSessionMapper.insert(ObjectUtils.clone(dbSession, o -> { 84 + userSessionMapper.insert(ObjectUtils.clone(dbSession, o -> {
189 o.setId(randomString()); 85 o.setId(randomString());
190 o.setUserIp("testUserIp"); 86 o.setUserIp("testUserIp");
191 })); 87 }));
192 // 准备参数 88 // 准备参数
193 - SysUserSessionPageReqVO reqVo = new SysUserSessionPageReqVO();  
194 - reqVo.setUserIp(userIp); 89 + SysUserSessionPageReqVO reqVO = new SysUserSessionPageReqVO();
  90 + reqVO.setUsername(dbUser.getUsername());
  91 + reqVO.setUserIp(userIp);
  92 +
195 // 调用 93 // 调用
196 - PageResult<SysUserSessionDO> pageResult = sysUserSessionService.getUserSessionPage(reqVo); 94 + PageResult<SysUserSessionDO> pageResult = userSessionService.getUserSessionPage(reqVO);
197 // 断言 95 // 断言
198 - assertEquals(3, pageResult.getTotal());  
199 - assertEquals(3, pageResult.getList().size()); 96 + assertEquals(1, pageResult.getTotal());
  97 + assertEquals(1, pageResult.getList().size());
200 assertPojoEquals(dbSession, pageResult.getList().get(0)); 98 assertPojoEquals(dbSession, pageResult.getList().get(0));
201 } 99 }
202 100
  101 + // TODO 芋艿:单测写的有问题
203 @Test 102 @Test
204 - public void testClearSessionTimeout_success() throws Exception { 103 + public void testClearSessionTimeout_success() {
205 // 准备超时数据 120 条, 在线用户 1 条 104 // 准备超时数据 120 条, 在线用户 1 条
206 int expectedTimeoutCount = 120, expectedTotal = 1; 105 int expectedTimeoutCount = 120, expectedTotal = 1;
207 106
@@ -209,17 +108,23 @@ public class SysUserSessionServiceImplTest extends BaseDbAndRedisUnitTest { @@ -209,17 +108,23 @@ public class SysUserSessionServiceImplTest extends BaseDbAndRedisUnitTest {
209 List<SysUserSessionDO> prepareData = Stream 108 List<SysUserSessionDO> prepareData = Stream
210 .iterate(0, i -> i) 109 .iterate(0, i -> i)
211 .limit(expectedTimeoutCount) 110 .limit(expectedTimeoutCount)
212 - .map(i -> RandomUtils.randomPojo(SysUserSessionDO.class, o -> o.setSessionTimeout(DateUtil.offsetSecond(new Date(), -1)))) 111 + .map(i -> randomPojo(SysUserSessionDO.class, o -> {
  112 + o.setUserType(randomEle(UserTypeEnum.values()).getValue());
  113 + o.setSessionTimeout(DateUtil.offsetSecond(new Date(), -1));
  114 + }))
213 .collect(Collectors.toList()); 115 .collect(Collectors.toList());
214 - SysUserSessionDO sessionDO = RandomUtils.randomPojo(SysUserSessionDO.class, o -> o.setSessionTimeout(DateUtil.offsetMinute(new Date(), 30))); 116 + SysUserSessionDO sessionDO = randomPojo(SysUserSessionDO.class, o -> {
  117 + o.setUserType(randomEle(UserTypeEnum.values()).getValue());
  118 + o.setSessionTimeout(DateUtil.offsetMinute(new Date(), 30));
  119 + });
215 prepareData.add(sessionDO); 120 prepareData.add(sessionDO);
216 - prepareData.forEach(sysUserSessionMapper::insert); 121 + prepareData.forEach(userSessionMapper::insert);
217 122
218 - //清空超时数据  
219 - long actualTimeoutCount = sysUserSessionService.clearSessionTimeout();  
220 - //校验 123 + // 清空超时数据
  124 + long actualTimeoutCount = userSessionService.clearSessionTimeout();
  125 + // 校验
221 assertEquals(expectedTimeoutCount, actualTimeoutCount); 126 assertEquals(expectedTimeoutCount, actualTimeoutCount);
222 - List<SysUserSessionDO> userSessionDOS = sysUserSessionMapper.selectList(); 127 + List<SysUserSessionDO> userSessionDOS = userSessionMapper.selectList();
223 assertEquals(expectedTotal, userSessionDOS.size()); 128 assertEquals(expectedTotal, userSessionDOS.size());
224 AssertUtils.assertPojoEquals(sessionDO, userSessionDOS.get(0), "updateTime"); 129 AssertUtils.assertPojoEquals(sessionDO, userSessionDOS.get(0), "updateTime");
225 } 130 }
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogServiceImplTest.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.adminserver.modules.system.service.logger; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.adminserver.modules.system.service.logger;
3 import cn.hutool.core.util.RandomUtil; 3 import cn.hutool.core.util.RandomUtil;
4 import cn.iocoder.yudao.adminserver.BaseDbUnitTest; 4 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
5 import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO; 5 import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
  6 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; 8 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
8 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; 9 import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO;
@@ -62,6 +63,7 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest { @@ -62,6 +63,7 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest {
62 SysLoginLogDO loginLogDO = RandomUtils.randomPojo(SysLoginLogDO.class, logDO -> { 63 SysLoginLogDO loginLogDO = RandomUtils.randomPojo(SysLoginLogDO.class, logDO -> {
63 logDO.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType()); 64 logDO.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType());
64 logDO.setTraceId(TracerUtils.getTraceId()); 65 logDO.setTraceId(TracerUtils.getTraceId());
  66 + logDO.setUserType(RandomUtil.randomEle(UserTypeEnum.values()).getValue());
65 67
66 logDO.setUserIp("192.168.199.16"); 68 logDO.setUserIp("192.168.199.16");
67 logDO.setUsername("wangkai"); 69 logDO.setUsername("wangkai");
@@ -100,13 +102,13 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest { @@ -100,13 +102,13 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest {
100 102
101 @Test 103 @Test
102 public void testGetLoginLogList() { 104 public void testGetLoginLogList() {
103 -  
104 // 构造测试数据 105 // 构造测试数据
105 106
106 // 登录成功的 107 // 登录成功的
107 SysLoginLogDO loginLogDO = RandomUtils.randomPojo(SysLoginLogDO.class, logDO -> { 108 SysLoginLogDO loginLogDO = RandomUtils.randomPojo(SysLoginLogDO.class, logDO -> {
108 logDO.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType()); 109 logDO.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType());
109 logDO.setTraceId(TracerUtils.getTraceId()); 110 logDO.setTraceId(TracerUtils.getTraceId());
  111 + logDO.setUserType(RandomUtil.randomEle(UserTypeEnum.values()).getValue());
110 112
111 logDO.setUserIp("192.168.111.16"); 113 logDO.setUserIp("192.168.111.16");
112 logDO.setUsername("wangxiaokai"); 114 logDO.setUsername("wangxiaokai");
yudao-admin-server/src/test/resources/application-unit-test.yaml
@@ -36,34 +36,9 @@ mybatis: @@ -36,34 +36,9 @@ mybatis:
36 # Lock4j 配置项(单元测试,禁用 Lock4j) 36 # Lock4j 配置项(单元测试,禁用 Lock4j)
37 37
38 # Resilience4j 配置项 38 # Resilience4j 配置项
39 -resilience4j:  
40 - ratelimiter:  
41 - instances:  
42 - backendA:  
43 - limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50  
44 - limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500  
45 - timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s  
46 - register-health-indicator: true # 是否注册到健康监测  
47 39
48 --- #################### 监控相关配置 #################### 40 --- #################### 监控相关配置 ####################
49 41
50 --- #################### 芋道相关配置 #################### 42 --- #################### 芋道相关配置 ####################
51 43
52 # 芋道配置项,设置当前项目所有自定义的配置 44 # 芋道配置项,设置当前项目所有自定义的配置
53 -yudao:  
54 - security:  
55 - token-header: Authorization  
56 - token-secret: abcdefghijklmnopqrstuvwxyz  
57 - token-timeout: 1d  
58 - session-timeout: 30m  
59 - mock-enable: true  
60 - mock-secret: test  
61 - swagger:  
62 - enable: false # 单元测试,禁用 Swagger  
63 - file:  
64 - base-path: http://127.0.0.1:${server.port}/${yudao.web.api-prefix}/file/get/  
65 - xss:  
66 - enable: false  
67 - exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系  
68 - - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求  
69 - - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求  
yudao-admin-server/src/test/resources/sql/create_tables.sql
@@ -179,6 +179,7 @@ CREATE TABLE IF NOT EXISTS &quot;sys_dict_type&quot; ( @@ -179,6 +179,7 @@ CREATE TABLE IF NOT EXISTS &quot;sys_dict_type&quot; (
179 CREATE TABLE IF NOT EXISTS `sys_user_session` ( 179 CREATE TABLE IF NOT EXISTS `sys_user_session` (
180 `id` varchar(32) NOT NULL, 180 `id` varchar(32) NOT NULL,
181 `user_id` bigint DEFAULT NULL, 181 `user_id` bigint DEFAULT NULL,
  182 + "user_type" tinyint NOT NULL,
182 `username` varchar(50) NOT NULL DEFAULT '', 183 `username` varchar(50) NOT NULL DEFAULT '',
183 `user_ip` varchar(50) DEFAULT NULL, 184 `user_ip` varchar(50) DEFAULT NULL,
184 `user_agent` varchar(512) DEFAULT NULL, 185 `user_agent` varchar(512) DEFAULT NULL,
@@ -223,6 +224,8 @@ CREATE TABLE IF NOT EXISTS &quot;sys_notice&quot; ( @@ -223,6 +224,8 @@ CREATE TABLE IF NOT EXISTS &quot;sys_notice&quot; (
223 CREATE TABLE IF NOT EXISTS `sys_login_log` ( 224 CREATE TABLE IF NOT EXISTS `sys_login_log` (
224 `id` bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, 225 `id` bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY,
225 `log_type` bigint(4) NOT NULL, 226 `log_type` bigint(4) NOT NULL,
  227 + "user_id" bigint not null default '0',
  228 + "user_type" tinyint NOT NULL,
226 `trace_id` varchar(64) NOT NULL DEFAULT '', 229 `trace_id` varchar(64) NOT NULL DEFAULT '',
227 `username` varchar(50) NOT NULL DEFAULT '', 230 `username` varchar(50) NOT NULL DEFAULT '',
228 `result` tinyint(4) NOT NULL, 231 `result` tinyint(4) NOT NULL,
yudao-core-service/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>yudao</artifactId>
  7 + <groupId>cn.iocoder.boot</groupId>
  8 + <version>1.1.0-snapshot</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>yudao-core-service</artifactId>
  13 + <packaging>jar</packaging>
  14 +
  15 + <name>yudao-admin-server</name>
  16 + <description>
  17 + 公共服务,通过 jar 包的方式,被 yudao-admin-server、yudao-user-service 使用。例如说:
  18 + 1. 日志相关:访问日志、登录日志、异常日志等等
  19 + 2. 认证相关:在线 Session
  20 + 3. 短信相关:短信模板、短信日志
  21 + 等等
  22 + </description>
  23 + <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
  24 +
  25 + <dependencies>
  26 + <!-- Web 相关 -->
  27 + <dependency>
  28 + <groupId>cn.iocoder.boot</groupId>
  29 + <artifactId>yudao-spring-boot-starter-web</artifactId>
  30 + </dependency>
  31 + <!-- spring boot 配置所需依赖 -->
  32 + <dependency>
  33 + <groupId>org.springframework.boot</groupId>
  34 + <artifactId>spring-boot-configuration-processor</artifactId>
  35 + <optional>true</optional>
  36 + </dependency>
  37 +
  38 + <dependency>
  39 + <groupId>cn.iocoder.boot</groupId>
  40 + <artifactId>yudao-spring-boot-starter-security</artifactId>
  41 + </dependency>
  42 +
  43 + <!-- DB 相关 -->
  44 + <dependency>
  45 + <groupId>cn.iocoder.boot</groupId>
  46 + <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
  47 + </dependency>
  48 +
  49 + <dependency>
  50 + <groupId>cn.iocoder.boot</groupId>
  51 + <artifactId>yudao-spring-boot-starter-redis</artifactId>
  52 + </dependency>
  53 +
  54 + <!-- Test 测试相关 -->
  55 + <dependency>
  56 + <groupId>cn.iocoder.boot</groupId>
  57 + <artifactId>yudao-spring-boot-starter-test</artifactId>
  58 + <scope>test</scope>
  59 + </dependency>
  60 + </dependencies>
  61 +
  62 +</project>
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/package-info.java 0 → 100644
  1 +/**
  2 + * infra 包下,我们放基础设施的运维与管理,支撑上层的通用与核心业务。
  3 + * 例如说:定时任务的管理、服务器的信息等等
  4 + *
  5 + * 缩写:inf
  6 + */
  7 +package cn.iocoder.yudao.coreservice.modules.infra;
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/package-info.java 0 → 100644
  1 +/**
  2 + * member 包下,我们放会员业务.
  3 + * 例如说:会员中心等等
  4 + *
  5 + * 缩写:mbr
  6 + */
  7 +package cn.iocoder.yudao.coreservice.modules.member;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/auth/SysUserSessionDO.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/auth/SysUserSessionDO.java
1 -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.auth; 1 +package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth;
2 2
  3 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import cn.iocoder.yudao.framework.security.core.LoginUser; 5 import cn.iocoder.yudao.framework.security.core.LoginUser;
5 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;  
6 import com.baomidou.mybatisplus.annotation.IdType; 6 import com.baomidou.mybatisplus.annotation.IdType;
7 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
8 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
@@ -35,7 +35,7 @@ public class SysUserSessionDO extends BaseDO { @@ -35,7 +35,7 @@ public class SysUserSessionDO extends BaseDO {
35 /** 35 /**
36 * 用户编号 36 * 用户编号
37 * 37 *
38 - * 关联 {@link SysUserDO#getId()} 38 + * 关联 SysUserDO.id 或者 MbrUserDO.id
39 */ 39 */
40 private Long userId; 40 private Long userId;
41 /** 41 /**
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject;
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/auth/SysUserSessionCoreMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.auth;
  2 +
  3 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +@Mapper
  8 +public interface SysUserSessionCoreMapper extends BaseMapperX<SysUserSessionDO> {
  9 +
  10 +}
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.dal.mysql;
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/SysRedisKeyCoreConstants.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.dal.redis;
  2 +
  3 +import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
  4 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  5 +
  6 +import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING;
  7 +
  8 +/**
  9 + * System Redis Key 枚举类
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +public interface SysRedisKeyCoreConstants {
  14 +
  15 + RedisKeyDefine LOGIN_USER = new RedisKeyDefine("登录用户的缓存",
  16 + "login_user:%s", // 参数为 sessionId
  17 + STRING, LoginUser.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);
  18 +
  19 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/auth/SysLoginUserRedisDAO.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/auth/SysLoginUserCoreRedisDAO.java
1 -package cn.iocoder.yudao.adminserver.modules.system.dal.redis.auth; 1 +package cn.iocoder.yudao.coreservice.modules.system.dal.redis.auth;
2 2
3 -import cn.iocoder.yudao.framework.security.core.LoginUser;  
4 -import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;  
5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  4 +import cn.iocoder.yudao.framework.security.config.SecurityProperties;
  5 +import cn.iocoder.yudao.framework.security.core.LoginUser;
6 import org.springframework.data.redis.core.StringRedisTemplate; 6 import org.springframework.data.redis.core.StringRedisTemplate;
7 import org.springframework.stereotype.Repository; 7 import org.springframework.stereotype.Repository;
8 8
9 import javax.annotation.Resource; 9 import javax.annotation.Resource;
10 -import java.time.Duration;  
11 10
12 -import static cn.iocoder.yudao.adminserver.modules.system.dal.redis.SysRedisKeyConstants.LOGIN_USER; 11 +import static cn.iocoder.yudao.coreservice.modules.system.dal.redis.SysRedisKeyCoreConstants.LOGIN_USER;
13 12
14 /** 13 /**
15 * {@link LoginUser} 的 RedisDAO 14 * {@link LoginUser} 的 RedisDAO
@@ -17,12 +16,13 @@ import static cn.iocoder.yudao.adminserver.modules.system.dal.redis.SysRedisKeyC @@ -17,12 +16,13 @@ import static cn.iocoder.yudao.adminserver.modules.system.dal.redis.SysRedisKeyC
17 * @author 芋道源码 16 * @author 芋道源码
18 */ 17 */
19 @Repository 18 @Repository
20 -public class SysLoginUserRedisDAO { 19 +public class SysLoginUserCoreRedisDAO {
21 20
22 @Resource 21 @Resource
23 private StringRedisTemplate stringRedisTemplate; 22 private StringRedisTemplate stringRedisTemplate;
  23 +
24 @Resource 24 @Resource
25 - private SysUserSessionService sysUserSessionService; // TODO 芋艿:得看看怎么拿出去 25 + private SecurityProperties securityProperties;
26 26
27 public LoginUser get(String sessionId) { 27 public LoginUser get(String sessionId) {
28 String redisKey = formatKey(sessionId); 28 String redisKey = formatKey(sessionId);
@@ -32,7 +32,7 @@ public class SysLoginUserRedisDAO { @@ -32,7 +32,7 @@ public class SysLoginUserRedisDAO {
32 public void set(String sessionId, LoginUser loginUser) { 32 public void set(String sessionId, LoginUser loginUser) {
33 String redisKey = formatKey(sessionId); 33 String redisKey = formatKey(sessionId);
34 stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(loginUser), 34 stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(loginUser),
35 - Duration.ofMillis(sysUserSessionService.getSessionTimeoutMillis())); 35 + securityProperties.getSessionTimeout());
36 } 36 }
37 37
38 public void delete(String sessionId) { 38 public void delete(String sessionId) {
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/package-info.java 0 → 100644
  1 +/**
  2 + * system 包下,我们放通用业务,支撑上层的核心业务。
  3 + * 例如说:用户、部门、权限、数据字典等等
  4 + *
  5 + * 缩写:sys
  6 + */
  7 +package cn.iocoder.yudao.coreservice.modules.system;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysUserSessionService.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/auth/SysUserSessionCoreService.java
1 -package cn.iocoder.yudao.userserver.modules.system.service.auth; 1 +package cn.iocoder.yudao.coreservice.modules.system.service.auth;
2 2
3 import cn.iocoder.yudao.framework.security.core.LoginUser; 3 import cn.iocoder.yudao.framework.security.core.LoginUser;
4 4
5 /** 5 /**
6 - * 在线用户 Session Service 接口 6 + * 在线用户 Session Core Service 接口
7 * 7 *
8 * @author 芋道源码 8 * @author 芋道源码
9 */ 9 */
10 -public interface SysUserSessionService { 10 +public interface SysUserSessionCoreService {
11 11
12 /** 12 /**
13 * 创建在线用户 Session 13 * 创建在线用户 Session
@@ -43,13 +43,6 @@ public interface SysUserSessionService { @@ -43,13 +43,6 @@ public interface SysUserSessionService {
43 LoginUser getLoginUser(String sessionId); 43 LoginUser getLoginUser(String sessionId);
44 44
45 /** 45 /**
46 - * 获取当前登录用户信息  
47 - * @param username 用户名称  
48 - * @return 在线用户  
49 - */  
50 - String getSessionId(String username);  
51 -  
52 - /**  
53 * 获得 Session 超时时间,单位:毫秒 46 * 获得 Session 超时时间,单位:毫秒
54 * 47 *
55 * @return 超时时间 48 * @return 超时时间
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/auth/impl/SysUserSessionCoreServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.service.auth.impl;
  2 +
  3 +import cn.hutool.core.util.IdUtil;
  4 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO;
  5 +import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.auth.SysUserSessionCoreMapper;
  6 +import cn.iocoder.yudao.coreservice.modules.system.dal.redis.auth.SysLoginUserCoreRedisDAO;
  7 +import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
  8 +import cn.iocoder.yudao.framework.security.config.SecurityProperties;
  9 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  10 +import org.springframework.stereotype.Service;
  11 +
  12 +import javax.annotation.Resource;
  13 +import java.time.Duration;
  14 +import java.util.Date;
  15 +
  16 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;
  17 +
  18 +/**
  19 + * 在线用户 Session Core Service 实现类
  20 + *
  21 + * @author 芋道源码
  22 + */
  23 +@Service
  24 +public class SysUserSessionCoreServiceImpl implements SysUserSessionCoreService {
  25 +
  26 + @Resource
  27 + private SysUserSessionCoreMapper userSessionCoreMapper;
  28 +
  29 + @Resource
  30 + private SysLoginUserCoreRedisDAO loginUserCoreRedisDAO;
  31 +
  32 + @Resource
  33 + private SecurityProperties securityProperties;
  34 +
  35 + @Override
  36 + public String createUserSession(LoginUser loginUser, String userIp, String userAgent) {
  37 + // 生成 Session 编号
  38 + String sessionId = generateSessionId();
  39 + // 写入 Redis 缓存
  40 + loginUser.setUpdateTime(new Date());
  41 + loginUserCoreRedisDAO.set(sessionId, loginUser);
  42 + // 写入 DB 中
  43 + SysUserSessionDO userSession = SysUserSessionDO.builder().id(sessionId)
  44 + .userId(loginUser.getId()).userType(loginUser.getUserType())
  45 + .userIp(userIp).userAgent(userAgent).username(loginUser.getUsername())
  46 + .sessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis())))
  47 + .build();
  48 + userSessionCoreMapper.insert(userSession);
  49 + // 返回 Session 编号
  50 + return sessionId;
  51 + }
  52 +
  53 + @Override
  54 + public void refreshUserSession(String sessionId, LoginUser loginUser) {
  55 + // 写入 Redis 缓存
  56 + loginUser.setUpdateTime(new Date());
  57 + loginUserCoreRedisDAO.set(sessionId, loginUser);
  58 + // 更新 DB 中
  59 + SysUserSessionDO updateObj = SysUserSessionDO.builder().id(sessionId).build();
  60 + updateObj.setUsername(loginUser.getUsername());
  61 + updateObj.setUpdateTime(new Date());
  62 + updateObj.setSessionTimeout(addTime(Duration.ofMillis(getSessionTimeoutMillis())));
  63 + userSessionCoreMapper.updateById(updateObj);
  64 + }
  65 +
  66 + @Override
  67 + public void deleteUserSession(String sessionId) {
  68 + // 删除 Redis 缓存
  69 + loginUserCoreRedisDAO.delete(sessionId);
  70 + // 删除 DB 记录
  71 + userSessionCoreMapper.deleteById(sessionId);
  72 + }
  73 +
  74 + @Override
  75 + public LoginUser getLoginUser(String sessionId) {
  76 + return loginUserCoreRedisDAO.get(sessionId);
  77 + }
  78 +
  79 + @Override
  80 + public Long getSessionTimeoutMillis() {
  81 + return securityProperties.getSessionTimeout().toMillis();
  82 + }
  83 +
  84 + /**
  85 + * 生成 Session 编号,目前采用 UUID 算法
  86 + *
  87 + * @return Session 编号
  88 + */
  89 + private static String generateSessionId() {
  90 + return IdUtil.fastSimpleUUID();
  91 + }
  92 +
  93 +}
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.service;
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/tool/package-info.java 0 → 100644
  1 +/**
  2 + * tool 包下,我们放研发工具,提升研发效率与质量。
  3 + * 例如说:代码生成器、接口文档等等
  4 + *
  5 + * 缩写:tool
  6 + */
  7 +package cn.iocoder.yudao.coreservice.modules.tool;
yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/BaseDbAndRedisUnitTest.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice;
  2 +
  3 +import cn.iocoder.yudao.coreservice.config.RedisTestConfiguration;
  4 +import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
  5 +import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
  6 +import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
  7 +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
  8 +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
  9 +import org.redisson.spring.starter.RedissonAutoConfiguration;
  10 +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
  11 +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  12 +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
  13 +import org.springframework.boot.test.context.SpringBootTest;
  14 +import org.springframework.context.annotation.Import;
  15 +import org.springframework.test.context.ActiveProfiles;
  16 +import org.springframework.test.context.jdbc.Sql;
  17 +
  18 +/**
  19 + * 依赖内存 DB + Redis 的单元测试
  20 + *
  21 + * 相比 {@link BaseDbUnitTest} 来说,额外增加了内存 Redis
  22 + *
  23 + * @author 芋道源码
  24 + */
  25 +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisUnitTest.Application.class)
  26 +@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
  27 +@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB
  28 +public class BaseDbAndRedisUnitTest {
  29 +
  30 + @Import({
  31 + // DB 配置类
  32 + YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类
  33 + DataSourceAutoConfiguration.class, // Spring DB 自动配置类
  34 + DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
  35 + DruidDataSourceAutoConfigure.class, // Druid 自动配置类
  36 + // MyBatis 配置类
  37 + YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
  38 + MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
  39 + // Redis 配置类
  40 + RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer
  41 + RedisAutoConfiguration.class, // Spring Redis 自动配置类
  42 + YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
  43 + RedissonAutoConfiguration.class, // Redisson 自动高配置类
  44 + })
  45 + public static class Application {
  46 + }
  47 +
  48 +}
yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/BaseDbUnitTest.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice;
  2 +
  3 +import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
  4 +import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
  5 +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
  6 +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
  7 +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  8 +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
  9 +import org.springframework.boot.test.context.SpringBootTest;
  10 +import org.springframework.context.annotation.Import;
  11 +import org.springframework.test.context.ActiveProfiles;
  12 +import org.springframework.test.context.jdbc.Sql;
  13 +
  14 +/**
  15 + * 依赖内存 DB 的单元测试
  16 + *
  17 + * 注意,Service 层同样适用。对于 Service 层的单元测试,我们针对自己模块的 Mapper 走的是 H2 内存数据库,针对别的模块的 Service 走的是 Mock 方法
  18 + *
  19 + * @author 芋道源码
  20 + */
  21 +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class)
  22 +@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
  23 +@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB
  24 +public class BaseDbUnitTest {
  25 +
  26 + @Import({
  27 + // DB 配置类
  28 + YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类
  29 + DataSourceAutoConfiguration.class, // Spring DB 自动配置类
  30 + DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
  31 + DruidDataSourceAutoConfigure.class, // Druid 自动配置类
  32 + // MyBatis 配置类
  33 + YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
  34 + MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
  35 + })
  36 + public static class Application {
  37 + }
  38 +
  39 +}
yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/BaseRedisUnitTest.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice;
  2 +
  3 +import cn.iocoder.yudao.coreservice.config.RedisTestConfiguration;
  4 +import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
  5 +import org.redisson.spring.starter.RedissonAutoConfiguration;
  6 +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
  7 +import org.springframework.boot.test.context.SpringBootTest;
  8 +import org.springframework.context.annotation.Import;
  9 +import org.springframework.test.context.ActiveProfiles;
  10 +
  11 +/**
  12 + * 依赖内存 Redis 的单元测试
  13 + *
  14 + * 相比 {@link BaseDbUnitTest} 来说,从内存 DB 改成了内存 Redis
  15 + *
  16 + * @author 芋道源码
  17 + */
  18 +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseRedisUnitTest.Application.class)
  19 +@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
  20 +public class BaseRedisUnitTest {
  21 +
  22 + @Import({
  23 + // Redis 配置类
  24 + RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer
  25 + RedisAutoConfiguration.class, // Spring Redis 自动配置类
  26 + YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
  27 + RedissonAutoConfiguration.class, // Redisson 自动高配置类
  28 + })
  29 + public static class Application {
  30 + }
  31 +
  32 +}
yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/config/RedisTestConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.config;
  2 +
  3 +import com.github.fppt.jedismock.RedisServer;
  4 +import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
  5 +import org.springframework.boot.context.properties.EnableConfigurationProperties;
  6 +import org.springframework.context.annotation.Bean;
  7 +import org.springframework.context.annotation.Configuration;
  8 +import org.springframework.context.annotation.Lazy;
  9 +
  10 +import java.io.IOException;
  11 +
  12 +@Configuration(proxyBeanMethods = false)
  13 +@Lazy(false) // 禁止延迟加载
  14 +@EnableConfigurationProperties(RedisProperties.class)
  15 +public class RedisTestConfiguration {
  16 +
  17 + /**
  18 + * 创建模拟的 Redis Server 服务器
  19 + */
  20 + @Bean
  21 + public RedisServer redisServer(RedisProperties properties) throws IOException {
  22 + RedisServer redisServer = new RedisServer(properties.getPort());
  23 + // TODO 芋艿:一次执行多个单元测试时,貌似创建多个 spring 容器,导致不进行 stop。这样,就导致端口被占用,无法启动。。。
  24 + try {
  25 + redisServer.start();
  26 + } catch (Exception ignore) {}
  27 + return redisServer;
  28 + }
  29 +
  30 +}
yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/auth/SysUserSessionCoreServiceTest.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.service.auth;
  2 +
  3 +import cn.iocoder.yudao.coreservice.BaseDbAndRedisUnitTest;
  4 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO;
  5 +import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.auth.SysUserSessionCoreMapper;
  6 +import cn.iocoder.yudao.coreservice.modules.system.dal.redis.auth.SysLoginUserCoreRedisDAO;
  7 +import cn.iocoder.yudao.coreservice.modules.system.service.auth.impl.SysUserSessionCoreServiceImpl;
  8 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  9 +import cn.iocoder.yudao.framework.security.config.SecurityProperties;
  10 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  11 +import org.junit.jupiter.api.Test;
  12 +import org.springframework.boot.test.mock.mockito.MockBean;
  13 +import org.springframework.context.annotation.Import;
  14 +
  15 +import javax.annotation.Resource;
  16 +import java.time.Duration;
  17 +import java.util.Date;
  18 +
  19 +import static cn.hutool.core.util.RandomUtil.randomEle;
  20 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;
  21 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
  22 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
  23 +import static org.junit.jupiter.api.Assertions.*;
  24 +import static org.mockito.Mockito.when;
  25 +
  26 +@Import({SysUserSessionCoreServiceImpl.class, SysLoginUserCoreRedisDAO.class})
  27 +public class SysUserSessionCoreServiceTest extends BaseDbAndRedisUnitTest {
  28 +
  29 + @Resource
  30 + private SysUserSessionCoreServiceImpl userSessionCoreService;
  31 +
  32 + @Resource
  33 + private SysUserSessionCoreMapper userSessionCoreMapper;
  34 + @Resource
  35 + private SysLoginUserCoreRedisDAO loginUserCoreRedisDAO;
  36 +
  37 + @MockBean
  38 + private SecurityProperties securityProperties;
  39 +
  40 + @Test
  41 + public void testCreateUserSession_success() {
  42 + // 准备参数
  43 + String userIp = randomString();
  44 + String userAgent = randomString();
  45 + LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setUserType(randomEle(UserTypeEnum.values()).getValue()));
  46 + // mock 方法
  47 + when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1));
  48 +
  49 + // 调用
  50 + String sessionId = userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
  51 + // 校验 SysUserSessionDO 记录
  52 + SysUserSessionDO userSessionDO = userSessionCoreMapper.selectById(sessionId);
  53 + assertPojoEquals(loginUser, userSessionDO, "id", "updateTime");
  54 + assertEquals(sessionId, userSessionDO.getId());
  55 + assertEquals(userIp, userSessionDO.getUserIp());
  56 + assertEquals(userAgent, userSessionDO.getUserAgent());
  57 + // 校验 LoginUser 缓存
  58 + LoginUser redisLoginUser = loginUserCoreRedisDAO.get(sessionId);
  59 + assertPojoEquals(loginUser, redisLoginUser, "username", "password");
  60 + }
  61 +
  62 + @Test
  63 + public void testCreateRefreshUserSession_success() {
  64 + // 准备参数
  65 + String sessionId = randomString();
  66 + String userIp = randomString();
  67 + String userAgent = randomString();
  68 + long timeLong = randomLongId();
  69 + String userName = randomString();
  70 + Date date = randomDate();
  71 + LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setUserType(randomEle(UserTypeEnum.values()).getValue()));
  72 + // mock 方法
  73 + when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1));
  74 + // mock 数据
  75 + loginUser.setUpdateTime(date);
  76 + loginUserCoreRedisDAO.set(sessionId, loginUser);
  77 + SysUserSessionDO userSession = SysUserSessionDO.builder().id(sessionId)
  78 + .userId(loginUser.getId()).userType(loginUser.getUserType())
  79 + .userIp(userIp).userAgent(userAgent).username(userName)
  80 + .sessionTimeout(addTime(Duration.ofMillis(timeLong)))
  81 + .build();
  82 + userSessionCoreMapper.insert(userSession);
  83 +
  84 + // 调用
  85 + userSessionCoreService.refreshUserSession(sessionId, loginUser);
  86 + // 校验 LoginUser 缓存
  87 + LoginUser redisLoginUser = loginUserCoreRedisDAO.get(sessionId);
  88 + assertNotEquals(redisLoginUser.getUpdateTime(), date);
  89 + // 校验 SysUserSessionDO 记录
  90 + SysUserSessionDO updateDO = userSessionCoreMapper.selectById(sessionId);
  91 + assertEquals(updateDO.getUsername(), loginUser.getUsername());
  92 + assertNotEquals(updateDO.getUpdateTime(), userSession.getUpdateTime());
  93 + assertNotEquals(updateDO.getSessionTimeout(), addTime(Duration.ofMillis(timeLong)));
  94 + }
  95 +
  96 + @Test
  97 + public void testDeleteUserSession_success() {
  98 + // 准备参数
  99 + String sessionId = randomString();
  100 + String userIp = randomString();
  101 + String userAgent = randomString();
  102 + Long timeLong = randomLongId();
  103 + LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setUserType(randomEle(UserTypeEnum.values()).getValue()));
  104 + // mock 存入 Redis
  105 + when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1));
  106 + // mock 数据
  107 + loginUserCoreRedisDAO.set(sessionId, loginUser);
  108 + SysUserSessionDO userSession = SysUserSessionDO.builder().id(sessionId)
  109 + .userId(loginUser.getId()).userType(loginUser.getUserType())
  110 + .userIp(userIp).userAgent(userAgent).username(loginUser.getUsername())
  111 + .sessionTimeout(addTime(Duration.ofMillis(timeLong)))
  112 + .build();
  113 + userSessionCoreMapper.insert(userSession);
  114 +
  115 + // 调用
  116 + userSessionCoreService.deleteUserSession(sessionId);
  117 + // 校验数据不存在了
  118 + assertNull(loginUserCoreRedisDAO.get(sessionId));
  119 + assertNull(userSessionCoreMapper.selectById(sessionId));
  120 + }
  121 +
  122 +}
yudao-core-service/src/test/java/cn/iocoder/yudao/coreservice/modules/system/service/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.service;
yudao-core-service/src/test/resources/application-unit-test.yaml 0 → 100644
  1 +spring:
  2 + main:
  3 + lazy-initialization: true # 开启懒加载,加快速度
  4 + banner-mode: off # 单元测试,禁用 Banner
  5 +
  6 +--- #################### 数据库相关配置 ####################
  7 +
  8 +spring:
  9 + # 数据源配置项
  10 + datasource:
  11 + name: ruoyi-vue-pro
  12 + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
  13 + driver-class-name: org.h2.Driver
  14 + username: sa
  15 + password:
  16 + schema: classpath:sql/create_tables.sql # MySQL 转 H2 的语句,使用 https://www.jooq.org/translate/ 工具
  17 + druid:
  18 + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
  19 + initial-size: 1 # 单元测试,配置为 1,提升启动速度
  20 +
  21 + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
  22 + redis:
  23 + host: 127.0.0.1 # 地址
  24 + port: 16379 # 端口(单元测试,使用 16379 端口)
  25 + database: 0 # 数据库索引
  26 +
  27 +mybatis:
  28 + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
  29 +
  30 +--- #################### 定时任务相关配置 ####################
  31 +
  32 +--- #################### 配置中心相关配置 ####################
  33 +
  34 +--- #################### 服务保障相关配置 ####################
  35 +
  36 +# Lock4j 配置项(单元测试,禁用 Lock4j)
  37 +
  38 +# Resilience4j 配置项
  39 +
  40 +--- #################### 监控相关配置 ####################
  41 +
  42 +--- #################### 芋道相关配置 ####################
  43 +
  44 +# 芋道配置项,设置当前项目所有自定义的配置
yudao-core-service/src/test/resources/application.yaml 0 → 100644
  1 +spring:
  2 + application:
  3 + name: yudao-core-service
  4 +
  5 + # Jackson 配置项
  6 + jackson:
  7 + serialization:
  8 + write-dates-as-timestamps: true # 设置 Date 的格式,使用时间戳
  9 + write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401
  10 + write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳
  11 + fail-on-empty-beans: false # 允许序列化无属性的 Bean
  12 +
  13 +# MyBatis Plus 的配置项
  14 +mybatis-plus:
  15 + configuration:
  16 + map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
  17 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志
  18 + global-config:
  19 + db-config:
  20 + id-type: AUTO # 自增 ID
  21 + logic-delete-value: 1 # 逻辑已删除值(默认为 1)
  22 + logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
  23 + mapper-locations: classpath*:mapper/*.xml
  24 + type-aliases-package: ${yudao.core-service.base-package}.modules.*.dal.dataobject
  25 +
  26 +--- #################### 芋道相关配置 ####################
  27 +
  28 +yudao:
  29 + info:
  30 + version: 1.0.0
  31 + base-package: cn.iocoder.yudao.coreservice
  32 + core-service:
  33 + base-package: cn.iocoder.yudao.coreservice
  34 +
  35 +debug: false
yudao-core-service/src/test/resources/logback-spring.xml 0 → 100644
  1 +<configuration>
  2 + <!-- 引用 Spring Boot 的 logback 基础配置 -->
  3 + <include resource="org/springframework/boot/logging/logback/defaults.xml" />
  4 +</configuration>
yudao-core-service/src/test/resources/sql/clean.sql 0 → 100644
  1 +-- inf 开头的 DB
  2 +
  3 +-- sys 开头的 DB
  4 +DELETE FROM "sys_user_session";
yudao-core-service/src/test/resources/sql/create_tables.sql 0 → 100644
  1 +-- inf 开头的 DB
  2 +
  3 +-- sys 开头的 DB
  4 +
  5 +CREATE TABLE IF NOT EXISTS `sys_user_session` (
  6 + `id` varchar(32) NOT NULL,
  7 + `user_id` bigint DEFAULT NULL,
  8 + "user_type" tinyint NOT NULL,
  9 + `username` varchar(50) NOT NULL DEFAULT '',
  10 + `user_ip` varchar(50) DEFAULT NULL,
  11 + `user_agent` varchar(512) DEFAULT NULL,
  12 + `session_timeout` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  13 + "creator" varchar(64) DEFAULT '',
  14 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  15 + `updater` varchar(64) DEFAULT '' ,
  16 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  17 + "deleted" bit NOT NULL DEFAULT FALSE,
  18 + PRIMARY KEY (`id`)
  19 +) COMMENT '用户在线 Session';
  20 +
yudao-dependencies/pom.xml
@@ -74,6 +74,11 @@ @@ -74,6 +74,11 @@
74 <!-- 业务组件 --> 74 <!-- 业务组件 -->
75 <dependency> 75 <dependency>
76 <groupId>cn.iocoder.boot</groupId> 76 <groupId>cn.iocoder.boot</groupId>
  77 + <artifactId>yudao-core-service</artifactId>
  78 + <version>${revision}</version>
  79 + </dependency>
  80 + <dependency>
  81 + <groupId>cn.iocoder.boot</groupId>
77 <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId> 82 <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
78 <version>${revision}</version> 83 <version>${revision}</version>
79 </dependency> 84 </dependency>
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java
@@ -15,7 +15,7 @@ import org.springframework.context.annotation.Configuration; @@ -15,7 +15,7 @@ import org.springframework.context.annotation.Configuration;
15 * @author 芋道源码 15 * @author 芋道源码
16 */ 16 */
17 @Configuration 17 @Configuration
18 -@MapperScan(value = "${yudao.info.base-package}", annotationClass = Mapper.class, 18 +@MapperScan(value = {"${yudao.info.base-package}", "${yudao.core-service.base-package}"}, annotationClass = Mapper.class,
19 lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试 19 lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试
20 public class YudaoMybatisAutoConfiguration { 20 public class YudaoMybatisAutoConfiguration {
21 21
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java
1 package cn.iocoder.yudao.framework.security.core; 1 package cn.iocoder.yudao.framework.security.core;
2 2
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
4 import com.fasterxml.jackson.annotation.JsonIgnore; 5 import com.fasterxml.jackson.annotation.JsonIgnore;
5 import lombok.Data; 6 import lombok.Data;
6 import org.springframework.security.core.GrantedAuthority; 7 import org.springframework.security.core.GrantedAuthority;
@@ -24,6 +25,12 @@ public class LoginUser implements UserDetails { @@ -24,6 +25,12 @@ public class LoginUser implements UserDetails {
24 */ 25 */
25 private Long id; 26 private Long id;
26 /** 27 /**
  28 + * 用户类型
  29 + *
  30 + * 关联 {@link UserTypeEnum}
  31 + */
  32 + private Integer userType;
  33 + /**
27 * 部门编号 34 * 部门编号
28 */ 35 */
29 private Long deptId; 36 private Long deptId;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/package-info.java deleted
1 -package cn.iocoder.yudao.userserver.modules;  
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysUserSessionServiceImpl.java deleted
1 -package cn.iocoder.yudao.userserver.modules.system.service.auth.impl;  
2 -  
3 -import cn.iocoder.yudao.framework.security.core.LoginUser;  
4 -import cn.iocoder.yudao.userserver.modules.system.service.auth.SysUserSessionService;  
5 -import lombok.extern.slf4j.Slf4j;  
6 -import org.springframework.stereotype.Service;  
7 -  
8 -/**  
9 - * 在线用户 Session Service 实现类  
10 - *  
11 - * @author 芋道源码  
12 - */  
13 -@Service  
14 -@Slf4j  
15 -public class SysUserSessionServiceImpl implements SysUserSessionService {  
16 -  
17 - @Override  
18 - public String createUserSession(LoginUser loginUser, String userIp, String userAgent) {  
19 - return null;  
20 - }  
21 -  
22 - @Override  
23 - public void refreshUserSession(String sessionId, LoginUser loginUser) {  
24 -  
25 - }  
26 -  
27 - @Override  
28 - public void deleteUserSession(String sessionId) {  
29 -  
30 - }  
31 -  
32 - @Override  
33 - public LoginUser getLoginUser(String sessionId) {  
34 - return null;  
35 - }  
36 -  
37 - @Override  
38 - public String getSessionId(String username) {  
39 - return null;  
40 - }  
41 -  
42 - @Override  
43 - public Long getSessionTimeoutMillis() {  
44 - return null;  
45 - }  
46 -  
47 -}