微调
This commit is contained in:
@@ -16,6 +16,7 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_002_000_005, "未绑定账号,需要进行绑定");
|
||||
ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1_002_000_007, "手机号不存在");
|
||||
ErrorCode AUTH_REGISTER_CAPTCHA_CODE_ERROR = new ErrorCode(1_002_000_008, "验证码不正确,原因:{}");
|
||||
ErrorCode AUTH_LOGIN_USER_RESIGNED = new ErrorCode(1_002_000_009, "登录失败,账号已离职");
|
||||
|
||||
// ========== 菜单模块 1-002-001-000 ==========
|
||||
ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1_002_001_000, "已经存在该名字的菜单");
|
||||
@@ -45,6 +46,7 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode USER_IMPORT_INIT_PASSWORD = new ErrorCode(1_002_003_009, "初始密码不能为空");
|
||||
ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1_002_003_010, "该手机号尚未注册");
|
||||
ErrorCode USER_REGISTER_DISABLED = new ErrorCode(1_002_003_011, "注册功能已关闭");
|
||||
ErrorCode USER_IS_RESIGNED = new ErrorCode(1_002_003_012, "名字为【{}】的用户已离职");
|
||||
|
||||
// ========== 部门模块 1-002-004-000 ==========
|
||||
ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
|
||||
@@ -62,6 +64,7 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode POST_NOT_ENABLE = new ErrorCode(1_002_005_001, "岗位({}) 不处于开启状态,不允许选择");
|
||||
ErrorCode POST_NAME_DUPLICATE = new ErrorCode(1_002_005_002, "已经存在该名字的岗位");
|
||||
ErrorCode POST_CODE_DUPLICATE = new ErrorCode(1_002_005_003, "已经存在该标识的岗位");
|
||||
ErrorCode POST_TYPE_INVALID = new ErrorCode(1_002_005_004, "岗位类型({})不合法");
|
||||
|
||||
// ========== 字典类型 1-002-006-000 ==========
|
||||
ErrorCode DICT_TYPE_NOT_EXISTS = new ErrorCode(1_002_006_001, "当前字典类型不存在");
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.njcn.rdms.module.system.enums.dept;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 岗位类型枚举
|
||||
*/
|
||||
public enum PostTypeEnum {
|
||||
|
||||
MANAGEMENT("management"),
|
||||
TECHNICAL("technical"),
|
||||
BUSINESS("business");
|
||||
|
||||
private final String type;
|
||||
|
||||
PostTypeEnum(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static boolean isValid(String type) {
|
||||
return Arrays.stream(values()).anyMatch(item -> item.type.equals(type));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,6 +13,7 @@ public enum LoginResultEnum {
|
||||
SUCCESS(0), // 成功
|
||||
BAD_CREDENTIALS(10), // 账号或密码不正确
|
||||
USER_DISABLED(20), // 用户被禁用
|
||||
USER_RESIGNED(21), // 用户已离职
|
||||
CAPTCHA_NOT_FOUND(30), // 图片验证码不存在
|
||||
CAPTCHA_CODE_ERROR(31), // 图片验证码不正确
|
||||
|
||||
|
||||
@@ -16,6 +16,12 @@ public class PostPageReqVO extends PageParam {
|
||||
@Schema(description = "岗位名称,模糊匹配", example = "灿能")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "岗位类型", example = "technical")
|
||||
private String postType;
|
||||
|
||||
@Schema(description = "岗位级别", example = "8")
|
||||
private Integer levelRank;
|
||||
|
||||
@Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1")
|
||||
private Integer status;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.njcn.rdms.module.system.controller.admin.dept.vo.post;
|
||||
import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
|
||||
import com.njcn.rdms.framework.common.validation.InEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
@@ -30,6 +31,7 @@ public class PostSaveReqVO {
|
||||
private String postType;
|
||||
|
||||
@Schema(description = "岗位级别", example = "8")
|
||||
@Min(value = 0, message = "岗位级别不能小于 0")
|
||||
private Integer levelRank;
|
||||
|
||||
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
|
||||
@@ -16,4 +16,16 @@ public class PostSimpleRespVO {
|
||||
@ExcelProperty("岗位名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "岗位编码", example = "backend")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "岗位类型", example = "technical")
|
||||
private String postType;
|
||||
|
||||
@Schema(description = "岗位级别", example = "8")
|
||||
private Integer levelRank;
|
||||
|
||||
@Schema(description = "岗位排序", example = "1")
|
||||
private Integer sort;
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ public interface PostMapper extends BaseMapperX<PostDO> {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<PostDO>()
|
||||
.likeIfPresent(PostDO::getCode, reqVO.getCode())
|
||||
.likeIfPresent(PostDO::getName, reqVO.getName())
|
||||
.eqIfPresent(PostDO::getPostType, reqVO.getPostType())
|
||||
.eqIfPresent(PostDO::getLevelRank, reqVO.getLevelRank())
|
||||
.eqIfPresent(PostDO::getStatus, reqVO.getStatus())
|
||||
.orderByDesc(PostDO::getId));
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_CAPTCHA_CODE_ERROR;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_USER_DISABLED;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_USER_RESIGNED;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.AUTH_REGISTER_CAPTCHA_CODE_ERROR;
|
||||
|
||||
/**
|
||||
@@ -83,6 +84,10 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.USER_DISABLED);
|
||||
throw exception(AUTH_LOGIN_USER_DISABLED);
|
||||
}
|
||||
if (userService.isUserResigned(user)) {
|
||||
createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.USER_RESIGNED);
|
||||
throw exception(AUTH_LOGIN_USER_RESIGNED);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.njcn.rdms.module.system.service.dept;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
|
||||
import com.njcn.rdms.framework.common.pojo.PageResult;
|
||||
import com.njcn.rdms.framework.common.util.object.BeanUtils;
|
||||
@@ -8,6 +9,8 @@ import com.njcn.rdms.module.system.controller.admin.dept.vo.post.PostPageReqVO;
|
||||
import com.njcn.rdms.module.system.controller.admin.dept.vo.post.PostSaveReqVO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.dept.PostDO;
|
||||
import com.njcn.rdms.module.system.dal.mysql.dept.PostMapper;
|
||||
import com.njcn.rdms.module.system.enums.dept.PostTypeEnum;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -36,7 +39,7 @@ public class PostServiceImpl implements PostService {
|
||||
@Override
|
||||
public Long createPost(PostSaveReqVO createReqVO) {
|
||||
// 校验正确性
|
||||
validatePostForCreateOrUpdate(null, createReqVO.getName(), createReqVO.getCode());
|
||||
validatePostForCreateOrUpdate(null, createReqVO.getName(), createReqVO.getCode(), createReqVO.getPostType());
|
||||
|
||||
// 插入岗位
|
||||
PostDO post = BeanUtils.toBean(createReqVO, PostDO.class);
|
||||
@@ -47,7 +50,7 @@ public class PostServiceImpl implements PostService {
|
||||
@Override
|
||||
public void updatePost(PostSaveReqVO updateReqVO) {
|
||||
// 校验正确性
|
||||
validatePostForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getName(), updateReqVO.getCode());
|
||||
validatePostForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getName(), updateReqVO.getCode(), updateReqVO.getPostType());
|
||||
|
||||
// 更新岗位
|
||||
PostDO updateObj = BeanUtils.toBean(updateReqVO, PostDO.class);
|
||||
@@ -67,16 +70,19 @@ public class PostServiceImpl implements PostService {
|
||||
postMapper.deleteByIds(ids);
|
||||
}
|
||||
|
||||
private void validatePostForCreateOrUpdate(Long id, String name, String code) {
|
||||
private void validatePostForCreateOrUpdate(Long id, String name, String code, String postType) {
|
||||
// 校验自己存在
|
||||
validatePostExists(id);
|
||||
// 校验岗位名的唯一性
|
||||
validatePostNameUnique(id, name);
|
||||
// 校验岗位编码的唯一性
|
||||
validatePostCodeUnique(id, code);
|
||||
// 校验岗位类型
|
||||
validatePostType(postType);
|
||||
}
|
||||
|
||||
private void validatePostNameUnique(Long id, String name) {
|
||||
@VisibleForTesting
|
||||
void validatePostNameUnique(Long id, String name) {
|
||||
PostDO post = postMapper.selectByName(name);
|
||||
if (post == null) {
|
||||
return;
|
||||
@@ -90,7 +96,8 @@ public class PostServiceImpl implements PostService {
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePostCodeUnique(Long id, String code) {
|
||||
@VisibleForTesting
|
||||
void validatePostCodeUnique(Long id, String code) {
|
||||
PostDO post = postMapper.selectByCode(code);
|
||||
if (post == null) {
|
||||
return;
|
||||
@@ -104,6 +111,16 @@ public class PostServiceImpl implements PostService {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void validatePostType(String postType) {
|
||||
if (StrUtil.isBlank(postType)) {
|
||||
return;
|
||||
}
|
||||
if (!PostTypeEnum.isValid(postType)) {
|
||||
throw exception(POST_TYPE_INVALID, postType);
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePostExists(Long id) {
|
||||
if (id == null) {
|
||||
return;
|
||||
|
||||
@@ -162,6 +162,7 @@ public interface AdminUserService {
|
||||
* 校验用户们是否有效。如下情况,视为无效:
|
||||
* 1. 用户编号不存在
|
||||
* 2. 用户被禁用
|
||||
* 3. 用户已离职生效
|
||||
*
|
||||
* @param ids 用户编号数组
|
||||
*/
|
||||
@@ -214,4 +215,24 @@ public interface AdminUserService {
|
||||
*/
|
||||
boolean isPasswordMatch(String rawPassword, String encodedPassword);
|
||||
|
||||
/**
|
||||
* 判断用户是否已离职生效
|
||||
*
|
||||
* @param user 用户
|
||||
* @return 是否已离职
|
||||
*/
|
||||
boolean isUserResigned(AdminUserDO user);
|
||||
|
||||
/**
|
||||
* 判断用户当前是否可用
|
||||
*
|
||||
* 口径:
|
||||
* 1. `status` 必须为启用
|
||||
* 2. `resignedAt` 为空,或者晚于当前时间
|
||||
*
|
||||
* @param user 用户
|
||||
* @return 是否可用
|
||||
*/
|
||||
boolean isUserAvailable(AdminUserDO user);
|
||||
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_EMAIL_EX
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_IMPORT_INIT_PASSWORD;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_IMPORT_LIST_IS_EMPTY;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_IS_DISABLE;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_IS_RESIGNED;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_MOBILE_EXISTS;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
|
||||
import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_PASSWORD_FAILED;
|
||||
@@ -147,6 +148,10 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
// 3. 记录操作日志上下文
|
||||
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldUser, UserSaveReqVO.class));
|
||||
LogRecordContext.putVariable("user", oldUser);
|
||||
// 4. 如果更新后用户已不可用,主动移除其 token
|
||||
if (!isUserAvailable(buildAvailabilityUser(oldUser, updateReqVO.getResignedAt(), oldUser.getStatus()))) {
|
||||
oauth2TokenService.removeAccessToken(oldUser.getId(), UserTypeEnum.ADMIN.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -193,14 +198,14 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
@Override
|
||||
public void updateUserStatus(Long id, Integer status) {
|
||||
// 校验用户存在
|
||||
validateUserExists(id);
|
||||
AdminUserDO user = validateUserExists(id);
|
||||
// 更新状态
|
||||
AdminUserDO updateObj = new AdminUserDO();
|
||||
updateObj.setId(id);
|
||||
updateObj.setStatus(status);
|
||||
userMapper.updateById(updateObj);
|
||||
// 如果是禁用用户,则删除其 Token 信息
|
||||
if (CommonStatusEnum.isDisable(status)) {
|
||||
// 如果更新后用户不可用,则删除其 Token 信息
|
||||
if (!isUserAvailable(buildAvailabilityUser(user, user.getResignedAt(), status))) {
|
||||
oauth2TokenService.removeAccessToken(id, UserTypeEnum.ADMIN.getValue());
|
||||
}
|
||||
}
|
||||
@@ -295,9 +300,12 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
if (user == null) {
|
||||
throw exception(USER_NOT_EXISTS);
|
||||
}
|
||||
if (!CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus())) {
|
||||
if (CommonStatusEnum.isDisable(user.getStatus())) {
|
||||
throw exception(USER_IS_DISABLE, user.getNickname());
|
||||
}
|
||||
if (isUserResigned(user)) {
|
||||
throw exception(USER_IS_RESIGNED, user.getNickname());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -477,6 +485,21 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
return passwordEncoder.matches(rawPassword, encodedPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserResigned(AdminUserDO user) {
|
||||
if (user == null || user.getResignedAt() == null) {
|
||||
return false;
|
||||
}
|
||||
return !user.getResignedAt().isAfter(LocalDateTime.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserAvailable(AdminUserDO user) {
|
||||
return user != null
|
||||
&& CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus())
|
||||
&& !isUserResigned(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对密码进行加密
|
||||
*
|
||||
@@ -498,4 +521,12 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
return config != null ? config.getValue() : null;
|
||||
}
|
||||
|
||||
private AdminUserDO buildAvailabilityUser(AdminUserDO user, LocalDateTime resignedAt, Integer status) {
|
||||
return new AdminUserDO()
|
||||
.setId(user.getId())
|
||||
.setNickname(user.getNickname())
|
||||
.setStatus(status)
|
||||
.setResignedAt(resignedAt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user