🎨 feat: 修改用户缓存使用事件监听
This commit is contained in:
parent
382f0e4e92
commit
94e0d7f264
|
@ -26,6 +26,7 @@ ENTRYPOINT ["java","-jar","/home/server/app.jar"]
|
||||||
|
|
||||||
#暴露 8000 端口
|
#暴露 8000 端口
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
EXPOSE 7070
|
||||||
|
|
||||||
# 生产环境
|
# 生产环境
|
||||||
# mvn clean package -Pprod -DskipTests
|
# mvn clean package -Pprod -DskipTests
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package cn.bunny.services.controller.configuration;
|
package cn.bunny.services.controller.configuration;
|
||||||
|
|
||||||
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
|
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||||
import cn.bunny.services.domain.system.email.dto.EmailTemplateAddDto;
|
import cn.bunny.services.domain.system.email.dto.EmailTemplateAddDto;
|
||||||
import cn.bunny.services.domain.system.email.dto.EmailTemplateDto;
|
import cn.bunny.services.domain.system.email.dto.EmailTemplateDto;
|
||||||
import cn.bunny.services.domain.system.email.dto.EmailTemplateUpdateDto;
|
import cn.bunny.services.domain.system.email.dto.EmailTemplateUpdateDto;
|
||||||
import cn.bunny.services.domain.system.email.entity.EmailTemplate;
|
import cn.bunny.services.domain.system.email.entity.EmailTemplate;
|
||||||
import cn.bunny.services.domain.system.email.vo.EmailTemplateVo;
|
import cn.bunny.services.domain.system.email.vo.EmailTemplateVo;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
|
||||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
|
||||||
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
|
||||||
import cn.bunny.services.service.configuration.EmailTemplateService;
|
import cn.bunny.services.service.configuration.EmailTemplateService;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
@ -71,7 +71,7 @@ public class EmailTemplateController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "全部邮件类型列表", description = "获取全部邮件类型列表", tags = "emailTemplate::query")
|
@Operation(summary = "全部邮件类型列表", description = "获取全部邮件类型列表", tags = "emailTemplate::query")
|
||||||
@GetMapping("public")
|
@GetMapping("private")
|
||||||
public Result<List<Map<String, String>>> getEmailTypeList() {
|
public Result<List<Map<String, String>>> getEmailTypeList() {
|
||||||
List<Map<String, String>> list = emailTemplateService.getEmailTypeList();
|
List<Map<String, String>> list = emailTemplateService.getEmailTypeList();
|
||||||
return Result.success(list);
|
return Result.success(list);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
server:
|
server:
|
||||||
port: 8000
|
port: 8000
|
||||||
|
tomcat:
|
||||||
|
threads:
|
||||||
|
max: 1000
|
||||||
spring:
|
spring:
|
||||||
profiles:
|
profiles:
|
||||||
active: @profiles.active@
|
active: @profiles.active@
|
||||||
|
|
|
@ -107,15 +107,4 @@ public class UserAuthorizationCacheService {
|
||||||
|
|
||||||
return permissionList;
|
return permissionList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 清除缓存
|
|
||||||
* 如有需要清除当前服务缓存
|
|
||||||
*/
|
|
||||||
public void deleteRoleAndPermissionCache(String key) {
|
|
||||||
String permissionCodePrefix = RedisUserConstant.getUserPermissionCodePrefix(key);
|
|
||||||
String rolesCodePrefix = RedisUserConstant.getUserRolesCodePrefix(key);
|
|
||||||
redisTemplate.delete(permissionCodePrefix);
|
|
||||||
redisTemplate.delete(rolesCodePrefix);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package cn.bunny.services.core.cache;
|
||||||
|
|
||||||
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class UserCacheCleaner {
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
public void cleanUserLoginCache(String username) {
|
||||||
|
String key = RedisUserConstant.getUserLoginInfoPrefix(username);
|
||||||
|
redisTemplate.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanUserRoleCache(String username) {
|
||||||
|
String key = RedisUserConstant.getUserRolesCodePrefix(username);
|
||||||
|
redisTemplate.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanUserPermissionCache(String username) {
|
||||||
|
String key = RedisUserConstant.getUserPermissionCodePrefix(username);
|
||||||
|
redisTemplate.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanAllUserCache(String username) {
|
||||||
|
cleanUserLoginCache(username);
|
||||||
|
cleanUserRoleCache(username);
|
||||||
|
cleanUserPermissionCache(username);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,25 +0,0 @@
|
||||||
package cn.bunny.services.core.cache;
|
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
|
||||||
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class UserCacheService {
|
|
||||||
@Resource
|
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据用户名获取缓存中内容
|
|
||||||
*
|
|
||||||
* @param username 用户名
|
|
||||||
* @return LoginVo
|
|
||||||
*/
|
|
||||||
public LoginVo getLoginVoByUsername(String username) {
|
|
||||||
Object loginVoObject = redisTemplate.opsForValue().get(RedisUserConstant.getUserLoginInfoPrefix(username));
|
|
||||||
return JSON.parseObject(JSON.toJSONString(loginVoObject), LoginVo.class);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package cn.bunny.services.core.event.event;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ClearAllUserCacheEvent extends ApplicationEvent {
|
||||||
|
private final String key;
|
||||||
|
|
||||||
|
public ClearAllUserCacheEvent(Object source, String key) {
|
||||||
|
super(source);
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cn.bunny.services.core.event.event;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class UpdateUserinfoByPermissionIdsEvent extends ApplicationEvent {
|
||||||
|
private final List<Long> permissionIds;
|
||||||
|
|
||||||
|
public UpdateUserinfoByPermissionIdsEvent(Object source, List<Long> permissionIds) {
|
||||||
|
super(source);
|
||||||
|
this.permissionIds = permissionIds;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cn.bunny.services.core.event.event;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class UpdateUserinfoByRoleIdsEvent extends ApplicationEvent {
|
||||||
|
private final List<Long> roleIds;
|
||||||
|
|
||||||
|
public UpdateUserinfoByRoleIdsEvent(Object source, List<Long> roleIds) {
|
||||||
|
super(source);
|
||||||
|
this.roleIds = roleIds;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package cn.bunny.services.core.event.event;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class UpdateUserinfoByUserIdsEvent extends ApplicationEvent {
|
||||||
|
private final List<Long> userIds;
|
||||||
|
|
||||||
|
public UpdateUserinfoByUserIdsEvent(Object source, List<Long> userIds) {
|
||||||
|
super(source);
|
||||||
|
this.userIds = userIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.bunny.services.core.excel;
|
package cn.bunny.services.core.event.listener.excel;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.dto.excel.I18nExcel;
|
import cn.bunny.services.domain.common.model.dto.excel.I18nExcel;
|
||||||
import cn.bunny.services.domain.system.i18n.entity.I18n;
|
import cn.bunny.services.domain.system.i18n.entity.I18n;
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.bunny.services.core.excel;
|
package cn.bunny.services.core.event.listener.excel;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.model.dto.excel.PermissionExcel;
|
import cn.bunny.services.domain.common.model.dto.excel.PermissionExcel;
|
||||||
import cn.bunny.services.domain.system.system.entity.Permission;
|
import cn.bunny.services.domain.system.system.entity.Permission;
|
|
@ -1,4 +1,4 @@
|
||||||
package cn.bunny.services.core.excel;
|
package cn.bunny.services.core.event.listener.excel;
|
||||||
|
|
||||||
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.common.model.dto.excel.RoleExcel;
|
import cn.bunny.services.domain.common.model.dto.excel.RoleExcel;
|
|
@ -0,0 +1,34 @@
|
||||||
|
package cn.bunny.services.core.event.listener.user;
|
||||||
|
|
||||||
|
import cn.bunny.services.core.cache.UserCacheCleaner;
|
||||||
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
|
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
||||||
|
import cn.bunny.services.mapper.system.UserMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Component("AbstractUserInfoUpdateHandler")
|
||||||
|
public abstract class AbstractUserInfoUpdateHandler {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected UserMapper userMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected UserCacheCleaner userCacheCleaner;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
public void processUserUpdate(List<Long> userIds, Consumer<AdminUser> postProcess) {
|
||||||
|
if (userIds.isEmpty()) return;
|
||||||
|
|
||||||
|
List<AdminUser> adminUsers = userMapper.selectBatchIds(userIds);
|
||||||
|
adminUsers.stream()
|
||||||
|
.filter(user -> redisTemplate.hasKey(RedisUserConstant.getUserLoginInfoPrefix(user.getUsername())))
|
||||||
|
.forEach(postProcess);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package cn.bunny.services.core.event.listener.user;
|
||||||
|
|
||||||
|
import cn.bunny.services.core.cache.UserLoginVoBuilderCacheService;
|
||||||
|
import cn.bunny.services.core.event.event.ClearAllUserCacheEvent;
|
||||||
|
import cn.bunny.services.core.event.event.UpdateUserinfoByPermissionIdsEvent;
|
||||||
|
import cn.bunny.services.core.event.event.UpdateUserinfoByRoleIdsEvent;
|
||||||
|
import cn.bunny.services.core.event.event.UpdateUserinfoByUserIdsEvent;
|
||||||
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
|
import cn.bunny.services.domain.system.system.entity.RolePermission;
|
||||||
|
import cn.bunny.services.domain.system.system.entity.UserRole;
|
||||||
|
import cn.bunny.services.mapper.system.RolePermissionMapper;
|
||||||
|
import cn.bunny.services.mapper.system.UserRoleMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component("UserinfoUpdateListener")
|
||||||
|
public class UserinfoUpdateListener extends AbstractUserInfoUpdateHandler {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserLoginVoBuilderCacheService userLoginVoBuilderCacheService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserRoleMapper userRoleMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RolePermissionMapper rolePermissionMapper;
|
||||||
|
|
||||||
|
/* 根据用户id更新用户信息,重新生成LoginVo对象 */
|
||||||
|
@EventListener
|
||||||
|
public void handlerUpdateUserinfoByUserIds(UpdateUserinfoByUserIdsEvent event) {
|
||||||
|
List<Long> userIds = event.getUserIds();
|
||||||
|
processUserUpdate(userIds, user -> {
|
||||||
|
userCacheCleaner.cleanAllUserCache(user.getUsername());
|
||||||
|
userLoginVoBuilderCacheService.buildLoginUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 根据角色id更新用户信息,重新生成LoginVo对象 */
|
||||||
|
@EventListener
|
||||||
|
public void handlerUserinfoUpdateByRoleId(UpdateUserinfoByRoleIdsEvent event) {
|
||||||
|
List<Long> roleIds = event.getRoleIds();
|
||||||
|
List<UserRole> userRoles = userRoleMapper.selectListByRoleIds(roleIds);
|
||||||
|
List<Long> userIds = userRoles.stream().map(UserRole::getUserId).toList();
|
||||||
|
|
||||||
|
UpdateUserinfoByUserIdsEvent userIdsEvent = new UpdateUserinfoByUserIdsEvent(event.getSource(), userIds);
|
||||||
|
handlerUpdateUserinfoByUserIds(userIdsEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 根据角色id更新用户信息,重新生成LoginVo对象 */
|
||||||
|
@EventListener
|
||||||
|
public void handlerUserinfoUpdateByPermissionId(UpdateUserinfoByPermissionIdsEvent event) {
|
||||||
|
List<Long> permissionIds = event.getPermissionIds();
|
||||||
|
List<RolePermission> rolePermissions = rolePermissionMapper.selectRolePermissionListByPermissionIds(permissionIds);
|
||||||
|
List<Long> roleIds = rolePermissions.stream().map(RolePermission::getRoleId).toList();
|
||||||
|
|
||||||
|
UpdateUserinfoByRoleIdsEvent roleIdsEvent = new UpdateUserinfoByRoleIdsEvent(event.getSource(), roleIds);
|
||||||
|
handlerUserinfoUpdateByRoleId(roleIdsEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 清除用户登录、角色、权限所有缓存 */
|
||||||
|
@EventListener
|
||||||
|
public void handlerDeleteAllUserCache(ClearAllUserCacheEvent event) {
|
||||||
|
userCacheCleaner.cleanAllUserCache(event.getKey());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,160 +0,0 @@
|
||||||
package cn.bunny.services.core.utils;
|
|
||||||
|
|
||||||
import cn.bunny.services.core.cache.UserAuthorizationCacheService;
|
|
||||||
import cn.bunny.services.core.cache.UserLoginVoBuilderCacheService;
|
|
||||||
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
|
||||||
import cn.bunny.services.domain.system.log.entity.UserLoginLog;
|
|
||||||
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
|
||||||
import cn.bunny.services.domain.system.system.entity.RolePermission;
|
|
||||||
import cn.bunny.services.domain.system.system.entity.UserRole;
|
|
||||||
import cn.bunny.services.mapper.log.UserLoginLogMapper;
|
|
||||||
import cn.bunny.services.mapper.system.RolePermissionMapper;
|
|
||||||
import cn.bunny.services.mapper.system.UserMapper;
|
|
||||||
import cn.bunny.services.mapper.system.UserRoleMapper;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.scheduling.annotation.Async;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class UserServiceHelper {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private UserRoleMapper userRoleMapper;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private UserLoginVoBuilderCacheService userLoginVoBuilderCacheService;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private UserLoginLogMapper userLoginLogMapper;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RolePermissionMapper rolePermissionMapper;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private UserMapper userMapper;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private UserAuthorizationCacheService userAuthorizationCacheService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置用户登录日志内容
|
|
||||||
* <p>
|
|
||||||
* 该方法用于将管理员用户信息复制到用户登录日志对象中,同时处理特殊字段映射关系。
|
|
||||||
* <p>
|
|
||||||
* 实现说明:
|
|
||||||
* 1. 使用BeanUtils.copyProperties()复制属性时,会自动将AdminUser.id复制到UserLoginLog.id
|
|
||||||
* 2. 由于UserLoginLog实际需要的是userId字段而非id字段,需要特殊处理:
|
|
||||||
* - 先进行属性复制
|
|
||||||
* - 然后将UserLoginLog.userId设置为AdminUser.id
|
|
||||||
* - 最后将UserLoginLog.id显式设为null(避免自动生成的id被覆盖)
|
|
||||||
*
|
|
||||||
* @param user 管理员用户实体对象,包含用户基本信息
|
|
||||||
* @param token 本次登录/退出的认证令牌
|
|
||||||
* @param type 操作类型(LOGIN-登录/LOGOUT-退出)
|
|
||||||
*/
|
|
||||||
public void setUserLoginLog(AdminUser user, String token, String type) {
|
|
||||||
UserLoginLog userLoginLog = new UserLoginLog();
|
|
||||||
BeanUtils.copyProperties(user, userLoginLog);
|
|
||||||
userLoginLog.setUserId(user.getId());
|
|
||||||
userLoginLog.setId(null);
|
|
||||||
userLoginLog.setToken(token);
|
|
||||||
userLoginLog.setType(type);
|
|
||||||
|
|
||||||
// 当前请求request
|
|
||||||
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
|
||||||
if (requestAttributes != null) {
|
|
||||||
HttpServletRequest request = requestAttributes.getRequest();
|
|
||||||
|
|
||||||
// 获取User-Agent
|
|
||||||
String userAgent = request.getHeader("User-Agent");
|
|
||||||
userLoginLog.setUserAgent(userAgent);
|
|
||||||
|
|
||||||
// 获取X-Requested-With
|
|
||||||
String xRequestedWith = request.getHeader("X-Requested-With");
|
|
||||||
userLoginLog.setXRequestedWith(xRequestedWith);
|
|
||||||
}
|
|
||||||
|
|
||||||
userLoginLogMapper.insert(userLoginLog);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量更新Redis中用户权限信息,设计用户和角色就用这个
|
|
||||||
*
|
|
||||||
* @param userIds 需要更新的用户ID集合
|
|
||||||
* (仅处理集合中存在的有效用户)
|
|
||||||
* @see RedisUserConstant Redis键前缀常量
|
|
||||||
*/
|
|
||||||
public void updateUserRedisInfo(List<Long> userIds) {
|
|
||||||
if (userIds.isEmpty()) return;
|
|
||||||
|
|
||||||
// 批量查询用户
|
|
||||||
List<AdminUser> adminUsers = userMapper.selectBatchIds(userIds);
|
|
||||||
// 并行处理用户更新
|
|
||||||
adminUsers.stream()
|
|
||||||
.filter(user -> redisTemplate.hasKey(RedisUserConstant.getUserLoginInfoPrefix(user.getUsername())))
|
|
||||||
.forEach(user -> {
|
|
||||||
// 更新时清除缓存中的角色和权限
|
|
||||||
String username = user.getUsername();
|
|
||||||
userAuthorizationCacheService.deleteRoleAndPermissionCache(username);
|
|
||||||
|
|
||||||
// 更新用户权限信息
|
|
||||||
userLoginVoBuilderCacheService.buildLoginUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理角色更新事件
|
|
||||||
*
|
|
||||||
* @param roleIds 角色ID
|
|
||||||
*/
|
|
||||||
@Async
|
|
||||||
public void updateBatchUserRedisInfoByRoleId(List<Long> roleIds) {
|
|
||||||
// 批量查询关联用户ID
|
|
||||||
List<UserRole> userRoles = userRoleMapper.selectListByRoleIds(roleIds);
|
|
||||||
List<Long> userIds = userRoles.stream().map(UserRole::getUserId).toList();
|
|
||||||
updateUserRedisInfo(userIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理权限更新事件
|
|
||||||
*
|
|
||||||
* @param permissionIds 权限ID
|
|
||||||
*/
|
|
||||||
@Async
|
|
||||||
public void updateBatchUserRedisInfoByPermissionId(List<Long> permissionIds) {
|
|
||||||
// 批量查询关联用户ID
|
|
||||||
List<RolePermission> rolePermissions = rolePermissionMapper.selectRolePermissionListByPermissionIds(permissionIds);
|
|
||||||
List<Long> roleIds = rolePermissions.stream().map(RolePermission::getRoleId).toList();
|
|
||||||
updateBatchUserRedisInfoByRoleId(roleIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清除用户登录时的缓存
|
|
||||||
*
|
|
||||||
* @param username 用户名
|
|
||||||
*/
|
|
||||||
public void deleteLoginUserCache(String username) {
|
|
||||||
String userRolesCodePrefix = RedisUserConstant.getUserRolesCodePrefix(username);
|
|
||||||
redisTemplate.delete(userRolesCodePrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清除用户登录时的缓存
|
|
||||||
*
|
|
||||||
* @param username 用户名
|
|
||||||
*/
|
|
||||||
public void deleteUserCache(String username) {
|
|
||||||
userAuthorizationCacheService.deleteRoleAndPermissionCache(username);
|
|
||||||
deleteLoginUserCache(username);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +1,15 @@
|
||||||
package cn.bunny.services.security.service;
|
package cn.bunny.services.security.service;
|
||||||
|
|
||||||
import cn.bunny.services.core.cache.UserCacheService;
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.common.model.dto.security.TokenInfo;
|
import cn.bunny.services.domain.common.model.dto.security.TokenInfo;
|
||||||
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
||||||
import cn.bunny.services.security.exception.CustomAuthenticationException;
|
import cn.bunny.services.security.exception.CustomAuthenticationException;
|
||||||
import cn.bunny.services.utils.JwtTokenUtil;
|
import cn.bunny.services.utils.JwtTokenUtil;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,7 +19,7 @@ import org.springframework.stereotype.Service;
|
||||||
public class TokenValidationService {
|
public class TokenValidationService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private UserCacheService userCacheService;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
public TokenInfo validateToken(HttpServletRequest request) {
|
public TokenInfo validateToken(HttpServletRequest request) {
|
||||||
// 判断是否有 token
|
// 判断是否有 token
|
||||||
|
@ -37,7 +39,8 @@ public class TokenValidationService {
|
||||||
Long userId = JwtTokenUtil.getUserId(token);
|
Long userId = JwtTokenUtil.getUserId(token);
|
||||||
|
|
||||||
// 查找 Redis
|
// 查找 Redis
|
||||||
LoginVo loginVo = userCacheService.getLoginVoByUsername(username);
|
Object loginVoObject = redisTemplate.opsForValue().get(RedisUserConstant.getUserLoginInfoPrefix(username));
|
||||||
|
LoginVo loginVo = JSON.parseObject(JSON.toJSONString(loginVoObject), LoginVo.class);
|
||||||
|
|
||||||
return TokenInfo.builder().userId(userId).username(username).token(token).loginVo(loginVo).build();
|
return TokenInfo.builder().userId(userId).username(username).token(token).loginVo(loginVo).build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.bunny.services.service.configuration.impl;
|
package cn.bunny.services.service.configuration.impl;
|
||||||
|
|
||||||
import cn.bunny.services.core.excel.I18nExcelListener;
|
import cn.bunny.services.core.event.listener.excel.I18nExcelListener;
|
||||||
import cn.bunny.services.core.strategy.export.ExcelExportStrategy;
|
import cn.bunny.services.core.strategy.export.ExcelExportStrategy;
|
||||||
import cn.bunny.services.core.strategy.export.JsonExportStrategy;
|
import cn.bunny.services.core.strategy.export.JsonExportStrategy;
|
||||||
import cn.bunny.services.domain.common.constant.FileType;
|
import cn.bunny.services.domain.common.constant.FileType;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package cn.bunny.services.service.system.impl;
|
package cn.bunny.services.service.system.impl;
|
||||||
|
|
||||||
import cn.bunny.services.core.excel.PermissionExcelListener;
|
import cn.bunny.services.core.event.event.UpdateUserinfoByPermissionIdsEvent;
|
||||||
|
import cn.bunny.services.core.event.listener.excel.PermissionExcelListener;
|
||||||
import cn.bunny.services.core.strategy.export.ExcelExportStrategy;
|
import cn.bunny.services.core.strategy.export.ExcelExportStrategy;
|
||||||
import cn.bunny.services.core.strategy.export.JsonExportStrategy;
|
import cn.bunny.services.core.strategy.export.JsonExportStrategy;
|
||||||
import cn.bunny.services.core.template.PermissionTreeProcessor;
|
import cn.bunny.services.core.template.PermissionTreeProcessor;
|
||||||
import cn.bunny.services.core.utils.UserServiceHelper;
|
|
||||||
import cn.bunny.services.domain.common.constant.FileType;
|
import cn.bunny.services.domain.common.constant.FileType;
|
||||||
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.common.model.dto.excel.PermissionExcel;
|
import cn.bunny.services.domain.common.model.dto.excel.PermissionExcel;
|
||||||
|
@ -32,6 +32,7 @@ import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.cache.annotation.Caching;
|
import org.springframework.cache.annotation.Caching;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
@ -63,7 +64,7 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
|
||||||
private static final String CACHE_NAMES = "permission";
|
private static final String CACHE_NAMES = "permission";
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private UserServiceHelper userServiceHelper;
|
private ApplicationEventPublisher applicationEventPublisher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将树形结构权限数据扁平化为列表
|
* 将树形结构权限数据扁平化为列表
|
||||||
|
@ -156,7 +157,8 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
|
||||||
BeanUtils.copyProperties(dto, permission);
|
BeanUtils.copyProperties(dto, permission);
|
||||||
updateById(permission);
|
updateById(permission);
|
||||||
|
|
||||||
userServiceHelper.updateBatchUserRedisInfoByPermissionId(List.of(dto.getId()));
|
List<Long> ids = List.of(dto.getId());
|
||||||
|
applicationEventPublisher.publishEvent(new UpdateUserinfoByPermissionIdsEvent(this, ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,7 +176,7 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
|
||||||
if (ids.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.REQUEST_IS_EMPTY);
|
if (ids.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.REQUEST_IS_EMPTY);
|
||||||
|
|
||||||
// 删除缓存中所有这个权限关联的用户,角色和权限信息
|
// 删除缓存中所有这个权限关联的用户,角色和权限信息
|
||||||
userServiceHelper.updateBatchUserRedisInfoByPermissionId(ids);
|
applicationEventPublisher.publishEvent(new UpdateUserinfoByPermissionIdsEvent(this, ids));
|
||||||
|
|
||||||
// 删除权限
|
// 删除权限
|
||||||
removeByIds(ids);
|
removeByIds(ids);
|
||||||
|
@ -190,7 +192,8 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
|
||||||
@CacheEvict(cacheNames = CACHE_NAMES, key = "'permissionList'", beforeInvocation = true),
|
@CacheEvict(cacheNames = CACHE_NAMES, key = "'permissionList'", beforeInvocation = true),
|
||||||
})
|
})
|
||||||
public void updatePermissionListByParentId(PermissionUpdateBatchByParentIdDto dto) {
|
public void updatePermissionListByParentId(PermissionUpdateBatchByParentIdDto dto) {
|
||||||
List<Permission> permissionList = dto.getIds().stream().map(id -> {
|
List<Long> ids = dto.getIds();
|
||||||
|
List<Permission> permissionList = ids.stream().map(id -> {
|
||||||
Permission permission = new Permission();
|
Permission permission = new Permission();
|
||||||
permission.setId(id);
|
permission.setId(id);
|
||||||
permission.setParentId(dto.getParentId());
|
permission.setParentId(dto.getParentId());
|
||||||
|
@ -198,7 +201,7 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
// 删除缓存中所有这个权限关联的用户,角色和权限信息
|
// 删除缓存中所有这个权限关联的用户,角色和权限信息
|
||||||
userServiceHelper.updateBatchUserRedisInfoByPermissionId(dto.getIds());
|
applicationEventPublisher.publishEvent(new UpdateUserinfoByPermissionIdsEvent(this, ids));
|
||||||
|
|
||||||
updateBatchById(permissionList);
|
updateBatchById(permissionList);
|
||||||
}
|
}
|
||||||
|
@ -312,6 +315,6 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
|
||||||
|
|
||||||
// 删除缓存中所有这个权限关联的用户,角色和权限信息
|
// 删除缓存中所有这个权限关联的用户,角色和权限信息
|
||||||
List<Long> ids = list.stream().map(PermissionUpdateDto::getId).toList();
|
List<Long> ids = list.stream().map(PermissionUpdateDto::getId).toList();
|
||||||
userServiceHelper.updateBatchUserRedisInfoByPermissionId(ids);
|
applicationEventPublisher.publishEvent(new UpdateUserinfoByPermissionIdsEvent(this, ids));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.bunny.services.service.system.impl;
|
package cn.bunny.services.service.system.impl;
|
||||||
|
|
||||||
import cn.bunny.services.core.utils.UserServiceHelper;
|
import cn.bunny.services.core.event.event.UpdateUserinfoByRoleIdsEvent;
|
||||||
import cn.bunny.services.domain.system.system.dto.AssignPowersToRoleDto;
|
import cn.bunny.services.domain.system.system.dto.AssignPowersToRoleDto;
|
||||||
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
||||||
import cn.bunny.services.domain.system.system.entity.RolePermission;
|
import cn.bunny.services.domain.system.system.entity.RolePermission;
|
||||||
|
@ -12,6 +12,7 @@ import cn.bunny.services.service.system.RolePermissionService;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ public class RolePermissionServiceImpl extends ServiceImpl<RolePermissionMapper,
|
||||||
private UserRoleMapper userRoleMapper;
|
private UserRoleMapper userRoleMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private UserServiceHelper userServiceHelper;
|
private ApplicationEventPublisher applicationEventPublisher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * 根据角色id获取权限内容
|
* * 根据角色id获取权限内容
|
||||||
|
@ -63,7 +64,8 @@ public class RolePermissionServiceImpl extends ServiceImpl<RolePermissionMapper,
|
||||||
Long roleId = dto.getRoleId();
|
Long roleId = dto.getRoleId();
|
||||||
|
|
||||||
// 删除这个角色下所有权限
|
// 删除这个角色下所有权限
|
||||||
baseMapper.deleteBatchRoleIds(List.of(roleId));
|
List<Long> ids = List.of(roleId);
|
||||||
|
baseMapper.deleteBatchRoleIds(ids);
|
||||||
|
|
||||||
// 保存分配数据
|
// 保存分配数据
|
||||||
List<RolePermission> rolePermissionList = powerIds.stream().map(powerId -> {
|
List<RolePermission> rolePermissionList = powerIds.stream().map(powerId -> {
|
||||||
|
@ -85,6 +87,6 @@ public class RolePermissionServiceImpl extends ServiceImpl<RolePermissionMapper,
|
||||||
if (adminUsers.isEmpty()) return;
|
if (adminUsers.isEmpty()) return;
|
||||||
|
|
||||||
// 更新角色绑定的用户
|
// 更新角色绑定的用户
|
||||||
userServiceHelper.updateBatchUserRedisInfoByRoleId(List.of(roleId));
|
applicationEventPublisher.publishEvent(new UpdateUserinfoByRoleIdsEvent(this, ids));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.bunny.services.service.system.impl;
|
package cn.bunny.services.service.system.impl;
|
||||||
|
|
||||||
import cn.bunny.services.core.excel.RoleExcelListener;
|
import cn.bunny.services.core.event.event.UpdateUserinfoByRoleIdsEvent;
|
||||||
import cn.bunny.services.core.utils.UserServiceHelper;
|
import cn.bunny.services.core.event.listener.excel.RoleExcelListener;
|
||||||
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.common.model.dto.excel.RoleExcel;
|
import cn.bunny.services.domain.common.model.dto.excel.RoleExcel;
|
||||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||||
|
@ -12,9 +12,6 @@ import cn.bunny.services.domain.system.system.entity.Role;
|
||||||
import cn.bunny.services.domain.system.system.vo.RoleVo;
|
import cn.bunny.services.domain.system.system.vo.RoleVo;
|
||||||
import cn.bunny.services.exception.AuthCustomerException;
|
import cn.bunny.services.exception.AuthCustomerException;
|
||||||
import cn.bunny.services.mapper.system.RoleMapper;
|
import cn.bunny.services.mapper.system.RoleMapper;
|
||||||
import cn.bunny.services.mapper.system.RolePermissionMapper;
|
|
||||||
import cn.bunny.services.mapper.system.RouterRoleMapper;
|
|
||||||
import cn.bunny.services.mapper.system.UserRoleMapper;
|
|
||||||
import cn.bunny.services.service.system.RoleService;
|
import cn.bunny.services.service.system.RoleService;
|
||||||
import cn.bunny.services.utils.FileUtil;
|
import cn.bunny.services.utils.FileUtil;
|
||||||
import com.alibaba.excel.EasyExcel;
|
import com.alibaba.excel.EasyExcel;
|
||||||
|
@ -28,6 +25,7 @@ import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.cache.annotation.Caching;
|
import org.springframework.cache.annotation.Caching;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
@ -59,16 +57,7 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements Ro
|
||||||
private static final String CACHE_NAMES = "role";
|
private static final String CACHE_NAMES = "role";
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private UserRoleMapper userRoleMapper;
|
private ApplicationEventPublisher applicationEventPublisher;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RolePermissionMapper rolePermissionMapper;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private RouterRoleMapper routerRoleMapper;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private UserServiceHelper userServiceHelper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色 服务实现类
|
* 角色 服务实现类
|
||||||
|
@ -231,7 +220,8 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements Ro
|
||||||
updateById(role);
|
updateById(role);
|
||||||
|
|
||||||
// 发布角色更新事件
|
// 发布角色更新事件
|
||||||
userServiceHelper.updateBatchUserRedisInfoByRoleId(List.of(roleId));
|
List<Long> ids = List.of(roleId);
|
||||||
|
applicationEventPublisher.publishEvent(new UpdateUserinfoByRoleIdsEvent(this, ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -249,7 +239,7 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements Ro
|
||||||
if (ids.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.REQUEST_IS_EMPTY);
|
if (ids.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.REQUEST_IS_EMPTY);
|
||||||
|
|
||||||
// 重新构建角色和用户缓存
|
// 重新构建角色和用户缓存
|
||||||
userServiceHelper.updateBatchUserRedisInfoByRoleId(ids);
|
applicationEventPublisher.publishEvent(new UpdateUserinfoByRoleIdsEvent(this, ids));
|
||||||
|
|
||||||
// 删除角色
|
// 删除角色
|
||||||
removeByIds(ids);
|
removeByIds(ids);
|
||||||
|
|
|
@ -3,12 +3,12 @@ package cn.bunny.services.service.system.impl;
|
||||||
import cn.bunny.services.context.BaseContext;
|
import cn.bunny.services.context.BaseContext;
|
||||||
import cn.bunny.services.core.cache.EmailCacheService;
|
import cn.bunny.services.core.cache.EmailCacheService;
|
||||||
import cn.bunny.services.core.cache.UserLoginVoBuilderCacheService;
|
import cn.bunny.services.core.cache.UserLoginVoBuilderCacheService;
|
||||||
|
import cn.bunny.services.core.event.event.ClearAllUserCacheEvent;
|
||||||
import cn.bunny.services.core.strategy.login.DefaultLoginStrategy;
|
import cn.bunny.services.core.strategy.login.DefaultLoginStrategy;
|
||||||
import cn.bunny.services.core.strategy.login.EmailLoginStrategy;
|
import cn.bunny.services.core.strategy.login.EmailLoginStrategy;
|
||||||
import cn.bunny.services.core.strategy.login.LoginContext;
|
import cn.bunny.services.core.strategy.login.LoginContext;
|
||||||
import cn.bunny.services.core.strategy.login.LoginStrategy;
|
import cn.bunny.services.core.strategy.login.LoginStrategy;
|
||||||
import cn.bunny.services.core.template.email.ConcreteSenderEmailTemplate;
|
import cn.bunny.services.core.template.email.ConcreteSenderEmailTemplate;
|
||||||
import cn.bunny.services.core.utils.UserServiceHelper;
|
|
||||||
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
import cn.bunny.services.domain.common.constant.UserConstant;
|
import cn.bunny.services.domain.common.constant.UserConstant;
|
||||||
import cn.bunny.services.domain.common.enums.EmailTemplateEnums;
|
import cn.bunny.services.domain.common.enums.EmailTemplateEnums;
|
||||||
|
@ -16,6 +16,7 @@ import cn.bunny.services.domain.common.enums.LoginEnums;
|
||||||
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
||||||
import cn.bunny.services.domain.system.email.entity.EmailTemplate;
|
import cn.bunny.services.domain.system.email.entity.EmailTemplate;
|
||||||
|
import cn.bunny.services.domain.system.log.entity.UserLoginLog;
|
||||||
import cn.bunny.services.domain.system.system.dto.user.AdminUserUpdateByLocalUserDto;
|
import cn.bunny.services.domain.system.system.dto.user.AdminUserUpdateByLocalUserDto;
|
||||||
import cn.bunny.services.domain.system.system.dto.user.LoginDto;
|
import cn.bunny.services.domain.system.system.dto.user.LoginDto;
|
||||||
import cn.bunny.services.domain.system.system.dto.user.RefreshTokenDto;
|
import cn.bunny.services.domain.system.system.dto.user.RefreshTokenDto;
|
||||||
|
@ -23,6 +24,7 @@ import cn.bunny.services.domain.system.system.entity.AdminUser;
|
||||||
import cn.bunny.services.domain.system.system.vo.user.RefreshTokenVo;
|
import cn.bunny.services.domain.system.system.vo.user.RefreshTokenVo;
|
||||||
import cn.bunny.services.exception.AuthCustomerException;
|
import cn.bunny.services.exception.AuthCustomerException;
|
||||||
import cn.bunny.services.mapper.configuration.EmailTemplateMapper;
|
import cn.bunny.services.mapper.configuration.EmailTemplateMapper;
|
||||||
|
import cn.bunny.services.mapper.log.UserLoginLogMapper;
|
||||||
import cn.bunny.services.mapper.system.UserMapper;
|
import cn.bunny.services.mapper.system.UserMapper;
|
||||||
import cn.bunny.services.minio.MinioHelper;
|
import cn.bunny.services.minio.MinioHelper;
|
||||||
import cn.bunny.services.service.system.UserLoginService;
|
import cn.bunny.services.service.system.UserLoginService;
|
||||||
|
@ -34,20 +36,21 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> implements UserLoginService {
|
public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> implements UserLoginService {
|
||||||
|
|
||||||
@Resource
|
|
||||||
private UserServiceHelper userServiceHelper;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private PasswordEncoder passwordEncoder;
|
private PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
@ -57,6 +60,9 @@ public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> imp
|
||||||
@Resource
|
@Resource
|
||||||
private EmailTemplateMapper emailTemplateMapper;
|
private EmailTemplateMapper emailTemplateMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserLoginLogMapper userLoginLogMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ConcreteSenderEmailTemplate concreteSenderEmailTemplate;
|
private ConcreteSenderEmailTemplate concreteSenderEmailTemplate;
|
||||||
|
|
||||||
|
@ -70,7 +76,7 @@ public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> imp
|
||||||
private EmailCacheService emailCacheService;
|
private EmailCacheService emailCacheService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private UserServiceHelper serviceHelper;
|
private ApplicationEventPublisher applicationEventPublisher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 前台用户登录接口
|
* 前台用户登录接口
|
||||||
|
@ -131,7 +137,7 @@ public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> imp
|
||||||
LoginVo loginVo = userLoginVoBuilderCacheService.buildLoginUserVo(user, readMeDay);
|
LoginVo loginVo = userLoginVoBuilderCacheService.buildLoginUserVo(user, readMeDay);
|
||||||
|
|
||||||
// 将用户登录保存在用户登录日志表中
|
// 将用户登录保存在用户登录日志表中
|
||||||
userServiceHelper.setUserLoginLog(user, loginVo.getToken(), UserConstant.LOGIN);
|
setUserLoginLog(user, loginVo.getToken(), UserConstant.LOGIN);
|
||||||
|
|
||||||
return loginVo;
|
return loginVo;
|
||||||
}
|
}
|
||||||
|
@ -225,12 +231,11 @@ public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> imp
|
||||||
AdminUser adminUser = getOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getId, userId));
|
AdminUser adminUser = getOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getId, userId));
|
||||||
adminUser.setIpAddress(ipAddr);
|
adminUser.setIpAddress(ipAddr);
|
||||||
adminUser.setIpRegion(ipRegion);
|
adminUser.setIpRegion(ipRegion);
|
||||||
userServiceHelper.setUserLoginLog(adminUser, token, UserConstant.LOGOUT);
|
setUserLoginLog(adminUser, token, UserConstant.LOGOUT);
|
||||||
|
|
||||||
// 删除Redis中用户信息
|
// 删除Redis中用户信息
|
||||||
String username = adminUser.getUsername();
|
String username = adminUser.getUsername();
|
||||||
|
applicationEventPublisher.publishEvent(new ClearAllUserCacheEvent(this, username));
|
||||||
serviceHelper.deleteUserCache(username);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -289,6 +294,48 @@ public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> imp
|
||||||
updateById(adminUser);
|
updateById(adminUser);
|
||||||
|
|
||||||
// 删除Redis中登录用户信息、角色、权限信息
|
// 删除Redis中登录用户信息、角色、权限信息
|
||||||
serviceHelper.deleteUserCache(adminUser.getUsername());
|
String username = adminUser.getUsername();
|
||||||
|
applicationEventPublisher.publishEvent(new ClearAllUserCacheEvent(this, username));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置用户登录日志内容
|
||||||
|
* <p>
|
||||||
|
* 该方法用于将管理员用户信息复制到用户登录日志对象中,同时处理特殊字段映射关系。
|
||||||
|
* <p>
|
||||||
|
* 实现说明:
|
||||||
|
* 1. 使用BeanUtils.copyProperties()复制属性时,会自动将AdminUser.id复制到UserLoginLog.id
|
||||||
|
* 2. 由于UserLoginLog实际需要的是userId字段而非id字段,需要特殊处理:
|
||||||
|
* - 先进行属性复制
|
||||||
|
* - 然后将UserLoginLog.userId设置为AdminUser.id
|
||||||
|
* - 最后将UserLoginLog.id显式设为null(避免自动生成的id被覆盖)
|
||||||
|
*
|
||||||
|
* @param user 管理员用户实体对象,包含用户基本信息
|
||||||
|
* @param token 本次登录/退出的认证令牌
|
||||||
|
* @param type 操作类型(LOGIN-登录/LOGOUT-退出)
|
||||||
|
*/
|
||||||
|
public void setUserLoginLog(AdminUser user, String token, String type) {
|
||||||
|
UserLoginLog userLoginLog = new UserLoginLog();
|
||||||
|
BeanUtils.copyProperties(user, userLoginLog);
|
||||||
|
userLoginLog.setUserId(user.getId());
|
||||||
|
userLoginLog.setId(null);
|
||||||
|
userLoginLog.setToken(token);
|
||||||
|
userLoginLog.setType(type);
|
||||||
|
|
||||||
|
// 当前请求request
|
||||||
|
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
|
if (requestAttributes != null) {
|
||||||
|
HttpServletRequest request = requestAttributes.getRequest();
|
||||||
|
|
||||||
|
// 获取User-Agent
|
||||||
|
String userAgent = request.getHeader("User-Agent");
|
||||||
|
userLoginLog.setUserAgent(userAgent);
|
||||||
|
|
||||||
|
// 获取X-Requested-With
|
||||||
|
String xRequestedWith = request.getHeader("X-Requested-With");
|
||||||
|
userLoginLog.setXRequestedWith(xRequestedWith);
|
||||||
|
}
|
||||||
|
|
||||||
|
userLoginLogMapper.insert(userLoginLog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.bunny.services.service.system.impl;
|
package cn.bunny.services.service.system.impl;
|
||||||
|
|
||||||
import cn.bunny.services.core.utils.UserServiceHelper;
|
import cn.bunny.services.core.event.event.UpdateUserinfoByUserIdsEvent;
|
||||||
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.system.system.dto.user.AssignRolesToUsersDto;
|
import cn.bunny.services.domain.system.system.dto.user.AssignRolesToUsersDto;
|
||||||
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
import cn.bunny.services.domain.system.system.entity.AdminUser;
|
||||||
|
@ -12,6 +12,7 @@ import cn.bunny.services.service.system.UserRoleService;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> i
|
||||||
private UserMapper userMapper;
|
private UserMapper userMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private UserServiceHelper serviceHelper;
|
private ApplicationEventPublisher applicationEventPublisher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * 根据用户id获取角色列表
|
* * 根据用户id获取角色列表
|
||||||
|
@ -69,7 +70,8 @@ public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> i
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除这个用户下所有已经分配好的角色内容
|
// 删除这个用户下所有已经分配好的角色内容
|
||||||
baseMapper.deleteBatchIdsByUserIds(List.of(userId));
|
List<Long> ids = List.of(userId);
|
||||||
|
baseMapper.deleteBatchIdsByUserIds(ids);
|
||||||
|
|
||||||
// 保存分配好的角色信息
|
// 保存分配好的角色信息
|
||||||
List<UserRole> roleList = roleIds.stream().map(roleId -> {
|
List<UserRole> roleList = roleIds.stream().map(roleId -> {
|
||||||
|
@ -81,6 +83,6 @@ public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> i
|
||||||
saveBatch(roleList);
|
saveBatch(roleList);
|
||||||
|
|
||||||
// 重新设置Redis中的用户存储信息vo对象
|
// 重新设置Redis中的用户存储信息vo对象
|
||||||
serviceHelper.updateUserRedisInfo(List.of(userId));
|
applicationEventPublisher.publishEvent(new UpdateUserinfoByUserIdsEvent(this, ids));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package cn.bunny.services.service.system.impl;
|
package cn.bunny.services.service.system.impl;
|
||||||
|
|
||||||
import cn.bunny.services.core.cache.RedisService;
|
import cn.bunny.services.core.cache.RedisService;
|
||||||
import cn.bunny.services.core.cache.UserCacheService;
|
import cn.bunny.services.core.event.event.ClearAllUserCacheEvent;
|
||||||
import cn.bunny.services.core.utils.UserServiceHelper;
|
import cn.bunny.services.core.event.event.UpdateUserinfoByUserIdsEvent;
|
||||||
import cn.bunny.services.domain.common.constant.MinioConstant;
|
import cn.bunny.services.domain.common.constant.MinioConstant;
|
||||||
|
import cn.bunny.services.domain.common.constant.RedisUserConstant;
|
||||||
import cn.bunny.services.domain.common.constant.UserConstant;
|
import cn.bunny.services.domain.common.constant.UserConstant;
|
||||||
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||||
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
import cn.bunny.services.domain.common.model.vo.LoginVo;
|
||||||
|
@ -29,6 +30,7 @@ import cn.bunny.services.mapper.system.UserRoleMapper;
|
||||||
import cn.bunny.services.minio.MinioHelper;
|
import cn.bunny.services.minio.MinioHelper;
|
||||||
import cn.bunny.services.service.system.FilesService;
|
import cn.bunny.services.service.system.FilesService;
|
||||||
import cn.bunny.services.service.system.UserService;
|
import cn.bunny.services.service.system.UserService;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
@ -37,6 +39,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
@ -81,10 +85,10 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
||||||
private RedisService redisService;
|
private RedisService redisService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private UserCacheService userCacheService;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private UserServiceHelper userServiceHelper;
|
private ApplicationEventPublisher applicationEventPublisher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户信息
|
* 获取用户信息
|
||||||
|
@ -144,7 +148,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
||||||
|
|
||||||
// 删除Redis中用户信息
|
// 删除Redis中用户信息
|
||||||
String username = adminUser.getUsername();
|
String username = adminUser.getUsername();
|
||||||
userServiceHelper.deleteUserCache(username);
|
applicationEventPublisher.publishEvent(new ClearAllUserCacheEvent(this, username));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -189,7 +193,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
||||||
List<String> keys = redisService.scannerRedisKeyByPage(pageNum, pageSize);
|
List<String> keys = redisService.scannerRedisKeyByPage(pageNum, pageSize);
|
||||||
|
|
||||||
List<UserVo> list = keys.stream().map(key -> {
|
List<UserVo> list = keys.stream().map(key -> {
|
||||||
LoginVo loginVo = userCacheService.getLoginVoByUsername(key);
|
Object loginVoObject = redisTemplate.opsForValue().get(RedisUserConstant.getUserLoginInfoPrefix(key));
|
||||||
|
LoginVo loginVo = JSON.parseObject(JSON.toJSONString(loginVoObject), LoginVo.class);
|
||||||
|
|
||||||
UserVo userVo = new UserVo();
|
UserVo userVo = new UserVo();
|
||||||
BeanUtils.copyProperties(loginVo, userVo);
|
BeanUtils.copyProperties(loginVo, userVo);
|
||||||
|
@ -305,7 +310,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
||||||
updateById(adminUser);
|
updateById(adminUser);
|
||||||
|
|
||||||
// 同步到 Redis
|
// 同步到 Redis
|
||||||
userServiceHelper.updateUserRedisInfo(List.of(adminUser.getId()));
|
List<Long> ids = List.of(adminUser.getId());
|
||||||
|
applicationEventPublisher.publishEvent(new UpdateUserinfoByUserIdsEvent(this, ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -324,11 +330,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
||||||
if (!roleList.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.ADMIN_ROLE_CAN_NOT_DELETED);
|
if (!roleList.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.ADMIN_ROLE_CAN_NOT_DELETED);
|
||||||
|
|
||||||
// 清除Redis中数据
|
// 清除Redis中数据
|
||||||
List<AdminUser> adminUserList = list(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getId, ids));
|
applicationEventPublisher.publishEvent(new UpdateUserinfoByUserIdsEvent(this, ids));
|
||||||
adminUserList.parallelStream().forEach(adminUser -> {
|
|
||||||
String username = adminUser.getUsername();
|
|
||||||
userServiceHelper.deleteLoginUserCache(username);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 删除部门相关
|
// 删除部门相关
|
||||||
userDeptMapper.deleteBatchIdsByUserIds(ids);
|
userDeptMapper.deleteBatchIdsByUserIds(ids);
|
||||||
|
|
Loading…
Reference in New Issue