Add token related interfaces (#495)

This commit is contained in:
Wu Clan
2025-01-23 13:12:46 +08:00
committed by GitHub
parent 7553ccf14d
commit 3b65679fb0
14 changed files with 306 additions and 116 deletions
+2
View File
@@ -12,6 +12,7 @@ from backend.app.admin.api.v1.sys.dict_type import router as dict_type_router
from backend.app.admin.api.v1.sys.menu import router as menu_router
from backend.app.admin.api.v1.sys.notice import router as notice_router
from backend.app.admin.api.v1.sys.role import router as role_router
from backend.app.admin.api.v1.sys.token import router as token_router
from backend.app.admin.api.v1.sys.user import router as user_router
router = APIRouter(prefix='/sys')
@@ -27,3 +28,4 @@ router.include_router(role_router, prefix='/roles', tags=['系统角色'])
router.include_router(user_router, prefix='/users', tags=['系统用户'])
router.include_router(data_rule_router, prefix='/data-rules', tags=['系统数据权限规则'])
router.include_router(notice_router, prefix='/notices', tags=['系统通知公告'])
router.include_router(token_router, prefix='/tokens', tags=['系统令牌'])
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
from typing import Annotated
from fastapi import APIRouter, Depends, Path, Query, Request
from backend.app.admin.schema.token import GetTokenDetail, KickOutToken
from backend.common.enums import StatusType
from backend.common.response.response_schema import ResponseModel, ResponseSchemaModel, response_base
from backend.common.security.jwt import DependsJwtAuth, jwt_decode, superuser_verify
from backend.common.security.permission import RequestPermission
from backend.common.security.rbac import DependsRBAC
from backend.core.conf import settings
from backend.database.redis import redis_client
router = APIRouter()
@router.get('', summary='获取令牌列表', dependencies=[DependsJwtAuth])
async def get_tokens(username: Annotated[str | None, Query()] = None) -> ResponseSchemaModel[list[GetTokenDetail]]:
token_keys = await redis_client.keys(f'{settings.TOKEN_REDIS_PREFIX}:*')
token_online = await redis_client.smembers(settings.TOKEN_ONLINE_REDIS_PREFIX)
data = []
for key in token_keys:
token = await redis_client.get(key)
token_payload = jwt_decode(token)
session_uuid = token_payload.session_uuid
token_detail = GetTokenDetail(
id=token_payload.id,
session_uuid=session_uuid,
username='未知',
nickname='未知',
ip='未知',
os='未知',
browser='未知',
device='未知',
status=StatusType.disable if session_uuid not in token_online else StatusType.enable,
last_login_time='未知',
expire_time=token_payload.expire_time,
)
extra_info = await redis_client.get(f'{settings.TOKEN_EXTRA_INFO_REDIS_PREFIX}:{session_uuid}')
if extra_info:
def append_token_detail():
data.append(
token_detail.model_copy(
update={
'username': extra_info.get('username'),
'nickname': extra_info.get('nickname'),
'ip': extra_info.get('ip'),
'os': extra_info.get('os'),
'browser': extra_info.get('browser'),
'device': extra_info.get('device'),
'last_login_time': extra_info.get('last_login_time'),
}
)
)
extra_info = json.loads(extra_info)
if extra_info.get('login_type') != 'swagger':
if username:
if username == extra_info.get('username'):
append_token_detail()
else:
append_token_detail()
else:
data.append(token_detail)
return response_base.success(data=data)
@router.delete(
'/{pk}',
summary='踢下线',
dependencies=[
Depends(RequestPermission('sys:token:kick')),
DependsRBAC,
],
)
async def kick_out(request: Request, pk: Annotated[int, Path(...)], session_uuid: KickOutToken) -> ResponseModel:
superuser_verify(request)
await redis_client.delete(f'{settings.TOKEN_REDIS_PREFIX}:{pk}:{session_uuid}')
return response_base.success()