from iti.applications.extensions import eventbus from iti_system.events.names import ( UserEvents, UserRelEvents, RoleEvents, MenuEvents, RoleRelEvents, ) from iti_system.models import User, Role, SysMenu, sys_role_menu, sys_user_role from iti.applications.extensions import cache_simple, db from sqlalchemy import select, distinct class UserCacheEventHandler: """ 用户数据缓存 事件处理器 """ def __init__(self, app=None): if app: self.init_app(app) def init_app(self, app): self.app = app self._register_handlers() def _register_handlers(self): """ 注册事件处理器 """ # 用户 eventbus.register_handler( UserEvents.USER_UPDATED, self._handle_user_updated, order=-1, async_mode=True, ) eventbus.register_handler( UserEvents.USER_DELETED, self._handle_user_deleted, order=-1, async_mode=True, ) eventbus.register_handler( UserEvents.USER_AUTH_REFRESHED, self._handle_user_updated, order=-1, async_mode=True, ) eventbus.register_handler( UserEvents.USER_LOGOUT, self._handle_user_updated, order=-1, async_mode=True, ) eventbus.register_handler( UserEvents.USER_PASSWORD_UPDATED, self._handle_user_updated, order=-1, async_mode=True, ) # 用户关系 eventbus.register_handler( UserRelEvents.USER_ROLES_UPDATED, self._handle_user_updated, order=-1, async_mode=True, ) eventbus.register_handler( UserRelEvents.USER_DEPTS_UPDATED, self._handle_user_updated, order=-1, async_mode=True, ) # 角色删除 eventbus.register_handler( RoleEvents.ROLE_DELETED, self._handle_role_changed, order=-1, async_mode=True, ) eventbus.register_handler( RoleRelEvents.ROLE_MENUS_UPDATED.value, self._handle_role_changed, order=-1, async_mode=True, ) # 菜单 eventbus.register_handler( MenuEvents.MENU_UPDATED, self._handle_menu_updated, order=-1, async_mode=True, ) eventbus.register_handler( MenuEvents.MENU_DELETED, self._handle_menu_deleted, order=-1, async_mode=True, ) def _invalidate_user_cache(self, user_id): """ 清理用户缓存 """ if user_id: cache_simple.delete(f"user_{user_id}") def _handle_user_updated(self, user: User): self._invalidate_user_cache(user.id) def _handle_user_deleted(self, user_id): self._invalidate_user_cache(user_id) def _handle_role_changed(self, role: Role): # 角色关联的用户缓存都应该被删除 if role.users: for user in role.users: self._invalidate_user_cache(user.id) def _handle_menu_updated(self, menu: SysMenu, old_menu: SysMenu): # 若菜单更新了权限字段 if old_menu and old_menu.auth_code != menu.auth_code: # 与该菜单相关的角色的用户缓存都应该被删除 # 查询菜单相关的角色关联的所有用户ID self._handle_menu_deleted(menu) def _handle_menu_deleted(self, menu: SysMenu): # 与该菜单相关的角色的用户缓存都应该被删除 # 查询菜单相关的角色关联的所有用户ID user_ids = db.session.scalars( select(distinct(sys_user_role.c.user_id)) .join(sys_user_role, sys_role_menu.c.role_id == sys_user_role.c.role_id) .where(sys_role_menu.c.menu_id == menu.id) ).all() for user_id in user_ids: self._invalidate_user_cache(user_id)