123 lines
4.3 KiB
Python
123 lines
4.3 KiB
Python
"""Consolidate user and superadmin sessions into unified sessions table.
|
|
|
|
Revision ID: c8d2e4f6a1b3
|
|
Revises: b7e3f1a92c4d
|
|
Create Date: 2026-04-28 00:00:00.000000
|
|
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects import postgresql
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision = 'c8d2e4f6a1b3'
|
|
down_revision = 'b7e3f1a92c4d'
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade():
|
|
# 1. Add new columns (nullable initially for data migration)
|
|
op.add_column('sessions', sa.Column('owner_type', sa.String(20), nullable=True))
|
|
op.add_column('sessions', sa.Column('owner_id', sa.String(36), nullable=True))
|
|
|
|
# 2. Backfill existing user sessions: owner_type = 'user', owner_id = user_id
|
|
op.execute("""
|
|
UPDATE sessions
|
|
SET owner_type = 'user',
|
|
owner_id = user_id
|
|
WHERE owner_type IS NULL
|
|
""")
|
|
|
|
# 3. Migrate superadmin sessions into the sessions table
|
|
op.execute("""
|
|
INSERT INTO sessions (
|
|
id, owner_type, owner_id, token, status,
|
|
ip_address, user_agent, device_info,
|
|
expires_at, last_activity_at, revoked_at, revoked_reason,
|
|
is_compliance_only, created_at, updated_at, deleted_at
|
|
)
|
|
SELECT
|
|
id, 'superadmin', superadmin_id, token, 'ACTIVE',
|
|
ip_address, user_agent, NULL,
|
|
expires_at, last_activity_at, revoked_at, revoked_reason,
|
|
FALSE, created_at, updated_at, deleted_at
|
|
FROM superadmin_sessions
|
|
""")
|
|
|
|
# 4. Make owner_type and owner_id NOT NULL
|
|
op.alter_column('sessions', 'owner_type', nullable=False)
|
|
op.alter_column('sessions', 'owner_id', nullable=False)
|
|
|
|
# 5. Make user_id nullable (no longer the sole owner reference)
|
|
op.alter_column('sessions', 'user_id', nullable=True)
|
|
|
|
# 6. Create indexes for efficient owner-scoped queries
|
|
op.create_index(
|
|
'ix_sessions_owner_type_owner_id',
|
|
'sessions',
|
|
['owner_type', 'owner_id']
|
|
)
|
|
op.create_index(
|
|
'ix_sessions_owner_type',
|
|
'sessions',
|
|
['owner_type']
|
|
)
|
|
op.create_index(
|
|
'ix_sessions_owner_id',
|
|
'sessions',
|
|
['owner_id']
|
|
)
|
|
|
|
# 7. Drop the now-redundant superadmin_sessions table
|
|
op.drop_table('superadmin_sessions')
|
|
|
|
|
|
def downgrade():
|
|
# 1. Recreate superadmin_sessions table
|
|
op.create_table(
|
|
'superadmin_sessions',
|
|
sa.Column('id', sa.String(36), primary_key=True),
|
|
sa.Column('superadmin_id', sa.String(36), sa.ForeignKey('superadmins.id'), nullable=False, index=True),
|
|
sa.Column('token', sa.String(255), unique=True, nullable=False, index=True),
|
|
sa.Column('expires_at', sa.DateTime, nullable=False),
|
|
sa.Column('last_activity_at', sa.DateTime, nullable=False),
|
|
sa.Column('ip_address', sa.String(45), nullable=True),
|
|
sa.Column('user_agent', sa.Text, nullable=True),
|
|
sa.Column('revoked_at', sa.DateTime, nullable=True),
|
|
sa.Column('revoked_reason', sa.String(255), nullable=True),
|
|
sa.Column('created_at', sa.DateTime, nullable=False),
|
|
sa.Column('updated_at', sa.DateTime, nullable=False),
|
|
sa.Column('deleted_at', sa.DateTime, nullable=True),
|
|
)
|
|
|
|
# 2. Move superadmin sessions back to superadmin_sessions
|
|
op.execute("""
|
|
INSERT INTO superadmin_sessions (
|
|
id, superadmin_id, token, expires_at, last_activity_at,
|
|
ip_address, user_agent, revoked_at, revoked_reason,
|
|
created_at, updated_at, deleted_at
|
|
)
|
|
SELECT
|
|
id, owner_id, token, expires_at, last_activity_at,
|
|
ip_address, user_agent, revoked_at, revoked_reason,
|
|
created_at, updated_at, deleted_at
|
|
FROM sessions
|
|
WHERE owner_type = 'superadmin'
|
|
""")
|
|
|
|
# 3. Remove superadmin sessions from sessions table
|
|
op.execute("DELETE FROM sessions WHERE owner_type = 'superadmin'")
|
|
|
|
# 4. Drop indexes
|
|
op.drop_index('ix_sessions_owner_id', table_name='sessions')
|
|
op.drop_index('ix_sessions_owner_type', table_name='sessions')
|
|
op.drop_index('ix_sessions_owner_type_owner_id', table_name='sessions')
|
|
|
|
# 5. Remove new columns
|
|
op.drop_column('sessions', 'owner_id')
|
|
op.drop_column('sessions', 'owner_type')
|
|
|
|
# 6. Make user_id NOT NULL again
|
|
op.alter_column('sessions', 'user_id', nullable=False)
|