"""Create audit trail tables Revision ID: 005 Revises: 004 Create Date: 2024-12-29 """ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import mysql # revision identifiers, used by Alembic. revision = '005' down_revision = '004' branch_labels = None depends_on = None def upgrade() -> None: # Create audit_logs table op.create_table( 'pjctrl_audit_logs', sa.Column('id', sa.String(36), primary_key=True), sa.Column('event_type', sa.String(50), nullable=False), sa.Column('resource_type', sa.String(50), nullable=False), sa.Column('resource_id', sa.String(36), nullable=True), sa.Column('user_id', sa.String(36), sa.ForeignKey('pjctrl_users.id', ondelete='SET NULL'), nullable=True), sa.Column('action', sa.Enum('create', 'update', 'delete', 'restore', 'login', 'logout', name='audit_action_enum'), nullable=False), sa.Column('changes', sa.JSON, nullable=True), sa.Column('request_metadata', sa.JSON, nullable=True), sa.Column('sensitivity_level', sa.Enum('low', 'medium', 'high', 'critical', name='sensitivity_level_enum'), server_default='low', nullable=False), sa.Column('checksum', sa.String(64), nullable=False), sa.Column('created_at', sa.DateTime, server_default=sa.func.now(), nullable=False), ) # Create indexes for audit_logs op.create_index('idx_audit_user', 'pjctrl_audit_logs', ['user_id', 'created_at']) op.create_index('idx_audit_resource', 'pjctrl_audit_logs', ['resource_type', 'resource_id', 'created_at']) op.create_index('idx_audit_time', 'pjctrl_audit_logs', ['created_at']) # Create audit_alerts table op.create_table( 'pjctrl_audit_alerts', sa.Column('id', sa.String(36), primary_key=True), sa.Column('audit_log_id', sa.String(36), sa.ForeignKey('pjctrl_audit_logs.id', ondelete='CASCADE'), nullable=False), sa.Column('alert_type', sa.String(50), nullable=False), sa.Column('recipients', sa.JSON, nullable=False), sa.Column('message', sa.Text, nullable=True), sa.Column('is_acknowledged', sa.Boolean, server_default='0', nullable=False), sa.Column('acknowledged_by', sa.String(36), sa.ForeignKey('pjctrl_users.id', ondelete='SET NULL'), nullable=True), sa.Column('acknowledged_at', sa.DateTime, nullable=True), sa.Column('created_at', sa.DateTime, server_default=sa.func.now(), nullable=False), ) def downgrade() -> None: op.drop_table('pjctrl_audit_alerts') op.drop_index('idx_audit_time', table_name='pjctrl_audit_logs') op.drop_index('idx_audit_resource', table_name='pjctrl_audit_logs') op.drop_index('idx_audit_user', table_name='pjctrl_audit_logs') op.drop_table('pjctrl_audit_logs') op.execute("DROP TYPE IF EXISTS audit_action_enum") op.execute("DROP TYPE IF EXISTS sensitivity_level_enum")