56 lines
1.9 KiB
Python
56 lines
1.9 KiB
Python
"""Email/password columns on users + webUI auth (Stage 4).
|
|
|
|
Revision ID: 0003
|
|
Revises: 0002
|
|
Create Date: 2026-08-12
|
|
|
|
Adds nullable email/password_hash/reset columns to the existing Telegram-only
|
|
users table. Existing Telegram rows remain valid (telegram_id still satisfies
|
|
the new users_identity_present check). Email is unique; both telegram_id and
|
|
email may co-exist on one row (linking the two identities later is a no-op).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Sequence
|
|
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision: str = "0003"
|
|
down_revision: str | None = "0002"
|
|
branch_labels: str | Sequence[str] | None = None
|
|
depends_on: str | Sequence[str] | None = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.add_column("users", sa.Column("email", sa.Text(), nullable=True))
|
|
op.add_column("users", sa.Column("password_hash", sa.Text(), nullable=True))
|
|
op.add_column("users", sa.Column("password_reset_token_hash", sa.Text(), nullable=True))
|
|
op.add_column(
|
|
"users", sa.Column("password_reset_expires_at", sa.DateTime(timezone=True), nullable=True)
|
|
)
|
|
op.add_column(
|
|
"users",
|
|
sa.Column("is_active", sa.Boolean(), nullable=False, server_default=sa.text("true")),
|
|
)
|
|
|
|
op.create_unique_constraint("users_email_unique", "users", ["email"])
|
|
|
|
# A user must have at least one identity anchor (telegram_id OR email).
|
|
op.create_check_constraint(
|
|
"users_identity_present",
|
|
"users",
|
|
"telegram_id IS NOT NULL OR email IS NOT NULL",
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_constraint("users_identity_present", "users", type_="check")
|
|
op.drop_constraint("users_email_unique", "users", type_="unique")
|
|
op.drop_column("users", "is_active")
|
|
op.drop_column("users", "password_reset_expires_at")
|
|
op.drop_column("users", "password_reset_token_hash")
|
|
op.drop_column("users", "password_hash")
|
|
op.drop_column("users", "email")
|