"""add_comprehensive_gdpr_tables Revision ID: 7a899ef55e3b Revises: dbafe747c931 Create Date: 2025-12-01 04:10:25.699589 """ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import mysql # revision identifiers, used by Alembic. revision = '7a899ef55e3b' down_revision = 'dbafe747c931' branch_labels = None depends_on = None def upgrade() -> None: # Consent table op.create_table( 'consents', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('user_id', sa.Integer(), nullable=False), sa.Column('consent_type', sa.Enum('marketing', 'analytics', 'necessary', 'preferences', 'third_party_sharing', 'profiling', 'automated_decision_making', name='consenttype'), nullable=False), sa.Column('status', sa.Enum('granted', 'withdrawn', 'pending', 'expired', name='consentstatus'), nullable=False), sa.Column('granted_at', sa.DateTime(), nullable=True), sa.Column('withdrawn_at', sa.DateTime(), nullable=True), sa.Column('expires_at', sa.DateTime(), nullable=True), sa.Column('legal_basis', sa.String(length=100), nullable=True), sa.Column('consent_method', sa.String(length=50), nullable=True), sa.Column('consent_version', sa.String(length=20), nullable=True), sa.Column('ip_address', sa.String(length=45), nullable=True), sa.Column('user_agent', sa.String(length=255), nullable=True), sa.Column('source', sa.String(length=100), nullable=True), sa.Column('extra_metadata', sa.JSON(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=False), sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_consents_id'), 'consents', ['id'], unique=False) op.create_index(op.f('ix_consents_user_id'), 'consents', ['user_id'], unique=False) op.create_index(op.f('ix_consents_consent_type'), 'consents', ['consent_type'], unique=False) op.create_index(op.f('ix_consents_status'), 'consents', ['status'], unique=False) op.create_index(op.f('ix_consents_created_at'), 'consents', ['created_at'], unique=False) # Data processing records table op.create_table( 'data_processing_records', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('processing_category', sa.Enum('collection', 'storage', 'usage', 'sharing', 'deletion', 'anonymization', 'transfer', name='processingcategory'), nullable=False), sa.Column('legal_basis', sa.Enum('consent', 'contract', 'legal_obligation', 'vital_interests', 'public_task', 'legitimate_interests', name='legalbasis'), nullable=False), sa.Column('purpose', sa.Text(), nullable=False), sa.Column('data_categories', sa.JSON(), nullable=True), sa.Column('data_subjects', sa.JSON(), nullable=True), sa.Column('recipients', sa.JSON(), nullable=True), sa.Column('third_parties', sa.JSON(), nullable=True), sa.Column('transfers_to_third_countries', sa.Boolean(), nullable=False), sa.Column('transfer_countries', sa.JSON(), nullable=True), sa.Column('safeguards', sa.Text(), nullable=True), sa.Column('retention_period', sa.String(length=100), nullable=True), sa.Column('retention_criteria', sa.Text(), nullable=True), sa.Column('security_measures', sa.Text(), nullable=True), sa.Column('user_id', sa.Integer(), nullable=True), sa.Column('related_booking_id', sa.Integer(), nullable=True), sa.Column('related_payment_id', sa.Integer(), nullable=True), sa.Column('processed_by', sa.Integer(), nullable=True), sa.Column('processing_timestamp', sa.DateTime(), nullable=False), sa.Column('extra_metadata', sa.JSON(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=False), sa.ForeignKeyConstraint(['processed_by'], ['users.id'], ), sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_data_processing_records_id'), 'data_processing_records', ['id'], unique=False) op.create_index(op.f('ix_data_processing_records_processing_category'), 'data_processing_records', ['processing_category'], unique=False) op.create_index(op.f('ix_data_processing_records_legal_basis'), 'data_processing_records', ['legal_basis'], unique=False) op.create_index(op.f('ix_data_processing_records_user_id'), 'data_processing_records', ['user_id'], unique=False) op.create_index(op.f('ix_data_processing_records_processing_timestamp'), 'data_processing_records', ['processing_timestamp'], unique=False) op.create_index(op.f('ix_data_processing_records_created_at'), 'data_processing_records', ['created_at'], unique=False) # Data breaches table op.create_table( 'data_breaches', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('breach_type', sa.Enum('confidentiality', 'integrity', 'availability', name='breachtype'), nullable=False), sa.Column('status', sa.Enum('detected', 'investigating', 'contained', 'reported_to_authority', 'notified_data_subjects', 'resolved', name='breachstatus'), nullable=False), sa.Column('description', sa.Text(), nullable=False), sa.Column('affected_data_categories', sa.JSON(), nullable=True), sa.Column('affected_data_subjects', sa.JSON(), nullable=True), sa.Column('detected_at', sa.DateTime(), nullable=False), sa.Column('occurred_at', sa.DateTime(), nullable=True), sa.Column('contained_at', sa.DateTime(), nullable=True), sa.Column('reported_to_authority_at', sa.DateTime(), nullable=True), sa.Column('authority_reference', sa.String(length=255), nullable=True), sa.Column('notified_data_subjects_at', sa.DateTime(), nullable=True), sa.Column('notification_method', sa.String(length=100), nullable=True), sa.Column('likely_consequences', sa.Text(), nullable=True), sa.Column('measures_proposed', sa.Text(), nullable=True), sa.Column('risk_level', sa.String(length=20), nullable=True), sa.Column('reported_by', sa.Integer(), nullable=False), sa.Column('investigated_by', sa.Integer(), nullable=True), sa.Column('extra_metadata', sa.JSON(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=False), sa.ForeignKeyConstraint(['investigated_by'], ['users.id'], ), sa.ForeignKeyConstraint(['reported_by'], ['users.id'], ), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_data_breaches_id'), 'data_breaches', ['id'], unique=False) op.create_index(op.f('ix_data_breaches_breach_type'), 'data_breaches', ['breach_type'], unique=False) op.create_index(op.f('ix_data_breaches_status'), 'data_breaches', ['status'], unique=False) op.create_index(op.f('ix_data_breaches_detected_at'), 'data_breaches', ['detected_at'], unique=False) # Retention rules table op.create_table( 'retention_rules', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('data_category', sa.String(length=100), nullable=False), sa.Column('retention_period_days', sa.Integer(), nullable=False), sa.Column('retention_period_months', sa.Integer(), nullable=True), sa.Column('retention_period_years', sa.Integer(), nullable=True), sa.Column('legal_basis', sa.Text(), nullable=True), sa.Column('legal_requirement', sa.Text(), nullable=True), sa.Column('action_after_retention', sa.String(length=50), nullable=False), sa.Column('conditions', sa.JSON(), nullable=True), sa.Column('is_active', sa.Boolean(), nullable=False), sa.Column('description', sa.Text(), nullable=True), sa.Column('created_by', sa.Integer(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=False), sa.ForeignKeyConstraint(['created_by'], ['users.id'], ), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('data_category') ) op.create_index(op.f('ix_retention_rules_id'), 'retention_rules', ['id'], unique=False) op.create_index(op.f('ix_retention_rules_data_category'), 'retention_rules', ['data_category'], unique=True) op.create_index(op.f('ix_retention_rules_is_active'), 'retention_rules', ['is_active'], unique=False) # Data retention logs table op.create_table( 'data_retention_logs', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('retention_rule_id', sa.Integer(), nullable=False), sa.Column('data_category', sa.String(length=100), nullable=False), sa.Column('action_taken', sa.String(length=50), nullable=False), sa.Column('records_affected', sa.Integer(), nullable=False), sa.Column('affected_ids', sa.JSON(), nullable=True), sa.Column('executed_by', sa.Integer(), nullable=True), sa.Column('executed_at', sa.DateTime(), nullable=False), sa.Column('success', sa.Boolean(), nullable=False), sa.Column('error_message', sa.Text(), nullable=True), sa.Column('extra_metadata', sa.JSON(), nullable=True), sa.ForeignKeyConstraint(['executed_by'], ['users.id'], ), sa.ForeignKeyConstraint(['retention_rule_id'], ['retention_rules.id'], ), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_data_retention_logs_id'), 'data_retention_logs', ['id'], unique=False) op.create_index(op.f('ix_data_retention_logs_retention_rule_id'), 'data_retention_logs', ['retention_rule_id'], unique=False) op.create_index(op.f('ix_data_retention_logs_data_category'), 'data_retention_logs', ['data_category'], unique=False) op.create_index(op.f('ix_data_retention_logs_executed_at'), 'data_retention_logs', ['executed_at'], unique=False) def downgrade() -> None: # Drop foreign keys first, then indexes, then tables op.drop_table('data_retention_logs') op.drop_table('retention_rules') op.drop_table('data_breaches') op.drop_table('data_processing_records') op.drop_table('consents')