Files
ctms/backend/app/models/permission_access_log.py
Cheng Zhou f11a5c84d9
Client Quality Gates / Shared client and Web (push) Has been cancelled
Client Quality Gates / macOS Desktop (push) Has been cancelled
feat(监控): 完善系统监控、登录状态与访问审计能力
2026-07-10 17:12:13 +08:00

58 lines
2.6 KiB
Python

"""权限访问日志模型"""
from __future__ import annotations
import uuid
from datetime import datetime
from typing import Optional
from sqlalchemy import JSON, Boolean, DateTime, Float, ForeignKey, Index, String
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.sql import func
from app.db.base_class import Base
JSONB_TYPE = JSON().with_variant(JSONB, "postgresql")
class PermissionAccessLog(Base):
__tablename__ = "permission_access_logs"
__table_args__ = (
Index("ix_perm_log_study_created", "study_id", "created_at"),
Index("ix_perm_log_user_created", "user_id", "created_at"),
Index("ix_perm_log_endpoint_created", "endpoint_key", "created_at"),
Index("ix_perm_log_created_at", "created_at"),
Index("ix_perm_log_allowed", "allowed", "created_at"),
Index("ix_perm_log_ip_created", "ip_address", "created_at"),
Index("ix_perm_log_client_source_created", "client_type", "created_at"),
Index("ix_perm_log_request_id", "request_id"),
)
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
)
study_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), ForeignKey("studies.id"), nullable=False
)
user_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), ForeignKey("users.id"), nullable=False
)
endpoint_key: Mapped[str] = mapped_column(String(100), nullable=False)
role: Mapped[str] = mapped_column(String(30), nullable=False)
allowed: Mapped[bool] = mapped_column(Boolean, nullable=False)
elapsed_ms: Mapped[float] = mapped_column(Float, nullable=False)
ip_address: Mapped[Optional[str]] = mapped_column(String(45), nullable=True)
user_agent: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
client_type: Mapped[Optional[str]] = mapped_column(String(16), nullable=True)
client_version: Mapped[Optional[str]] = mapped_column(String(32), nullable=True)
client_platform: Mapped[Optional[str]] = mapped_column(String(16), nullable=True)
build_channel: Mapped[Optional[str]] = mapped_column(String(16), nullable=True)
build_commit: Mapped[Optional[str]] = mapped_column(String(64), nullable=True)
request_headers: Mapped[Optional[dict]] = mapped_column(JSONB_TYPE, nullable=True)
request_snapshot: Mapped[Optional[dict]] = mapped_column(JSONB_TYPE, nullable=True)
request_id: Mapped[Optional[str]] = mapped_column(String(36), nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), nullable=False, server_default=func.now()
)