61 lines
2.4 KiB
Python
61 lines
2.4 KiB
Python
"""Fix schema drifts — VARCHAR lengths + missing tables.
|
|
|
|
Revision ID: 0135
|
|
Revises: 0134
|
|
Create Date: 2026-08-21
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
|
|
|
revision = "0135"
|
|
down_revision = "0134"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
# 1. Fix VARCHAR length mismatches (model defines longer than DB)
|
|
# Drop notifications_legacy view first — it depends on notifications.type column
|
|
op.execute("DROP VIEW IF EXISTS notifications_legacy CASCADE;")
|
|
op.execute("ALTER TABLE contacts ALTER COLUMN status TYPE VARCHAR(30);")
|
|
op.execute("ALTER TABLE notifications ALTER COLUMN type TYPE VARCHAR(100);")
|
|
op.execute("ALTER TABLE notification_preferences ALTER COLUMN type_key TYPE VARCHAR(100);")
|
|
|
|
# 2. Create missing table: forgejo_reported_errors (only if not exists)
|
|
op.execute("""
|
|
CREATE TABLE IF NOT EXISTS forgejo_reported_errors (
|
|
id SERIAL PRIMARY KEY,
|
|
dedup_key VARCHAR(64) NOT NULL UNIQUE,
|
|
message TEXT NOT NULL,
|
|
stack TEXT,
|
|
forgejo_issue_number INTEGER,
|
|
reported_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
|
status VARCHAR(20) NOT NULL DEFAULT 'reported'
|
|
)
|
|
""")
|
|
|
|
# 3. Create missing table: pgp_keys (only if not exists)
|
|
op.execute("""
|
|
CREATE TABLE IF NOT EXISTS pgp_keys (
|
|
id UUID DEFAULT gen_random_uuid() NOT NULL PRIMARY KEY,
|
|
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL,
|
|
key_id VARCHAR(255) NOT NULL,
|
|
encrypted_private_key TEXT NOT NULL,
|
|
public_key_armored TEXT NOT NULL
|
|
)
|
|
""")
|
|
op.execute("CREATE INDEX IF NOT EXISTS ix_pgp_keys_user ON pgp_keys (user_id);")
|
|
op.execute("ALTER TABLE pgp_keys ENABLE ROW LEVEL SECURITY;")
|
|
op.execute("DROP POLICY IF EXISTS pgp_keys_tenant_isolation ON pgp_keys;")
|
|
op.execute("CREATE POLICY pgp_keys_tenant_isolation ON pgp_keys USING (tenant_id::text = current_setting('app.current_tenant_id', true));")
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_table("pgp_keys")
|
|
op.drop_table("forgejo_reported_errors")
|
|
op.execute("ALTER TABLE notification_preferences ALTER COLUMN type_key TYPE VARCHAR(20);")
|
|
op.execute("ALTER TABLE notifications ALTER COLUMN type TYPE VARCHAR(20);")
|
|
op.execute("ALTER TABLE contacts ALTER COLUMN status TYPE VARCHAR(20);")
|