diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/util/DataPermissionUtils.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/util/DataPermissionUtils.java index c154bd5f5..583c482b2 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/util/DataPermissionUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/util/DataPermissionUtils.java @@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.datapermission.core.aop.DataPermissionContextHolder; import lombok.SneakyThrows; +import java.util.concurrent.Callable; + /** * 数据权限 Util * @@ -40,4 +42,22 @@ public class DataPermissionUtils { } } + /** + * 忽略数据权限,执行对应的逻辑 + * + * @param callable 逻辑 + * @return 执行结果 + */ + @SneakyThrows + public static T executeIgnore(Callable callable) { + DataPermission dataPermission = getDisableDataPermissionDisable(); + DataPermissionContextHolder.add(dataPermission); + try { + // 执行 callable + return callable.call(); + } finally { + DataPermissionContextHolder.remove(); + } + } + } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/LogRecordConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/LogRecordConstants.java new file mode 100644 index 000000000..4ee384073 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/LogRecordConstants.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.system.enums; + +/** + * System 操作日志枚举 + * 目的:统一管理,也减少 Service 里各种“复杂”字符串 + * + * @author 芋道源码 + */ +public interface LogRecordConstants { + + // ======================= SYSTEM_USER 用户 ======================= + + String SYSTEM_USER_TYPE = "SYSTEM 用户"; + String SYSTEM_USER_CREATE_SUB_TYPE = "创建用户"; + String SYSTEM_USER_CREATE_SUCCESS = "创建了用户【{{#user.nickname}}】"; + String SYSTEM_USER_UPDATE_SUB_TYPE = "更新用户"; + String SYSTEM_USER_UPDATE_SUCCESS = "更新了用户【{{#user.nickname}}】: {_DIFF{#updateReqVO}}"; + String SYSTEM_USER_DELETE_SUB_TYPE = "删除用户"; + String SYSTEM_USER_DELETE_SUCCESS = "删除了用户【{{#user.nickname}}】"; + String SYSTEM_USER_UPDATE_PASSWORD_SUB_TYPE = "重置用户密码"; + String SYSTEM_USER_UPDATE_PASSWORD_SUCCESS = "将用户【{{#user.nickname}}】的密码从【{{#user.password}}】重置为【{{#newPassword}}】"; + + // ======================= SYSTEM_ROLE 角色 ======================= + + String SYSTEM_ROLE_TYPE = "SYSTEM 角色"; + String SYSTEM_ROLE_CREATE_SUB_TYPE = "创建角色"; + String SYSTEM_ROLE_CREATE_SUCCESS = "创建了角色【{{#role.name}}】"; + String SYSTEM_ROLE_UPDATE_SUB_TYPE = "更新角色"; + String SYSTEM_ROLE_UPDATE_SUCCESS = "更新了角色【{{#role.name}}】: {_DIFF{#updateReqVO}}"; + String SYSTEM_ROLE_DELETE_SUB_TYPE = "删除角色"; + String SYSTEM_ROLE_DELETE_SUCCESS = "删除了角色【{{#role.name}}】"; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.java index 327921d06..bf04ff117 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.java @@ -52,14 +52,6 @@ public class RoleController { return success(true); } - @PutMapping("/update-status") - @Operation(summary = "修改角色状态") - @PreAuthorize("@ss.hasPermission('system:role:update')") - public CommonResult updateRoleStatus(@Valid @RequestBody RoleUpdateStatusReqVO reqVO) { - roleService.updateRoleStatus(reqVO.getId(), reqVO.getStatus()); - return success(true); - } - @DeleteMapping("/delete") @Operation(summary = "删除角色") @Parameter(name = "id", description = "角色编号", required = true, example = "1024") @@ -87,10 +79,10 @@ public class RoleController { @GetMapping({"/list-all-simple", "/simple-list"}) @Operation(summary = "获取角色精简信息列表", description = "只包含被开启的角色,主要用于前端的下拉选项") - public CommonResult> getSimpleRoleList() { + public CommonResult> getSimpleRoleList() { List list = roleService.getRoleListByStatus(singleton(CommonStatusEnum.ENABLE.getStatus())); list.sort(Comparator.comparing(RoleDO::getSort)); - return success(BeanUtils.toBean(list, RoleSimpleRespVO.class)); + return success(BeanUtils.toBean(list, RoleRespVO.class)); } @GetMapping("/export-excel") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSaveReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSaveReqVO.java index 5a59b5f4c..3c8a686ed 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSaveReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSaveReqVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; +import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -7,7 +8,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -@Schema(description = "管理后台 - 角色创建 Request VO") +@Schema(description = "管理后台 - 角色创建/更新 Request VO") @Data public class RoleSaveReqVO { @@ -16,19 +17,23 @@ public class RoleSaveReqVO { @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "管理员") @NotBlank(message = "角色名称不能为空") - @Size(max = 30, message = "角色名称长度不能超过30个字符") + @Size(max = 30, message = "角色名称长度不能超过 30 个字符") + @DiffLogField(name = "角色名称") private String name; @NotBlank(message = "角色标志不能为空") - @Size(max = 100, message = "角色标志长度不能超过100个字符") + @Size(max = 100, message = "角色标志长度不能超过 100 个字符") @Schema(description = "角色编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ADMIN") + @DiffLogField(name = "角色标志") private String code; @Schema(description = "显示顺序不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @NotNull(message = "显示顺序不能为空") + @DiffLogField(name = "显示顺序") private Integer sort; @Schema(description = "备注", example = "我是一个角色") + @DiffLogField(name = "备注") private String remark; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleUpdateStatusReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleUpdateStatusReqVO.java deleted file mode 100644 index f11e56980..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleUpdateStatusReqVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 角色更新状态 Request VO") -@Data -public class RoleUpdateStatusReqVO { - - @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "角色编号不能为空") - private Long id; - - @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "状态不能为空") - @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") - private Integer status; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java index 4644b39b9..f196e651d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java @@ -2,12 +2,16 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.module.system.framework.operatelog.core.DeptParseFunction; +import cn.iocoder.yudao.module.system.framework.operatelog.core.PostParseFunction; +import cn.iocoder.yudao.module.system.framework.operatelog.core.SexParseFunction; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.*; import lombok.Data; import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.*; import java.util.Set; @Schema(description = "管理后台 - 用户创建/修改 Request VO") @@ -21,34 +25,43 @@ public class UserSaveReqVO { @NotBlank(message = "用户账号不能为空") @Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成") @Size(min = 4, max = 30, message = "用户账号长度为 4-30 个字符") + @DiffLogField(name = "用户账号") private String username; @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") @Size(max = 30, message = "用户昵称长度不能超过30个字符") + @DiffLogField(name = "用户昵称") private String nickname; @Schema(description = "备注", example = "我是一个用户") + @DiffLogField(name = "备注") private String remark; - @Schema(description = "部门ID", example = "我是一个用户") + @Schema(description = "部门编号", example = "我是一个用户") + @DiffLogField(name = "部门", function = DeptParseFunction.NAME) private Long deptId; @Schema(description = "岗位编号数组", example = "1") + @DiffLogField(name = "岗位", function = PostParseFunction.NAME) private Set postIds; @Schema(description = "用户邮箱", example = "yudao@iocoder.cn") @Email(message = "邮箱格式不正确") @Size(max = 50, message = "邮箱长度不能超过 50 个字符") + @DiffLogField(name = "用户邮箱") private String email; @Schema(description = "手机号码", example = "15601691300") @Mobile + @DiffLogField(name = "手机号码") private String mobile; @Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1") + @DiffLogField(name = "用户性别", function = SexParseFunction.NAME) private Integer sex; @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png") + @DiffLogField(name = "用户头像") private String avatar; // ========== 仅【创建】时,需要传递的字段 ========== diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AdminUserParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AdminUserParseFunction.java index 5170c94b7..a883217dd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AdminUserParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AdminUserParseFunction.java @@ -1,8 +1,9 @@ package cn.iocoder.yudao.module.system.framework.operatelog.core; +import cn.hutool.core.convert.Convert; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; import com.mzt.logapi.service.IParseFunction; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -21,7 +22,7 @@ public class AdminUserParseFunction implements IParseFunction { public static final String NAME = "getAdminUserById"; @Resource - private AdminUserApi adminUserApi; + private AdminUserService adminUserService; @Override public String functionName() { @@ -35,7 +36,7 @@ public class AdminUserParseFunction implements IParseFunction { } // 获取用户信息 - AdminUserRespDTO user = adminUserApi.getUser(Long.parseLong(value.toString())).getCheckedData(); + AdminUserDO user = adminUserService.getUser(Convert.toLong(value)); if (user == null) { log.warn("[apply][获取用户{{}}为空", value); return ""; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AreaParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AreaParseFunction.java index e22ab5cf2..f2b908901 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AreaParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AreaParseFunction.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.framework.operatelog.core; +import cn.hutool.core.convert.Convert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import com.mzt.logapi.service.IParseFunction; @@ -32,7 +33,7 @@ public class AreaParseFunction implements IParseFunction { if (StrUtil.isEmptyIfStr(value)) { return ""; } - return AreaUtils.format(Integer.parseInt(value.toString())); + return AreaUtils.format(Convert.toInt(value)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/DeptParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/DeptParseFunction.java index db922ce01..e2a6fdc72 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/DeptParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/DeptParseFunction.java @@ -1,8 +1,9 @@ package cn.iocoder.yudao.module.system.framework.operatelog.core; +import cn.hutool.core.convert.Convert; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.system.api.dept.DeptApi; -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.service.dept.DeptService; import com.mzt.logapi.service.IParseFunction; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -10,7 +11,7 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; /** - * 管理员名字的 {@link IParseFunction} 实现类 + * 部门名字的 {@link IParseFunction} 实现类 * * @author HUIHUI */ @@ -21,7 +22,7 @@ public class DeptParseFunction implements IParseFunction { public static final String NAME = "getDeptById"; @Resource - private DeptApi deptApi; + private DeptService deptService; @Override public String functionName() { @@ -35,7 +36,7 @@ public class DeptParseFunction implements IParseFunction { } // 获取部门信息 - DeptRespDTO dept = deptApi.getDept(Long.parseLong(value.toString())).getCheckedData(); + DeptDO dept = deptService.getDept(Convert.toLong(value)); if (dept == null) { log.warn("[apply][获取部门{{}}为空", value); return ""; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/PostParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/PostParseFunction.java new file mode 100644 index 000000000..e246d1234 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/PostParseFunction.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.system.framework.operatelog.core; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; +import cn.iocoder.yudao.module.system.service.dept.PostService; +import com.mzt.logapi.service.IParseFunction; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * 岗位名字的 {@link IParseFunction} 实现类 + * + * @author HUIHUI + */ +@Slf4j +@Component +public class PostParseFunction implements IParseFunction { + + public static final String NAME = "getPostById"; + + @Resource + private PostService postService; + + @Override + public String functionName() { + return NAME; + } + + @Override + public String apply(Object value) { + if (StrUtil.isEmptyIfStr(value)) { + return ""; + } + + // 获取岗位信息 + PostDO post = postService.getPost(Convert.toLong(value)); + if (post == null) { + log.warn("[apply][获取岗位{{}}为空", value); + return ""; + } + return post.getName(); + } + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java index 978444e17..c7f124832 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java @@ -1 +1,4 @@ +/** + * 占位文件,避免文件夹缩进 + */ package cn.iocoder.yudao.module.system.framework.operatelog; \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java index a97eb796d..44ec11003 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java @@ -40,14 +40,6 @@ public interface RoleService { */ void deleteRole(Long id); - /** - * 更新角色状态 - * - * @param id 角色编号 - * @param status 状态 - */ - void updateRoleStatus(Long id, Integer status); - /** * 设置角色的数据权限 * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java index f29a76a65..af3aa8a57 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java @@ -17,6 +17,9 @@ import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; import com.google.common.annotations.VisibleForTesting; +import com.mzt.logapi.context.LogRecordContext; +import com.mzt.logapi.starter.annotation.LogRecord; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; @@ -24,12 +27,12 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; -import javax.annotation.Resource; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.system.enums.LogRecordConstants.*; /** * 角色 Service 实现类 @@ -48,41 +51,40 @@ public class RoleServiceImpl implements RoleService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(type = SYSTEM_ROLE_TYPE, subType = SYSTEM_ROLE_CREATE_SUB_TYPE, bizNo = "{{#role.id}}", + success = SYSTEM_ROLE_CREATE_SUCCESS) public Long createRole(RoleSaveReqVO createReqVO, Integer type) { - // 校验角色 + // 1. 校验角色 validateRoleDuplicate(createReqVO.getName(), createReqVO.getCode(), null); - // 插入到数据库 - RoleDO role = BeanUtils.toBean(createReqVO, RoleDO.class); - role.setType(ObjectUtil.defaultIfNull(type, RoleTypeEnum.CUSTOM.getType())); - role.setStatus(CommonStatusEnum.ENABLE.getStatus()); - role.setDataScope(DataScopeEnum.ALL.getScope()); // 默认可查看所有数据。原因是,可能一些项目不需要项目权限 + + // 2. 插入到数据库 + RoleDO role = BeanUtils.toBean(createReqVO, RoleDO.class) + .setType(ObjectUtil.defaultIfNull(type, RoleTypeEnum.CUSTOM.getType())) + .setStatus(CommonStatusEnum.ENABLE.getStatus()) + .setDataScope(DataScopeEnum.ALL.getScope()); // 默认可查看所有数据。原因是,可能一些项目不需要项目权限 roleMapper.insert(role); - // 返回 + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("role", role); return role.getId(); } @Override @CacheEvict(value = RedisKeyConstants.ROLE, key = "#updateReqVO.id") + @LogRecord(type = SYSTEM_ROLE_TYPE, subType = SYSTEM_ROLE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", + success = SYSTEM_ROLE_UPDATE_SUCCESS) public void updateRole(RoleSaveReqVO updateReqVO) { - // 校验是否可以更新 - validateRoleForUpdate(updateReqVO.getId()); - // 校验角色的唯一字段是否重复 + // 1.1 校验是否可以更新 + RoleDO role = validateRoleForUpdate(updateReqVO.getId()); + // 1.2 校验角色的唯一字段是否重复 validateRoleDuplicate(updateReqVO.getName(), updateReqVO.getCode(), updateReqVO.getId()); - // 更新到数据库 + // 2. 更新到数据库 RoleDO updateObj = BeanUtils.toBean(updateReqVO, RoleDO.class); roleMapper.updateById(updateObj); - } - @Override - @CacheEvict(value = RedisKeyConstants.ROLE, key = "#id") - public void updateRoleStatus(Long id, Integer status) { - // 校验是否可以更新 - validateRoleForUpdate(id); - - // 更新状态 - RoleDO updateObj = new RoleDO().setId(id).setStatus(status); - roleMapper.updateById(updateObj); + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("role", role); } @Override @@ -102,13 +104,19 @@ public class RoleServiceImpl implements RoleService { @Override @Transactional(rollbackFor = Exception.class) @CacheEvict(value = RedisKeyConstants.ROLE, key = "#id") + @LogRecord(type = SYSTEM_ROLE_TYPE, subType = SYSTEM_ROLE_DELETE_SUB_TYPE, bizNo = "{{#id}}", + success = SYSTEM_ROLE_DELETE_SUCCESS) public void deleteRole(Long id) { - // 校验是否可以更新 - validateRoleForUpdate(id); - // 标记删除 + // 1. 校验是否可以更新 + RoleDO role = validateRoleForUpdate(id); + + // 2.1 标记删除 roleMapper.deleteById(id); - // 删除相关数据 + // 2.2 删除相关数据 permissionService.processRoleDeleted(id); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("role", role); } /** @@ -149,15 +157,16 @@ public class RoleServiceImpl implements RoleService { * @param id 角色编号 */ @VisibleForTesting - void validateRoleForUpdate(Long id) { - RoleDO roleDO = roleMapper.selectById(id); - if (roleDO == null) { + RoleDO validateRoleForUpdate(Long id) { + RoleDO role = roleMapper.selectById(id); + if (role == null) { throw exception(ROLE_NOT_EXISTS); } // 内置角色,不允许删除 - if (RoleTypeEnum.SYSTEM.getType().equals(roleDO.getType())) { + if (RoleTypeEnum.SYSTEM.getType().equals(role.getType())) { throw exception(ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE); } + return role; } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java index 5f438708c..efae327f8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java @@ -27,6 +27,10 @@ import cn.iocoder.yudao.module.system.service.dept.PostService; import cn.iocoder.yudao.module.system.service.permission.PermissionService; import cn.iocoder.yudao.module.system.service.tenant.TenantService; import com.google.common.annotations.VisibleForTesting; +import com.mzt.logapi.context.LogRecordContext; +import com.mzt.logapi.service.impl.DiffParseFunction; +import com.mzt.logapi.starter.annotation.LogRecord; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; @@ -34,7 +38,6 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import javax.annotation.Resource; import java.io.InputStream; import java.time.LocalDateTime; import java.util.*; @@ -43,6 +46,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.system.enums.LogRecordConstants.*; /** * 后台用户 Service 实现类 @@ -79,42 +83,54 @@ public class AdminUserServiceImpl implements AdminUserService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}", + success = SYSTEM_USER_CREATE_SUCCESS) public Long createUser(UserSaveReqVO createReqVO) { - // 校验账户配合 + // 1.1 校验账户配合 tenantService.handleTenantInfo(tenant -> { long count = userMapper.selectCount(); if (count >= tenant.getAccountCount()) { throw exception(USER_COUNT_MAX, tenant.getAccountCount()); } }); - // 校验正确性 + // 1.2 校验正确性 validateUserForCreateOrUpdate(null, createReqVO.getUsername(), createReqVO.getMobile(), createReqVO.getEmail(), createReqVO.getDeptId(), createReqVO.getPostIds()); - // 插入用户 + // 2.1 插入用户 AdminUserDO user = BeanUtils.toBean(createReqVO, AdminUserDO.class); user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 user.setPassword(encodePassword(createReqVO.getPassword())); // 加密密码 userMapper.insert(user); - // 插入关联岗位 + // 2.2 插入关联岗位 if (CollectionUtil.isNotEmpty(user.getPostIds())) { userPostMapper.insertBatch(convertList(user.getPostIds(), postId -> new UserPostDO().setUserId(user.getId()).setPostId(postId))); } + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("user", user); return user.getId(); } @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", + success = SYSTEM_USER_UPDATE_SUCCESS) public void updateUser(UserSaveReqVO updateReqVO) { updateReqVO.setPassword(null); // 特殊:此处不更新密码 - // 校验正确性 - validateUserForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getUsername(), + // 1. 校验正确性 + AdminUserDO oldUser = validateUserForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getUsername(), updateReqVO.getMobile(), updateReqVO.getEmail(), updateReqVO.getDeptId(), updateReqVO.getPostIds()); - // 更新用户 + + // 2.1 更新用户 AdminUserDO updateObj = BeanUtils.toBean(updateReqVO, AdminUserDO.class); userMapper.updateById(updateObj); - // 更新岗位 + // 2.2 更新岗位 updateUserPost(updateReqVO, updateObj); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldUser, UserSaveReqVO.class)); + LogRecordContext.putVariable("user", oldUser); } private void updateUserPost(UserSaveReqVO reqVO, AdminUserDO updateObj) { @@ -124,7 +140,7 @@ public class AdminUserServiceImpl implements AdminUserService { Set postIds = CollUtil.emptyIfNull(updateObj.getPostIds()); Collection createPostIds = CollUtil.subtract(postIds, dbPostIds); Collection deletePostIds = CollUtil.subtract(dbPostIds, postIds); - // 执行新增和删除。对于已经授权的菜单,不用做任何处理 + // 执行新增和删除。对于已经授权的岗位,不用做任何处理 if (!CollectionUtil.isEmpty(createPostIds)) { userPostMapper.insertBatch(convertList(createPostIds, postId -> new UserPostDO().setUserId(userId).setPostId(postId))); @@ -173,14 +189,21 @@ public class AdminUserServiceImpl implements AdminUserService { } @Override + @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_UPDATE_PASSWORD_SUB_TYPE, bizNo = "{{#id}}", + success = SYSTEM_USER_UPDATE_PASSWORD_SUCCESS) public void updateUserPassword(Long id, String password) { - // 校验用户存在 - validateUserExists(id); - // 更新密码 + // 1. 校验用户存在 + AdminUserDO user = validateUserExists(id); + + // 2. 更新密码 AdminUserDO updateObj = new AdminUserDO(); updateObj.setId(id); updateObj.setPassword(encodePassword(password)); // 加密密码 userMapper.updateById(updateObj); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("user", user); + LogRecordContext.putVariable("newPassword", updateObj.getPassword()); } @Override @@ -196,15 +219,21 @@ public class AdminUserServiceImpl implements AdminUserService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_DELETE_SUB_TYPE, bizNo = "{{#id}}", + success = SYSTEM_USER_DELETE_SUCCESS) public void deleteUser(Long id) { - // 校验用户存在 - validateUserExists(id); - // 删除用户 + // 1. 校验用户存在 + AdminUserDO user = validateUserExists(id); + + // 2.1 删除用户 userMapper.deleteById(id); - // 删除用户关联数据 + // 2.2 删除用户关联数据 permissionService.processUserDeleted(id); - // 删除用户岗位 + // 2.2 删除用户岗位 userPostMapper.deleteByUserId(id); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("user", user); } @Override @@ -294,12 +323,12 @@ public class AdminUserServiceImpl implements AdminUserService { return deptIds; } - private void validateUserForCreateOrUpdate(Long id, String username, String mobile, String email, + private AdminUserDO validateUserForCreateOrUpdate(Long id, String username, String mobile, String email, Long deptId, Set postIds) { // 关闭数据权限,避免因为没有数据权限,查询不到数据,进而导致唯一校验不正确 - DataPermissionUtils.executeIgnore(() -> { + return DataPermissionUtils.executeIgnore(() -> { // 校验用户存在 - validateUserExists(id); + AdminUserDO user = validateUserExists(id); // 校验用户名唯一 validateUsernameUnique(id, username); // 校验手机号唯一 @@ -310,18 +339,20 @@ public class AdminUserServiceImpl implements AdminUserService { deptService.validateDeptList(CollectionUtils.singleton(deptId)); // 校验岗位处于开启状态 postService.validatePostList(postIds); + return user; }); } @VisibleForTesting - void validateUserExists(Long id) { + AdminUserDO validateUserExists(Long id) { if (id == null) { - return; + return null; } AdminUserDO user = userMapper.selectById(id); if (user == null) { throw exception(USER_NOT_EXISTS); } + return user; } @VisibleForTesting