"""Add users and invite_codes tables for creator authentication. Revision ID: 016_add_users_and_invite_codes Revises: 015_add_creator_profile """ from alembic import op revision = "016_add_users_and_invite_codes" down_revision = "015_add_creator_profile" branch_labels = None depends_on = None def upgrade() -> None: # Use raw SQL to avoid SQLAlchemy's Enum double-creation bug with asyncpg op.execute(""" DO $$ BEGIN CREATE TYPE user_role AS ENUM ('creator', 'admin'); EXCEPTION WHEN duplicate_object THEN NULL; END $$ """) op.execute(""" CREATE TABLE IF NOT EXISTS users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email VARCHAR(255) NOT NULL UNIQUE, hashed_password VARCHAR(255) NOT NULL, display_name VARCHAR(255) NOT NULL, role user_role NOT NULL DEFAULT 'creator', creator_id UUID REFERENCES creators(id) ON DELETE SET NULL, is_active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP NOT NULL DEFAULT now(), updated_at TIMESTAMP NOT NULL DEFAULT now() ) """) op.execute(""" CREATE TABLE IF NOT EXISTS invite_codes ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), code VARCHAR(100) NOT NULL UNIQUE, uses_remaining INTEGER NOT NULL DEFAULT 1, created_by UUID REFERENCES users(id) ON DELETE SET NULL, expires_at TIMESTAMP, created_at TIMESTAMP NOT NULL DEFAULT now() ) """) def downgrade() -> None: op.execute("DROP TABLE IF EXISTS invite_codes") op.execute("DROP TABLE IF EXISTS users") op.execute("DROP TYPE IF EXISTS user_role")