79 lines
2.8 KiB
Python

import enum
import uuid
from datetime import datetime
from sqlalchemy import ForeignKey, Index, Integer, String, Text, func
from sqlalchemy.dialects.postgresql import ENUM
from sqlalchemy.orm import Mapped, mapped_column, relationship
from proxy_pool.db.base import Base, TimestampMixin, UUIDPrimaryKeyMixin
class CreditTxType(str, enum.Enum):
PURCHASE = "purchase"
ACQUIRE = "acquire"
REFUND = "refund"
ADMIN_ADJUST = "admin_adjust"
class User(UUIDPrimaryKeyMixin, TimestampMixin, Base):
__tablename__ = "users"
email: Mapped[str] = mapped_column(String(320), unique=True)
display_name: Mapped[str | None] = mapped_column(String(128))
is_active: Mapped[bool] = mapped_column(default=True)
api_keys: Mapped[list["ApiKey"]] = relationship(back_populates="user")
credit_entries: Mapped[list["CreditLedger"]] = relationship(back_populates="user")
class ApiKey(UUIDPrimaryKeyMixin, TimestampMixin, Base):
__tablename__ = "api_keys"
__table_args__ = (
Index("ix_api_keys_hash", "key_hash", unique=True),
Index("ix_api_keys_prefix", "prefix"),
)
user_id: Mapped[uuid.UUID] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"),
)
key_hash: Mapped[str] = mapped_column(String(128))
prefix: Mapped[str] = mapped_column(String(8))
label: Mapped[str | None] = mapped_column(String(128))
is_active: Mapped[bool] = mapped_column(default=True)
last_used_at: Mapped[datetime | None] = mapped_column()
expires_at: Mapped[datetime | None] = mapped_column()
user: Mapped["User"] = relationship(back_populates="api_keys")
class CreditLedger(UUIDPrimaryKeyMixin, TimestampMixin, Base):
__tablename__ = "credit_ledger"
__table_args__ = (Index("ix_ledger_user_created", "user_id", "created_at"),)
user_id: Mapped[uuid.UUID] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"),
)
amount: Mapped[int] = mapped_column(Integer)
tx_type: Mapped[CreditTxType] = mapped_column(
ENUM(CreditTxType, name="credit_tx_type"),
)
description: Mapped[str | None] = mapped_column(Text)
reference_id: Mapped[uuid.UUID | None] = mapped_column()
user: Mapped["User"] = relationship(back_populates="credit_entries")
class ProxyLease(UUIDPrimaryKeyMixin, Base):
__tablename__ = "proxy_leases"
__table_args__ = (
Index("ix_leases_user", "user_id"),
Index("ix_leases_proxy_active", "proxy_id", "is_released"),
)
user_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("users.id"))
proxy_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("proxies.id"))
acquired_at: Mapped[datetime] = mapped_column(server_default=func.now())
expires_at: Mapped[datetime] = mapped_column()
is_released: Mapped[bool] = mapped_column(default=False)