checkpoint: 权限即时生效——角色/用户变更自动踢下线 + roleless 用户自读修复

- online/service: kick_user_sessions 扫描 USER_SESSION 匹配目标用户,删三键使登录时固化的权限快照即时失效
- role service+controller: 更新/删除/改状态/改权限后踢下线绑定该角色的用户
- user service+controller: 停用/改密等变更后踢下线(对应用户即时 401 重登)
- permission: 无角色用户读自身记录时按 id 匹配放行(修复 409 真 bug)
This commit is contained in:
34047007@qq.com
2026-08-07 21:47:51 +08:00
parent c1fa752d9b
commit 20b7184b44
6 changed files with 132 additions and 20 deletions
@@ -2,11 +2,12 @@ from typing import Annotated
from fastapi import APIRouter, Body, Depends, Path, Query, Security, status
from fastapi.responses import JSONResponse, StreamingResponse
from redis.asyncio.client import Redis
from sqlalchemy.ext.asyncio import AsyncSession
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema, PaginationQueryParam
from app.core.dependencies import AuthPermission, db_getter
from app.core.dependencies import AuthPermission, db_getter, redis_getter
from app.core.router_class import OperationLogRoute
from app.utils.common_util import bytes2file_response
@@ -56,10 +57,11 @@ async def create_role_controller(
async def update_role_controller(
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:role:update"]))],
db: Annotated[AsyncSession, Depends(db_getter)],
redis: Annotated[Redis, Depends(redis_getter)],
id: Annotated[int, Path(description="角色ID", ge=1)],
data: Annotated[RoleUpdateSchema, Body(description="角色修改参数")],
) -> JSONResponse:
result_dict = await RoleService(auth, db).update(id=id, data=data)
result_dict = await RoleService(auth, db).update(id=id, data=data, redis=redis)
return SuccessResponse(data=result_dict, msg="修改角色成功")
@@ -67,9 +69,10 @@ async def update_role_controller(
async def delete_role_controller(
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:role:delete"]))],
db: Annotated[AsyncSession, Depends(db_getter)],
redis: Annotated[Redis, Depends(redis_getter)],
ids: Annotated[list[int], Body(description="ID列表")],
) -> JSONResponse:
await RoleService(auth, db).delete(ids=ids)
await RoleService(auth, db).delete(ids=ids, redis=redis)
return SuccessResponse(msg="删除角色成功")
@@ -77,9 +80,10 @@ async def delete_role_controller(
async def batch_set_available_role_controller(
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:role:patch"]))],
db: Annotated[AsyncSession, Depends(db_getter)],
redis: Annotated[Redis, Depends(redis_getter)],
data: Annotated[BatchSetAvailable, Body(description="状态设置")],
) -> JSONResponse:
await RoleService(auth, db).set_available(data=data)
await RoleService(auth, db).set_available(data=data, redis=redis)
return SuccessResponse(msg="批量修改角色状态成功")
@@ -87,9 +91,10 @@ async def batch_set_available_role_controller(
async def set_role_permission_controller(
auth: Annotated[AuthSchema, Security(AuthPermission(["module_system:role:permission"]))],
db: Annotated[AsyncSession, Depends(db_getter)],
redis: Annotated[Redis, Depends(redis_getter)],
data: Annotated[RolePermissionSettingSchema, Body(description="角色授权参数")],
) -> JSONResponse:
await RoleService(auth, db).set_permission(data=data)
await RoleService(auth, db).set_permission(data=data, redis=redis)
return SuccessResponse(msg="授权角色成功")