Build lightweight AI agent admin

This commit is contained in:
Codex
2026-06-08 18:14:59 +08:00
commit e164840f43
2530 changed files with 435693 additions and 0 deletions
+150
View File
@@ -0,0 +1,150 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
API Token Service
"""
import hashlib
import secrets
from datetime import datetime, timezone
from typing import Optional, List, Tuple
from sqlalchemy import select, func, desc
from sqlalchemy.ext.asyncio import AsyncSession
from core.api_token.model import ApiToken
TOKEN_PREFIX = "zqpat_"
def generate_token() -> str:
"""生成随机API Token"""
return TOKEN_PREFIX + secrets.token_hex(32)
def hash_token(token: str) -> str:
"""对token进行SHA-256哈希"""
return hashlib.sha256(token.encode()).hexdigest()
def get_token_display_prefix(token: str) -> str:
"""获取token的展示前缀(前12位 + ..."""
return token[:12] + "..."
class ApiTokenService:
"""API Token 服务层"""
@classmethod
async def create_token(
cls,
db: AsyncSession,
user_id: str,
name: str,
expires_at: Optional[datetime] = None,
description: Optional[str] = None,
) -> Tuple[ApiToken, str]:
"""
创建API Token
:return: (数据库记录, 明文token) - 明文token仅返回一次
"""
raw_token = generate_token()
db_obj = ApiToken(
name=name,
token_hash=hash_token(raw_token),
token_prefix=get_token_display_prefix(raw_token),
user_id=user_id,
expires_at=expires_at,
description=description,
is_active=True,
sys_creator_id=user_id,
)
db.add(db_obj)
await db.commit()
await db.refresh(db_obj)
return db_obj, raw_token
@classmethod
async def get_user_tokens(
cls,
db: AsyncSession,
user_id: str,
) -> List[ApiToken]:
"""获取用户的所有API Token"""
result = await db.execute(
select(ApiToken)
.where(
ApiToken.user_id == user_id,
ApiToken.is_deleted == False, # noqa: E712
)
.order_by(desc(ApiToken.sys_create_datetime))
)
return list(result.scalars().all())
@classmethod
async def get_token_by_id(
cls,
db: AsyncSession,
token_id: str,
user_id: str,
) -> Optional[ApiToken]:
"""根据ID获取Token(限定用户)"""
result = await db.execute(
select(ApiToken).where(
ApiToken.id == token_id,
ApiToken.user_id == user_id,
ApiToken.is_deleted == False, # noqa: E712
)
)
return result.scalar_one_or_none()
@classmethod
async def revoke_token(
cls,
db: AsyncSession,
token_id: str,
user_id: str,
) -> bool:
"""撤销(软删除)Token"""
token = await cls.get_token_by_id(db, token_id, user_id)
if not token:
return False
token.is_deleted = True
token.is_active = False
await db.commit()
return True
@classmethod
async def verify_token(
cls,
db: AsyncSession,
raw_token: str,
) -> Optional[ApiToken]:
"""
验证API Token
:return: 有效则返回Token记录,否则返回None
"""
token_hash_value = hash_token(raw_token)
result = await db.execute(
select(ApiToken).where(
ApiToken.token_hash == token_hash_value,
ApiToken.is_deleted == False, # noqa: E712
ApiToken.is_active == True, # noqa: E712
)
)
token = result.scalar_one_or_none()
if not token:
return None
now_utc = datetime.now(timezone.utc)
if token.expires_at:
expires = token.expires_at if token.expires_at.tzinfo else token.expires_at.replace(tzinfo=timezone.utc)
if expires < now_utc:
return None
token.last_used_at = now_utc.replace(tzinfo=None)
await db.commit()
return token