# ============================================================================= # 企微IT智能服务台 — 审计日志模型 # ============================================================================= # 说明: 对应数据库 audit_logs 表,记录所有高危/RBAC 操作 + 登录/MFA 事件 # 给 auditor 角色 + admin 提供只读审计能力 # # 何时写入: # - 高危操作 (role_change / config_change / data_export / account_disable / account_create_reset) # - RBAC 操作 (assign_role / revoke_role / create_mapping_rule / delete_mapping_rule) # - 登录事件 (qrcode_login / sso_login / password_login) # - MFA 事件 (bind / verify / reset) # - 业务敏感操作 (resolve_conversation / transfer_conversation) # ============================================================================= import uuid from datetime import datetime from typing import Optional from sqlalchemy import JSON, DateTime, Index, String, Text from sqlalchemy.orm import Mapped, mapped_column from app.database import Base class AuditLog(Base): """审计日志模型 — 对应 audit_logs 表。 Attributes: id: 日志唯一标识(UUID) employee_id: 操作人(企微 UserID,系统操作填 "system") action: 操作类型(如 "role_change", "login", "mfa_verify") resource: 目标资源类型("agent" / "conversation" / "system_config" 等) resource_id: 目标资源 ID details: 详细上下文(JSON,前后值/IP/UA 等) result: "success" / "failure" / "partial" ip_address: 操作来源 IP(可选) user_agent: 操作来源 UA(可选) created_at: 时间 """ __tablename__ = "audit_logs" # 主键:UUID id: Mapped[str] = mapped_column( String(36), primary_key=True, default=lambda: str(uuid.uuid4()), ) # 操作人(企微 UserID, 系统操作填 "system") employee_id: Mapped[str] = mapped_column( String(100), nullable=False, comment="操作人(employee_id / 'system')", ) # 操作类型 # 例: "role_change" / "config_change" / "login" / "mfa_verify" / # "qrcode_login" / "sso_login" / "password_login" / # "resolve_conversation" / "transfer_conversation" / "data_export" action: Mapped[str] = mapped_column( String(50), nullable=False, comment="操作类型", ) # 目标资源类型 # 例: "agent" / "conversation" / "system_config" / "role" / "user_role" resource: Mapped[str] = mapped_column( String(50), nullable=False, comment="目标资源类型", ) # 目标资源 ID(字符串,跨表通用) resource_id: Mapped[Optional[str]] = mapped_column( String(100), nullable=True, comment="目标资源 ID", ) # 详细上下文(JSON) # 例: {"role": "agent", "reason": "新员工转岗", "ip": "10.80.0.5"} details: Mapped[Optional[dict]] = mapped_column( JSON, nullable=True, comment="详细上下文(JSON)", ) # 结果 # "success" / "failure" / "partial" result: Mapped[str] = mapped_column( String(20), nullable=False, default="success", comment="执行结果", ) # 来源 IP ip_address: Mapped[Optional[str]] = mapped_column( String(64), nullable=True, comment="来源 IP", ) # 来源 User-Agent user_agent: Mapped[Optional[str]] = mapped_column( Text, nullable=True, comment="来源 User-Agent", ) # 时间 created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, default=datetime.now, comment="时间", ) # 索引:按 employee_id / action / time 查询 __table_args__ = ( Index("idx_audit_employee_id", "employee_id"), Index("idx_audit_action", "action"), Index("idx_audit_resource", "resource", "resource_id"), Index("idx_audit_created_at", "created_at"), ) def __repr__(self) -> str: return f""