import uuid from datetime import datetime, timezone from typing import Optional from flask_login import UserMixin from sqlalchemy import DateTime, String, Text, UniqueConstraint, Uuid from sqlalchemy.orm import Mapped, mapped_column from werkzeug.security import check_password_hash, generate_password_hash from . import Base class User(UserMixin, Base): __tablename__ = "users" id: Mapped[int] = mapped_column(primary_key=True) username: Mapped[str] = mapped_column( String(64), index=True, unique=True, ) password_hash: Mapped[Optional[str]] = mapped_column(String(256)) def __repr__(self): return f"" def set_password(self, password): self.password_hash = generate_password_hash(password) def check_password(self, password): return check_password_hash( self.password_hash, password, ) class ReceivedWebmention(Base): __tablename__ = "received_webmentions" uuid: Mapped[uuid.UUID] = mapped_column( Uuid(as_uuid=True), primary_key=True, ) source: Mapped[str] = mapped_column( Text(), nullable=False, ) target: Mapped[str] = mapped_column( Text(), nullable=False, ) status: Mapped[str] = mapped_column( Text(), nullable=False, default="received", ) failure_reason: Mapped[str | None] = mapped_column( Text(), nullable=True, default=None, ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), nullable=False, ) __table_args__ = ( UniqueConstraint( "source", "target", name="uq_webmention_source_target", ), ) @property def verified(self) -> bool: return self.status == "verified" @property def created_at(self) -> datetime: return datetime.fromtimestamp( self.uuid.time / 1000, tz=timezone.utc, )