d354da5b51
Users who forget their password can now request a reset link via email. Tokens are SHA-256 hashed before storage, expire after 1 hour, and previous unused tokens are invalidated on new requests. The forgot-password endpoint always returns success to prevent email enumeration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
26 lines
814 B
Python
26 lines
814 B
Python
"""Add password_reset_tokens table."""
|
|
|
|
from alembic import op
|
|
|
|
revision = "0011"
|
|
down_revision = "0010"
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.execute("""
|
|
CREATE TABLE password_reset_tokens (
|
|
id SERIAL PRIMARY KEY,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
token_hash TEXT NOT NULL UNIQUE,
|
|
expires_at TIMESTAMPTZ NOT NULL,
|
|
used BOOLEAN NOT NULL DEFAULT FALSE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
)
|
|
""")
|
|
op.execute("CREATE INDEX ix_password_reset_tokens_token_hash ON password_reset_tokens (token_hash)")
|
|
op.execute("CREATE INDEX ix_password_reset_tokens_user_id ON password_reset_tokens (user_id)")
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.execute("DROP TABLE IF EXISTS password_reset_tokens")
|