From c590b1b6931b0779862ee488245c1bd52e9a12d7 Mon Sep 17 00:00:00 2001 From: xujun Date: Thu, 4 Jun 2026 17:40:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AE=89=E5=85=A8=E8=A7=84?= =?UTF-8?q?=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/common/cache/enums/AppCache.java | 7 + .../app/common/task/enums/TaskType.java | 2 + .../app/sys/api/SysUserPasswdRuleApi.java | 14 + .../app/sys/controller/SysUserController.java | 17 + .../SysUserPasswdRuleController.java | 135 +++++++ .../sys/convert/SysUserPasswdRuleConvert.java | 72 ++++ .../java/xtools/app/sys/job/SysUserJob.java | 35 ++ .../sys/mapper/SysUserPasswdRuleMapper.java | 19 + .../dto/excel/SysUserPasswdRuleExcel.java | 156 ++++++++ .../app/sys/model/dto/req/SysUserAddReq.java | 7 + .../dto/req/SysUserPasswdRuleAddReq.java | 174 ++++++++ .../dto/req/SysUserPasswdRulePageReq.java | 192 +++++++++ .../dto/req/SysUserPasswdRuleUpdateReq.java | 180 +++++++++ .../sys/model/dto/req/SysUserUpdateReq.java | 7 + .../model/dto/resp/SysBaseUserInfoResp.java | 6 + .../model/dto/resp/SysUserPasswdRuleResp.java | 181 +++++++++ .../app/sys/model/dto/resp/SysUserResp.java | 22 +- .../app/sys/model/entity/SysAddress.java | 3 +- .../xtools/app/sys/model/entity/SysDept.java | 3 +- .../xtools/app/sys/model/entity/SysDict.java | 3 +- .../app/sys/model/entity/SysDictItem.java | 3 +- .../xtools/app/sys/model/entity/SysFile.java | 3 +- .../xtools/app/sys/model/entity/SysLog.java | 3 +- .../xtools/app/sys/model/entity/SysMenu.java | 3 +- .../app/sys/model/entity/SysNotice.java | 3 +- .../app/sys/model/entity/SysOptLog.java | 3 +- .../xtools/app/sys/model/entity/SysParam.java | 3 +- .../xtools/app/sys/model/entity/SysRisk.java | 3 +- .../xtools/app/sys/model/entity/SysRole.java | 3 +- .../app/sys/model/entity/SysRoleMenu.java | 3 +- .../xtools/app/sys/model/entity/SysTask.java | 3 +- .../sys/model/entity/SysUpdateHistory.java | 3 +- .../xtools/app/sys/model/entity/SysUser.java | 33 +- .../app/sys/model/entity/SysUserNotice.java | 3 +- .../sys/model/entity/SysUserPasswdRule.java | 213 ++++++++++ .../app/sys/model/entity/SysUserRole.java | 3 +- .../app/sys/service/SysPasswdService.java | 43 ++ .../sys/service/SysUserPasswdRuleService.java | 99 +++++ .../app/sys/service/SysUserService.java | 13 + .../base/SysUserPasswdRuleBaseService.java | 20 + .../sys/service/impl/SysBaseServiceImpl.java | 98 ++++- .../sys/service/impl/SysLoginServiceImpl.java | 76 +++- .../service/impl/SysPasswdServiceImpl.java | 248 ++++++++++++ .../impl/SysUserPasswdRuleServiceImpl.java | 377 ++++++++++++++++++ .../sys/service/impl/SysUserServiceImpl.java | 106 ++++- .../app/sys/call/SysUserPasswdRuleCall.java | 18 + 46 files changed, 2576 insertions(+), 45 deletions(-) create mode 100644 xtools-app-sys/xtools-app-sys-api/src/main/java/xtools/app/sys/api/SysUserPasswdRuleApi.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/controller/SysUserPasswdRuleController.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/convert/SysUserPasswdRuleConvert.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/job/SysUserJob.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/mapper/SysUserPasswdRuleMapper.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/excel/SysUserPasswdRuleExcel.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserPasswdRuleAddReq.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserPasswdRulePageReq.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserPasswdRuleUpdateReq.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysUserPasswdRuleResp.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUserPasswdRule.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysPasswdService.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysUserPasswdRuleService.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/base/SysUserPasswdRuleBaseService.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysPasswdServiceImpl.java create mode 100644 xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysUserPasswdRuleServiceImpl.java create mode 100644 xtools-app-sys/xtools-app-sys-call/src/main/java/xtools/app/sys/call/SysUserPasswdRuleCall.java diff --git a/xtools-app-common/xtools-app-common-cache/src/main/java/xtools/app/common/cache/enums/AppCache.java b/xtools-app-common/xtools-app-common-cache/src/main/java/xtools/app/common/cache/enums/AppCache.java index 0b84d27..944e3fe 100644 --- a/xtools-app-common/xtools-app-common-cache/src/main/java/xtools/app/common/cache/enums/AppCache.java +++ b/xtools-app-common/xtools-app-common-cache/src/main/java/xtools/app/common/cache/enums/AppCache.java @@ -34,6 +34,8 @@ public enum AppCache implements BaseCacheEnum { // JOB锁 LOCK_JOB("lock:job:", 5 * 60L), + // SYS用户锁 + LOCK_SYS_USER("lock:sys-user:", -1L), // 风控IP RISK_IP("risk:ip:", -1L), @@ -42,12 +44,17 @@ public enum AppCache implements BaseCacheEnum { // 系统参数缓存 SYS_CACHE_PARAM("sys:cache:param:", -1L), + // 账号密码规则缓存 + SYS_CACHE_AP_RULE("sys:cache:ap-rule", -1L), // 系统JAR包缓存 SYS_CACHE_JAR("sys:cache:jar:", -1L), // 地址缓存 SYS_CACHE_ADDR("sys:cache:addr:", 60 * 60L), // 天气缓存 SYS_CACHE_HOME_WEATHER("sys:cache:home:weather:", 30 * 60L), + + // 系统账号密码错误次数 + COUNT_SYS_USER_PASSWD_ERR("count:sys-user:passwd-err:", -1L) ; /** diff --git a/xtools-app-common/xtools-app-common-task/src/main/java/xtools/app/common/task/enums/TaskType.java b/xtools-app-common/xtools-app-common-task/src/main/java/xtools/app/common/task/enums/TaskType.java index 62a3496..ce068a0 100644 --- a/xtools-app-common/xtools-app-common-task/src/main/java/xtools/app/common/task/enums/TaskType.java +++ b/xtools-app-common/xtools-app-common-task/src/main/java/xtools/app/common/task/enums/TaskType.java @@ -22,6 +22,8 @@ public enum TaskType implements BaseTaskType { DEL_SYS_LOG(20, "删除系统日志"), // 删除系统文件 DEL_SYS_FILE(30, "删除系统文件"), + // 删除禁用的系统用户 + DEL_DISABLE_SYS_USER(40, "删除禁用的系统用户"), ; /** diff --git a/xtools-app-sys/xtools-app-sys-api/src/main/java/xtools/app/sys/api/SysUserPasswdRuleApi.java b/xtools-app-sys/xtools-app-sys-api/src/main/java/xtools/app/sys/api/SysUserPasswdRuleApi.java new file mode 100644 index 0000000..ffdb192 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-api/src/main/java/xtools/app/sys/api/SysUserPasswdRuleApi.java @@ -0,0 +1,14 @@ +package xtools.app.sys.api; + +/** + *

Title : SysUserPasswdRuleApi

+ *

Description : 用户名密码规则 Api

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +public interface SysUserPasswdRuleApi { + +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/controller/SysUserController.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/controller/SysUserController.java index 8d17ef5..7d270c1 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/controller/SysUserController.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/controller/SysUserController.java @@ -109,6 +109,23 @@ public class SysUserController { return sysUserService.delById(req.getIdList()); } + /** + * 重置密码 + * + * @param id 用户ID + * @return 重置密码结果 + */ + @Operation(summary = "重置密码") + @PostMapping("reset-passwd/{id}") + public Result resetPasswd( + @Schema(description = "ID", example = "1") + @Min(value = 1L, message = "不能小于1") + @NotNull(message = "不能为空") + @PathVariable Long id + ) { + return sysUserService.resetPasswd(id); + } + /** * 根据 ID 集合查询 * diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/controller/SysUserPasswdRuleController.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/controller/SysUserPasswdRuleController.java new file mode 100644 index 0000000..e6086e5 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/controller/SysUserPasswdRuleController.java @@ -0,0 +1,135 @@ +package xtools.app.sys.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import xtools.app.sys.api.SysUserPasswdRuleApi; +import xtools.app.sys.model.dto.excel.SysUserPasswdRuleExcel; +import xtools.app.sys.model.dto.req.SysUserPasswdRuleAddReq; +import xtools.app.sys.model.dto.req.SysUserPasswdRulePageReq; +import xtools.app.sys.model.dto.req.SysUserPasswdRuleUpdateReq; +import xtools.app.sys.model.dto.resp.SysUserPasswdRuleResp; +import xtools.app.sys.service.SysUserPasswdRuleService; +import xtools.boot.api.exection.BizError; +import xtools.boot.api.exection.BizWarning; +import xtools.boot.api.model.dto.Result; +import xtools.boot.api.model.dto.page.PageReq; +import xtools.boot.api.model.dto.page.PageResp; +import xtools.boot.api.model.dto.req.IdListReq; +import xtools.core.CollectionUtils; +import xtools.extend.office.FesodUtils; +import xtools.web.HttpServletUtils; + +import java.io.IOException; +import java.util.List; + +/** + *

Title : SysUserPasswdRuleController

+ *

Description : 用户名密码规则 Controller

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +@RequiredArgsConstructor +@Tag(name = "用户名密码规则") +@RestController +@RequestMapping("/sys/user-passwd-rule") +public class SysUserPasswdRuleController implements SysUserPasswdRuleApi { + + private final SysUserPasswdRuleService sysUserPasswdRuleService; + + @Operation(summary = "分页请求") + @PostMapping("page") + public Result> page(@RequestBody @Valid PageReq pageReq) { + return sysUserPasswdRuleService.page(pageReq); + } + + @Operation(summary = "获取数据") + @GetMapping("base/{id}") + public Result getById( + @Schema(description = "ID", example = "1") + @Min(value = 1L, message = "不能小于1") + @NotNull(message = "不能为空") + @PathVariable Long id + ) { + return sysUserPasswdRuleService.getById(id); + } + + @Operation(summary = "添加数据") + @PostMapping("base") + public Result add(@RequestBody @Valid SysUserPasswdRuleAddReq req) { + return sysUserPasswdRuleService.add(req); + } + + @Operation(summary = "更新数据") + @PutMapping("base") + public Result update(@RequestBody @Valid SysUserPasswdRuleUpdateReq req) { + return sysUserPasswdRuleService.update(req); + } + + @Operation(summary = "删除数据") + @DeleteMapping("base") + public Result delById(@RequestBody @Valid IdListReq req) { + return sysUserPasswdRuleService.delById(req); + } + + @Operation(summary = "设置默认") + @PostMapping("set-def/{id}") + public Result setDef( + @Schema(description = "ID", example = "1") + @Min(value = 1L, message = "不能小于1") + @NotNull(message = "不能为空") + @PathVariable Long id + ) { + return sysUserPasswdRuleService.setDef(id); + } + + @Operation(summary = "导出Excel") + @PostMapping("export") + public void exportExcel(@RequestBody @Valid SysUserPasswdRulePageReq req, HttpServletResponse response) { + String sheetName = "用户名密码规则"; + String filename = sheetName + ".xlsx"; + List dataList = sysUserPasswdRuleService.exportExcel(req); + try { + FesodUtils.write(response.getOutputStream(), SysUserPasswdRuleExcel.class, sheetName, dataList); + } catch (IOException e) { + throw new BizError("导出Excel失败"); + } + // 设置 header 和 contentType.写在最后的原因是,避免报错时,响应 contentType 已经被修改 + HttpServletUtils.addDownloadHeader(response, filename); + } + + @Operation(summary = "导入Excel") + @PostMapping("import") + public Result importExcel(@RequestParam("file") MultipartFile file) { + List dataList; + try { + dataList = FesodUtils.read(file.getInputStream(), SysUserPasswdRuleExcel.class); + } catch (IOException e) { + throw new BizError("导入Excel失败"); + } + if (CollectionUtils.isEmpty(dataList)) { + throw new BizWarning("导入Excel没有包含有效数据"); + } + sysUserPasswdRuleService.importExcel(dataList); + return Result.ok(true); + } + +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/convert/SysUserPasswdRuleConvert.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/convert/SysUserPasswdRuleConvert.java new file mode 100644 index 0000000..8f86488 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/convert/SysUserPasswdRuleConvert.java @@ -0,0 +1,72 @@ +package xtools.app.sys.convert; + +import org.mapstruct.Mapper; +import xtools.app.sys.model.dto.excel.SysUserPasswdRuleExcel; +import xtools.app.sys.model.dto.req.SysUserPasswdRuleAddReq; +import xtools.app.sys.model.dto.req.SysUserPasswdRuleUpdateReq; +import xtools.app.sys.model.dto.resp.SysUserPasswdRuleResp; +import xtools.app.sys.model.entity.SysUserPasswdRule; + +import java.util.List; + +/** + *

Title : SysUserPasswdRuleConvert

+ *

Description : 用户名密码规则 Convert

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +@Mapper(componentModel = "spring") +public interface SysUserPasswdRuleConvert { + + /** + * 添加请求转实体 + * + * @param req 添加请求 + * @return 实体 + */ + SysUserPasswdRule addReqToEntity(SysUserPasswdRuleAddReq req); + + /** + * 修改请求转实体 + * + * @param req 修改请求 + * @return 实体 + */ + SysUserPasswdRule updateReqToEntity(SysUserPasswdRuleUpdateReq req); + + /** + * 实体转响应 + * + * @param data 实体 + * @return 响应 + */ + SysUserPasswdRuleResp entityToResp(SysUserPasswdRule data); + + /** + * 批量实体转响应 + * + * @param dataList 批量实体 + * @return 响应 + */ + List entityToRespList(List dataList); + + /** + * 实体转Excel + * + * @param data 实体 + * @return Excel + */ + SysUserPasswdRuleExcel entityToExcel(SysUserPasswdRule data); + + /** + * Excel转实体 + * + * @param data Excel + * @return 实体 + */ + SysUserPasswdRule excelToEntity(SysUserPasswdRuleExcel data); + +} \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/job/SysUserJob.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/job/SysUserJob.java new file mode 100644 index 0000000..e4478a1 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/job/SysUserJob.java @@ -0,0 +1,35 @@ +package xtools.app.sys.job; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import xtools.app.common.job.base.BaseJob; +import xtools.app.sys.service.SysUserService; + +/** + *

Title : SysUserJob

+ *

Description : SysUserJob

+ *

DevelopTools : Idea_x64_v2026.1

+ *

DevelopSystem : macOS Sequoia 15.7.5

+ *

Company : org.xujun

+ * + * @author : XuJun + * @version : 1.0.0 + * @date : 2026/3/17 21:24 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class SysUserJob extends BaseJob { + + private final SysUserService sysUserService; + + /** + * 运行作业 + */ + @Override + public void runJob() { + sysUserService.cleanSysUserJob(); + } + +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/mapper/SysUserPasswdRuleMapper.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/mapper/SysUserPasswdRuleMapper.java new file mode 100644 index 0000000..c5a4463 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/mapper/SysUserPasswdRuleMapper.java @@ -0,0 +1,19 @@ +package xtools.app.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import xtools.app.sys.model.entity.SysUserPasswdRule; + +/** + *

Title : SysUserPasswdRuleMapper

+ *

Description : 用户名密码规则 Mapper 接口

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +@Mapper +public interface SysUserPasswdRuleMapper extends BaseMapper { + +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/excel/SysUserPasswdRuleExcel.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/excel/SysUserPasswdRuleExcel.java new file mode 100644 index 0000000..2b7d047 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/excel/SysUserPasswdRuleExcel.java @@ -0,0 +1,156 @@ +package xtools.app.sys.model.dto.excel; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelProperty; + +import java.io.Serializable; + +/** + *

Title : SysUserPasswdRuleExcel

+ *

Description : 用户名密码规则Excel对象

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SysUserPasswdRuleExcel implements Serializable { + + /** + * 规则名称 + */ + @ExcelProperty("规则名称") + private String ruleName; + + /** + * 规则描述 + */ + @ExcelProperty("规则描述") + private String ruleDesc; + + /** + * 规则编码 + */ + @ExcelProperty("规则编码") + private String ruleCode; + + /** + * 最小密码长度 + */ + @ExcelProperty("最小密码长度") + private Integer passwdMinLength; + + /** + * 最大密码长度 + */ + @ExcelProperty("最大密码长度") + private Integer passwdMaxLength; + + /** + * 最少数字字符个数 + */ + @ExcelProperty("最少数字字符个数") + private Integer minNumCount; + + /** + * 最少特殊字符个数 + */ + @ExcelProperty("最少特殊字符个数") + private Integer minSpecCount; + + /** + * 最少小写字母个数 + */ + @ExcelProperty("最少小写字母个数") + private Integer minLowerCount; + + /** + * 最少大写字母个数 + */ + @ExcelProperty("最少大写字母个数") + private Integer minUpperCount; + + /** + * 禁止使用历史最近多少次口令 + */ + @ExcelProperty("禁止使用历史最近多少次口令") + private Integer hisPasswdCount; + + /** + * 禁止使用键盘连续3个字符 + */ + @ExcelProperty("禁止使用键盘连续3个字符") + private Integer continuousCheck; + + /** + * 禁止使用弱口令字典中的口令 + */ + @ExcelProperty("禁止使用弱口令字典中的口令") + private Integer invalidCheck; + + /** + * 禁止账号名在密码中所占长度超过一半 + */ + @ExcelProperty("禁止账号名在密码中所占长度超过一半") + private Integer coverHalfCheck; + + /** + * 密码有效期天数 + */ + @ExcelProperty("密码有效期天数") + private Integer validityDays; + + /** + * 密码修改后剩余多少天进行提示 + */ + @ExcelProperty("密码修改后剩余多少天进行提示") + private Integer residueTipsDays; + + /** + * 账号锁定后多久没启用进行账号注销 + */ + @ExcelProperty("账号锁定后多久没启用进行账号注销") + private Integer lockCancelDays; + + /** + * 密码错误时间窗口 + */ + @ExcelProperty("密码错误时间窗口") + private Integer errorPasswdWindowMinutes; + + /** + * 错误密码次数 + */ + @ExcelProperty("错误密码次数") + private Integer errorPasswdCount; + + /** + * 账号锁定分钟数 + */ + @ExcelProperty("账号锁定分钟数") + private Integer errorPasswdLockMinutes; + + /** + * 账号有效期,默认值为90天 + */ + @ExcelProperty("账号有效期") + private Integer accountValidityDays; + + /** + * 账号有效期剩余天数提示,默认值为15天 + */ + @ExcelProperty("账号有效期剩余天数提示") + private Integer accountTipsDays; + + /** + * 备注 + */ + @ExcelProperty("备注") + private String memo; + +} \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserAddReq.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserAddReq.java index 93c071c..fc6e5ba 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserAddReq.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserAddReq.java @@ -6,6 +6,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; +import java.time.Instant; /** *

Title : SysUserAddReq

@@ -69,6 +70,12 @@ public class SysUserAddReq implements Serializable { @Schema(description = "状态", example = "1") private Integer status; + /** + * 账号失效时间,空则不失效 + */ + @Schema(description = "账号失效时间,空则不失效") + private Instant accountExpirationTime; + /** * 创建人 ID */ diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserPasswdRuleAddReq.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserPasswdRuleAddReq.java new file mode 100644 index 0000000..03ee9d0 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserPasswdRuleAddReq.java @@ -0,0 +1,174 @@ +package xtools.app.sys.model.dto.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

