diff --git a/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java b/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java new file mode 100644 index 000000000..11937f1a7 --- /dev/null +++ b/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java @@ -0,0 +1,171 @@ +package cn.iocoder.dashboard.modules.system.service.logger; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.iocoder.dashboard.BaseSpringBootUnitTest; +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; +import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; +import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; +import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO; +import cn.iocoder.dashboard.modules.system.convert.logger.SysLoginLogConvert; +import cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysLoginLogDO; +import cn.iocoder.dashboard.modules.system.dal.mysql.logger.SysLoginLogMapper; +import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum; +import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum; +import cn.iocoder.dashboard.modules.system.service.logger.impl.SysLoginLogServiceImpl; +import cn.iocoder.dashboard.util.RandomUtils; +import cn.iocoder.dashboard.util.object.ObjectUtils; +import org.junit.jupiter.api.Test; + +import javax.annotation.Resource; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.dashboard.util.date.DateUtils.buildTime; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class SysLoginLogServiceImplTest extends BaseSpringBootUnitTest { + + @Resource + private SysLoginLogServiceImpl sysLoginLogService; + + @Resource + private SysLoginLogMapper loginLogMapper; + + @Test + public void testCreateLoginLog() { + + String traceId = TracerUtils.getTraceId(); + SysLoginLogCreateReqVO reqVO = RandomUtils.randomPojo(SysLoginLogCreateReqVO.class, vo -> { + // 指定随机的范围,避免超出范围入库失败 + vo.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType()); + vo.setResult(RandomUtil.randomEle(SysLoginResultEnum.values()).getResult()); + // 使用TracerUtils生成的TraceId + vo.setTraceId(traceId); + }); + + + // 执行service方法 + sysLoginLogService.createLoginLog(reqVO); + + // 查询插入的数据 + SysLoginLogDO sysLoginLogDO = loginLogMapper.selectOne("trace_id", traceId); + + // 断言,忽略基本字段 + assertPojoEquals( + SysLoginLogConvert.INSTANCE.convert(reqVO), + sysLoginLogDO, + getBaseDOFields() + ); + } + + + @Test + public void testGetLoginLogPage() { + + // 构造测试数据 + + // 登录成功的 + SysLoginLogDO loginLogDO = RandomUtils.randomPojo(SysLoginLogDO.class, logDO -> { + logDO.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType()); + logDO.setTraceId(TracerUtils.getTraceId()); + + logDO.setUserIp("192.168.199.16"); + logDO.setUsername("wangkai"); + logDO.setCreateTime(buildTime(2021, 3, 6)); + logDO.setResult(SysLoginResultEnum.SUCCESS.getResult()); + }); + loginLogMapper.insert(loginLogDO); + + // 下面几个都是不匹配的数据 + // 登录失败的 + loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult()))); + // 不同ip段的 + loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18"))); + // 不同username + loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUsername("yunai"))); + // 构造一个早期时间 2021-02-06 00:00:00 + loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6)))); + + + // 构造调用参数 + SysLoginLogPageReqVO reqVO = new SysLoginLogPageReqVO(); + reqVO.setUsername("wangkai"); + reqVO.setUserIp("192.168.199"); + reqVO.setStatus(true); + reqVO.setBeginTime(buildTime(2021, 3, 5)); + reqVO.setEndTime(buildTime(2021, 3, 7)); + + // 调用service方法 + PageResult pageResult = sysLoginLogService.getLoginLogPage(reqVO); + + // 断言,只查到了一条符合条件的 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(loginLogDO, pageResult.getList().get(0)); + } + + @Test + public void testGetLoginLogList() { + + // 构造测试数据 + + // 登录成功的 + SysLoginLogDO loginLogDO = RandomUtils.randomPojo(SysLoginLogDO.class, logDO -> { + logDO.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType()); + logDO.setTraceId(TracerUtils.getTraceId()); + + logDO.setUserIp("192.168.111.16"); + logDO.setUsername("wangxiaokai"); + logDO.setCreateTime(buildTime(2021, 3, 6)); + logDO.setResult(SysLoginResultEnum.SUCCESS.getResult()); + }); + loginLogMapper.insert(loginLogDO); + + // 下面几个都是不匹配的数据 + // 登录失败的 + loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult()))); + // 不同ip段的 + loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18"))); + // 不同username + loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUsername("yunai"))); + // 构造一个早期时间 2021-02-06 00:00:00 + loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6)))); + + + // 构造调用参数 + SysLoginLogExportReqVO reqVO = new SysLoginLogExportReqVO(); + reqVO.setUsername("wangxiaokai"); + reqVO.setUserIp("192.168.111"); + reqVO.setStatus(true); + reqVO.setBeginTime(buildTime(2021, 3, 5)); + reqVO.setEndTime(buildTime(2021, 3, 7)); + + + // 调用service方法 + List loginLogList = sysLoginLogService.getLoginLogList(reqVO); + + // 断言 + assertEquals(1, loginLogList.size()); + assertPojoEquals(loginLogDO, loginLogList.get(0)); + } + + + private static String[] getBaseDOFields() { + Field[] fields = ReflectUtil.getFields(BaseDO.class); + + List collect = Arrays.stream(fields) + .map(Field::getName) + .collect(Collectors.toList()); + collect.add("id"); + + return ArrayUtil.toArray(collect, String.class); + } + +} diff --git a/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java b/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java new file mode 100644 index 000000000..86e03bba5 --- /dev/null +++ b/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java @@ -0,0 +1,216 @@ +package cn.iocoder.dashboard.modules.system.service.logger; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.iocoder.dashboard.BaseSpringBootUnitTest; +import cn.iocoder.dashboard.common.enums.CommonStatusEnum; +import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum; +import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; +import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogCreateReqVO; +import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO; +import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO; +import cn.iocoder.dashboard.modules.system.convert.logger.SysOperateLogConvert; +import cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysOperateLogDO; +import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.dashboard.modules.system.dal.mysql.logger.SysOperateLogMapper; +import cn.iocoder.dashboard.modules.system.dal.mysql.user.SysUserMapper; +import cn.iocoder.dashboard.modules.system.enums.common.SysSexEnum; +import cn.iocoder.dashboard.util.RandomUtils; +import cn.iocoder.dashboard.util.object.ObjectUtils; +import org.junit.jupiter.api.Test; + +import javax.annotation.Resource; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.dashboard.util.date.DateUtils.buildTime; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class SysOperateLogServiceImplTest extends BaseSpringBootUnitTest { + + @Resource + private SysOperateLogService sysOperateLogServiceImpl; + + @Resource + private SysOperateLogMapper sysOperateLogMapper; + + @Resource + private SysUserMapper sysUserMapper; + + @Test + public void testCreateOperateLogAsync() throws InterruptedException { + + String traceId = TracerUtils.getTraceId(); + SysOperateLogCreateReqVO reqVO = RandomUtils.randomPojo(SysOperateLogCreateReqVO.class, vo -> { + vo.setTraceId(traceId); + vo.setUserId(RandomUtil.randomLong(1, Long.MAX_VALUE)); + + Map map = new HashMap<>(); + map.put("orderId", 1); + vo.setExts(map); + }); + + // 执行service方法 + sysOperateLogServiceImpl.createOperateLogAsync(reqVO); + + // 等异步执行完 + Thread.sleep(2000); + + // 查询插入的数据 + SysOperateLogDO sysOperateLogDO = sysOperateLogMapper.selectOne("trace_id", traceId); + + // 断言 + assertNotNull(sysOperateLogDO); + // 断言,忽略基本字段 + assertPojoEquals( + SysOperateLogConvert.INSTANCE.convert(reqVO), + sysOperateLogDO, + getBaseDOFields() + ); + } + + + @Test + public void testPageOperateLog() { + + // 构造测试数据 + + // 先构造用户 + SysUserDO user = RandomUtils.randomPojo(SysUserDO.class, sysUserDO -> { + sysUserDO.setNickname("wangkai"); + sysUserDO.setSex(SysSexEnum.MALE.getSEX()); + sysUserDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + }); + sysUserMapper.insert(user); + Long userId = user.getId(); + + + // 构造操作日志 + SysOperateLogDO sysOperateLogDO = RandomUtils.randomPojo(SysOperateLogDO.class, entity -> { + entity.setTraceId(TracerUtils.getTraceId()); + entity.setUserId(userId); + entity.setModule("order"); + entity.setType(OperateTypeEnum.CREATE.getType()); + entity.setStartTime(buildTime(2021, 3, 6)); + entity.setResultCode(GlobalErrorCodeConstants.SUCCESS.getCode()); + + Map map = new HashMap<>(); + map.put("orderId", 1); + entity.setExts(map); + }); + + sysOperateLogMapper.insert(sysOperateLogDO); + + // 下面几个是不匹配的数据 + // 随机userId + sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setUserId(userId + 1))); + // module不同 + sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setModule("user"))); + // type不同 + sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType()))); + // createTime不同 + sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6)))); + // resultCode不同 + sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode()))); + + // 构造调用参数 + SysOperateLogPageReqVO reqVO = new SysOperateLogPageReqVO(); + reqVO.setUserNickname("wangkai"); + reqVO.setModule("order"); + reqVO.setType(OperateTypeEnum.CREATE.getType()); + reqVO.setBeginTime(buildTime(2021, 3, 5)); + reqVO.setEndTime(buildTime(2021, 3, 7)); + reqVO.setSuccess(true); + + // 调用service方法 + PageResult pageResult = sysOperateLogServiceImpl.pageOperateLog(reqVO); + + // 断言,只查到了一条符合条件的 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(sysOperateLogDO, pageResult.getList().get(0)); + } + + @Test + public void testListOperateLogs() { + + // 构造测试数据 + + // 先构造用户 + SysUserDO user = RandomUtils.randomPojo(SysUserDO.class, sysUserDO -> { + sysUserDO.setNickname("wangkai"); + sysUserDO.setSex(SysSexEnum.MALE.getSEX()); + sysUserDO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + }); + sysUserMapper.insert(user); + Long userId = user.getId(); + + + // 构造操作日志 + SysOperateLogDO sysOperateLogDO = RandomUtils.randomPojo(SysOperateLogDO.class, entity -> { + entity.setTraceId(TracerUtils.getTraceId()); + entity.setUserId(userId); + entity.setModule("order"); + entity.setType(OperateTypeEnum.CREATE.getType()); + entity.setStartTime(buildTime(2021, 3, 6)); + entity.setResultCode(GlobalErrorCodeConstants.SUCCESS.getCode()); + + Map map = new HashMap<>(); + map.put("orderId", 1); + entity.setExts(map); + }); + + sysOperateLogMapper.insert(sysOperateLogDO); + + // 下面几个是不匹配的数据 + // 随机userId + sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setUserId(userId + 1))); + // module不同 + sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setModule("user"))); + // type不同 + sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType()))); + // createTime不同 + sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6)))); + // resultCode不同 + sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode()))); + + // 构造调用参数 + SysOperateLogExportReqVO reqVO = new SysOperateLogExportReqVO(); + reqVO.setUserNickname("wangkai"); + reqVO.setModule("order"); + reqVO.setType(OperateTypeEnum.CREATE.getType()); + reqVO.setBeginTime(buildTime(2021, 3, 5)); + reqVO.setEndTime(buildTime(2021, 3, 7)); + reqVO.setSuccess(true); + + // 调用service方法 + List list = sysOperateLogServiceImpl.listOperateLogs(reqVO); + + // 断言,只查到了一条符合条件的 + assertEquals(1, list.size()); + assertPojoEquals(sysOperateLogDO, list.get(0)); + } + + + private static String[] getBaseDOFields() { + Field[] fields = ReflectUtil.getFields(BaseDO.class); + + List collect = Arrays.stream(fields) + .map(Field::getName) + .collect(Collectors.toList()); + collect.add("id"); + + return ArrayUtil.toArray(collect, String.class); + } + +} diff --git a/src/test/resources/sql/clean.sql b/src/test/resources/sql/clean.sql index 2887b4e9d..e23b555a1 100644 --- a/src/test/resources/sql/clean.sql +++ b/src/test/resources/sql/clean.sql @@ -7,3 +7,6 @@ DELETE FROM "sys_dict_data"; DELETE FROM "sys_role"; DELETE FROM "sys_role_menu"; DELETE FROM "sys_menu"; +DELETE FROM "sys_login_log"; +DELETE FROM "sys_operate_log"; +DELETE FROM "sys_user"; diff --git a/src/test/resources/sql/create_tables.sql b/src/test/resources/sql/create_tables.sql index 183554519..e8f20cfde 100644 --- a/src/test/resources/sql/create_tables.sql +++ b/src/test/resources/sql/create_tables.sql @@ -100,3 +100,71 @@ CREATE TABLE IF NOT EXISTS "sys_menu" ( "deleted" bit NOT NULL DEFAULT FALSE, PRIMARY KEY ("id") ) COMMENT '菜单权限表'; + +CREATE TABLE IF NOT EXISTS `sys_login_log` ( + `id` bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, + `log_type` bigint(4) NOT NULL, + `trace_id` varchar(64) NOT NULL DEFAULT '', + `username` varchar(50) NOT NULL DEFAULT '', + `result` tinyint(4) NOT NULL, + `user_ip` varchar(50) NOT NULL, + `user_agent` varchar(512) NOT NULL, + `create_by` varchar(64) DEFAULT '', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `update_by` varchar(64) DEFAULT '', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted` bit(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) COMMENT ='系统访问记录'; + + +CREATE TABLE `sys_operate_log` ( + `id` bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, + `trace_id` varchar(64) NOT NULL DEFAULT '', + `user_id` bigint(20) NOT NULL, + `module` varchar(50) NOT NULL, + `name` varchar(50) NOT NULL, + `operate_type` bigint(4) NOT NULL DEFAULT '0', + `content` varchar(2000) NOT NULL DEFAULT '', + `exts` varchar(512) NOT NULL DEFAULT '', + `request_method` varchar(16) DEFAULT '', + `request_url` varchar(255) DEFAULT '', + `user_ip` varchar(50) DEFAULT NULL, + `user_agent` varchar(200) DEFAULT NULL, + `java_method` varchar(512) NOT NULL DEFAULT '', + `java_method_args` varchar(8000) DEFAULT '', + `start_time` datetime NOT NULL, + `duration` int(11) NOT NULL, + `result_code` int(11) NOT NULL DEFAULT '0', + `result_msg` varchar(512) DEFAULT '', + `result_data` varchar(4000) DEFAULT '', + `create_by` varchar(64) DEFAULT '', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `update_by` varchar(64) DEFAULT '', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted` bit(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) COMMENT ='操作日志记录'; + +create table "sys_user" ( + "id" bigint not null GENERATED BY DEFAULT AS IDENTITY, + "username" varchar(30) not null, + "password" varchar(100) not null default '', + "nickname" varchar(30) not null, + "remark" varchar(500) default null, + "dept_id" bigint default null, + "post_ids" varchar(255) default null, + "email" varchar(50) default '', + "mobile" varchar(11) default '', + "sex" tinyint default '0', + "avatar" varchar(100) default '', + "status" tinyint not null default '0', + "login_ip" varchar(50) default '', + "login_date" timestamp default null, + "create_by" varchar(64) default '', + "create_time" timestamp not null default current_timestamp, + "update_by" varchar(64) default '', + "update_time" timestamp not null default current_timestamp, + "deleted" bit not null default false, + primary key ("id") +) comment '用户信息表'; \ No newline at end of file