updates
This commit is contained in:
BIN
Backend/alembic/__pycache__/env.cpython-312.pyc
Normal file
BIN
Backend/alembic/__pycache__/env.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
218
Backend/alembic/versions/add_enterprise_features.py
Normal file
218
Backend/alembic/versions/add_enterprise_features.py
Normal file
@@ -0,0 +1,218 @@
|
||||
"""
|
||||
Add enterprise features: approval workflows, GDPR requests, sessions, webhooks, API keys.
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
revision = 'add_enterprise_features'
|
||||
down_revision = 'add_sections_blog' # Depends on latest migration
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
def upgrade() -> None:
|
||||
# Approval workflow table
|
||||
op.create_table(
|
||||
'approval_requests',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('approval_type', sa.Enum('invoice_update', 'payment_refund', 'invoice_mark_paid', 'financial_adjustment', 'user_role_change', 'large_transaction', name='approvaltype'), nullable=False),
|
||||
sa.Column('status', sa.Enum('pending', 'approved', 'rejected', 'cancelled', name='approvalstatus'), nullable=False),
|
||||
sa.Column('requested_by', sa.Integer(), nullable=False),
|
||||
sa.Column('requested_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('approved_by', sa.Integer(), nullable=True),
|
||||
sa.Column('approved_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('rejection_reason', sa.Text(), nullable=True),
|
||||
sa.Column('resource_type', sa.String(length=50), nullable=False),
|
||||
sa.Column('resource_id', sa.Integer(), nullable=False),
|
||||
sa.Column('request_data', sa.JSON(), nullable=True),
|
||||
sa.Column('current_data', sa.JSON(), nullable=True),
|
||||
sa.Column('priority', sa.String(length=20), nullable=True),
|
||||
sa.Column('notes', sa.Text(), 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(['approved_by'], ['users.id'], ),
|
||||
sa.ForeignKeyConstraint(['requested_by'], ['users.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index(op.f('ix_approval_requests_id'), 'approval_requests', ['id'], unique=False)
|
||||
op.create_index(op.f('ix_approval_requests_approval_type'), 'approval_requests', ['approval_type'], unique=False)
|
||||
op.create_index(op.f('ix_approval_requests_status'), 'approval_requests', ['status'], unique=False)
|
||||
op.create_index(op.f('ix_approval_requests_requested_by'), 'approval_requests', ['requested_by'], unique=False)
|
||||
op.create_index(op.f('ix_approval_requests_approved_by'), 'approval_requests', ['approved_by'], unique=False)
|
||||
op.create_index(op.f('ix_approval_requests_resource_type'), 'approval_requests', ['resource_type'], unique=False)
|
||||
op.create_index(op.f('ix_approval_requests_resource_id'), 'approval_requests', ['resource_id'], unique=False)
|
||||
|
||||
# GDPR requests table
|
||||
op.create_table(
|
||||
'gdpr_requests',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('request_type', sa.Enum('data_export', 'data_deletion', 'data_rectification', 'consent_withdrawal', name='gdprrequesttype'), nullable=False),
|
||||
sa.Column('status', sa.Enum('pending', 'processing', 'completed', 'rejected', 'cancelled', name='gdprrequeststatus'), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_email', sa.String(length=255), nullable=False),
|
||||
sa.Column('request_data', sa.JSON(), nullable=True),
|
||||
sa.Column('verification_token', sa.String(length=255), nullable=True),
|
||||
sa.Column('verified_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('processed_by', sa.Integer(), nullable=True),
|
||||
sa.Column('processed_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('processing_notes', sa.Text(), nullable=True),
|
||||
sa.Column('export_file_path', sa.String(length=500), nullable=True),
|
||||
sa.Column('deletion_log', sa.JSON(), nullable=True),
|
||||
sa.Column('ip_address', sa.String(length=45), nullable=True),
|
||||
sa.Column('user_agent', sa.String(length=255), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('expires_at', sa.DateTime(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['processed_by'], ['users.id'], ),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index(op.f('ix_gdpr_requests_id'), 'gdpr_requests', ['id'], unique=False)
|
||||
op.create_index(op.f('ix_gdpr_requests_request_type'), 'gdpr_requests', ['request_type'], unique=False)
|
||||
op.create_index(op.f('ix_gdpr_requests_status'), 'gdpr_requests', ['status'], unique=False)
|
||||
op.create_index(op.f('ix_gdpr_requests_user_id'), 'gdpr_requests', ['user_id'], unique=False)
|
||||
op.create_index(op.f('ix_gdpr_requests_verification_token'), 'gdpr_requests', ['verification_token'], unique=True)
|
||||
|
||||
# User sessions table
|
||||
op.create_table(
|
||||
'user_sessions',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=False),
|
||||
sa.Column('session_token', sa.String(length=255), nullable=False),
|
||||
sa.Column('refresh_token', sa.String(length=255), nullable=True),
|
||||
sa.Column('ip_address', sa.String(length=45), nullable=True),
|
||||
sa.Column('user_agent', sa.String(length=500), nullable=True),
|
||||
sa.Column('device_info', sa.Text(), nullable=True),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('last_activity', sa.DateTime(), nullable=False),
|
||||
sa.Column('expires_at', sa.DateTime(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index(op.f('ix_user_sessions_id'), 'user_sessions', ['id'], unique=False)
|
||||
op.create_index(op.f('ix_user_sessions_user_id'), 'user_sessions', ['user_id'], unique=False)
|
||||
op.create_index(op.f('ix_user_sessions_session_token'), 'user_sessions', ['session_token'], unique=True)
|
||||
op.create_index(op.f('ix_user_sessions_refresh_token'), 'user_sessions', ['refresh_token'], unique=True)
|
||||
op.create_index(op.f('ix_user_sessions_is_active'), 'user_sessions', ['is_active'], unique=False)
|
||||
op.create_index(op.f('ix_user_sessions_last_activity'), 'user_sessions', ['last_activity'], unique=False)
|
||||
op.create_index(op.f('ix_user_sessions_expires_at'), 'user_sessions', ['expires_at'], unique=False)
|
||||
|
||||
# Webhooks table
|
||||
op.create_table(
|
||||
'webhooks',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('url', sa.String(length=500), nullable=False),
|
||||
sa.Column('secret', sa.String(length=255), nullable=False),
|
||||
sa.Column('events', sa.JSON(), nullable=False),
|
||||
sa.Column('status', sa.Enum('active', 'inactive', 'paused', name='webhookstatus'), nullable=False),
|
||||
sa.Column('retry_count', sa.Integer(), nullable=False),
|
||||
sa.Column('timeout_seconds', sa.Integer(), 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')
|
||||
)
|
||||
op.create_index(op.f('ix_webhooks_id'), 'webhooks', ['id'], unique=False)
|
||||
op.create_index(op.f('ix_webhooks_status'), 'webhooks', ['status'], unique=False)
|
||||
|
||||
# Webhook deliveries table
|
||||
op.create_table(
|
||||
'webhook_deliveries',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('webhook_id', sa.Integer(), nullable=False),
|
||||
sa.Column('event_type', sa.String(length=100), nullable=False),
|
||||
sa.Column('event_id', sa.String(length=255), nullable=False),
|
||||
sa.Column('status', sa.Enum('pending', 'success', 'failed', 'retrying', name='webhookdeliverystatus'), nullable=False),
|
||||
sa.Column('payload', sa.JSON(), nullable=False),
|
||||
sa.Column('response_status', sa.Integer(), nullable=True),
|
||||
sa.Column('response_body', sa.Text(), nullable=True),
|
||||
sa.Column('error_message', sa.Text(), nullable=True),
|
||||
sa.Column('attempt_count', sa.Integer(), nullable=False),
|
||||
sa.Column('next_retry_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('delivered_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['webhook_id'], ['webhooks.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index(op.f('ix_webhook_deliveries_id'), 'webhook_deliveries', ['id'], unique=False)
|
||||
op.create_index(op.f('ix_webhook_deliveries_webhook_id'), 'webhook_deliveries', ['webhook_id'], unique=False)
|
||||
op.create_index(op.f('ix_webhook_deliveries_event_type'), 'webhook_deliveries', ['event_type'], unique=False)
|
||||
op.create_index(op.f('ix_webhook_deliveries_event_id'), 'webhook_deliveries', ['event_id'], unique=False)
|
||||
op.create_index(op.f('ix_webhook_deliveries_status'), 'webhook_deliveries', ['status'], unique=False)
|
||||
op.create_index(op.f('ix_webhook_deliveries_created_at'), 'webhook_deliveries', ['created_at'], unique=False)
|
||||
|
||||
# API keys table
|
||||
op.create_table(
|
||||
'api_keys',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('key_hash', sa.String(length=255), nullable=False),
|
||||
sa.Column('key_prefix', sa.String(length=20), nullable=False),
|
||||
sa.Column('scopes', sa.JSON(), nullable=False),
|
||||
sa.Column('rate_limit', sa.Integer(), nullable=False),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('expires_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.Column('last_used_at', sa.DateTime(), 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')
|
||||
)
|
||||
op.create_index(op.f('ix_api_keys_id'), 'api_keys', ['id'], unique=False)
|
||||
op.create_index(op.f('ix_api_keys_key_hash'), 'api_keys', ['key_hash'], unique=True)
|
||||
op.create_index(op.f('ix_api_keys_key_prefix'), 'api_keys', ['key_prefix'], unique=False)
|
||||
op.create_index(op.f('ix_api_keys_is_active'), 'api_keys', ['is_active'], unique=False)
|
||||
op.create_index(op.f('ix_api_keys_expires_at'), 'api_keys', ['expires_at'], unique=False)
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index(op.f('ix_api_keys_expires_at'), table_name='api_keys')
|
||||
op.drop_index(op.f('ix_api_keys_is_active'), table_name='api_keys')
|
||||
op.drop_index(op.f('ix_api_keys_key_prefix'), table_name='api_keys')
|
||||
op.drop_index(op.f('ix_api_keys_key_hash'), table_name='api_keys')
|
||||
op.drop_index(op.f('ix_api_keys_id'), table_name='api_keys')
|
||||
op.drop_table('api_keys')
|
||||
|
||||
op.drop_index(op.f('ix_webhook_deliveries_created_at'), table_name='webhook_deliveries')
|
||||
op.drop_index(op.f('ix_webhook_deliveries_status'), table_name='webhook_deliveries')
|
||||
op.drop_index(op.f('ix_webhook_deliveries_event_id'), table_name='webhook_deliveries')
|
||||
op.drop_index(op.f('ix_webhook_deliveries_event_type'), table_name='webhook_deliveries')
|
||||
op.drop_index(op.f('ix_webhook_deliveries_webhook_id'), table_name='webhook_deliveries')
|
||||
op.drop_index(op.f('ix_webhook_deliveries_id'), table_name='webhook_deliveries')
|
||||
op.drop_table('webhook_deliveries')
|
||||
|
||||
op.drop_index(op.f('ix_webhooks_status'), table_name='webhooks')
|
||||
op.drop_index(op.f('ix_webhooks_id'), table_name='webhooks')
|
||||
op.drop_table('webhooks')
|
||||
|
||||
op.drop_index(op.f('ix_user_sessions_expires_at'), table_name='user_sessions')
|
||||
op.drop_index(op.f('ix_user_sessions_last_activity'), table_name='user_sessions')
|
||||
op.drop_index(op.f('ix_user_sessions_is_active'), table_name='user_sessions')
|
||||
op.drop_index(op.f('ix_user_sessions_refresh_token'), table_name='user_sessions')
|
||||
op.drop_index(op.f('ix_user_sessions_session_token'), table_name='user_sessions')
|
||||
op.drop_index(op.f('ix_user_sessions_user_id'), table_name='user_sessions')
|
||||
op.drop_index(op.f('ix_user_sessions_id'), table_name='user_sessions')
|
||||
op.drop_table('user_sessions')
|
||||
|
||||
op.drop_index(op.f('ix_gdpr_requests_verification_token'), table_name='gdpr_requests')
|
||||
op.drop_index(op.f('ix_gdpr_requests_user_id'), table_name='gdpr_requests')
|
||||
op.drop_index(op.f('ix_gdpr_requests_status'), table_name='gdpr_requests')
|
||||
op.drop_index(op.f('ix_gdpr_requests_request_type'), table_name='gdpr_requests')
|
||||
op.drop_index(op.f('ix_gdpr_requests_id'), table_name='gdpr_requests')
|
||||
op.drop_table('gdpr_requests')
|
||||
|
||||
op.drop_index(op.f('ix_approval_requests_resource_id'), table_name='approval_requests')
|
||||
op.drop_index(op.f('ix_approval_requests_resource_type'), table_name='approval_requests')
|
||||
op.drop_index(op.f('ix_approval_requests_approved_by'), table_name='approval_requests')
|
||||
op.drop_index(op.f('ix_approval_requests_requested_by'), table_name='approval_requests')
|
||||
op.drop_index(op.f('ix_approval_requests_status'), table_name='approval_requests')
|
||||
op.drop_index(op.f('ix_approval_requests_approval_type'), table_name='approval_requests')
|
||||
op.drop_index(op.f('ix_approval_requests_id'), table_name='approval_requests')
|
||||
op.drop_table('approval_requests')
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
"""merge_enterprise_and_borica
|
||||
|
||||
Revision ID: dbafe747c931
|
||||
Revises: add_enterprise_features, add_borica_payment_method
|
||||
Create Date: 2025-12-01 00:42:31.999574
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'dbafe747c931'
|
||||
down_revision = ('add_enterprise_features', 'add_borica_payment_method')
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
pass
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user