Files
2026-07-20 10:26:58 +08:00

95 lines
5.0 KiB
Python
Raw Permalink 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 datetime import datetime
from sqlalchemy import Integer, String, DateTime, ForeignKey, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship
from backend.database import Base
class Server(Base):
__tablename__ = "servers"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False)
platform: Mapped[str] = mapped_column(String(20), nullable=False) # linux / windows
token: Mapped[str] = mapped_column(String(100), nullable=False)
ip: Mapped[str | None] = mapped_column(String(50), nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
domains: Mapped[list["Domain"]] = relationship(back_populates="server", cascade="all, delete-orphan")
class Domain(Base):
__tablename__ = "domains"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
server_id: Mapped[int] = mapped_column(Integer, ForeignKey("servers.id"), nullable=False)
acme_config_id: Mapped[int | None] = mapped_column(Integer, ForeignKey("acme_configs.id"), nullable=True)
domain: Mapped[str] = mapped_column(String(200), nullable=False)
cert_dir: Mapped[str] = mapped_column(String(500), nullable=False)
check_cmd: Mapped[str] = mapped_column(String(200), nullable=False)
reload_cmd: Mapped[str] = mapped_column(String(200), nullable=False)
version: Mapped[str] = mapped_column(String(50), default="0")
cert_not_after: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
server: Mapped["Server"] = relationship(back_populates="domains")
acme_config: Mapped["AcmeConfig | None"] = relationship(back_populates="domains")
logs: Mapped[list["DeployLog"]] = relationship(back_populates="domain")
class DeployLog(Base):
__tablename__ = "deploy_logs"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
domain_id: Mapped[int] = mapped_column(Integer, ForeignKey("domains.id"), nullable=False)
server_id: Mapped[int] = mapped_column(Integer, ForeignKey("servers.id"), nullable=False)
hostname: Mapped[str | None] = mapped_column(String(200), nullable=True)
status: Mapped[str] = mapped_column(String(20), nullable=False) # success / failed / skipped
message: Mapped[str | None] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
domain: Mapped["Domain"] = relationship(back_populates="logs")
class AcmeConfig(Base):
"""ACME 配置(支持多个)"""
__tablename__ = "acme_configs"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String(100), nullable=False, default="默认配置")
# ACME 服务器地址
acme_server: Mapped[str] = mapped_column(String(500), default="https://acme-v02.api.letsencrypt.org/directory")
# 邮箱
email: Mapped[str] = mapped_column(String(200), default="")
# DNS 提商类型
dns_provider: Mapped[str] = mapped_column(String(50), default="aliyun") # aliyun / cloudflare / manual
# DNS 提商凭据(JSON
dns_credentials: Mapped[str] = mapped_column(Text, default="{}")
# 账户私钥(PEM
account_key: Mapped[str | None] = mapped_column(Text, nullable=True)
# 续签提前天数
renew_days: Mapped[int] = mapped_column(Integer, default=30)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
domains: Mapped[list["Domain"]] = relationship(back_populates="acme_config")
class AcmeLog(Base):
"""ACME 操作日志"""
__tablename__ = "acme_logs"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
domain_id: Mapped[int | None] = mapped_column(Integer, ForeignKey("domains.id"), nullable=True)
action: Mapped[str] = mapped_column(String(50), nullable=False) # issue / renew / revoke / register
status: Mapped[str] = mapped_column(String(20), nullable=False) # success / failed / pending
message: Mapped[str | None] = mapped_column(Text, nullable=True)
detail: Mapped[str | None] = mapped_column(Text, nullable=True) # certbot 原始输出
cert_not_after: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
cert_serial: Mapped[str | None] = mapped_column(String(100), nullable=True)
cert_san: Mapped[str | None] = mapped_column(String(500), nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
domain: Mapped["Domain | None"] = relationship()