Title : SysUserPasswdRuleAddReq

+ *

Description : 用户名密码规则添加请求对象

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SysUserPasswdRuleAddReq implements Serializable { + + /** + * 规则名称 + */ + @Schema(description = "规则名称") + private String ruleName; + + /** + * 规则描述 + */ + @Schema(description = "规则描述") + private String ruleDesc; + + /** + * 规则编码 + */ + @Schema(description = "规则编码") + private String ruleCode; + + /** + * 默认规则 + */ + @Schema(description = "默认规则") + private Integer ruleDefault; + + /** + * 最小密码长度 + */ + @Schema(description = "最小密码长度") + private Integer passwdMinLength; + + /** + * 最大密码长度 + */ + @Schema(description = "最大密码长度") + private Integer passwdMaxLength; + + /** + * 最少数字字符个数 + */ + @Schema(description = "最少数字字符个数") + private Integer minNumCount; + + /** + * 最少特殊字符个数 + */ + @Schema(description = "最少特殊字符个数") + private Integer minSpecCount; + + /** + * 最少小写字母个数 + */ + @Schema(description = "最少小写字母个数") + private Integer minLowerCount; + + /** + * 最少大写字母个数 + */ + @Schema(description = "最少大写字母个数") + private Integer minUpperCount; + + /** + * 禁止使用历史最近多少次口令 + */ + @Schema(description = "禁止使用历史最近多少次口令") + private Integer hisPasswdCount; + + /** + * 禁止使用键盘连续3个字符 + */ + @Schema(description = "禁止使用键盘连续3个字符") + private Integer continuousCheck; + + /** + * 禁止使用弱口令字典中的口令 + */ + @Schema(description = "禁止使用弱口令字典中的口令") + private Integer invalidCheck; + + /** + * 禁止账号名在密码中所占长度超过一半 + */ + @Schema(description = "禁止账号名在密码中所占长度超过一半") + private Integer coverHalfCheck; + + /** + * 密码有效期天数 + */ + @Schema(description = "密码有效期天数") + private Integer validityDays; + + /** + * 密码修改后剩余多少天进行提示 + */ + @Schema(description = "密码修改后剩余多少天进行提示") + private Integer residueTipsDays; + + /** + * 账号锁定后多久没启用进行账号注销 + */ + @Schema(description = "账号锁定后多久没启用进行账号注销") + private Integer lockCancelDays; + + /** + * 密码错误时间窗口 + */ + @Schema(description = "密码错误时间窗口") + private Integer errorPasswdWindowMinutes; + + /** + * 错误密码次数 + */ + @Schema(description = "错误密码次数") + private Integer errorPasswdCount; + + /** + * 账号锁定分钟数 + */ + @Schema(description = "账号锁定分钟数") + private Integer errorPasswdLockMinutes; + + /** + * 账号有效期,默认值为90天 + */ + @Schema(description = "账号有效期,默认值为90天") + private Integer accountValidityDays; + + /** + * 账号有效期剩余天数提示,默认值为15天 + */ + @Schema(description = "账号有效期剩余天数提示,默认值为15天") + private Integer accountTipsDays; + + /** + * 创建人 ID + */ + @Schema(description = "创建人 ID") + private Long createBy; + + /** + * 修改人 ID + */ + @Schema(description = "修改人 ID") + private Long updateBy; + + /** + * 备注 + */ + @Schema(description = "备注") + private String memo; + +} \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserPasswdRulePageReq.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserPasswdRulePageReq.java new file mode 100644 index 0000000..b296d08 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserPasswdRulePageReq.java @@ -0,0 +1,192 @@ +package xtools.app.sys.model.dto.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.time.Instant; + +/** + *

Title : SysUserPasswdRulePageReq

+ *

Description : 用户名密码规则分页请求对象

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SysUserPasswdRulePageReq implements Serializable { + + /** + * 规则主键id + */ + @Schema(description = "规则主键id") + private Long id; + + /** + * 规则名称 + */ + @Schema(description = "规则名称") + private String ruleName; + + /** + * 规则描述 + */ + @Schema(description = "规则描述") + private String ruleDesc; + + /** + * 规则编码 + */ + @Schema(description = "规则编码") + private String ruleCode; + + /** + * 默认规则 + */ + @Schema(description = "默认规则") + private Integer ruleDefault; + + /** + * 最小密码长度 + */ + @Schema(description = "最小密码长度") + private Integer passwdMinLength; + + /** + * 最大密码长度 + */ + @Schema(description = "最大密码长度") + private Integer passwdMaxLength; + + /** + * 最少数字字符个数 + */ + @Schema(description = "最少数字字符个数") + private Integer minNumCount; + + /** + * 最少特殊字符个数 + */ + @Schema(description = "最少特殊字符个数") + private Integer minSpecCount; + + /** + * 最少小写字母个数 + */ + @Schema(description = "最少小写字母个数") + private Integer minLowerCount; + + /** + * 最少大写字母个数 + */ + @Schema(description = "最少大写字母个数") + private Integer minUpperCount; + + /** + * 禁止使用历史最近多少次口令 + */ + @Schema(description = "禁止使用历史最近多少次口令") + private Integer hisPasswdCount; + + /** + * 禁止使用键盘连续3个字符 + */ + @Schema(description = "禁止使用键盘连续3个字符") + private Integer continuousCheck; + + /** + * 禁止使用弱口令字典中的口令 + */ + @Schema(description = "禁止使用弱口令字典中的口令") + private Integer invalidCheck; + + /** + * 禁止账号名在密码中所占长度超过一半 + */ + @Schema(description = "禁止账号名在密码中所占长度超过一半") + private Integer coverHalfCheck; + + /** + * 密码有效期天数 + */ + @Schema(description = "密码有效期天数") + private Integer validityDays; + + /** + * 密码修改后剩余多少天进行提示 + */ + @Schema(description = "密码修改后剩余多少天进行提示") + private Integer residueTipsDays; + + /** + * 账号锁定后多久没启用进行账号注销 + */ + @Schema(description = "账号锁定后多久没启用进行账号注销") + private Integer lockCancelDays; + + /** + * 密码错误时间窗口 + */ + @Schema(description = "密码错误时间窗口") + private Integer errorPasswdWindowMinutes; + + /** + * 错误密码次数 + */ + @Schema(description = "错误密码次数") + private Integer errorPasswdCount; + + /** + * 账号锁定分钟数 + */ + @Schema(description = "账号锁定分钟数") + private Integer errorPasswdLockMinutes; + + /** + * 账号有效期,默认值为90天 + */ + @Schema(description = "账号有效期,默认值为90天") + private Integer accountValidityDays; + + /** + * 账号有效期剩余天数提示,默认值为15天 + */ + @Schema(description = "账号有效期剩余天数提示,默认值为15天") + private Integer accountTipsDays; + + /** + * 创建人 ID + */ + @Schema(description = "创建人 ID") + private Long createBy; + + /** + * 修改人 ID + */ + @Schema(description = "修改人 ID") + private Long updateBy; + + /** + * 备注 + */ + @Schema(description = "备注") + private String memo; + + /** + * 创建时间(范围) + */ + @Schema(description = "创建时间(范围)", example = "['2026-01-01 00:00:00', '2026-01-01 12:00:00']") + private Instant[] gmtCreateRange; + + /** + * 更新时间(范围) + */ + @Schema(description = "更新时间(范围)", example = "['2026-01-01 00:00:00', '2026-01-01 12:00:00']") + private Instant[] gmtModifiedRange; +} \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserPasswdRuleUpdateReq.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserPasswdRuleUpdateReq.java new file mode 100644 index 0000000..16b9a73 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserPasswdRuleUpdateReq.java @@ -0,0 +1,180 @@ +package xtools.app.sys.model.dto.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

