Files
docqube_backend/alembic/versions/a2b3c4d5e6f7_update_access_model_with_hierarchy.py
T
2026-09-08 11:00:05 +05:30

76 lines
2.7 KiB
Python

"""Update Access model with hierarchical permission support
Revision ID: a2b3c4d5e6f7
Revises: a1b2c3d4e5f6
Create Date: 2026-03-05 10:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'a2b3c4d5e6f7'
down_revision = 'a1b2c3d4e5f6'
branch_labels = None
depends_on = None
def upgrade() -> None:
# FIRST: Drop any existing unique constraint on `name` (constraints may be named differently depending on DB)
op.execute("ALTER TABLE accesses DROP CONSTRAINT IF EXISTS uq_accesses_name CASCADE")
op.execute("ALTER TABLE accesses DROP CONSTRAINT IF EXISTS accesses_name_key CASCADE")
# also drop postgresql-generated index if it survived
op.execute("DROP INDEX IF EXISTS accesses_name_key")
# Add new columns to accesses table (all nullable first)
op.add_column('accesses', sa.Column('access_code', sa.String(255), nullable=True))
op.add_column('accesses', sa.Column('category', sa.String(100), nullable=True))
op.add_column('accesses', sa.Column('parent_id', sa.Integer(), nullable=True))
# Create indexes on new columns
op.create_index('ix_access_code', 'accesses', ['access_code'])
op.create_index('ix_category', 'accesses', ['category'])
op.create_index('ix_accesses_parent_id', 'accesses', ['parent_id'])
# Set default values from existing 'name' field
op.execute("""
UPDATE accesses
SET access_code = LOWER(REPLACE(name, ' ', '_')),
category = 'General'
WHERE access_code IS NULL
""")
# Now make columns NOT NULL
op.alter_column('accesses', 'access_code', existing_type=sa.String(255), nullable=False)
op.alter_column('accesses', 'category', existing_type=sa.String(100), nullable=False)
# Create unique constraint on access_code
op.create_unique_constraint('uq_accesses_access_code', 'accesses', ['access_code'])
# Create foreign key for parent_id
op.create_foreign_key('fk_accesses_parent_id', 'accesses', 'accesses', ['parent_id'], ['id'], ondelete='CASCADE')
def downgrade() -> None:
# Drop foreign key
op.drop_constraint('fk_accesses_parent_id', 'accesses', type_='foreignkey')
# Drop unique constraint
op.drop_constraint('uq_accesses_access_code', 'accesses', type_='unique')
# Drop indexes
op.drop_index('ix_accesses_parent_id', 'accesses')
op.drop_index('ix_category', 'accesses')
op.drop_index('ix_access_code', 'accesses')
# Drop columns
op.drop_column('accesses', 'parent_id')
op.drop_column('accesses', 'category')
op.drop_column('accesses', 'access_code')
# Re-add unique constraint on 'name'
op.create_unique_constraint('uq_accesses_name', 'accesses', ['name'])