forked from github/cool-admin-java
feat: 用户管理增强 - username字段、注销释放唯一索引、禁用清除缓存
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
.git
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
.vscode
|
||||
.DS_Store
|
||||
@@ -2,23 +2,72 @@ package com.cool.modules.user.controller.admin;
|
||||
|
||||
import static com.cool.modules.user.entity.table.UserInfoEntityTableDef.USER_INFO_ENTITY;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.core.security.jwt.JwtUser;
|
||||
import com.cool.modules.user.entity.UserInfoEntity;
|
||||
import com.cool.modules.user.service.UserInfoService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "用户信息", description = "用户信息")
|
||||
@CoolRestController(api = {"add", "delete", "update", "page", "list", "info"})
|
||||
public class AdminUserInfoController extends BaseController<UserInfoService, UserInfoEntity> {
|
||||
|
||||
private final UserInfoService userInfoService;
|
||||
private final CoolCache coolCache;
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
|
||||
setPageOption(createOp().fieldEq(USER_INFO_ENTITY.STATUS, USER_INFO_ENTITY.GENDER,
|
||||
USER_INFO_ENTITY.LOGIN_TYPE)
|
||||
.keyWordLikeFields(USER_INFO_ENTITY.NICK_NAME, USER_INFO_ENTITY.PHONE));
|
||||
.keyWordLikeFields(USER_INFO_ENTITY.NICK_NAME, USER_INFO_ENTITY.PHONE,
|
||||
USER_INFO_ENTITY.USERNAME, USER_INFO_ENTITY.EMAIL));
|
||||
}
|
||||
|
||||
@Override
|
||||
@PostMapping("/update")
|
||||
protected R update(@RequestBody UserInfoEntity t, @RequestAttribute JSONObject requestParams) {
|
||||
Long id = t.getId();
|
||||
if (id != null) {
|
||||
UserInfoEntity before = userInfoService.getById(id);
|
||||
if (before != null && !ObjUtil.equals(before.getStatus(), t.getStatus())) {
|
||||
coolCache.del("app:userDetails:" + id);
|
||||
}
|
||||
}
|
||||
return super.update(t, requestParams);
|
||||
}
|
||||
|
||||
@Operation(summary = "注销用户")
|
||||
@PostMapping("/logoff")
|
||||
public R logoff(@RequestBody JSONObject requestParams) {
|
||||
Long id = requestParams.getLong("id");
|
||||
userInfoService.adminLogoff(id);
|
||||
coolCache.del("app:userDetails:" + id);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Override
|
||||
@PostMapping("/delete")
|
||||
protected R delete(HttpServletRequest request, @RequestBody Map<String, Object> params,
|
||||
@RequestAttribute JSONObject requestParams) {
|
||||
Long[] ids = Convert.toLongArray(getIds(params));
|
||||
if (ids != null) {
|
||||
Arrays.stream(ids).forEach(userInfoService::checkLogoffBeforeDelete);
|
||||
}
|
||||
return super.delete(request, params, requestParams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ public class AppUserInfoController {
|
||||
public R updatePerson(@RequestAttribute JSONObject requestParams) {
|
||||
UserInfoEntity infoEntity = requestParams.toBean(UserInfoEntity.class);
|
||||
infoEntity.setId(CoolSecurityUtil.getCurrentUserId());
|
||||
infoEntity.setUsername(null);
|
||||
infoEntity.setEmail(null);
|
||||
return R.ok(
|
||||
userInfoService.updateById(infoEntity)
|
||||
);
|
||||
@@ -67,4 +69,20 @@ public class AppUserInfoController {
|
||||
userInfoService.bindPhone(CoolSecurityUtil.getCurrentUserId(), phone, code);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "绑定邮箱")
|
||||
@PostMapping("/bindEmail")
|
||||
public R bindEmail(@RequestAttribute JSONObject requestParams) {
|
||||
String email = requestParams.getStr("email");
|
||||
userInfoService.bindEmail(CoolSecurityUtil.getCurrentUserId(), email);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "绑定用户名")
|
||||
@PostMapping("/bindUsername")
|
||||
public R bindUsername(@RequestAttribute JSONObject requestParams) {
|
||||
String username = requestParams.getStr("username");
|
||||
userInfoService.bindUsername(CoolSecurityUtil.getCurrentUserId(), username);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ public class UserInfoEntity extends BaseEntity<UserInfoEntity> {
|
||||
@ColumnDefine(comment = "邮箱")
|
||||
private String email;
|
||||
|
||||
@UniIndex
|
||||
@ColumnDefine(comment = "用户名")
|
||||
private String username;
|
||||
|
||||
@ColumnDefine(comment = "性别 0-未知 1-男 2-女", defaultValue = "0")
|
||||
private Integer gender;
|
||||
|
||||
|
||||
@@ -25,4 +25,24 @@ public interface UserInfoService extends BaseService<UserInfoEntity> {
|
||||
* 绑定手机号
|
||||
*/
|
||||
void bindPhone(Long currentUserId, String phone, String code);
|
||||
|
||||
/**
|
||||
* 绑定邮箱
|
||||
*/
|
||||
void bindEmail(Long currentUserId, String email);
|
||||
|
||||
/**
|
||||
* 绑定用户名
|
||||
*/
|
||||
void bindUsername(Long currentUserId, String username);
|
||||
|
||||
/**
|
||||
* 注销(管理端)
|
||||
*/
|
||||
void adminLogoff(Long userId);
|
||||
|
||||
/**
|
||||
* 删除前校验:必须已注销
|
||||
*/
|
||||
void checkLogoffBeforeDelete(Long userId);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package com.cool.modules.user.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.crypto.digest.MD5;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.modules.user.entity.UserInfoEntity;
|
||||
import com.cool.modules.user.mapper.UserInfoMapper;
|
||||
import com.cool.modules.user.service.UserInfoService;
|
||||
import com.cool.modules.user.util.UserSmsUtil;
|
||||
import com.cool.modules.user.util.UserSmsUtil.SendSceneEnum;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -41,6 +44,29 @@ public class UserInfoServiceImpl extends BaseServiceImpl<UserInfoMapper, UserInf
|
||||
info.updateById();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adminLogoff(Long userId) {
|
||||
UserInfoEntity info = getById(userId);
|
||||
CoolPreconditions.checkEmpty(info, "用户不存在");
|
||||
CoolPreconditions.check(ObjUtil.equals(info.getStatus(), 2), "该用户已注销");
|
||||
info.setStatus(2);
|
||||
info.setNickName("已注销-00" + userId);
|
||||
if (info.getUsername() != null) {
|
||||
info.setUsername("__logoff__" + userId + "__" + System.currentTimeMillis());
|
||||
}
|
||||
if (info.getEmail() != null) {
|
||||
info.setEmail("__logoff__" + userId + "__" + System.currentTimeMillis() + "@deleted");
|
||||
}
|
||||
info.updateById();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkLogoffBeforeDelete(Long userId) {
|
||||
UserInfoEntity info = getById(userId);
|
||||
CoolPreconditions.checkEmpty(info, "用户不存在");
|
||||
CoolPreconditions.check(!ObjUtil.equals(info.getStatus(), 2), "只能删除已注销的用户");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindPhone(Long userId, String phone, String code) {
|
||||
userSmsUtil.checkVerifyCode(phone, code, SendSceneEnum.ALL);
|
||||
@@ -49,4 +75,30 @@ public class UserInfoServiceImpl extends BaseServiceImpl<UserInfoMapper, UserInf
|
||||
info.setPhone(phone);
|
||||
info.updateById();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindEmail(Long userId, String email) {
|
||||
UserInfoEntity info = getById(userId);
|
||||
CoolPreconditions.checkEmpty(info, "用户不存在");
|
||||
CoolPreconditions.check(ObjUtil.isNotEmpty(info.getEmail()), "该用户已绑定邮箱");
|
||||
UserInfoEntity existing = getOne(QueryWrapper.create()
|
||||
.eq(UserInfoEntity::getEmail, email)
|
||||
.ne(UserInfoEntity::getStatus, 2));
|
||||
CoolPreconditions.check(ObjUtil.isNotEmpty(existing), "该邮箱已被其他用户使用");
|
||||
info.setEmail(email);
|
||||
info.updateById();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindUsername(Long userId, String username) {
|
||||
UserInfoEntity info = getById(userId);
|
||||
CoolPreconditions.checkEmpty(info, "用户不存在");
|
||||
CoolPreconditions.check(ObjUtil.isNotEmpty(info.getUsername()), "该用户已绑定用户名");
|
||||
UserInfoEntity existing = getOne(QueryWrapper.create()
|
||||
.eq(UserInfoEntity::getUsername, username)
|
||||
.ne(UserInfoEntity::getStatus, 2));
|
||||
CoolPreconditions.check(ObjUtil.isNotEmpty(existing), "该用户名已被其他用户使用");
|
||||
info.setUsername(username);
|
||||
info.updateById();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@ public class UserLoginServiceImpl implements UserLoginService {
|
||||
userInfoEntity.setGender(userWxEntity.getGender());
|
||||
userInfoEntity.setAvatarUrl(userWxEntity.getAvatarUrl());
|
||||
userInfoEntity.setUnionid(unionId);
|
||||
userInfoEntity.setStatus(1);
|
||||
userInfoEntity.save();
|
||||
}
|
||||
return generateToken(userInfoEntity, null);
|
||||
@@ -144,6 +145,7 @@ public class UserLoginServiceImpl implements UserLoginService {
|
||||
UserInfoEntity userInfoEntity = userInfoService.getOne(
|
||||
QueryWrapper.create().eq(UserInfoEntity::getEmail, email));
|
||||
CoolPreconditions.checkEmpty(userInfoEntity, "邮箱或密码错误");
|
||||
CoolPreconditions.check(!ObjUtil.equals(userInfoEntity.getStatus(), 1), "账号已被禁用或注销");
|
||||
if (userInfoEntity.getPassword().equals(MD5.create().digestHex(password))) {
|
||||
return generateToken(userInfoEntity, null);
|
||||
}
|
||||
@@ -156,8 +158,9 @@ public class UserLoginServiceImpl implements UserLoginService {
|
||||
CoolPreconditions.checkEmpty(username, "用户名不能为空");
|
||||
CoolPreconditions.checkEmpty(password, "密码不能为空");
|
||||
UserInfoEntity userInfoEntity = userInfoService.getOne(
|
||||
QueryWrapper.create().eq(UserInfoEntity::getNickName, username));
|
||||
QueryWrapper.create().eq(UserInfoEntity::getUsername, username));
|
||||
CoolPreconditions.checkEmpty(userInfoEntity, "用户名或密码错误");
|
||||
CoolPreconditions.check(!ObjUtil.equals(userInfoEntity.getStatus(), 1), "账号已被禁用或注销");
|
||||
if (userInfoEntity.getPassword().equals(MD5.create().digestHex(password))) {
|
||||
return generateToken(userInfoEntity, null);
|
||||
}
|
||||
@@ -170,13 +173,15 @@ public class UserLoginServiceImpl implements UserLoginService {
|
||||
CoolPreconditions.checkEmpty(email, "邮箱不能为空");
|
||||
CoolPreconditions.checkEmpty(password, "密码不能为空");
|
||||
UserInfoEntity existing = userInfoService.getOne(
|
||||
QueryWrapper.create().eq(UserInfoEntity::getEmail, email));
|
||||
QueryWrapper.create().eq(UserInfoEntity::getEmail, email)
|
||||
.ne(UserInfoEntity::getStatus, 2));
|
||||
CoolPreconditions.check(ObjUtil.isNotEmpty(existing), "该邮箱已注册");
|
||||
UserInfoEntity userInfoEntity = new UserInfoEntity();
|
||||
userInfoEntity.setEmail(email);
|
||||
userInfoEntity.setPassword(MD5.create().digestHex(password));
|
||||
userInfoEntity.setNickName(ObjUtil.isNotEmpty(nickName) ? nickName : email.split("@")[0]);
|
||||
userInfoEntity.setNickName(generateRandomNickname());
|
||||
userInfoEntity.setLoginType("2");
|
||||
userInfoEntity.setStatus(1);
|
||||
userInfoEntity.save();
|
||||
return generateToken(userInfoEntity, null);
|
||||
}
|
||||
@@ -186,12 +191,15 @@ public class UserLoginServiceImpl implements UserLoginService {
|
||||
CoolPreconditions.checkEmpty(username, "用户名不能为空");
|
||||
CoolPreconditions.checkEmpty(password, "密码不能为空");
|
||||
UserInfoEntity existing = userInfoService.getOne(
|
||||
QueryWrapper.create().eq(UserInfoEntity::getNickName, username));
|
||||
QueryWrapper.create().eq(UserInfoEntity::getUsername, username)
|
||||
.ne(UserInfoEntity::getStatus, 2));
|
||||
CoolPreconditions.check(ObjUtil.isNotEmpty(existing), "该用户名已注册");
|
||||
UserInfoEntity userInfoEntity = new UserInfoEntity();
|
||||
userInfoEntity.setNickName(username);
|
||||
userInfoEntity.setUsername(username);
|
||||
userInfoEntity.setPassword(MD5.create().digestHex(password));
|
||||
userInfoEntity.setNickName(generateRandomNickname());
|
||||
userInfoEntity.setLoginType("2");
|
||||
userInfoEntity.setStatus(1);
|
||||
userInfoEntity.save();
|
||||
return generateToken(userInfoEntity, null);
|
||||
}
|
||||
@@ -206,8 +214,8 @@ public class UserLoginServiceImpl implements UserLoginService {
|
||||
if (ObjUtil.isEmpty(userInfoEntity)) {
|
||||
userInfoEntity = new UserInfoEntity();
|
||||
userInfoEntity.setPhone(phone);
|
||||
// 生成随机昵称
|
||||
userInfoEntity.setNickName(generateRandomNickname());
|
||||
userInfoEntity.setStatus(1);
|
||||
userInfoEntity.save();
|
||||
}
|
||||
return generateToken(userInfoEntity, null);
|
||||
@@ -218,10 +226,9 @@ public class UserLoginServiceImpl implements UserLoginService {
|
||||
* @return 生成的昵称
|
||||
*/
|
||||
private String generateRandomNickname() {
|
||||
// 定义昵称的长度
|
||||
int length = 8;
|
||||
// 生成随机字符串
|
||||
return RandomUtil.randomString(length);
|
||||
long timestamp = System.currentTimeMillis() % 10000000L;
|
||||
int random = RandomUtil.randomInt(0, 10);
|
||||
return "u" + String.format("%07d", timestamp) + random;
|
||||
}
|
||||
/**
|
||||
* 生成token
|
||||
|
||||
Reference in New Issue
Block a user