Title : SysUserPasswdRuleUpdateReq

+ *

Description : 用户名密码规则更新请求对象

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SysUserPasswdRuleUpdateReq implements Serializable { + + /** + * 规则主键id + */ + @Schema(description = "规则主键id") + private Long id; + + /** + * 规则名称 + */ + @Schema(description = "规则名称") + private String ruleName; + + /** + * 规则描述 + */ + @Schema(description = "规则描述") + private String ruleDesc; + + /** + * 规则编码 + */ + @Schema(description = "规则编码") + private String ruleCode; + + /** + * 默认规则 + */ + @Schema(description = "默认规则") + private Integer ruleDefault; + + /** + * 最小密码长度 + */ + @Schema(description = "最小密码长度") + private Integer passwdMinLength; + + /** + * 最大密码长度 + */ + @Schema(description = "最大密码长度") + private Integer passwdMaxLength; + + /** + * 最少数字字符个数 + */ + @Schema(description = "最少数字字符个数") + private Integer minNumCount; + + /** + * 最少特殊字符个数 + */ + @Schema(description = "最少特殊字符个数") + private Integer minSpecCount; + + /** + * 最少小写字母个数 + */ + @Schema(description = "最少小写字母个数") + private Integer minLowerCount; + + /** + * 最少大写字母个数 + */ + @Schema(description = "最少大写字母个数") + private Integer minUpperCount; + + /** + * 禁止使用历史最近多少次口令 + */ + @Schema(description = "禁止使用历史最近多少次口令") + private Integer hisPasswdCount; + + /** + * 禁止使用键盘连续3个字符 + */ + @Schema(description = "禁止使用键盘连续3个字符") + private Integer continuousCheck; + + /** + * 禁止使用弱口令字典中的口令 + */ + @Schema(description = "禁止使用弱口令字典中的口令") + private Integer invalidCheck; + + /** + * 禁止账号名在密码中所占长度超过一半 + */ + @Schema(description = "禁止账号名在密码中所占长度超过一半") + private Integer coverHalfCheck; + + /** + * 密码有效期天数 + */ + @Schema(description = "密码有效期天数") + private Integer validityDays; + + /** + * 密码修改后剩余多少天进行提示 + */ + @Schema(description = "密码修改后剩余多少天进行提示") + private Integer residueTipsDays; + + /** + * 账号锁定后多久没启用进行账号注销 + */ + @Schema(description = "账号锁定后多久没启用进行账号注销") + private Integer lockCancelDays; + + /** + * 密码错误时间窗口 + */ + @Schema(description = "密码错误时间窗口") + private Integer errorPasswdWindowMinutes; + + /** + * 错误密码次数 + */ + @Schema(description = "错误密码次数") + private Integer errorPasswdCount; + + /** + * 账号锁定分钟数 + */ + @Schema(description = "账号锁定分钟数") + private Integer errorPasswdLockMinutes; + + /** + * 账号有效期,默认值为90天 + */ + @Schema(description = "账号有效期,默认值为90天") + private Integer accountValidityDays; + + /** + * 账号有效期剩余天数提示,默认值为15天 + */ + @Schema(description = "账号有效期剩余天数提示,默认值为15天") + private Integer accountTipsDays; + + /** + * 创建人 ID + */ + @Schema(description = "创建人 ID") + private Long createBy; + + /** + * 修改人 ID + */ + @Schema(description = "修改人 ID") + private Long updateBy; + + /** + * 备注 + */ + @Schema(description = "备注") + private String memo; + +} \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserUpdateReq.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserUpdateReq.java index 154f323..c935c18 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserUpdateReq.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/req/SysUserUpdateReq.java @@ -6,6 +6,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; +import java.time.Instant; /** *

Title : SysUserUpdateReq

@@ -75,6 +76,12 @@ public class SysUserUpdateReq implements Serializable { @Schema(description = "状态", example = "1") private Integer status; + /** + * 账号失效时间,空则不失效 + */ + @Schema(description = "账号失效时间,空则不失效") + private Instant accountExpirationTime; + /** * 创建人 ID */ diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysBaseUserInfoResp.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysBaseUserInfoResp.java index 6d7b127..834d95f 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysBaseUserInfoResp.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysBaseUserInfoResp.java @@ -47,4 +47,10 @@ public class SysBaseUserInfoResp implements Serializable { */ @Schema(description = "按钮权限") private List btnPerms; + + /** + * 提示信息 + */ + @Schema(description = "提示信息") + private List tips; } diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysUserPasswdRuleResp.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysUserPasswdRuleResp.java new file mode 100644 index 0000000..5ce09de --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysUserPasswdRuleResp.java @@ -0,0 +1,181 @@ +package xtools.app.sys.model.dto.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import xtools.boot.api.model.entity.BaseEntity; + +/** + *

Title : SysUserPasswdRuleResp

+ *

Description : 用户名密码规则响应对象

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class SysUserPasswdRuleResp extends BaseEntity { + + /** + * 规则主键id + */ + @Schema(description = "规则主键id") + private Long id; + + /** + * 规则名称 + */ + @Schema(description = "规则名称") + private String ruleName; + + /** + * 规则描述 + */ + @Schema(description = "规则描述") + private String ruleDesc; + + /** + * 规则编码 + */ + @Schema(description = "规则编码") + private String ruleCode; + + /** + * 默认规则 + */ + @Schema(description = "默认规则") + private Integer ruleDefault; + + /** + * 最小密码长度 + */ + @Schema(description = "最小密码长度") + private Integer passwdMinLength; + + /** + * 最大密码长度 + */ + @Schema(description = "最大密码长度") + private Integer passwdMaxLength; + + /** + * 最少数字字符个数 + */ + @Schema(description = "最少数字字符个数") + private Integer minNumCount; + + /** + * 最少特殊字符个数 + */ + @Schema(description = "最少特殊字符个数") + private Integer minSpecCount; + + /** + * 最少小写字母个数 + */ + @Schema(description = "最少小写字母个数") + private Integer minLowerCount; + + /** + * 最少大写字母个数 + */ + @Schema(description = "最少大写字母个数") + private Integer minUpperCount; + + /** + * 禁止使用历史最近多少次口令 + */ + @Schema(description = "禁止使用历史最近多少次口令") + private Integer hisPasswdCount; + + /** + * 禁止使用键盘连续3个字符 + */ + @Schema(description = "禁止使用键盘连续3个字符") + private Integer continuousCheck; + + /** + * 禁止使用弱口令字典中的口令 + */ + @Schema(description = "禁止使用弱口令字典中的口令") + private Integer invalidCheck; + + /** + * 禁止账号名在密码中所占长度超过一半 + */ + @Schema(description = "禁止账号名在密码中所占长度超过一半") + private Integer coverHalfCheck; + + /** + * 密码有效期天数 + */ + @Schema(description = "密码有效期天数") + private Integer validityDays; + + /** + * 密码修改后剩余多少天进行提示 + */ + @Schema(description = "密码修改后剩余多少天进行提示") + private Integer residueTipsDays; + + /** + * 账号锁定后多久没启用进行账号注销 + */ + @Schema(description = "账号锁定后多久没启用进行账号注销") + private Integer lockCancelDays; + + /** + * 密码错误时间窗口 + */ + @Schema(description = "密码错误时间窗口") + private Integer errorPasswdWindowMinutes; + + /** + * 错误密码次数 + */ + @Schema(description = "错误密码次数") + private Integer errorPasswdCount; + + /** + * 账号锁定分钟数 + */ + @Schema(description = "账号锁定分钟数") + private Integer errorPasswdLockMinutes; + + /** + * 账号有效期,默认值为90天 + */ + @Schema(description = "账号有效期,默认值为90天") + private Integer accountValidityDays; + + /** + * 账号有效期剩余天数提示,默认值为15天 + */ + @Schema(description = "账号有效期剩余天数提示,默认值为15天") + private Integer accountTipsDays; + + /** + * 创建人 ID + */ + @Schema(description = "创建人 ID") + private Long createBy; + + /** + * 修改人 ID + */ + @Schema(description = "修改人 ID") + private Long updateBy; + + /** + * 备注 + */ + @Schema(description = "备注") + private String memo; + +} \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysUserResp.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysUserResp.java index 29c2fdd..380208f 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysUserResp.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/dto/resp/SysUserResp.java @@ -9,6 +9,7 @@ import xtools.boot.api.model.entity.BaseEntity; import xtools.boot.mask.anntation.Mask; import xtools.boot.mask.enums.MaskType; +import java.time.Instant; import java.util.List; /** @@ -62,7 +63,7 @@ public class SysUserResp extends BaseEntity { * 手机号 */ @Schema(description = "手机号", example = "13800138000") - @Mask(value = MaskType.MOBILE_PHONE, always = true) + @Mask(value = MaskType.MOBILE_PHONE) private String mobile; /** @@ -78,13 +79,6 @@ public class SysUserResp extends BaseEntity { @Schema(description = "性别", example = "1") private Integer sex; - /** - * 密码 - */ - @Schema(description = "密码", example = "******") - @Mask(MaskType.PASSWORD) - private String passwd; - /** * 状态 */ @@ -92,16 +86,10 @@ public class SysUserResp extends BaseEntity { private Integer status; /** - * 创建人 ID + * 账号失效时间,空则不失效 */ - @Schema(description = "创建人 ID", example = "1") - private Long createBy; - - /** - * 修改人 ID - */ - @Schema(description = "修改人 ID", example = "1") - private Long updateBy; + @Schema(description = "账号失效时间,空则不失效") + private Instant accountExpirationTime; /** * 备注 diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysAddress.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysAddress.java index 0455027..81864fd 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysAddress.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysAddress.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -80,7 +81,7 @@ public class SysAddress extends BaseEntity { * 公用地址-备注 */ @Schema(description = "公用地址-备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysDept.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysDept.java index c37588d..be12790 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysDept.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysDept.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -94,6 +95,6 @@ public class SysDept extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysDict.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysDict.java index c923d7f..82b46da 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysDict.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysDict.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -73,6 +74,6 @@ public class SysDict extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysDictItem.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysDictItem.java index 3d9bb45..d4d0b66 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysDictItem.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysDictItem.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -94,6 +95,6 @@ public class SysDictItem extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysFile.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysFile.java index abd97c7..c8a34b5 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysFile.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysFile.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -152,7 +153,7 @@ public class SysFile extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysLog.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysLog.java index 0731b10..2c322f9 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysLog.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysLog.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -157,6 +158,6 @@ public class SysLog extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysMenu.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysMenu.java index 54a2b99..da286e1 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysMenu.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysMenu.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -164,6 +165,6 @@ public class SysMenu extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysNotice.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysNotice.java index ff8c369..df42ecb 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysNotice.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysNotice.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -131,7 +132,7 @@ public class SysNotice extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysOptLog.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysOptLog.java index e725b55..d2f4487 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysOptLog.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysOptLog.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -94,7 +95,7 @@ public class SysOptLog implements Serializable { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; /** diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysParam.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysParam.java index 1bcff71..f12b4b4 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysParam.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysParam.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -73,7 +74,7 @@ public class SysParam extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysRisk.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysRisk.java index dd243c9..f654e0d 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysRisk.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysRisk.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -73,7 +74,7 @@ public class SysRisk extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysRole.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysRole.java index 2cdfa94..fce2ed3 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysRole.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysRole.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -87,6 +88,6 @@ public class SysRole extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysRoleMenu.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysRoleMenu.java index 482c162..e8c9752 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysRoleMenu.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysRoleMenu.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -52,6 +53,6 @@ public class SysRoleMenu extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysTask.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysTask.java index 4612b85..28be804 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysTask.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysTask.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -89,6 +90,6 @@ public class SysTask extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUpdateHistory.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUpdateHistory.java index 231d20b..535c9b0 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUpdateHistory.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUpdateHistory.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -66,6 +67,6 @@ public class SysUpdateHistory extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUser.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUser.java index 1c22fef..f6ff8a4 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUser.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUser.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -11,6 +12,8 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import xtools.boot.api.model.entity.BaseEntity; +import java.time.Instant; + /** *

Title : SysUser

*

Description : 系统用户表实体对象

@@ -97,6 +100,34 @@ public class SysUser extends BaseEntity { @TableField(value = "status") private Integer status; + /** + * 历史密码 + */ + @Schema(description = "历史密码") + @TableField(value = "history_passwd") + private String historyPasswd; + + /** + * 密码修改时间 + */ + @Schema(description = "密码修改时间") + @TableField(value = "passwd_gmt_modified") + private Instant passwdGmtModified; + + /** + * 账号失效时间,空则不失效 + */ + @Schema(description = "账号失效时间,空则不失效") + @TableField(value = "account_expiration_time", updateStrategy = FieldStrategy.ALWAYS) + private Instant accountExpirationTime; + + /** + * 账号禁用时间 + */ + @Schema(description = "账号禁用时间") + @TableField(value = "account_disabled_time", updateStrategy = FieldStrategy.ALWAYS) + private Instant accountDisabledTime; + /** * 创建人 ID */ @@ -115,6 +146,6 @@ public class SysUser extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUserNotice.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUserNotice.java index c4abf76..f6728d2 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUserNotice.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUserNotice.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -75,7 +76,7 @@ public class SysUserNotice extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUserPasswdRule.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUserPasswdRule.java new file mode 100644 index 0000000..618b4ce --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUserPasswdRule.java @@ -0,0 +1,213 @@ +package xtools.app.sys.model.entity; + +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import xtools.boot.api.model.entity.BaseEntity; + +/** + *

Title : SysUserPasswdRule

+ *

Description : 用户名密码规则实体对象

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@TableName("sys_user_passwd_rule") +public class SysUserPasswdRule extends BaseEntity { + + /** + * 规则主键id + */ + @Schema(description = "规则主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 规则名称 + */ + @Schema(description = "规则名称") + @TableField(value = "rule_name") + private String ruleName; + + /** + * 规则描述 + */ + @Schema(description = "规则描述") + @TableField(value = "rule_desc", updateStrategy = FieldStrategy.ALWAYS) + private String ruleDesc; + + /** + * 规则编码 + */ + @Schema(description = "规则编码") + @TableField(value = "rule_code") + private String ruleCode; + + /** + * 默认规则 + */ + @Schema(description = "默认规则") + @TableField(value = "rule_default") + private Integer ruleDefault; + + /** + * 最小密码长度 + */ + @Schema(description = "最小密码长度") + @TableField(value = "passwd_min_length") + private Integer passwdMinLength; + + /** + * 最大密码长度 + */ + @Schema(description = "最大密码长度") + @TableField(value = "passwd_max_length") + private Integer passwdMaxLength; + + /** + * 最少数字字符个数 + */ + @Schema(description = "最少数字字符个数") + @TableField(value = "min_num_count") + private Integer minNumCount; + + /** + * 最少特殊字符个数 + */ + @Schema(description = "最少特殊字符个数") + @TableField(value = "min_spec_count") + private Integer minSpecCount; + + /** + * 最少小写字母个数 + */ + @Schema(description = "最少小写字母个数") + @TableField(value = "min_lower_count") + private Integer minLowerCount; + + /** + * 最少大写字母个数 + */ + @Schema(description = "最少大写字母个数") + @TableField(value = "min_upper_count") + private Integer minUpperCount; + + /** + * 禁止使用历史最近多少次口令 + */ + @Schema(description = "禁止使用历史最近多少次口令") + @TableField(value = "his_passwd_count") + private Integer hisPasswdCount; + + /** + * 禁止使用键盘连续3个字符 + */ + @Schema(description = "禁止使用键盘连续3个字符") + @TableField(value = "continuous_check") + private Integer continuousCheck; + + /** + * 禁止使用弱口令字典中的口令 + */ + @Schema(description = "禁止使用弱口令字典中的口令") + @TableField(value = "invalid_check") + private Integer invalidCheck; + + /** + * 禁止账号名在密码中所占长度超过一半 + */ + @Schema(description = "禁止账号名在密码中所占长度超过一半") + @TableField(value = "cover_half_check") + private Integer coverHalfCheck; + + /** + * 密码有效期天数 + */ + @Schema(description = "密码有效期天数") + @TableField(value = "validity_days") + private Integer validityDays; + + /** + * 密码修改后剩余多少天进行提示 + */ + @Schema(description = "密码修改后剩余多少天进行提示") + @TableField(value = "residue_tips_days") + private Integer residueTipsDays; + + /** + * 账号锁定后多久没启用进行账号注销 + */ + @Schema(description = "账号锁定后多久没启用进行账号注销") + @TableField(value = "lock_cancel_days") + private Integer lockCancelDays; + + /** + * 密码错误时间窗口 + */ + @Schema(description = "密码错误时间窗口") + @TableField(value = "error_passwd_window_minutes") + private Integer errorPasswdWindowMinutes; + + /** + * 错误密码次数 + */ + @Schema(description = "错误密码次数") + @TableField(value = "error_passwd_count") + private Integer errorPasswdCount; + + /** + * 账号锁定分钟数 + */ + @Schema(description = "账号锁定分钟数") + @TableField(value = "error_passwd_lock_minutes") + private Integer errorPasswdLockMinutes; + + /** + * 账号有效期,默认值为90天 + */ + @Schema(description = "账号有效期,默认值为90天") + @TableField(value = "account_validity_days") + private Integer accountValidityDays; + + /** + * 账号有效期剩余天数提示,默认值为15天 + */ + @Schema(description = "账号有效期剩余天数提示,默认值为15天") + @TableField(value = "account_tips_days") + private Integer accountTipsDays; + + /** + * 创建人 ID + */ + @Schema(description = "创建人 ID") + @TableField(value = "create_by") + private Long createBy; + + /** + * 修改人 ID + */ + @Schema(description = "修改人 ID") + @TableField(value = "update_by") + private Long updateBy; + + /** + * 备注 + */ + @Schema(description = "备注") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) + private String memo; + +} \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUserRole.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUserRole.java index fcb50a8..6427ee5 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUserRole.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/model/entity/SysUserRole.java @@ -1,5 +1,6 @@ package xtools.app.sys.model.entity; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -52,6 +53,6 @@ public class SysUserRole extends BaseEntity { * 备注 */ @Schema(description = "备注") - @TableField(value = "memo") + @TableField(value = "memo", updateStrategy = FieldStrategy.ALWAYS) private String memo; } \ No newline at end of file diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysPasswdService.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysPasswdService.java new file mode 100644 index 0000000..5c05ee5 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysPasswdService.java @@ -0,0 +1,43 @@ +package xtools.app.sys.service; + +import xtools.app.sys.model.entity.SysUserPasswdRule; + +/** + *

Title : SysPasswdService

+ *

Description : SysPasswdService

+ *

DevelopTools : Idea_x64_v2026.1

+ *

DevelopSystem : macOS Sequoia 15.7.5

+ *

Company : org.xujun

+ * + * @author : XuJun + * @version : 1.0.0 + * @date : 2026/6/4 09:32 + */ +public interface SysPasswdService { + + /** + * 检查密码 + * + * @param passwd 密码 + * @param account 账号 + */ + void checkPasswd(String passwd, String account); + + /** + * 检查密码 + * + * @param passwd 密码 + * @param account 账号 + * @param ruleCode 规则码 + */ + void checkPasswd(String passwd, String account, String ruleCode); + + /** + * 检查密码 + * + * @param passwd 密码 + * @param account 账号 + * @param rule 规则 + */ + void checkPasswd(String passwd, String account, SysUserPasswdRule rule); +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysUserPasswdRuleService.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysUserPasswdRuleService.java new file mode 100644 index 0000000..e91b100 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysUserPasswdRuleService.java @@ -0,0 +1,99 @@ +package xtools.app.sys.service; + +import xtools.app.sys.api.SysUserPasswdRuleApi; +import xtools.app.sys.model.dto.excel.SysUserPasswdRuleExcel; +import xtools.app.sys.model.dto.req.SysUserPasswdRuleAddReq; +import xtools.app.sys.model.dto.req.SysUserPasswdRulePageReq; +import xtools.app.sys.model.dto.req.SysUserPasswdRuleUpdateReq; +import xtools.app.sys.model.dto.resp.SysUserPasswdRuleResp; +import xtools.app.sys.model.entity.SysUserPasswdRule; +import xtools.boot.api.model.dto.Result; +import xtools.boot.api.model.dto.page.PageReq; +import xtools.boot.api.model.dto.page.PageResp; +import xtools.boot.api.model.dto.req.IdListReq; + +import java.util.List; + +/** + *

Title : SysUserPasswdRuleService

+ *

Description : 用户名密码规则 Service

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +public interface SysUserPasswdRuleService extends SysUserPasswdRuleApi { + + /** + * 分页查询 + * + * @param pageReq 分页请求 + * @return 分页结果 + */ + Result> page(PageReq pageReq); + + /** + * 根据 ID 查询 + * + * @param id ID + * @return 结果 + */ + Result getById(Long id); + + /** + * 添加 + * + * @param req 添加请求 + * @return 添加结果 + */ + Result add(SysUserPasswdRuleAddReq req); + + /** + * 修改 + * + * @param req 修改请求 + * @return 修改结果 + */ + Result update(SysUserPasswdRuleUpdateReq req); + + /** + * 根据 ID 删除 + * + * @param req ID 集合 + * @return 删除结果 + */ + Result delById(IdListReq req); + + /** + * 设置默认 + * + * @param id ID + * @return 设置结果 + */ + Result setDef(Long id); + + /** + * 根据规则code获取数据,code为空则获取默认规则 + * + * @param code code + * @return 规则 + */ + SysUserPasswdRule getByCode(String code); + + /** + * 导出 Excel + * + * @param req 请求参数 + * @return Excel 数据 + */ + List exportExcel(SysUserPasswdRulePageReq req); + + /** + * 导入 Excel + * + * @param dataList Excel 数据 + */ + void importExcel(List dataList); + +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysUserService.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysUserService.java index 82215e3..30921db 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysUserService.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/SysUserService.java @@ -63,6 +63,14 @@ public interface SysUserService { */ Result delById(List idList); + /** + * 重置密码 + * + * @param id ID + * @return 重置密码结果 + */ + Result resetPasswd(Long id); + /** * 根据 ID 集合查询 * @@ -87,4 +95,9 @@ public interface SysUserService { */ boolean saveSysUser(UserInfoEditReq req); + /** + * 清理禁用账号Job + */ + void cleanSysUserJob(); + } diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/base/SysUserPasswdRuleBaseService.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/base/SysUserPasswdRuleBaseService.java new file mode 100644 index 0000000..9cabd90 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/base/SysUserPasswdRuleBaseService.java @@ -0,0 +1,20 @@ +package xtools.app.sys.service.base; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Component; + +import xtools.app.sys.mapper.SysUserPasswdRuleMapper; +import xtools.app.sys.model.entity.SysUserPasswdRule; + +/** + *

Title : SysUserPasswdRuleBaseService

+ *

Description : 用户名密码规则 BaseService

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +@Component +public class SysUserPasswdRuleBaseService extends ServiceImpl { +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysBaseServiceImpl.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysBaseServiceImpl.java index 569d2f6..311c649 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysBaseServiceImpl.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysBaseServiceImpl.java @@ -1,5 +1,6 @@ package xtools.app.sys.service.impl; +import com.alibaba.fastjson2.JSONArray; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; @@ -7,6 +8,7 @@ import org.springframework.transaction.annotation.Transactional; import xtools.app.sys.auth.model.dto.LoginUserDto; import xtools.app.sys.auth.utils.AuthUtils; import xtools.app.sys.convert.SysBaseConvert; +import xtools.app.sys.convert.SysUserConvert; import xtools.app.sys.model.dto.Sm2KeyDto; import xtools.app.sys.model.dto.req.IgnoreMaskReq; import xtools.app.sys.model.dto.req.UserInfoEditReq; @@ -15,19 +17,28 @@ import xtools.app.sys.model.dto.resp.SysBaseUserInfoResp; import xtools.app.sys.model.dto.resp.SysIpAddrResp; import xtools.app.sys.model.entity.SysMenu; import xtools.app.sys.model.entity.SysUser; +import xtools.app.sys.model.entity.SysUserPasswdRule; import xtools.app.sys.service.SysBaseService; import xtools.app.sys.service.SysCommonService; import xtools.app.sys.service.SysMenuService; +import xtools.app.sys.service.SysPasswdService; +import xtools.app.sys.service.SysUserPasswdRuleService; import xtools.app.sys.service.SysUserService; import xtools.app.sys.service.base.SysUserBaseService; import xtools.app.sys.utils.PasswdUtils; import xtools.base.config.BaseParams; import xtools.boot.api.exection.BizError; +import xtools.boot.api.exection.BizWarning; import xtools.boot.api.model.dto.Result; import xtools.boot.ip.utils.IpUtils; import xtools.core.CollectionUtils; +import xtools.core.StringUtils; +import xtools.core.time.InstantUtils; import xtools.extend.dto.IpAddrDto; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -49,6 +60,10 @@ public class SysBaseServiceImpl implements SysBaseService, BaseParams { private final SysCommonService sysCommonService; + private final SysUserPasswdRuleService sysUserPasswdRuleService; + + private final SysPasswdService sysPasswdService; + private final SysMenuService sysMenuService; private final SysUserService sysUserService; @@ -57,6 +72,8 @@ public class SysBaseServiceImpl implements SysBaseService, BaseParams { private final SysBaseConvert sysBaseConvert; + private final SysUserConvert sysUserConvert; + /** * 获取用户信息 * @@ -64,15 +81,18 @@ public class SysBaseServiceImpl implements SysBaseService, BaseParams { */ @Override public Result getUserInfo() { - // 用户信息响应 - SysBaseUserInfoResp resp = new SysBaseUserInfoResp(); - // 获取登录用户信息 LoginUserDto loginUser = AuthUtils.get(); + SysUser sysUser = sysUserBaseService.getById(loginUser.getId()); + if (Objects.isNull(sysUser)) { + throw new BizWarning("用户不存在"); + } + // 用户信息响应 + SysBaseUserInfoResp resp = new SysBaseUserInfoResp(); // 设置用户信息 - resp.setSysUser(sysUserService.getUserInfo(loginUser.getId())); - + resp.setSysUser(sysUserConvert.entityToResp(sysUser)); + resp.setTips(checkUser(sysUser)); // 获取用户角色信息 List roleIds = loginUser.getRoleIds(); if (CollectionUtils.isNotEmpty(roleIds)) { @@ -85,6 +105,35 @@ public class SysBaseServiceImpl implements SysBaseService, BaseParams { return Result.ok(resp); } + /** + * 检查用户信息 + * + * @param sysUser 用户信息 + * @return 检查结果 + */ + private List checkUser(SysUser sysUser) { + SysUserPasswdRule rule = sysUserPasswdRuleService.getByCode(null); + if (Objects.isNull(rule)) { + throw new BizError("安全规则不存在"); + } + List tips = new ArrayList<>(); + // 密码过期提醒 + Integer validityDays = rule.getValidityDays(); + if (validityDays > CP_NUM0) { + Instant passwdGmtModified = sysUser.getPasswdGmtModified(); + if (Objects.nonNull(passwdGmtModified) && Instant.now().isAfter(passwdGmtModified.plus(validityDays - rule.getResidueTipsDays(), ChronoUnit.DAYS))) { + Instant expirationTime = passwdGmtModified.plus(validityDays, ChronoUnit.DAYS); + tips.add("密码将于[" + InstantUtils.format(expirationTime) + "]过期,请及时修改密码,届时将无法登录"); + } + } + // 账号过期提醒 + Instant accountExpirationTime = sysUser.getAccountExpirationTime(); + if (Objects.nonNull(accountExpirationTime) && Instant.now().isAfter(accountExpirationTime.plus(-rule.getAccountTipsDays(), ChronoUnit.DAYS))) { + tips.add("账户将于[" + InstantUtils.format(accountExpirationTime) + "]过期,请联系管理员,届时将无法登录"); + } + return tips; + } + /** * 修改用户信息 * @@ -115,15 +164,50 @@ public class SysBaseServiceImpl implements SysBaseService, BaseParams { Long userId = AuthUtils.get().getId(); SysUser sysUser = sysUserBaseService.getById(userId); if (Objects.isNull(sysUser)) { - throw new BizError("用户不存在"); + throw new BizWarning("用户不存在"); } if (!PasswdUtils.check(oldPasswd, sysUser.getPasswd())) { - throw new BizError("原密码错误"); + throw new BizWarning("原密码错误"); } + // 获取安全规则 + SysUserPasswdRule rule = sysUserPasswdRuleService.getByCode(null); + if (Objects.isNull(rule)) { + throw new BizError("安全规则不存在"); + } + // 检查密码 + sysPasswdService.checkPasswd(passwd, sysUser.getAccount(), rule); + // 加密密码 + String encryptPasswd = PasswdUtils.encrypt(passwd); + // 历史密码 + final Integer hisPasswdCount = rule.getHisPasswdCount(); + String historyPasswd = sysUser.getHistoryPasswd(); + JSONArray historyPasswdArr; + if (StringUtils.isBlank(historyPasswd)) { + historyPasswdArr = new JSONArray(); + } else { + historyPasswdArr = JSONArray.parseArray(historyPasswd); + } + // 检查历史密码 + int size = historyPasswdArr.size(); + if (hisPasswdCount > CP_NUM0 && historyPasswdArr.contains(encryptPasswd)) { + for (int i = size - CP_NUM1; i > size - hisPasswdCount; i--) { + if (historyPasswdArr.getString(i).equals(encryptPasswd)) { + throw new BizWarning("密码不能与近" + hisPasswdCount + "次的历史密码相同"); + } + } + } + // 保存最近20次的历史密码 + if (size >= CP_NUM20) { + historyPasswdArr.removeFirst(); + } + historyPasswdArr.add(sysUser.getPasswd()); + // 修改密码 SysUser update = new SysUser(); update.setId(userId); update.setPasswd(PasswdUtils.encrypt(passwd)); + update.setHistoryPasswd(historyPasswdArr.toJSONString()); + update.setPasswdGmtModified(Instant.now()); return Result.ok(sysUserBaseService.updateById(update)); } diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysLoginServiceImpl.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysLoginServiceImpl.java index f66d3c0..63c1acb 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysLoginServiceImpl.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysLoginServiceImpl.java @@ -15,8 +15,10 @@ import xtools.app.sys.convert.SysLoginConvert; import xtools.app.sys.model.dto.Sm2KeyDto; import xtools.app.sys.model.dto.req.SysLoginReq; import xtools.app.sys.model.entity.SysUser; +import xtools.app.sys.model.entity.SysUserPasswdRule; import xtools.app.sys.service.SysCommonService; import xtools.app.sys.service.SysLoginService; +import xtools.app.sys.service.SysUserPasswdRuleService; import xtools.app.sys.service.base.SysUserBaseService; import xtools.app.sys.service.base.SysUserRoleBaseService; import xtools.app.sys.utils.PasswdUtils; @@ -25,6 +27,7 @@ import xtools.boot.api.exection.BizError; import xtools.boot.api.exection.BizWarning; import xtools.boot.api.model.dto.Result; import xtools.boot.cache.redis.base.RedisService; +import xtools.core.BytesUtils; import xtools.core.StringUtils; import xtools.core.dto.ArithmeticDto; import xtools.core.encrypt.Base64Utils; @@ -34,6 +37,8 @@ import xtools.core.img.ImgUtils; import java.awt.*; import java.io.IOException; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Objects; @@ -54,9 +59,15 @@ import java.util.Objects; public class SysLoginServiceImpl implements SysLoginService, BaseParams { private final SysCommonService sysCommonService; + + private final SysUserPasswdRuleService sysUserPasswdRuleService; + private final SysUserRoleBaseService sysUserRoleBaseService; + private final SysUserBaseService sysUserBaseService; + private final SysLoginConvert sysLoginConvert; + @Resource private RedisService redisService; @@ -123,7 +134,7 @@ public class SysLoginServiceImpl implements SysLoginService, BaseParams { ArithmeticDto arithmeticDto = ArithmeticUtils.create(); // 根据随机验证码生成图片验证码 byte[] imgCode = ImgUtils.getBytesImgCode(128, 36, arithmeticDto.getArithmetic()); - if (imgCode == null) { + if (BytesUtils.isEmpty(imgCode)) { throw new BizError("验证码生成失败"); } AppCache cacheParam = AppCache.UID_CAPTCHA; @@ -168,10 +179,26 @@ public class SysLoginServiceImpl implements SysLoginService, BaseParams { throw new BizWarning("账户不存在"); } SysUser user = userList.get(CP_NUM0); + checkLock(user.getId()); if (!Objects.equals(user.getStatus(), CP_NUM1)) { throw new BizWarning("账户被禁用"); } + Instant accountExpirationTime = user.getAccountExpirationTime(); + if (Objects.nonNull(accountExpirationTime) && Instant.now().isAfter(accountExpirationTime)) { + throw new BizWarning("账户已过期,请联系管理员"); + } + SysUserPasswdRule rule = sysUserPasswdRuleService.getByCode(null); + if (Objects.isNull(rule)) { + throw new BizError("安全规则不存在"); + } + if (rule.getValidityDays() > CP_NUM0) { + Instant passwdGmtModified = user.getPasswdGmtModified(); + if (Objects.nonNull(passwdGmtModified) && Instant.now().isAfter(passwdGmtModified.plus(rule.getValidityDays(), ChronoUnit.DAYS))) { + throw new BizWarning("密码已过期,请联系管理员"); + } + } if (!PasswdUtils.check(passwd, user.getPasswd())) { + passwdError(user.getId(), rule); throw new BizWarning("密码错误"); } LoginUserDto loginUserDto = sysLoginConvert.entityToCacheDto(user); @@ -179,4 +206,51 @@ public class SysLoginServiceImpl implements SysLoginService, BaseParams { redisService.del(captchaKey); return Result.ok(AuthUtils.createToken(loginUserDto)); } + + + /** + * 校验账号是否被锁定 + * + * @param id 用户id + */ + private void checkLock(Long id) { + String lockKey = getLockKey(id); + Long lock = redisService.get(lockKey, Long.class); + if (Objects.nonNull(lock)) { + Long time = redisService.getExpire(lockKey); + throw new BizWarning("账户已锁定,请" + Math.round(time / 60.0) + "分钟后解锁"); + } + } + + /** + * 密码错误 + * + * @param id 用户id + * @param rule 规则 + */ + private void passwdError(Long id, SysUserPasswdRule rule) { + String key = AppCache.COUNT_SYS_USER_PASSWD_ERR.key() + id; + // 获取密码错误次数 + Long count = redisService.incr(key); + if (count >= rule.getErrorPasswdCount()) { + // 大于阈值锁定 + redisService.set(getLockKey(id), CP_NUM1, (long) rule.getErrorPasswdLockMinutes() * BaseParams.CP_NUM60); + redisService.del(key); + throw new BizWarning("密码错误次数超过" + rule.getErrorPasswdCount() + "次,账户已锁定" + rule.getErrorPasswdLockMinutes() + "分钟"); + } else { + // 更新密码错误时间窗口 + redisService.expire(key, (long) rule.getErrorPasswdWindowMinutes() * BaseParams.CP_NUM60); + } + } + + /** + * 获取锁定key + * + * @param id 用户id + * @return 锁定key + */ + private String getLockKey(Long id) { + return AppCache.LOCK_SYS_USER.key() + id; + } + } diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysPasswdServiceImpl.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysPasswdServiceImpl.java new file mode 100644 index 0000000..b9bdab1 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysPasswdServiceImpl.java @@ -0,0 +1,248 @@ +package xtools.app.sys.service.impl; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import xtools.app.sys.model.entity.SysUserPasswdRule; +import xtools.app.sys.service.SysPasswdService; +import xtools.app.sys.service.SysUserPasswdRuleService; +import xtools.base.config.BaseParams; +import xtools.boot.api.exection.BizError; +import xtools.boot.api.exection.BizWarning; +import xtools.core.StringUtils; + +import java.util.Objects; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + *

Title : SysPasswdServiceImpl

+ *

Description : SysPasswdServiceImpl

+ *

DevelopTools : Idea_x64_v2026.1

+ *

DevelopSystem : macOS Sequoia 15.7.5

+ *

Company : org.xujun

+ * + * @author : XuJun + * @version : 1.0.0 + * @date : 2026/6/4 09:32 + */ +@Primary +@Service +@RequiredArgsConstructor +public class SysPasswdServiceImpl implements SysPasswdService, BaseParams { + + /** + * 键盘连续字符序列 + */ + private static final String[] KEYBOARD_SEQUENCES = { + "1234567890", + "qwertyuiop", + "asdfghjkl", + "zxcvbnm", + "qwerty", + "asdfgh", + "zxcvbn", + "qazwsx", + "edcrfv", + "tgbyhn", + "ujmik," + }; + /** + * 常见弱口令列表 + */ + private static final Set WEAK_PASSWORDS = Set.of( + "111111", + "123456", + "1234567", + "12345678", + "123456789", + "1234567890", + "abc123", + "admin", + "root", + "password", + "qwerty", + "welcome", + "monkey", + "login", + "princess", + "dragon", + "master", + "qwertyuiop" + ); + + private final SysUserPasswdRuleService sysUserPasswdRuleService; + + /** + * 检查密码 + * + * @param passwd 密码 + * @param account 账号 + */ + @Override + public void checkPasswd(String passwd, String account) { + checkPasswd(passwd, account, CP_EMPTY); + } + + /** + * 检查密码 + * + * @param passwd 密码 + * @param account 账号 + * @param ruleCode 规则码 + */ + @Override + public void checkPasswd(String passwd, String account, String ruleCode) { + SysUserPasswdRule rule = sysUserPasswdRuleService.getByCode(ruleCode); + if (Objects.isNull(rule)) { + throw new BizError("安全规则不存在"); + } + checkPasswd(passwd, account, rule); + } + + /** + * 检查密码 + * + * @param passwd 密码 + * @param account 账号 + * @param rule 规则 + */ + @Override + public void checkPasswd(String passwd, String account, SysUserPasswdRule rule) { + if (StringUtils.isBlank(passwd)) { + throw new BizError("密码不能为空"); + } + + // 校验最小密码长度 + if (Objects.nonNull(rule.getPasswdMinLength()) && passwd.length() < rule.getPasswdMinLength()) { + throw new BizWarning("密码长度不能少于" + rule.getPasswdMinLength() + "个字符"); + } + + // 校验最大密码长度 + if (Objects.nonNull(rule.getPasswdMaxLength()) && passwd.length() > rule.getPasswdMaxLength()) { + throw new BizWarning("密码长度不能超过" + rule.getPasswdMaxLength() + "个字符"); + } + + // 校验最少数字字符个数 + if (Objects.nonNull(rule.getMinNumCount()) && rule.getMinNumCount() > CP_NUM0) { + int numCount = countMatches(passwd, "\\d"); + if (numCount < rule.getMinNumCount()) { + throw new BizWarning("密码中至少需要包含" + rule.getMinNumCount() + "个数字"); + } + } + + // 校验最少特殊字符个数 + if (Objects.nonNull(rule.getMinSpecCount()) && rule.getMinSpecCount() > CP_NUM0) { + int specCount = countMatches(passwd, "[^a-zA-Z0-9]"); + if (specCount < rule.getMinSpecCount()) { + throw new BizWarning("密码中至少需要包含" + rule.getMinSpecCount() + "个特殊字符"); + } + } + + // 校验最少小写字母个数 + if (Objects.nonNull(rule.getMinLowerCount()) && rule.getMinLowerCount() > CP_NUM0) { + int lowerCount = countMatches(passwd, "[a-z]"); + if (lowerCount < rule.getMinLowerCount()) { + throw new BizWarning("密码中至少需要包含" + rule.getMinLowerCount() + "个小写字母"); + } + } + + // 校验最少大写字母个数 + if (Objects.nonNull(rule.getMinUpperCount()) && rule.getMinUpperCount() > CP_NUM0) { + int upperCount = countMatches(passwd, "[A-Z]"); + if (upperCount < rule.getMinUpperCount()) { + throw new BizWarning("密码中至少需要包含" + rule.getMinUpperCount() + "个大写字母"); + } + } + + // 校验键盘连续字符 + if (Objects.nonNull(rule.getContinuousCheck()) && rule.getContinuousCheck() > CP_NUM0) { + checkKeyboardSequence(passwd); + } + + // 校验弱口令字典 + if (Objects.nonNull(rule.getInvalidCheck()) && rule.getInvalidCheck() > CP_NUM0) { + checkWeakPassword(passwd); + } + + // 校验账号名在密码中占比 + if (Objects.nonNull(rule.getCoverHalfCheck()) && rule.getCoverHalfCheck() > CP_NUM0) { + checkAccountInPassword(passwd, account); + } + } + + /** + * 统计正则匹配的次数 + * + * @param password 密码 + * @param regex 正则表达式 + * @return 匹配次数 + */ + private int countMatches(String password, String regex) { + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(password); + int count = CP_NUM0; + while (matcher.find()) { + count++; + } + return count; + } + + /** + * 检查键盘连续字符 + * + * @param password 密码 + */ + private void checkKeyboardSequence(String password) { + int length = CP_NUM3; + String lowerPassword = password.toLowerCase(); + for (String sequence : KEYBOARD_SEQUENCES) { + for (int i = CP_NUM0; i <= sequence.length() - length; i++) { + String subSequence = sequence.substring(i, i + length); + if (lowerPassword.contains(subSequence)) { + throw new BizWarning("密码不能包含键盘连续字符"); + } + // 检查反向序列 + String reversedSequence = new StringBuilder(subSequence).reverse().toString(); + if (lowerPassword.contains(reversedSequence)) { + throw new BizWarning("密码不能包含键盘连续字符"); + } + } + } + } + + /** + * 检查弱口令 + * + * @param password 密码 + */ + private void checkWeakPassword(String password) { + if (WEAK_PASSWORDS.contains(password.toLowerCase())) { + throw new BizWarning("密码过于简单,请使用更复杂的密码"); + } + } + + /** + * 检查账号名在密码中的占比 + * + * @param password 密码 + * @param account 账号名 + */ + private void checkAccountInPassword(String password, String account) { + if (StringUtils.isBlank(account)) { + return; + } + String lowerPassword = password.toLowerCase(); + String lowerAccount = account.toLowerCase(); + // 检查账号名是否出现在密码中 + if (lowerPassword.contains(lowerAccount)) { + // 计算账号名在密码中的占比 + double ratio = (double) account.length() / password.length(); + if (ratio > 0.5) { + throw new BizWarning("账号名在密码中所占长度不能超过一半"); + } + } + } + +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysUserPasswdRuleServiceImpl.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysUserPasswdRuleServiceImpl.java new file mode 100644 index 0000000..ef2d403 --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysUserPasswdRuleServiceImpl.java @@ -0,0 +1,377 @@ +package xtools.app.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import xtools.app.common.cache.enums.AppCache; +import xtools.app.sys.auth.model.dto.LoginUserDto; +import xtools.app.sys.auth.utils.AuthUtils; +import xtools.app.sys.convert.SysUserPasswdRuleConvert; +import xtools.app.sys.model.dto.excel.SysUserPasswdRuleExcel; +import xtools.app.sys.model.dto.req.SysUserPasswdRuleAddReq; +import xtools.app.sys.model.dto.req.SysUserPasswdRulePageReq; +import xtools.app.sys.model.dto.req.SysUserPasswdRuleUpdateReq; +import xtools.app.sys.model.dto.resp.SysUserPasswdRuleResp; +import xtools.app.sys.model.entity.SysUserPasswdRule; +import xtools.app.sys.service.SysUserPasswdRuleService; +import xtools.app.sys.service.base.SysUserPasswdRuleBaseService; +import xtools.base.config.BaseParams; +import xtools.boot.api.exection.BizError; +import xtools.boot.api.exection.BizWarning; +import xtools.boot.api.model.dto.Result; +import xtools.boot.api.model.dto.page.PageReq; +import xtools.boot.api.model.dto.page.PageResp; +import xtools.boot.api.model.dto.req.IdListReq; +import xtools.boot.cache.redis.base.RedisService; +import xtools.boot.db.mybatisplus.utils.QueryUtils; +import xtools.core.StringUtils; + +import java.util.List; +import java.util.Objects; + +/** + *

Title : SysUserPasswdRuleServiceImpl

+ *

Description : 用户名密码规则 ServiceImpl

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +@Primary +@Service +@RequiredArgsConstructor +public class SysUserPasswdRuleServiceImpl implements SysUserPasswdRuleService, BaseParams { + + private final static AppCache CACHE_PARAM = AppCache.SYS_CACHE_AP_RULE; + private final SysUserPasswdRuleBaseService sysUserPasswdRuleBaseService; + private final SysUserPasswdRuleConvert sysUserPasswdRuleConvert; + @Resource + private RedisService redisService; + + /** + * 分页查询 + * + * @param pageReq 分页请求 + * @return 分页结果 + */ + @Override + public Result> page(PageReq pageReq) { + // 分页查询 + Page page = getPageData(pageReq.getCurrentPage(), pageReq.getPageSize(), pageReq.getQuery()); + // 分装结果 + PageResp pageResp = new PageResp<>(pageReq, page.getTotal(), sysUserPasswdRuleConvert.entityToRespList(page.getRecords())); + return Result.ok(pageResp); + } + + /** + * 根据 ID 查询 + * + * @param id ID + * @return 结果 + */ + @Override + public Result getById(Long id) { + SysUserPasswdRule data = sysUserPasswdRuleBaseService.getById(id); + return Result.ok(sysUserPasswdRuleConvert.entityToResp(data)); + } + + /** + * 添加 + * + * @param req 添加请求 + * @return 添加结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Result add(SysUserPasswdRuleAddReq req) { + SysUserPasswdRule entity = sysUserPasswdRuleConvert.addReqToEntity(req); + if (Objects.nonNull(existsEntity(entity))) { + throw new BizWarning("数据已存在"); + } + LoginUserDto loginUser = AuthUtils.get(); + entity.setCreateBy(loginUser.getId()); + entity.setUpdateBy(loginUser.getId()); + return Result.ok(sysUserPasswdRuleBaseService.save(entity)); + } + + /** + * 修改 + * + * @param req 修改请求 + * @return 修改结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Result update(SysUserPasswdRuleUpdateReq req) { + SysUserPasswdRule entity = sysUserPasswdRuleConvert.updateReqToEntity(req); + if (Objects.nonNull(existsEntity(entity))) { + throw new BizWarning("数据已存在"); + } + LoginUserDto loginUser = AuthUtils.get(); + entity.setUpdateBy(loginUser.getId()); + boolean updated = sysUserPasswdRuleBaseService.updateById(entity); + if (!updated) { + throw new BizError("修改失败"); + } + delCache(); + return Result.ok(true); + } + + /** + * 根据 ID 删除 + * + * @param req ID 集合 + * @return 删除结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Result delById(IdListReq req) { + boolean removed = sysUserPasswdRuleBaseService.removeByIds(req.getIdList()); + if (!removed) { + throw new BizError("删除失败"); + } + delCache(); + return Result.ok(true); + } + + /** + * 设置默认 + * + * @param id ID + * @return 设置结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Result setDef(Long id) { + SysUserPasswdRule entity = new SysUserPasswdRule(); + entity.setRuleDefault(CP_NUM0); + sysUserPasswdRuleBaseService.update(entity, null); + + entity.setId(id); + entity.setRuleDefault(CP_NUM1); + sysUserPasswdRuleBaseService.updateById(entity); + + delCache(); + + return Result.ok(true); + } + + /** + * 根据规则code获取数据,code为空则获取默认规则 + * + * @param code code + * @return 规则 + */ + @Override + public SysUserPasswdRule getByCode(String code) { + // 默认规则code + String defaultCode = "default"; + + // 从缓存获取规则 + String cacheKey = StringUtils.isBlank(code) ? defaultCode : code; + SysUserPasswdRule rule = redisService.hashGet(CACHE_PARAM.key(), cacheKey, SysUserPasswdRule.class); + if (Objects.nonNull(rule)) { + return rule; + } + + // 创建查询条件 + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + if (StringUtils.isBlank(code)) { + query.eq(SysUserPasswdRule::getRuleDefault, CP_NUM1); + } else { + query.eq(SysUserPasswdRule::getRuleCode, code); + } + rule = sysUserPasswdRuleBaseService.getOne(query); + if (Objects.isNull(rule)) { + return null; + } + redisService.hashPut(CACHE_PARAM.key(), cacheKey, rule); + return rule; + } + + /** + * 删除缓存 + */ + private void delCache() { + redisService.del(CACHE_PARAM.key()); + } + + /** + * 导出 Excel + * + * @param req 请求参数 + * @return Excel 数据 + */ + @Override + public List exportExcel(SysUserPasswdRulePageReq req) { + // 创建查询条件 + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + // 查询字段 + query.select( + SysUserPasswdRule::getRuleName + , SysUserPasswdRule::getRuleDesc + , SysUserPasswdRule::getRuleCode + , SysUserPasswdRule::getPasswdMinLength + , SysUserPasswdRule::getPasswdMaxLength + , SysUserPasswdRule::getMinNumCount + , SysUserPasswdRule::getMinSpecCount + , SysUserPasswdRule::getMinLowerCount + , SysUserPasswdRule::getMinUpperCount + , SysUserPasswdRule::getHisPasswdCount + , SysUserPasswdRule::getContinuousCheck + , SysUserPasswdRule::getInvalidCheck + , SysUserPasswdRule::getCoverHalfCheck + , SysUserPasswdRule::getValidityDays + , SysUserPasswdRule::getResidueTipsDays + , SysUserPasswdRule::getLockCancelDays + , SysUserPasswdRule::getErrorPasswdWindowMinutes + , SysUserPasswdRule::getErrorPasswdCount + , SysUserPasswdRule::getErrorPasswdLockMinutes + , SysUserPasswdRule::getAccountValidityDays + , SysUserPasswdRule::getAccountTipsDays + , SysUserPasswdRule::getMemo + ); + // 设置查询条件 + setQueryWrapper(query, req); + // 排序 + query.orderByDesc(SysUserPasswdRule::getGmtCreate); + List dataList = sysUserPasswdRuleBaseService.list(query); + return dataList.stream().map(sysUserPasswdRuleConvert::entityToExcel).toList(); + } + + /** + * 导入 Excel + * + * @param dataList Excel 数据 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void importExcel(List dataList) { + for (SysUserPasswdRuleExcel excel : dataList) { + SysUserPasswdRule item = sysUserPasswdRuleConvert.excelToEntity(excel); + SysUserPasswdRule dbItem = existsEntity(item); + if (Objects.isNull(dbItem)) { + // 新增 + sysUserPasswdRuleBaseService.save(item); + } else { + // 修改 + item.setId(dbItem.getId()); + sysUserPasswdRuleBaseService.updateById(item); + } + } + } + + /** + * 获取分页数据 + * + * @param currentPage 当前页 + * @param pageSize 每页数量 + * @param req 请求参数 + * @return 分页数据 + */ + private Page getPageData(Integer currentPage, Integer pageSize, SysUserPasswdRulePageReq req) { + // 创建查询条件 + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + // 查询字段 + query.select( + SysUserPasswdRule::getId + , SysUserPasswdRule::getRuleName + , SysUserPasswdRule::getRuleDesc + , SysUserPasswdRule::getRuleCode + , SysUserPasswdRule::getRuleDefault + , SysUserPasswdRule::getPasswdMinLength + , SysUserPasswdRule::getPasswdMaxLength + , SysUserPasswdRule::getMinNumCount + , SysUserPasswdRule::getMinSpecCount + , SysUserPasswdRule::getMinLowerCount + , SysUserPasswdRule::getMinUpperCount + , SysUserPasswdRule::getHisPasswdCount + , SysUserPasswdRule::getContinuousCheck + , SysUserPasswdRule::getInvalidCheck + , SysUserPasswdRule::getCoverHalfCheck + , SysUserPasswdRule::getValidityDays + , SysUserPasswdRule::getResidueTipsDays + , SysUserPasswdRule::getLockCancelDays + , SysUserPasswdRule::getErrorPasswdWindowMinutes + , SysUserPasswdRule::getErrorPasswdCount + , SysUserPasswdRule::getErrorPasswdLockMinutes + , SysUserPasswdRule::getAccountValidityDays + , SysUserPasswdRule::getAccountTipsDays + , SysUserPasswdRule::getCreateBy + , SysUserPasswdRule::getUpdateBy + , SysUserPasswdRule::getMemo + , SysUserPasswdRule::getGmtCreate + , SysUserPasswdRule::getGmtModified + ); + // 设置查询条件 + setQueryWrapper(query, req); + // 排序 + query.orderByDesc(SysUserPasswdRule::getGmtCreate); + return sysUserPasswdRuleBaseService.page(QueryUtils.getPage(currentPage, pageSize), query); + } + + /** + * 设置查询条件 + * + * @param query 查询条件 + * @param req 请求参数 + */ + private void setQueryWrapper(LambdaQueryWrapper query, SysUserPasswdRulePageReq req) { + if (Objects.isNull(req)) { + return; + } + // 查询条件 + query.eq(Objects.nonNull(req.getId()), SysUserPasswdRule::getId, req.getId()); + query.like(StringUtils.isNotBlank(req.getRuleName()), SysUserPasswdRule::getRuleName, req.getRuleName()); + query.like(StringUtils.isNotBlank(req.getRuleDesc()), SysUserPasswdRule::getRuleDesc, req.getRuleDesc()); + query.like(StringUtils.isNotBlank(req.getRuleCode()), SysUserPasswdRule::getRuleCode, req.getRuleCode()); + query.eq(Objects.nonNull(req.getRuleDefault()), SysUserPasswdRule::getRuleDefault, req.getRuleDefault()); + query.eq(Objects.nonNull(req.getPasswdMinLength()), SysUserPasswdRule::getPasswdMinLength, req.getPasswdMinLength()); + query.eq(Objects.nonNull(req.getPasswdMaxLength()), SysUserPasswdRule::getPasswdMaxLength, req.getPasswdMaxLength()); + query.eq(Objects.nonNull(req.getMinNumCount()), SysUserPasswdRule::getMinNumCount, req.getMinNumCount()); + query.eq(Objects.nonNull(req.getMinSpecCount()), SysUserPasswdRule::getMinSpecCount, req.getMinSpecCount()); + query.eq(Objects.nonNull(req.getMinLowerCount()), SysUserPasswdRule::getMinLowerCount, req.getMinLowerCount()); + query.eq(Objects.nonNull(req.getMinUpperCount()), SysUserPasswdRule::getMinUpperCount, req.getMinUpperCount()); + query.eq(Objects.nonNull(req.getHisPasswdCount()), SysUserPasswdRule::getHisPasswdCount, req.getHisPasswdCount()); + query.eq(Objects.nonNull(req.getContinuousCheck()), SysUserPasswdRule::getContinuousCheck, req.getContinuousCheck()); + query.eq(Objects.nonNull(req.getInvalidCheck()), SysUserPasswdRule::getInvalidCheck, req.getInvalidCheck()); + query.eq(Objects.nonNull(req.getCoverHalfCheck()), SysUserPasswdRule::getCoverHalfCheck, req.getCoverHalfCheck()); + query.eq(Objects.nonNull(req.getValidityDays()), SysUserPasswdRule::getValidityDays, req.getValidityDays()); + query.eq(Objects.nonNull(req.getResidueTipsDays()), SysUserPasswdRule::getResidueTipsDays, req.getResidueTipsDays()); + query.eq(Objects.nonNull(req.getLockCancelDays()), SysUserPasswdRule::getLockCancelDays, req.getLockCancelDays()); + query.eq(Objects.nonNull(req.getErrorPasswdWindowMinutes()), SysUserPasswdRule::getErrorPasswdWindowMinutes, req.getErrorPasswdWindowMinutes()); + query.eq(Objects.nonNull(req.getErrorPasswdCount()), SysUserPasswdRule::getErrorPasswdCount, req.getErrorPasswdCount()); + query.eq(Objects.nonNull(req.getErrorPasswdLockMinutes()), SysUserPasswdRule::getErrorPasswdLockMinutes, req.getErrorPasswdLockMinutes()); + query.eq(Objects.nonNull(req.getAccountValidityDays()), SysUserPasswdRule::getAccountValidityDays, req.getAccountValidityDays()); + query.eq(Objects.nonNull(req.getAccountTipsDays()), SysUserPasswdRule::getAccountTipsDays, req.getAccountTipsDays()); + query.eq(Objects.nonNull(req.getCreateBy()), SysUserPasswdRule::getCreateBy, req.getCreateBy()); + query.eq(Objects.nonNull(req.getUpdateBy()), SysUserPasswdRule::getUpdateBy, req.getUpdateBy()); + query.like(StringUtils.isNotBlank(req.getMemo()), SysUserPasswdRule::getMemo, req.getMemo()); + QueryUtils.addTimeRange(query, req.getGmtCreateRange(), SysUserPasswdRule::getGmtCreate); + QueryUtils.addTimeRange(query, req.getGmtModifiedRange(), SysUserPasswdRule::getGmtModified); + } + + /** + * 判断实体是否存在 + * + * @param entity 实体 + * @return 是否存在 + */ + private SysUserPasswdRule existsEntity(SysUserPasswdRule entity) { + // 创建查询条件 + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + // 查询字段 + query.select(SysUserPasswdRule::getId); + // 排除当前数据 + query.ne(Objects.nonNull(entity.getId()), SysUserPasswdRule::getId, entity.getId()); + query.eq(StringUtils.isNotBlank(entity.getRuleCode()), SysUserPasswdRule::getRuleCode, entity.getRuleCode()); + // 校验数据时候存在的条件 + return sysUserPasswdRuleBaseService.getOne(query); + } + +} diff --git a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysUserServiceImpl.java b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysUserServiceImpl.java index d4fe896..a2b7b7a 100644 --- a/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysUserServiceImpl.java +++ b/xtools-app-sys/xtools-app-sys-biz/src/main/java/xtools/app/sys/service/impl/SysUserServiceImpl.java @@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import xtools.app.common.task.enums.TaskType; import xtools.app.sys.auth.utils.AuthUtils; import xtools.app.sys.config.SysConfig; import xtools.app.sys.convert.SysUserConvert; @@ -15,11 +16,14 @@ import xtools.app.sys.model.dto.req.SysUserUpdateReq; import xtools.app.sys.model.dto.req.UserInfoEditReq; import xtools.app.sys.model.dto.resp.SysUserResp; import xtools.app.sys.model.entity.SysUser; +import xtools.app.sys.model.entity.SysUserPasswdRule; +import xtools.app.sys.service.SysUserPasswdRuleService; import xtools.app.sys.service.SysUserService; import xtools.app.sys.service.base.SysDeptBaseService; import xtools.app.sys.service.base.SysUserBaseService; import xtools.app.sys.service.base.SysUserRoleBaseService; import xtools.app.sys.utils.PasswdUtils; +import xtools.base.config.BaseParams; import xtools.boot.api.exection.BizError; import xtools.boot.api.exection.BizWarning; import xtools.boot.api.model.dto.Result; @@ -27,9 +31,17 @@ import xtools.boot.api.model.dto.page.PageReq; import xtools.boot.api.model.dto.page.PageResp; import xtools.boot.api.model.dto.req.IdListReq; import xtools.boot.db.mybatisplus.utils.QueryUtils; +import xtools.boot.log.LogBus; +import xtools.boot.log.enums.LogBusBaseType; +import xtools.boot.task.TaskBus; +import xtools.boot.task.enums.TaskStatus; import xtools.core.StringUtils; +import xtools.core.UuidUtils; +import xtools.core.enums.LogLevel; import xtools.core.extend.CheckUtils; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -46,12 +58,14 @@ import java.util.Objects; @Primary @Service @RequiredArgsConstructor -public class SysUserServiceImpl implements SysUserService { +public class SysUserServiceImpl implements SysUserService, BaseParams { private final SysConfig sysConfig; private final SysDeptBaseService sysDeptBaseService; + private final SysUserPasswdRuleService sysUserPasswdRuleService; + private final SysUserRoleBaseService sysUserRoleBaseService; private final SysUserBaseService sysUserBaseService; @@ -89,7 +103,6 @@ public class SysUserServiceImpl implements SysUserService { SysUser data = sysUserBaseService.getById(id); SysUserResp sysUserResp = sysUserConvert.entityToResp(data); sysUserResp.setRoleIds(sysUserRoleBaseService.getUserRole(sysUserResp.getId())); - sysUserResp.setPasswd(null); return Result.ok(sysUserResp); } @@ -107,6 +120,13 @@ public class SysUserServiceImpl implements SysUserService { throw new BizWarning("数据已存在"); } entity.setPasswd(PasswdUtils.encrypt(sysConfig.getUser().getPasswd())); + if (Objects.isNull(entity.getAccountExpirationTime())) { + SysUserPasswdRule rule = sysUserPasswdRuleService.getByCode(null); + Integer validityDays = rule.getAccountValidityDays(); + if (validityDays > CP_NUM0) { + entity.setAccountExpirationTime(Instant.now().plus(validityDays, ChronoUnit.DAYS)); + } + } boolean saved = sysUserBaseService.save(entity); if (!saved) { throw new BizError("添加失败"); @@ -130,6 +150,7 @@ public class SysUserServiceImpl implements SysUserService { throw new BizWarning("数据已存在"); } entity.setPasswd(null); + entity.setAccountDisabledTime(Objects.equals(entity.getStatus(), CP_NUM0) ? Instant.now() : null); boolean updated = sysUserBaseService.updateById(entity); if (!updated) { throw new BizError("修改失败"); @@ -157,6 +178,30 @@ public class SysUserServiceImpl implements SysUserService { return Result.ok(true); } + /** + * 重置密码 + * + * @param id ID + * @return 重置密码结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Result resetPasswd(Long id) { + SysUser entity = sysUserBaseService.getById(id); + if (Objects.isNull(entity)) { + throw new BizError("用户不存在"); + } + SysUser update = new SysUser(); + update.setId(id); + update.setPasswd(PasswdUtils.encrypt(sysConfig.getUser().getPasswd())); + update.setPasswdGmtModified(Instant.now()); + boolean updated = sysUserBaseService.updateById(update); + if (!updated) { + throw new BizError("重置密码失败"); + } + return Result.ok(true); + } + /** * 根据 ID 集合查询 * @@ -208,6 +253,7 @@ public class SysUserServiceImpl implements SysUserService { SysUser::getEmail, SysUser::getSex, SysUser::getStatus, + SysUser::getAccountExpirationTime, SysUser::getMemo, SysUser::getGmtCreate, SysUser::getGmtModified @@ -303,4 +349,60 @@ public class SysUserServiceImpl implements SysUserService { return sysUserBaseService.updateById(entity); } + /** + * 清理禁用账号Job + */ + @Override + public void cleanSysUserJob() { + // 任务日志code + String code = UuidUtils.get(); + // 任务类型 + TaskType taskType = TaskType.DEL_DISABLE_SYS_USER; + + // 任务信息 + String info = "开始清理禁用账号,请稍候..."; + // 保存任务 + TaskBus.init(code, taskType, TaskStatus.ING).info(info).save(); + // 异常 + Exception ex = null; + try { + info = cleanSysUser(); + } catch (Exception e) { + ex = e; + info = "执行失败"; + throw e; + } finally { + // 保存任务 + TaskStatus status = Objects.isNull(ex) ? TaskStatus.SUCCESS : TaskStatus.ERROR; + TaskBus.init(code, taskType, status).info(info).save(); + if (Objects.nonNull(ex)) { + // 保存异常日志 + LogBus.init(LogLevel.ERROR, LogBusBaseType.TASK).error(ex).save(); + } + } + } + + /** + * 清理禁用账号 + * + * @return 清理结果 + */ + private String cleanSysUser() { + SysUserPasswdRule rule = sysUserPasswdRuleService.getByCode(null); + if (Objects.isNull(rule)) { + return "安全规则不存在"; + } + Integer lockCancelDays = rule.getLockCancelDays(); + if (lockCancelDays <= CP_NUM0) { + return "清理时间为0,则不清理禁用账号"; + } + Instant time = Instant.now().plus(-lockCancelDays, ChronoUnit.DAYS); + // 创建查询条件 + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + query.eq(SysUser::getStatus, CP_NUM0); + query.le(SysUser::getAccountDisabledTime, time); + boolean remove = sysUserBaseService.remove(query); + return remove ? "清理成功" : "清理失败"; + } + } diff --git a/xtools-app-sys/xtools-app-sys-call/src/main/java/xtools/app/sys/call/SysUserPasswdRuleCall.java b/xtools-app-sys/xtools-app-sys-call/src/main/java/xtools/app/sys/call/SysUserPasswdRuleCall.java new file mode 100644 index 0000000..c47870d --- /dev/null +++ b/xtools-app-sys/xtools-app-sys-call/src/main/java/xtools/app/sys/call/SysUserPasswdRuleCall.java @@ -0,0 +1,18 @@ +package xtools.app.sys.call; + +import org.springframework.web.service.annotation.HttpExchange; +import xtools.app.sys.api.SysUserPasswdRuleApi; + +/** + *

Title : SysUserPasswdRuleCall

+ *

Description : 用户名密码规则 Call

+ *

Company : org.xujun

+ * + * @author : xujun + * @version : 1.0.0 + * @date : 2026-06-03 16:26:10 + */ +@HttpExchange("/sys/user-passwd-rule") +public interface SysUserPasswdRuleCall extends SysUserPasswdRuleApi { + +}