From 37d50e328d7035e75de24aac5419835bc18963bd Mon Sep 17 00:00:00 2001 From: Phil Skentelbery Date: Mon, 22 Dec 2025 17:49:35 -0700 Subject: [PATCH] fix: regenerate Alembic migration with complete schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous migrations were empty (just 'pass'). Regenerated a single migration that includes all models: Admin, Exchange, Participant, MagicToken, and RateLimit tables with proper indexes and constraints. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- ...3_add_participant_and_magictoken_models.py | 29 ---- ...initial_schema_with_admin_and_exchange_.py | 29 ---- ...a3b9cc26_initial_schema_with_all_models.py | 141 ++++++++++++++++++ 3 files changed, 141 insertions(+), 58 deletions(-) delete mode 100644 migrations/versions/ccdbd24787d3_add_participant_and_magictoken_models.py delete mode 100644 migrations/versions/eeff6e1a89cd_initial_schema_with_admin_and_exchange_.py create mode 100644 migrations/versions/ef9ca3b9cc26_initial_schema_with_all_models.py diff --git a/migrations/versions/ccdbd24787d3_add_participant_and_magictoken_models.py b/migrations/versions/ccdbd24787d3_add_participant_and_magictoken_models.py deleted file mode 100644 index ca1116a..0000000 --- a/migrations/versions/ccdbd24787d3_add_participant_and_magictoken_models.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Add Participant and MagicToken models - -Revision ID: ccdbd24787d3 -Revises: eeff6e1a89cd -Create Date: 2025-12-22 16:20:45.755948 - -""" - -from collections.abc import Sequence - -# revision identifiers, used by Alembic. -revision: str = "ccdbd24787d3" -down_revision: str | Sequence[str] | None = "eeff6e1a89cd" -branch_labels: str | Sequence[str] | None = None -depends_on: str | Sequence[str] | None = None - - -def upgrade() -> None: - """Upgrade schema.""" - # ### commands auto generated by Alembic - please adjust! ### - pass - # ### end Alembic commands ### - - -def downgrade() -> None: - """Downgrade schema.""" - # ### commands auto generated by Alembic - please adjust! ### - pass - # ### end Alembic commands ### diff --git a/migrations/versions/eeff6e1a89cd_initial_schema_with_admin_and_exchange_.py b/migrations/versions/eeff6e1a89cd_initial_schema_with_admin_and_exchange_.py deleted file mode 100644 index 915e071..0000000 --- a/migrations/versions/eeff6e1a89cd_initial_schema_with_admin_and_exchange_.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Initial schema with Admin and Exchange models - -Revision ID: eeff6e1a89cd -Revises: -Create Date: 2025-12-22 11:24:00.652946 - -""" - -from collections.abc import Sequence - -# revision identifiers, used by Alembic. -revision: str = "eeff6e1a89cd" -down_revision: str | Sequence[str] | None = None -branch_labels: str | Sequence[str] | None = None -depends_on: str | Sequence[str] | None = None - - -def upgrade() -> None: - """Upgrade schema.""" - # ### commands auto generated by Alembic - please adjust! ### - pass - # ### end Alembic commands ### - - -def downgrade() -> None: - """Downgrade schema.""" - # ### commands auto generated by Alembic - please adjust! ### - pass - # ### end Alembic commands ### diff --git a/migrations/versions/ef9ca3b9cc26_initial_schema_with_all_models.py b/migrations/versions/ef9ca3b9cc26_initial_schema_with_all_models.py new file mode 100644 index 0000000..6d722e1 --- /dev/null +++ b/migrations/versions/ef9ca3b9cc26_initial_schema_with_all_models.py @@ -0,0 +1,141 @@ +"""Initial schema with all models + +Revision ID: ef9ca3b9cc26 +Revises: +Create Date: 2025-12-22 17:48:23.273368 + +""" + +from collections.abc import Sequence + +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "ef9ca3b9cc26" +down_revision: str | Sequence[str] | None = None +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "admin", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("email", sa.String(length=255), nullable=False), + sa.Column("password_hash", sa.String(length=255), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.Column("updated_at", sa.DateTime(), nullable=False), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index(op.f("ix_admin_email"), "admin", ["email"], unique=True) + op.create_table( + "exchange", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("slug", sa.String(length=12), nullable=False), + sa.Column("name", sa.String(length=255), nullable=False), + sa.Column("description", sa.Text(), nullable=True), + sa.Column("budget", sa.String(length=100), nullable=False), + sa.Column("max_participants", sa.Integer(), nullable=False), + sa.Column("registration_close_date", sa.DateTime(), nullable=False), + sa.Column("exchange_date", sa.DateTime(), nullable=False), + sa.Column("timezone", sa.String(length=50), nullable=False), + sa.Column("state", sa.String(length=20), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.Column("updated_at", sa.DateTime(), nullable=False), + sa.Column("completed_at", sa.DateTime(), nullable=True), + sa.CheckConstraint("max_participants >= 3", name="min_participants_check"), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index( + op.f("ix_exchange_completed_at"), "exchange", ["completed_at"], unique=False + ) + op.create_index(op.f("ix_exchange_slug"), "exchange", ["slug"], unique=True) + op.create_index(op.f("ix_exchange_state"), "exchange", ["state"], unique=False) + op.create_table( + "rate_limit", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("key", sa.String(length=255), nullable=False), + sa.Column("attempts", sa.Integer(), nullable=False), + sa.Column("window_start", sa.DateTime(), nullable=False), + sa.Column("expires_at", sa.DateTime(), nullable=False), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index(op.f("ix_rate_limit_key"), "rate_limit", ["key"], unique=True) + op.create_table( + "participant", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("exchange_id", sa.Integer(), nullable=False), + sa.Column("name", sa.String(length=255), nullable=False), + sa.Column("email", sa.String(length=255), nullable=False), + sa.Column("gift_ideas", sa.Text(), nullable=True), + sa.Column("reminder_enabled", sa.Boolean(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.Column("updated_at", sa.DateTime(), nullable=False), + sa.Column("withdrawn_at", sa.DateTime(), nullable=True), + sa.ForeignKeyConstraint(["exchange_id"], ["exchange.id"], ondelete="CASCADE"), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index("idx_participant_email", "participant", ["email"], unique=False) + op.create_index( + "idx_participant_exchange_email", + "participant", + ["exchange_id", "email"], + unique=True, + ) + op.create_index( + "idx_participant_exchange_id", "participant", ["exchange_id"], unique=False + ) + op.create_table( + "magic_token", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("token_hash", sa.String(length=255), nullable=False), + sa.Column("token_type", sa.String(length=20), nullable=False), + sa.Column("email", sa.String(length=255), nullable=False), + sa.Column("participant_id", sa.Integer(), nullable=True), + sa.Column("exchange_id", sa.Integer(), nullable=True), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.Column("expires_at", sa.DateTime(), nullable=False), + sa.Column("used_at", sa.DateTime(), nullable=True), + sa.ForeignKeyConstraint(["exchange_id"], ["exchange.id"], ondelete="CASCADE"), + sa.ForeignKeyConstraint( + ["participant_id"], ["participant.id"], ondelete="CASCADE" + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("token_hash"), + ) + op.create_index( + "idx_magic_token_expires_at", "magic_token", ["expires_at"], unique=False + ) + op.create_index("idx_magic_token_hash", "magic_token", ["token_hash"], unique=True) + op.create_index( + "idx_magic_token_type_email", + "magic_token", + ["token_type", "email"], + unique=False, + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index("idx_magic_token_type_email", table_name="magic_token") + op.drop_index("idx_magic_token_hash", table_name="magic_token") + op.drop_index("idx_magic_token_expires_at", table_name="magic_token") + op.drop_table("magic_token") + op.drop_index("idx_participant_exchange_id", table_name="participant") + op.drop_index("idx_participant_exchange_email", table_name="participant") + op.drop_index("idx_participant_email", table_name="participant") + op.drop_table("participant") + op.drop_index(op.f("ix_rate_limit_key"), table_name="rate_limit") + op.drop_table("rate_limit") + op.drop_index(op.f("ix_exchange_state"), table_name="exchange") + op.drop_index(op.f("ix_exchange_slug"), table_name="exchange") + op.drop_index(op.f("ix_exchange_completed_at"), table_name="exchange") + op.drop_table("exchange") + op.drop_index(op.f("ix_admin_email"), table_name="admin") + op.drop_table("admin") + # ### end Alembic commands ###