将 dict 和 login log 迁移到共享库里

This commit is contained in:
YunaiV 2021-10-10 02:38:38 +08:00
parent 5b723d02b2
commit 03ef1fc764
57 changed files with 366 additions and 529 deletions

View File

@ -88,6 +88,9 @@
| `yudao-admin-ui` | 管理后台的 UI 界面 |
| `yudao-user-server` | 用户前台的服务端 |
| `yudao-user-ui` | 用户前台的 UI 界面 |
| `yudao-core-service` | 通用服务,提供共享逻辑 |
> 友情提示:`yudao-admin-server` 和 `yudao-user-server` 会存在需要复用的逻辑,通过 `yudao-core-service` 实现。
### 后端

View File

@ -1,12 +1,12 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.dict;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.*;
import cn.iocoder.yudao.adminserver.modules.system.convert.dict.SysDictDataConvert;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.adminserver.modules.system.service.dict.SysDictDataService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.adminserver.modules.system.controller.logger;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
@ -9,7 +10,6 @@ import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog
import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogRespVO;
import cn.iocoder.yudao.adminserver.modules.system.convert.logger.SysLoginLogConvert;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

View File

@ -26,8 +26,7 @@ public interface SysAuthConvert {
SysAuthConvert INSTANCE = Mappers.getMapper(SysAuthConvert.class);
@Mapping(source = "updateTime", target = "updateTime", ignore = true)
// 字段相同但是含义不同忽略
@Mapping(source = "updateTime", target = "updateTime", ignore = true) // 字段相同但是含义不同忽略
LoginUser convert0(SysUserDO bean);
default LoginUser convert(SysUserDO bean) {

View File

@ -1,9 +1,9 @@
package cn.iocoder.yudao.adminserver.modules.system.convert.dict;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.*;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.*;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictDataDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

View File

@ -1,10 +1,9 @@
package cn.iocoder.yudao.adminserver.modules.system.convert.logger;
import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExcelVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogRespVO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@ -15,8 +14,6 @@ public interface SysLoginLogConvert {
SysLoginLogConvert INSTANCE = Mappers.getMapper(SysLoginLogConvert.class);
SysLoginLogDO convert(SysLoginLogCreateReqDTO bean);
PageResult<SysLoginLogRespVO> convertPage(PageResult<SysLoginLogDO> page);
List<SysLoginLogExcelVO> convertList(List<SysLoginLogDO> list);

View File

@ -1,11 +1,11 @@
package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dict;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataPageReqVO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictDataDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;

View File

@ -1,11 +1,11 @@
package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.logger;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
import org.apache.ibatis.annotations.Mapper;

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.adminserver.modules.system.mq.consumer.dict;
import cn.iocoder.yudao.coreservice.modules.system.service.dict.SysDictDataCoreService;
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener;
import cn.iocoder.yudao.adminserver.modules.system.mq.message.dict.SysDictDataRefreshMessage;
import cn.iocoder.yudao.adminserver.modules.system.service.dict.SysDictDataService;
@ -18,12 +19,12 @@ import javax.annotation.Resource;
public class SysDictDataRefreshConsumer extends AbstractChannelMessageListener<SysDictDataRefreshMessage> {
@Resource
private SysDictDataService dictDataService;
private SysDictDataCoreService dictDataCoreService;
@Override
public void onMessage(SysDictDataRefreshMessage message) {
log.info("[onMessage][收到 DictData 刷新消息]");
dictDataService.initLocalCache();
dictDataCoreService.initLocalCache();
}
}

View File

@ -12,13 +12,14 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeE
import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService;
import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;
import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
@ -65,7 +66,7 @@ public class SysAuthServiceImpl implements SysAuthService {
@Resource
private SysCaptchaService captchaService;
@Resource
private SysLoginLogService loginLogService;
private SysLoginLogCoreService loginLogCoreService;
@Resource
private SysUserSessionCoreService userSessionCoreService;
@Resource
@ -164,11 +165,12 @@ public class SysAuthServiceImpl implements SysAuthService {
if (user != null) {
reqDTO.setUserId(user.getId());
}
reqDTO.setUserType(UserTypeEnum.ADMIN.getValue());
reqDTO.setUsername(username);
reqDTO.setUserAgent(ServletUtils.getUserAgent());
reqDTO.setUserIp(ServletUtils.getClientIP());
reqDTO.setResult(loginResult.getResult());
loginLogService.createLoginLog(reqDTO);
loginLogCoreService.createLoginLog(reqDTO);
// 更新最后登录时间
if (user != null && Objects.equals(SysLoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) {
userService.updateUserLogin(user.getId(), ServletUtils.getClientIP());
@ -258,14 +260,16 @@ public class SysAuthServiceImpl implements SysAuthService {
}
private void createLogoutLog(String username) {
// TODO 芋艿这里未设置 userId
SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
reqDTO.setTraceId(TracerUtils.getTraceId());
reqDTO.setUserType(UserTypeEnum.ADMIN.getValue());
reqDTO.setUsername(username);
reqDTO.setUserAgent(ServletUtils.getUserAgent());
reqDTO.setUserIp(ServletUtils.getClientIP());
reqDTO.setResult(SysLoginResultEnum.SUCCESS.getResult());
loginLogService.createLoginLog(reqDTO);
loginLogCoreService.createLoginLog(reqDTO);
}
@Override

View File

@ -9,10 +9,12 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeE
import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;
import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO;
import cn.iocoder.yudao.coreservice.modules.system.dal.redis.auth.SysLoginUserCoreRedisDAO;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import com.google.common.collect.Lists;
@ -42,7 +44,7 @@ public class SysUserSessionServiceImpl implements SysUserSessionService {
@Resource
private SysUserService userService;
@Resource
private SysLoginLogService loginLogService;
private SysLoginLogCoreService loginLogCoreService;
@Resource
private SysLoginUserCoreRedisDAO loginUserCoreRedisDAO;
@ -84,11 +86,12 @@ public class SysUserSessionServiceImpl implements SysUserSessionService {
SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_TIMEOUT.getType());
reqDTO.setTraceId(TracerUtils.getTraceId());
reqDTO.setUserType(UserTypeEnum.ADMIN.getValue());
reqDTO.setUsername(timeoutSessionDO.getUsername());
reqDTO.setUserAgent(timeoutSessionDO.getUserAgent());
reqDTO.setUserIp(timeoutSessionDO.getUserIp());
reqDTO.setResult(SysLoginResultEnum.SUCCESS.getResult());
loginLogService.createLoginLog(reqDTO);
loginLogCoreService.createLoginLog(reqDTO);
}
}

View File

@ -1,12 +1,12 @@
package cn.iocoder.yudao.adminserver.modules.system.service.dict;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.dict.core.service.DictDataFrameworkService;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictDataDO;
import java.util.List;
@ -15,12 +15,7 @@ import java.util.List;
*
* @author ruoyi
*/
public interface SysDictDataService extends DictDataFrameworkService {
/**
* 初始化字典数据的本地缓存
*/
void initLocalCache();
public interface SysDictDataService {
/**
* 创建字典数据

View File

@ -1,35 +1,29 @@
package cn.iocoder.yudao.adminserver.modules.system.service.dict.impl;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.convert.dict.SysDictDataConvert;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictTypeDO;
import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dict.SysDictDataMapper;
import cn.iocoder.yudao.adminserver.modules.system.mq.producer.dict.SysDictDataProducer;
import cn.iocoder.yudao.adminserver.modules.system.service.dict.SysDictDataService;
import cn.iocoder.yudao.adminserver.modules.system.service.dict.SysDictTypeService;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableTable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
/**
* 字典数据 Service 实现类
@ -47,31 +41,6 @@ public class SysDictDataServiceImpl implements SysDictDataService {
.comparing(SysDictDataDO::getDictType)
.thenComparingInt(SysDictDataDO::getSort);
/**
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
* 因为已经通过 Redis Pub/Sub 机制所以频率不需要高
*/
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
/**
* 字典数据缓存第二个 key 使用 label
*
* key1字典类型 dictType
* key2字典标签 label
*/
private ImmutableTable<String, String, SysDictDataDO> labelDictDataCache;
/**
* 字典数据缓存第二个 key 使用 value
*
* key1字典类型 dictType
* key2字典值 value
*/
private ImmutableTable<String, String, SysDictDataDO> valueDictDataCache;
/**
* 缓存字典数据的最大更新时间用于后续的增量轮询判断是否有更新
*/
private volatile Date maxUpdateTime;
@Resource
private SysDictTypeService dictTypeService;
@ -81,34 +50,6 @@ public class SysDictDataServiceImpl implements SysDictDataService {
@Resource
private SysDictDataProducer dictDataProducer;
@Override
@PostConstruct
public synchronized void initLocalCache() {
// 获取字典数据列表如果有更新
List<SysDictDataDO> dataList = this.loadDictDataIfUpdate(maxUpdateTime);
if (CollUtil.isEmpty(dataList)) {
return;
}
// 构建缓存
ImmutableTable.Builder<String, String, SysDictDataDO> labelDictDataBuilder = ImmutableTable.builder();
ImmutableTable.Builder<String, String, SysDictDataDO> valueDictDataBuilder = ImmutableTable.builder();
dataList.forEach(dictData -> {
labelDictDataBuilder.put(dictData.getDictType(), dictData.getLabel(), dictData);
valueDictDataBuilder.put(dictData.getDictType(), dictData.getValue(), dictData);
});
labelDictDataCache = labelDictDataBuilder.build();
valueDictDataCache = valueDictDataBuilder.build();
assert dataList.size() > 0; // 断言避免告警
maxUpdateTime = dataList.stream().max(Comparator.comparing(BaseDO::getUpdateTime)).get().getUpdateTime();
log.info("[initLocalCache][缓存字典数据,数量为:{}]", dataList.size());
}
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
public void schedulePeriodicRefresh() {
initLocalCache();
}
/**
* 如果字典数据发生变化从数据库中获取最新的全量字典数据
* 如果未发生变化则返回空
@ -238,19 +179,4 @@ public class SysDictDataServiceImpl implements SysDictDataService {
}
}
@Override
public DictDataRespDTO getDictDataFromCache(String type, String value) {
return SysDictDataConvert.INSTANCE.convert02(valueDictDataCache.get(type, value));
}
@Override
public DictDataRespDTO parseDictDataFromCache(String type, String label) {
return SysDictDataConvert.INSTANCE.convert02(labelDictDataCache.get(type, label));
}
@Override
public List<DictDataRespDTO> listDictDatasFromCache(String type) {
return SysDictDataConvert.INSTANCE.convertList03(labelDictDataCache.row(type).values());
}
}

View File

@ -1,10 +1,9 @@
package cn.iocoder.yudao.adminserver.modules.system.service.logger;
import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import java.util.List;
@ -13,13 +12,6 @@ import java.util.List;
*/
public interface SysLoginLogService {
/**
* 创建登录日志
*
* @param reqDTO 日志信息
*/
void createLoginLog(SysLoginLogCreateReqDTO reqDTO);
/**
* 获得登录日志分页
*

View File

@ -2,12 +2,9 @@ package cn.iocoder.yudao.adminserver.modules.system.service.logger.impl;
import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.convert.logger.SysLoginLogConvert;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.logger.SysLoginLogMapper;
import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.springframework.stereotype.Service;
@ -23,14 +20,6 @@ public class SysLoginLogServiceImpl implements SysLoginLogService {
@Resource
private SysLoginLogMapper loginLogMapper;
@Override
public void createLoginLog(SysLoginLogCreateReqDTO reqDTO) {
SysLoginLogDO loginLog = SysLoginLogConvert.INSTANCE.convert(reqDTO);
loginLog.setUserType(UserTypeEnum.ADMIN.getValue());
// 插入
loginLogMapper.insert(loginLog);
}
@Override
public PageResult<SysLoginLogDO> getLoginLogPage(SysLoginLogPageReqVO reqVO) {
return loginLogMapper.selectPage(reqVO);

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.adminserver.modules.system.service.auth;
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;
import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
@ -11,7 +12,6 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeE
import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
import cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysAuthServiceImpl;
import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService;
import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
@ -59,7 +59,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
@MockBean
private SysCaptchaService captchaService;
@MockBean
private SysLoginLogService loginLogService;
private SysLoginLogCoreService loginLogCoreService;
@MockBean
private SysUserSessionCoreService userSessionCoreService;
@MockBean
@ -132,7 +132,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
// 调用, 并断言异常
assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_CAPTCHA_NOT_FOUND);
// 校验调用参数
verify(loginLogService, times(1)).createLoginLog(
verify(loginLogCoreService, times(1)).createLoginLog(
argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGIN_USERNAME.getType())
&& o.getResult().equals(SysLoginResultEnum.CAPTCHA_NOT_FOUND.getResult()))
);
@ -150,7 +150,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
// 调用, 并断言异常
assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_CAPTCHA_CODE_ERROR);
// 校验调用参数
verify(loginLogService, times(1)).createLoginLog(
verify(loginLogCoreService, times(1)).createLoginLog(
argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGIN_USERNAME.getType())
&& o.getResult().equals(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult()))
);
@ -171,7 +171,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_BAD_CREDENTIALS);
// 校验调用参数
verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid());
verify(loginLogService, times(1)).createLoginLog(
verify(loginLogCoreService, times(1)).createLoginLog(
argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGIN_USERNAME.getType())
&& o.getResult().equals(SysLoginResultEnum.BAD_CREDENTIALS.getResult()))
);
@ -192,7 +192,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_USER_DISABLED);
// 校验调用参数
verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid());
verify(loginLogService, times(1)).createLoginLog(
verify(loginLogCoreService, times(1)).createLoginLog(
argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGIN_USERNAME.getType())
&& o.getResult().equals(SysLoginResultEnum.USER_DISABLED.getResult()))
);
@ -213,7 +213,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
assertServiceException(() -> authService.login(reqVO, userIp, userAgent), AUTH_LOGIN_FAIL_UNKNOWN);
// 校验调用参数
verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid());
verify(loginLogService, times(1)).createLoginLog(
verify(loginLogCoreService, times(1)).createLoginLog(
argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGIN_USERNAME.getType())
&& o.getResult().equals(SysLoginResultEnum.UNKNOWN_ERROR.getResult()))
);
@ -247,7 +247,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
assertEquals(sessionId, login);
// 校验调用参数
verify(captchaService, times(1)).deleteCaptchaCode(reqVO.getUuid());
verify(loginLogService, times(1)).createLoginLog(
verify(loginLogCoreService, times(1)).createLoginLog(
argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGIN_USERNAME.getType())
&& o.getResult().equals(SysLoginResultEnum.SUCCESS.getResult()))
);
@ -264,7 +264,7 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
authService.logout(token);
// 校验调用参数
verify(userSessionCoreService, times(1)).deleteUserSession(token);
verify(loginLogService, times(1)).createLoginLog(
verify(loginLogCoreService, times(1)).createLoginLog(
argThat(o -> o.getLogType().equals(SysLoginLogTypeEnum.LOGOUT_SELF.getType())
&& o.getResult().equals(SysLoginResultEnum.SUCCESS.getResult()))
);

View File

@ -5,13 +5,13 @@ import cn.iocoder.yudao.adminserver.BaseDbAndRedisUnitTest;
import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO;
import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.auth.SysUserSessionMapper;
import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.user.SysUserMapper;
import cn.iocoder.yudao.adminserver.modules.system.enums.common.SysSexEnum;
import cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysUserSessionServiceImpl;
import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService;
import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth.SysUserSessionDO;
import cn.iocoder.yudao.coreservice.modules.system.dal.redis.auth.SysLoginUserCoreRedisDAO;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
@ -22,8 +22,6 @@ import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@ -55,7 +53,7 @@ public class SysUserSessionServiceImplTest extends BaseDbAndRedisUnitTest {
@MockBean
private SysUserService userService;
@MockBean
private SysLoginLogService loginLogService;
private SysLoginLogCoreService loginLogCoreService;
@MockBean
private SysLoginUserCoreRedisDAO loginUserCoreRedisDAO;

View File

@ -1,13 +1,13 @@
package cn.iocoder.yudao.adminserver.modules.system.service.dict;
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict.SysDictTypeDO;
import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dict.SysDictDataMapper;
import cn.iocoder.yudao.adminserver.modules.system.mq.producer.dict.SysDictDataProducer;
@ -51,37 +51,6 @@ public class SysDictDataServiceTest extends BaseDbUnitTest {
@MockBean
private SysDictDataProducer dictDataProducer;
/**
* 测试加载到新的字典数据的情况
*/
@Test
@SuppressWarnings("unchecked")
public void testInitLocalCache() {
// mock 数据
SysDictDataDO dictData01 = randomDictDataDO();
dictDataMapper.insert(dictData01);
SysDictDataDO dictData02 = randomDictDataDO();
dictDataMapper.insert(dictData02);
// 调用
dictDataService.initLocalCache();
// 断言 labelDictDataCache 缓存
ImmutableTable<String, String, SysDictDataDO> labelDictDataCache =
(ImmutableTable<String, String, SysDictDataDO>) getFieldValue(dictDataService, "labelDictDataCache");
assertEquals(2, labelDictDataCache.size());
assertPojoEquals(dictData01, labelDictDataCache.get(dictData01.getDictType(), dictData01.getLabel()));
assertPojoEquals(dictData02, labelDictDataCache.get(dictData02.getDictType(), dictData02.getLabel()));
// 断言 valueDictDataCache 缓存
ImmutableTable<String, String, SysDictDataDO> valueDictDataCache =
(ImmutableTable<String, String, SysDictDataDO>) getFieldValue(dictDataService, "valueDictDataCache");
assertEquals(2, valueDictDataCache.size());
assertPojoEquals(dictData01, valueDictDataCache.get(dictData01.getDictType(), dictData01.getValue()));
assertPojoEquals(dictData02, valueDictDataCache.get(dictData02.getDictType(), dictData02.getValue()));
// 断言 maxUpdateTime 缓存
Date maxUpdateTime = (Date) getFieldValue(dictDataService, "maxUpdateTime");
assertEquals(ObjectUtils.max(dictData01.getUpdateTime(), dictData02.getUpdateTime()), maxUpdateTime);
}
@Test
public void testGetDictDataPage() {
// mock 数据

View File

@ -2,13 +2,12 @@ package cn.iocoder.yudao.adminserver.modules.system.service.logger;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
import cn.iocoder.yudao.adminserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO;
import cn.iocoder.yudao.adminserver.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO;
import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.logger.SysLoginLogMapper;
import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum;
import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
@ -34,31 +33,9 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest {
@Resource
private SysLoginLogMapper loginLogMapper;
@Test
public void testCreateLoginLog() {
String traceId = TracerUtils.getTraceId();
SysLoginLogCreateReqDTO reqDTO = RandomUtils.randomPojo(SysLoginLogCreateReqDTO.class, vo -> {
// 指定随机的范围,避免超出范围入库失败
vo.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType());
vo.setResult(RandomUtil.randomEle(SysLoginResultEnum.values()).getResult());
// 使用TracerUtils生成的TraceId
vo.setTraceId(traceId);
});
// 执行service方法
sysLoginLogService.createLoginLog(reqDTO);
// 断言忽略基本字段
SysLoginLogDO sysLoginLogDO = loginLogMapper.selectOne(null);
assertPojoEquals(reqDTO, sysLoginLogDO);
}
@Test
public void testGetLoginLogPage() {
// 构造测试数据
// 登录成功的
SysLoginLogDO loginLogDO = RandomUtils.randomPojo(SysLoginLogDO.class, logDO -> {
logDO.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType());

View File

@ -23,6 +23,16 @@
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<dependencies>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-sms</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
@ -57,6 +67,12 @@
<artifactId>yudao-spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.userserver.modules.system.convert.dict;
package cn.iocoder.yudao.coreservice.modules.system.convert.dict;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO;
import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.dict.SysDictDataDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@ -9,9 +9,9 @@ import java.util.Collection;
import java.util.List;
@Mapper
public interface SysDictDataConvert {
public interface SysDictDataCoreConvert {
SysDictDataConvert INSTANCE = Mappers.getMapper(SysDictDataConvert.class);
SysDictDataCoreConvert INSTANCE = Mappers.getMapper(SysDictDataCoreConvert.class);
DictDataRespDTO convert02(SysDictDataDO bean);

View File

@ -0,0 +1,15 @@
package cn.iocoder.yudao.coreservice.modules.system.convert.logger;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface SysLoginLogCoreConvert {
SysLoginLogCoreConvert INSTANCE = Mappers.getMapper(SysLoginLogCoreConvert.class);
SysLoginLogDO convert(SysLoginLogCreateReqDTO bean);
}

View File

@ -0,0 +1,6 @@
/**
* 提供 POJO 类的实体转换
*
* 目前使用 MapStruct 框架
*/
package cn.iocoder.yudao.coreservice.modules.system.convert;

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dict;
package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;

View File

@ -1,9 +1,9 @@
package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger;
package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum;
import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginLogTypeEnum;
import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginResultEnum;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.dict;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Date;
@Mapper
public interface SysDictDataCoreMapper extends BaseMapperX<SysDictDataDO> {
default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
return selectOne(new QueryWrapper<SysDictDataDO>().select("id")
.gt("update_time", maxUpdateTime).last("LIMIT 1")) != null;
}
}

View File

@ -0,0 +1,10 @@
package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.logger;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SysLoginLogCoreMapper extends BaseMapperX<SysLoginLogDO> {
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.userserver.modules.system.enums.logger;
package cn.iocoder.yudao.coreservice.modules.system.enums.logger;
import lombok.AllArgsConstructor;
import lombok.Getter;

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.userserver.modules.system.enums.logger;
package cn.iocoder.yudao.coreservice.modules.system.enums.logger;
import lombok.AllArgsConstructor;
import lombok.Getter;

View File

@ -0,0 +1 @@
package cn.iocoder.yudao.coreservice.modules.system.enums;

View File

@ -1,13 +1,13 @@
package cn.iocoder.yudao.userserver.modules.system.service.dict;
package cn.iocoder.yudao.coreservice.modules.system.service.dict;
import cn.iocoder.yudao.framework.dict.core.service.DictDataFrameworkService;
/**
* 字典数据 Service 接口
*
* @author ruoyi
* @author 芋道源码
*/
public interface SysDictDataService extends DictDataFrameworkService {
public interface SysDictDataCoreService extends DictDataFrameworkService {
/**
* 初始化字典数据的本地缓存

View File

@ -1,12 +1,12 @@
package cn.iocoder.yudao.userserver.modules.system.service.dict.impl;
package cn.iocoder.yudao.coreservice.modules.system.service.dict.impl;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.coreservice.modules.system.convert.dict.SysDictDataCoreConvert;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.dict.SysDictDataCoreMapper;
import cn.iocoder.yudao.coreservice.modules.system.service.dict.SysDictDataCoreService;
import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.userserver.modules.system.convert.dict.SysDictDataConvert;
import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.userserver.modules.system.dal.mysql.dict.SysDictDataMapper;
import cn.iocoder.yudao.userserver.modules.system.service.dict.SysDictDataService;
import com.google.common.collect.ImmutableTable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
@ -21,11 +21,11 @@ import java.util.List;
/**
* 字典数据 Service 实现类
*
* @author ruoyi
* @author 芋道源码
*/
@Service
@Slf4j
public class SysDictDataServiceImpl implements SysDictDataService {
public class SysDictDataCoreServiceImpl implements SysDictDataCoreService {
/**
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
@ -53,7 +53,7 @@ public class SysDictDataServiceImpl implements SysDictDataService {
private volatile Date maxUpdateTime;
@Resource
private SysDictDataMapper dictDataMapper;
private SysDictDataCoreMapper dictDataCoreMapper;
@Override
@PostConstruct
@ -95,28 +95,28 @@ public class SysDictDataServiceImpl implements SysDictDataService {
if (maxUpdateTime == null) { // 如果更新时间为空说明 DB 一定有新数据
log.info("[loadDictDataIfUpdate][首次加载全量字典数据]");
} else { // 判断数据库中是否有更新的字典数据
if (!dictDataMapper.selectExistsByUpdateTimeAfter(maxUpdateTime)) {
if (!dictDataCoreMapper.selectExistsByUpdateTimeAfter(maxUpdateTime)) {
return null;
}
log.info("[loadDictDataIfUpdate][增量加载全量字典数据]");
}
// 第二步如果有更新则从数据库加载所有字典数据
return dictDataMapper.selectList();
return dictDataCoreMapper.selectList();
}
@Override
public DictDataRespDTO getDictDataFromCache(String type, String value) {
return SysDictDataConvert.INSTANCE.convert02(valueDictDataCache.get(type, value));
return SysDictDataCoreConvert.INSTANCE.convert02(valueDictDataCache.get(type, value));
}
@Override
public DictDataRespDTO parseDictDataFromCache(String type, String label) {
return SysDictDataConvert.INSTANCE.convert02(labelDictDataCache.get(type, label));
return SysDictDataCoreConvert.INSTANCE.convert02(labelDictDataCache.get(type, label));
}
@Override
public List<DictDataRespDTO> listDictDatasFromCache(String type) {
return SysDictDataConvert.INSTANCE.convertList03(labelDictDataCache.row(type).values());
return SysDictDataCoreConvert.INSTANCE.convertList03(labelDictDataCache.row(type).values());
}
}

View File

@ -0,0 +1,17 @@
package cn.iocoder.yudao.coreservice.modules.system.service.logger;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
/**
* 登录日志 Core Service 接口
*/
public interface SysLoginLogCoreService {
/**
* 创建登录日志
*
* @param reqDTO 日志信息
*/
void createLoginLog(SysLoginLogCreateReqDTO reqDTO);
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.adminserver.modules.system.service.logger.dto;
package cn.iocoder.yudao.coreservice.modules.system.service.logger.dto;
import lombok.Data;
@ -30,6 +30,11 @@ public class SysLoginLogCreateReqDTO {
* 用户编号
*/
private Long userId;
/**
* 用户类型
*/
@NotNull(message = "用户类型不能为空")
private Integer userType;
/**
* 用户账号
*/

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.coreservice.modules.system.service.logger.impl;
import cn.iocoder.yudao.coreservice.modules.system.convert.logger.SysLoginLogCoreConvert;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.logger.SysLoginLogCoreMapper;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 登录日志 Service Core 实现
*
* @author 芋道源码
*/
@Service
public class SysLoginLogCoreServiceImpl implements SysLoginLogCoreService {
@Resource
private SysLoginLogCoreMapper loginLogMapper;
@Override
public void createLoginLog(SysLoginLogCreateReqDTO reqDTO) {
SysLoginLogDO loginLog = SysLoginLogCoreConvert.INSTANCE.convert(reqDTO);
// 插入
loginLogMapper.insert(loginLog);
}
}

View File

@ -1 +0,0 @@
package cn.iocoder.yudao.coreservice.modules.system.service;

View File

@ -0,0 +1,78 @@
package cn.iocoder.yudao.coreservice.modules.system.service.dict;
import cn.iocoder.yudao.coreservice.BaseDbUnitTest;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dict.SysDictDataDO;
import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.dict.SysDictDataCoreMapper;
import cn.iocoder.yudao.coreservice.modules.system.service.dict.impl.SysDictDataCoreServiceImpl;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import com.google.common.collect.ImmutableTable;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import java.util.Date;
import java.util.function.Consumer;
import static cn.hutool.core.bean.BeanUtil.getFieldValue;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomCommonStatus;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* {@link SysDictDataCoreServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(SysDictDataCoreServiceImpl.class)
public class SysDictDataCoreServiceTest extends BaseDbUnitTest {
@Resource
private SysDictDataCoreServiceImpl dictDataCoreService;
@Resource
private SysDictDataCoreMapper dictDataMapper;
/**
* 测试加载到新的字典数据的情况
*/
@Test
@SuppressWarnings("unchecked")
public void testInitLocalCache() {
// mock 数据
SysDictDataDO dictData01 = randomDictDataDO();
dictDataMapper.insert(dictData01);
SysDictDataDO dictData02 = randomDictDataDO();
dictDataMapper.insert(dictData02);
// 调用
dictDataCoreService.initLocalCache();
// 断言 labelDictDataCache 缓存
ImmutableTable<String, String, SysDictDataDO> labelDictDataCache =
(ImmutableTable<String, String, SysDictDataDO>) getFieldValue(dictDataCoreService, "labelDictDataCache");
assertEquals(2, labelDictDataCache.size());
assertPojoEquals(dictData01, labelDictDataCache.get(dictData01.getDictType(), dictData01.getLabel()));
assertPojoEquals(dictData02, labelDictDataCache.get(dictData02.getDictType(), dictData02.getLabel()));
// 断言 valueDictDataCache 缓存
ImmutableTable<String, String, SysDictDataDO> valueDictDataCache =
(ImmutableTable<String, String, SysDictDataDO>) getFieldValue(dictDataCoreService, "valueDictDataCache");
assertEquals(2, valueDictDataCache.size());
assertPojoEquals(dictData01, valueDictDataCache.get(dictData01.getDictType(), dictData01.getValue()));
assertPojoEquals(dictData02, valueDictDataCache.get(dictData02.getDictType(), dictData02.getValue()));
// 断言 maxUpdateTime 缓存
Date maxUpdateTime = (Date) getFieldValue(dictDataCoreService, "maxUpdateTime");
assertEquals(ObjectUtils.max(dictData01.getUpdateTime(), dictData02.getUpdateTime()), maxUpdateTime);
}
// ========== 随机对象 ==========
@SafeVarargs
private static SysDictDataDO randomDictDataDO(Consumer<SysDictDataDO>... consumers) {
Consumer<SysDictDataDO> consumer = (o) -> {
o.setStatus(randomCommonStatus()); // 保证 status 的范围
};
return randomPojo(SysDictDataDO.class, ArrayUtils.append(consumer, consumers));
}
}

View File

@ -0,0 +1,45 @@
package cn.iocoder.yudao.coreservice.modules.system.service.logger;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.coreservice.BaseDbUnitTest;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.logger.SysLoginLogDO;
import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.logger.SysLoginLogCoreMapper;
import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginLogTypeEnum;
import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginResultEnum;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.impl.SysLoginLogCoreServiceImpl;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
@Import(SysLoginLogCoreServiceImpl.class)
public class SysLoginLogServiceImplTest extends BaseDbUnitTest {
@Resource
private SysLoginLogCoreServiceImpl loginLogCoreService;
@Resource
private SysLoginLogCoreMapper loginLogCoreMapper;
@Test
public void testCreateLoginLog() {
SysLoginLogCreateReqDTO reqDTO = RandomUtils.randomPojo(SysLoginLogCreateReqDTO.class, vo -> {
// 指定随机的范围,避免超出范围入库失败
vo.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType());
vo.setResult(RandomUtil.randomEle(SysLoginResultEnum.values()).getResult());
vo.setTraceId(TracerUtils.getTraceId());
});
// 调用
loginLogCoreService.createLoginLog(reqDTO);
// 断言忽略基本字段
SysLoginLogDO sysLoginLogDO = loginLogCoreMapper.selectOne(null);
assertPojoEquals(reqDTO, sysLoginLogDO);
}
}

View File

@ -2,3 +2,4 @@
-- sys 开头的 DB
DELETE FROM "sys_user_session";
DELETE FROM "sys_dict_data";

View File

@ -18,3 +18,18 @@ CREATE TABLE IF NOT EXISTS `sys_user_session` (
PRIMARY KEY (`id`)
) COMMENT '用户在线 Session';
CREATE TABLE IF NOT EXISTS "sys_dict_data" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"sort" int NOT NULL DEFAULT '0',
"label" varchar(100) NOT NULL DEFAULT '',
"value" varchar(100) NOT NULL DEFAULT '',
"dict_type" varchar(100) NOT NULL DEFAULT '',
"status" tinyint NOT NULL DEFAULT '0',
"remark" varchar(500) DEFAULT NULL,
"creator" varchar(64) DEFAULT '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '字典数据表';

View File

@ -18,6 +18,11 @@
<dependencies>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-core-service</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-dict</artifactId>

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.userserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class UserServerApplication {
@SuppressWarnings("SpringComponentScan") // 忽略 IDEA 无法识别 ${yudao.info.base-package} ${yudao.core-service.base-package}
@SpringBootApplication(scanBasePackages = {"${yudao.info.base-package}", "${yudao.core-service.base-package}"})public class UserServerApplication {
public static void main(String[] args) {
SpringApplication.run(UserServerApplication.class, args);

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.userserver.modules.member.convert.user;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.userserver.modules.member.dal.dataobject.user.MbrUserDO;
import org.mapstruct.Mapper;
@ -10,6 +11,11 @@ public interface MbrAuthConvert {
MbrAuthConvert INSTANCE = Mappers.getMapper(MbrAuthConvert.class);
LoginUser convert(MbrUserDO bean);
LoginUser convert0(MbrUserDO bean);
default LoginUser convert(MbrUserDO bean) {
// 目的为了设置 UserTypeEnum.MEMBER.getValue()
return convert0(bean).setUserType(UserTypeEnum.MEMBER.getValue());
}
}

View File

@ -1,20 +1,18 @@
package cn.iocoder.yudao.userserver.modules.member.service.auth.impl;
import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.userserver.modules.member.controller.auth.vo.MbrAuthLoginReqVO;
import cn.iocoder.yudao.userserver.modules.member.convert.user.MbrAuthConvert;
import cn.iocoder.yudao.userserver.modules.member.dal.dataobject.user.MbrUserDO;
import cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants;
import cn.iocoder.yudao.userserver.modules.member.service.auth.MbrAuthService;
import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
import cn.iocoder.yudao.userserver.modules.system.enums.logger.SysLoginLogTypeEnum;
import cn.iocoder.yudao.userserver.modules.system.enums.logger.SysLoginResultEnum;
import cn.iocoder.yudao.userserver.modules.system.service.auth.SysUserSessionService;
import cn.iocoder.yudao.userserver.modules.system.service.logger.SysLoginLogService;
import cn.iocoder.yudao.userserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import cn.iocoder.yudao.userserver.modules.system.service.logger.impl.SysLoginLogServiceImpl;
import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginLogTypeEnum;
import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
@ -29,7 +27,6 @@ import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -51,9 +48,9 @@ public class MbrAuthServiceImpl implements MbrAuthService {
@Resource
private MbrUserService userService;
@Resource
private SysLoginLogService loginLogService;
private SysLoginLogCoreService loginLogCoreService;
@Resource
private SysUserSessionService userSessionService;
private SysUserSessionCoreService userSessionCoreService;
@Override
public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
@ -72,7 +69,7 @@ public class MbrAuthServiceImpl implements MbrAuthService {
LoginUser loginUser = this.login0(reqVO.getMobile(), reqVO.getPassword());
// 缓存登录用户到 Redis 返回 sessionId 编号
return userSessionService.createUserSession(loginUser, userIp, userAgent);
return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
}
private LoginUser login0(String username, String password) {
@ -114,7 +111,7 @@ public class MbrAuthServiceImpl implements MbrAuthService {
reqDTO.setUserAgent(ServletUtils.getUserAgent());
reqDTO.setUserIp(ServletUtils.getClientIP());
reqDTO.setResult(loginResult.getResult());
loginLogService.createLoginLog(reqDTO);
loginLogCoreService.createLoginLog(reqDTO);
// 更新最后登录时间
if (user != null && Objects.equals(SysLoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) {
userService.updateUserLogin(user.getId(), ServletUtils.getClientIP());

View File

@ -1,15 +0,0 @@
package cn.iocoder.yudao.userserver.modules.system.convert.logger;
import cn.iocoder.yudao.userserver.modules.system.dal.mysql.logger.SysLoginLogDO;
import cn.iocoder.yudao.userserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface SysLoginLogConvert {
SysLoginLogConvert INSTANCE = Mappers.getMapper(SysLoginLogConvert.class);
SysLoginLogDO convert(SysLoginLogCreateReqDTO bean);
}

View File

@ -1,54 +0,0 @@
package cn.iocoder.yudao.userserver.modules.system.dal.dataobject.dict;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 字典数据表
*
* @author ruoyi
*/
@TableName("sys_dict_data")
@Data
@EqualsAndHashCode(callSuper = true)
public class SysDictDataDO extends BaseDO {
/**
* 字典数据编号
*/
@TableId
private Long id;
/**
* 字典排序
*/
private Integer sort;
/**
* 字典标签
*/
private String label;
/**
* 字典值
*/
private String value;
/**
* 字典类型
*
* 冗余 {@link SysDictDataDO#getDictType()}
*/
private String dictType;
/**
* 状态
*
* 枚举 {@link CommonStatusEnum}
*/
private Integer status;
/**
* 备注
*/
private String remark;
}

View File

@ -1,10 +0,0 @@
package cn.iocoder.yudao.userserver.modules.system.dal.dataobject.logger;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.userserver.modules.system.dal.mysql.logger.SysLoginLogDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SysLoginLogMapper extends BaseMapperX<SysLoginLogDO> {
}

View File

@ -1 +0,0 @@
package cn.iocoder.yudao.userserver.modules.system.dal.dataobject;

View File

@ -1,28 +0,0 @@
package cn.iocoder.yudao.userserver.modules.system.dal.mysql.dict;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.dict.SysDictDataDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Date;
@Mapper
public interface SysDictDataMapper extends BaseMapperX<SysDictDataDO> {
default SysDictDataDO selectByDictTypeAndValue(String dictType, String value) {
return selectOne(new QueryWrapper<SysDictDataDO>().eq("dict_type", dictType)
.eq("value", value));
}
default int selectCountByDictType(String dictType) {
return selectCount("dict_type", dictType);
}
default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
return selectOne(new QueryWrapper<SysDictDataDO>().select("id")
.gt("update_time", maxUpdateTime).last("LIMIT 1")) != null;
}
}

View File

@ -1,70 +0,0 @@
package cn.iocoder.yudao.userserver.modules.system.dal.mysql.logger;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.userserver.modules.system.enums.logger.SysLoginLogTypeEnum;
import cn.iocoder.yudao.userserver.modules.system.enums.logger.SysLoginResultEnum;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 登录日志表
*
* 注意包括登录和登出两种行为
*
* @author 芋道源码
*/
@TableName("sys_login_log")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SysLoginLogDO extends BaseDO {
/**
* 日志主键
*/
private Long id;
/**
* 日志类型
*
* 枚举 {@link SysLoginLogTypeEnum}
*/
private Integer logType;
/**
* 链路追踪编号
*/
private String traceId;
/**
* 用户编号
*/
private Long userId;
/**
* 用户类型
*
* 枚举 {@link UserTypeEnum}
*/
private Integer userType;
/**
* 用户账号
*
* 冗余因为账号可以变更
*/
private String username;
/**
* 登录结果
*
* 枚举 {@link SysLoginResultEnum}
*/
private Integer result;
/**
* 用户 IP
*/
private String userIp;
/**
* 浏览器 UA
*/
private String userAgent;
}

View File

@ -1 +0,0 @@
package cn.iocoder.yudao.userserver.modules.system.enums;

View File

@ -1,17 +0,0 @@
package cn.iocoder.yudao.userserver.modules.system.service.logger;
import cn.iocoder.yudao.userserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
/**
* 登录日志 Service 接口
*/
public interface SysLoginLogService {
/**
* 创建登录日志
*
* @param reqDTO 日志信息
*/
void createLoginLog(SysLoginLogCreateReqDTO reqDTO);
}

View File

@ -1,57 +0,0 @@
package cn.iocoder.yudao.userserver.modules.system.service.logger.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* 登录日志创建 Request DTO
*
* @author 芋道源码
*/
@Data
public class SysLoginLogCreateReqDTO {
/**
* 日志类型
*/
@NotNull(message = "日志类型不能为空")
private Integer logType;
/**
* 链路追踪编号
*/
@NotEmpty(message = "链路追踪编号不能为空")
private String traceId;
/**
* 用户编号
*/
private Long userId;
/**
* 用户账号
*/
@NotBlank(message = "用户账号不能为空")
@Size(max = 30, message = "用户账号长度不能超过30个字符")
private String username;
/**
* 登录结果
*/
@NotNull(message = "登录结果不能为空")
private Integer result;
/**
* 用户 IP
*/
@NotEmpty(message = "用户 IP 不能为空")
private String userIp;
/**
* 浏览器 UserAgent
*/
@NotEmpty(message = "浏览器 UserAgent 不能为空")
private String userAgent;
}

View File

@ -1,30 +0,0 @@
package cn.iocoder.yudao.userserver.modules.system.service.logger.impl;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.userserver.modules.system.convert.logger.SysLoginLogConvert;
import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.logger.SysLoginLogMapper;
import cn.iocoder.yudao.userserver.modules.system.dal.mysql.logger.SysLoginLogDO;
import cn.iocoder.yudao.userserver.modules.system.service.logger.SysLoginLogService;
import cn.iocoder.yudao.userserver.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 登录日志 Service 实现
*/
@Service
public class SysLoginLogServiceImpl implements SysLoginLogService {
@Resource
private SysLoginLogMapper loginLogMapper;
@Override
public void createLoginLog(SysLoginLogCreateReqDTO reqDTO) {
SysLoginLogDO loginLog = SysLoginLogConvert.INSTANCE.convert(reqDTO);
loginLog.setUserType(UserTypeEnum.MEMBER.getValue());
// 插入
loginLogMapper.insert(loginLog);
}
}

View File

@ -1 +0,0 @@
package cn.iocoder.yudao.userserver.modules.system.service;

View File

@ -31,7 +31,7 @@ mybatis-plus:
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject
type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject, ${yudao.core-service.base-package}.modules.*.dal.dataobject
--- #################### 芋道相关配置 ####################
@ -39,6 +39,8 @@ yudao:
info:
version: 1.0.0
base-package: cn.iocoder.yudao.userserver
core-service:
base-package: cn.iocoder.yudao.coreservice
web:
api-prefix: /api
controller-package: ${yudao.info.base-package}