agentic.email/backend/app/models.py
2026-10-05 21:00:05 +05:30

304 lines
9.8 KiB
Python

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)
org_role: Mapped[str] = mapped_column(String(20), default="user")
member_status: Mapped[str] = mapped_column(String(20), default="active")
created_by_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
ForeignKey("users.id"),
nullable=True,
)
invitation_email: Mapped[str | None] = mapped_column(String(320), nullable=True)
must_change_password: Mapped[bool] = mapped_column(Boolean, default=False)
section_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
ForeignKey("org_sections.id"),
nullable=True,
)
password_hash: Mapped[str] = mapped_column(String(255))
section: Mapped["OrgSection | None"] = relationship()
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")
class MemberInvitation(Base):
__tablename__ = "member_invitations"
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
account_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("users.id"),
index=True,
)
token_hash: Mapped[str] = mapped_column(String(64), unique=True, index=True)
expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
used_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True),
nullable=True,
)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
server_default=func.now(),
)
account: Mapped[Account] = relationship()
class OrgSection(Base):
__tablename__ = "org_sections"
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
company_domain: Mapped[str] = mapped_column(String(253), index=True)
name: Mapped[str] = mapped_column(String(120))
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
server_default=func.now(),
)
class OrgSecuritySettings(Base):
__tablename__ = "org_security_settings"
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
company_domain: Mapped[str] = mapped_column(String(253), unique=True, index=True)
require_strong_passwords: Mapped[bool] = mapped_column(Boolean, default=True)
require_mfa_admins: Mapped[bool] = mapped_column(Boolean, default=True)
require_mfa_all_users: Mapped[bool] = mapped_column(Boolean, default=False)
session_timeout_minutes: Mapped[int] = mapped_column(Integer, default=60)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
server_default=func.now(),
onupdate=func.now(),
)
class MailGroup(Base):
__tablename__ = "mail_groups"
__table_args__ = (
CheckConstraint(
"group_type IN ('distribution', 'dynamic')",
name="ck_mail_groups_group_type",
),
)
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
company_domain: Mapped[str] = mapped_column(String(253), index=True)
name: Mapped[str] = mapped_column(String(120))
email: Mapped[str] = mapped_column(String(320), unique=True, index=True)
group_type: Mapped[str] = mapped_column(String(20), default="distribution")
owner_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
ForeignKey("users.id"),
nullable=True,
)
send_permission: Mapped[str] = mapped_column(String(30), default="org_members")
description: Mapped[str | None] = mapped_column(Text, nullable=True)
created_by_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
ForeignKey("users.id"),
nullable=True,
)
owner: Mapped["Account | None"] = relationship(foreign_keys=[owner_id])
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
server_default=func.now(),
)
members: Mapped[list["MailGroupMember"]] = relationship(
back_populates="group",
cascade="all, delete-orphan",
)
class MailGroupMember(Base):
__tablename__ = "mail_group_members"
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
group_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("mail_groups.id"),
index=True,
)
account_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("users.id"),
index=True,
)
group: Mapped[MailGroup] = relationship(back_populates="members")
account: Mapped[Account] = relationship()
class MailAlias(Base):
__tablename__ = "mail_aliases"
__table_args__ = (
CheckConstraint(
"alias_type IN ('user', 'group')",
name="ck_mail_aliases_alias_type",
),
CheckConstraint(
"status IN ('active', 'disabled')",
name="ck_mail_aliases_status",
),
)
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
company_domain: Mapped[str] = mapped_column(String(253), index=True)
alias_address: Mapped[str] = mapped_column(String(320), unique=True, index=True)
forwards_to: Mapped[str] = mapped_column(String(320))
alias_type: Mapped[str] = mapped_column(String(20), default="user")
is_domain_alias: Mapped[bool] = mapped_column(Boolean, default=False)
status: Mapped[str] = mapped_column(String(20), default="active")
created_by_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True),
ForeignKey("users.id"),
nullable=True,
)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
server_default=func.now(),
)