Files
aiagent/backend/app/models/api_key.py
renjianbo f2e65a8fbb feat: virtual company module, team projects, PWA dishes app, and startup scripts overhaul
- Add company module (3-tier org, CEO planning, parallel departments)
- Add company orchestrator, knowledge extractor, presets, scheduler
- Add company API endpoints, models, and frontend views
- Add 今天吃啥 PWA app (69 dishes, real images, offline support)
- Add team_projects output directory structure
- Add unified manage.ps1 for service lifecycle
- Add Windows startup guide v1.0
- Add TTS troubleshooting doc
- Update frontend (AgentChat UX overhaul, new views)
- Update backend (voice engine fix, multi-tenant, RBAC)
- Remove deprecated startup scripts and old docs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-10 22:37:56 +08:00

63 lines
2.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
API Key 模型 — 用于第三方应用/脚本通过 API 调用平台服务
"""
import hashlib
import logging
from datetime import datetime
from typing import Optional
from sqlalchemy import Column, String, DateTime, JSON, func, ForeignKey
from sqlalchemy.dialects.mysql import CHAR
from sqlalchemy.orm import relationship, Session
from app.core.database import Base
import uuid
logger = logging.getLogger(__name__)
KEY_PREFIX = "sk-tg-"
class ApiKey(Base):
"""API Key 表"""
__tablename__ = "api_keys"
id = Column(CHAR(36), primary_key=True, default=lambda: str(uuid.uuid4()), comment="密钥ID")
user_id = Column(CHAR(36), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, comment="所属用户ID")
workspace_id = Column(CHAR(36), ForeignKey("workspaces.id", ondelete="CASCADE"), nullable=False, comment="所属工作区ID")
name = Column(String(100), nullable=False, comment="密钥名称(用于标识)")
key_prefix = Column(String(12), nullable=False, comment="密钥前缀(如 sk-tg-")
key_hash = Column(String(255), nullable=False, unique=True, comment="SHA256 哈希存储")
permissions = Column(JSON, nullable=True, comment="权限范围null=全部权限)")
last_used_at = Column(DateTime, nullable=True, comment="最后使用时间")
expires_at = Column(DateTime, nullable=True, comment="过期时间null=永不过期)")
status = Column(String(20), default="active", comment="状态: active/revoked")
created_at = Column(DateTime, default=func.now(), comment="创建时间")
# 关系
user = relationship("User", backref="api_keys")
def __repr__(self):
return f"<ApiKey(id={self.id}, name={self.name}, status={self.status})>"
def verify_api_key(api_key_str: str, db: Session) -> Optional["ApiKey"]:
"""验证 API Key 字符串,返回 ApiKey 对象或 None。"""
if not api_key_str or not api_key_str.startswith(KEY_PREFIX):
return None
key_hash = hashlib.sha256(api_key_str.encode()).hexdigest()
api_key = db.query(ApiKey).filter(
ApiKey.key_hash == key_hash,
ApiKey.status == "active",
).first()
if not api_key:
return None
if api_key.expires_at and api_key.expires_at < datetime.utcnow():
logger.warning("API Key %s 已过期", api_key.id)
return None
return api_key