import uuid from datetime import date, datetime from sqlalchemy import ( Boolean, CheckConstraint, Date, DateTime, ForeignKey, Integer, String, Text, func, ) from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship class Base(DeclarativeBase): pass class Account(Base): __tablename__ = "users" __table_args__ = ( CheckConstraint( "account_type IN ('individual', 'company')", name="ck_users_account_type", ), ) id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, ) account_type: Mapped[str] = mapped_column(String(20)) email: Mapped[str] = mapped_column(String(320), unique=True, index=True) first_name: Mapped[str] = mapped_column(String(80)) last_name: Mapped[str] = mapped_column(String(80)) date_of_birth: Mapped[date] = mapped_column(Date) phone_number: Mapped[str] = mapped_column(String(24), unique=True) company_domain: Mapped[str | None] = mapped_column(String(253), nullable=True) password_hash: Mapped[str] = mapped_column(String(255)) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), ) mail_domains: Mapped[list["MailDomain"]] = relationship(back_populates="account") class MailDomain(Base): __tablename__ = "mail_domains" id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, ) domain_name: Mapped[str] = mapped_column(String(253), unique=True, index=True) domain_type: Mapped[str] = mapped_column(String(20)) account_id: Mapped[uuid.UUID | None] = mapped_column( UUID(as_uuid=True), ForeignKey("users.id"), nullable=True, ) mail_host: Mapped[str] = mapped_column(String(253)) dkim_selector: Mapped[str] = mapped_column(String(63)) dkim_private_key: Mapped[str] = mapped_column(Text) dkim_public_key: Mapped[str] = mapped_column(Text) status: Mapped[str] = mapped_column(String(20), default="pending_dns") created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), ) account: Mapped[Account | None] = relationship(back_populates="mail_domains") dns_records: Mapped[list["DomainDnsRecord"]] = relationship( back_populates="domain", cascade="all, delete-orphan", ) smtp_credentials: Mapped[list["SmtpCredential"]] = relationship( back_populates="domain", cascade="all, delete-orphan", ) class DomainDnsRecord(Base): __tablename__ = "domain_dns_records" id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, ) domain_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("mail_domains.id"), index=True, ) record_type: Mapped[str] = mapped_column(String(10)) host: Mapped[str] = mapped_column(String(253)) value: Mapped[str] = mapped_column(Text) purpose: Mapped[str] = mapped_column(String(20)) ttl: Mapped[int] = mapped_column(Integer, default=3600) domain: Mapped[MailDomain] = relationship(back_populates="dns_records") class SmtpCredential(Base): __tablename__ = "smtp_credentials" id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, ) domain_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("mail_domains.id"), index=True, ) username: Mapped[str] = mapped_column(String(120), unique=True, index=True) password_hash: Mapped[str] = mapped_column(String(255)) label: Mapped[str] = mapped_column(String(120)) is_active: Mapped[bool] = mapped_column(Boolean, default=True) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), ) domain: Mapped[MailDomain] = relationship(back_populates="smtp_credentials")