Vastai-ConnectHub/app/db/models.py

191 lines
8.6 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.

from __future__ import annotations
import enum
from datetime import datetime
from typing import Any
from sqlalchemy import JSON, Boolean, Column, DateTime, Enum, ForeignKey, Integer, String, Table, Text, func
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
class Base(DeclarativeBase):
pass
user_roles = Table(
"user_roles",
Base.metadata,
Column("user_id", ForeignKey("users.id"), primary_key=True),
Column("role_id", ForeignKey("roles.id"), primary_key=True),
)
role_permissions = Table(
"role_permissions",
Base.metadata,
Column("role_id", ForeignKey("roles.id"), primary_key=True),
Column("permission_id", ForeignKey("permissions.id"), primary_key=True),
)
class Job(Base):
__tablename__ = "jobs"
id: Mapped[str] = mapped_column(String, primary_key=True)
cron_expr: Mapped[str] = mapped_column(String, nullable=False)
handler_path: Mapped[str] = mapped_column(String, nullable=False)
public_cfg: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False)
# 密文 tokenFernet 加密后的字符串)
secret_cfg: Mapped[str] = mapped_column(Text, default="", nullable=False)
enabled: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
last_run_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False
)
logs: Mapped[list["JobLog"]] = relationship(back_populates="job", cascade="all, delete-orphan")
class JobStatus(str, enum.Enum):
RUNNING = "RUNNING"
SUCCESS = "SUCCESS"
FAILURE = "FAILURE"
RETRY = "RETRY"
class JobLog(Base):
__tablename__ = "job_logs"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
job_id: Mapped[str] = mapped_column(ForeignKey("jobs.id"), index=True, nullable=False)
status: Mapped[JobStatus] = mapped_column(
Enum(JobStatus, native_enum=False, length=16),
nullable=False,
)
snapshot_params: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False)
message: Mapped[str] = mapped_column(Text, default="", nullable=False)
traceback: Mapped[str] = mapped_column(Text, default="", nullable=False)
# 本次执行期间捕获到的完整运行日志(可能很长,按上层捕获器做截断)
run_log: Mapped[str] = mapped_column(Text, default="", nullable=False)
celery_task_id: Mapped[str] = mapped_column(String, default="", nullable=False)
attempt: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
started_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False)
finished_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
job: Mapped[Job] = relationship(back_populates="logs")
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
username: Mapped[str] = mapped_column(String, unique=True, index=True, nullable=False)
password_hash: Mapped[str] = mapped_column(Text, default="", nullable=False)
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
is_superuser: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
is_ldap: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
last_login_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False
)
roles: Mapped[list["Role"]] = relationship(secondary=user_roles, back_populates="users")
class Role(Base):
__tablename__ = "roles"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String, unique=True, index=True, nullable=False)
description: Mapped[str] = mapped_column(Text, default="", nullable=False)
users: Mapped[list[User]] = relationship(secondary=user_roles, back_populates="roles")
permissions: Mapped[list["Permission"]] = relationship(secondary=role_permissions, back_populates="roles")
def __repr__(self) -> str:
return self.name
class Permission(Base):
__tablename__ = "permissions"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
code: Mapped[str] = mapped_column(String, unique=True, index=True, nullable=False)
description: Mapped[str] = mapped_column(Text, default="", nullable=False)
roles: Mapped[list[Role]] = relationship(secondary=role_permissions, back_populates="permissions")
class LdapGroup(Base):
__tablename__ = "ldap_groups"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
dn: Mapped[str] = mapped_column(String, unique=True, index=True, nullable=False)
name: Mapped[str] = mapped_column(String, index=True, nullable=False)
def __repr__(self) -> str:
return self.name or self.dn
class LdapGroupRole(Base):
__tablename__ = "ldap_group_roles"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
ldap_group_id: Mapped[int] = mapped_column(ForeignKey("ldap_groups.id"), nullable=False)
role_id: Mapped[int] = mapped_column(ForeignKey("roles.id"), nullable=False)
ldap_group: Mapped[LdapGroup] = relationship()
role: Mapped[Role] = relationship()
class LdapConfig(Base):
__tablename__ = "ldap_configs"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String, unique=True, index=True, default="default", nullable=False)
enabled: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
uri: Mapped[str] = mapped_column(String, default="", nullable=False)
bind_dn: Mapped[str] = mapped_column(String, default="", nullable=False)
bind_password_encrypted: Mapped[str] = mapped_column(Text, default="", nullable=False)
base_dn: Mapped[str] = mapped_column(String, default="", nullable=False)
user_filter: Mapped[str] = mapped_column(String, default="(uid={username})", nullable=False)
group_filter: Mapped[str] = mapped_column(String, default="(member={user_dn})", nullable=False)
use_starttls: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
verify_tls: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
last_test_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
last_test_result: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False)
updated_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id"), nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False
)
class AuditLog(Base):
__tablename__ = "audit_logs"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
actor_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id"), nullable=True)
action: Mapped[str] = mapped_column(String, index=True, nullable=False)
target: Mapped[str] = mapped_column(String, default="", nullable=False)
detail: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False)
ip: Mapped[str] = mapped_column(String, default="", nullable=False)
user_agent: Mapped[str] = mapped_column(Text, default="", nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False)
class Session(Base):
__tablename__ = "sessions"
id: Mapped[str] = mapped_column(String, primary_key=True)
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), nullable=False, index=True)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False)
expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
ip: Mapped[str] = mapped_column(String, default="", nullable=False)
user_agent: Mapped[str] = mapped_column(Text, default="", nullable=False)