From cd8b4dcaa696b099effaa8763154bf62b4086be4 Mon Sep 17 00:00:00 2001 From: Koncept Kit <63216427+konceptkit@users.noreply.github.com> Date: Sun, 4 Jan 2026 22:16:35 +0700 Subject: [PATCH] Fix database mismatches --- .../versions/004_add_document_file_sizes.py | 42 +++++ migrations/004_fix_all_permissions.sql | 172 ++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 alembic/versions/004_add_document_file_sizes.py create mode 100644 migrations/004_fix_all_permissions.sql diff --git a/alembic/versions/004_add_document_file_sizes.py b/alembic/versions/004_add_document_file_sizes.py new file mode 100644 index 0000000..ce5f27f --- /dev/null +++ b/alembic/versions/004_add_document_file_sizes.py @@ -0,0 +1,42 @@ +"""add_document_file_sizes + +Revision ID: 004_add_document_file_sizes +Revises: 003_add_user_invitation_fields +Create Date: 2026-01-04 + +Adds file_size_bytes to all document tables: +- newsletter_archives +- financial_reports +- bylaws_documents +""" +from typing import Sequence, Union +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '004_add_document_file_sizes' +down_revision: Union[str, None] = '003_add_user_invitation_fields' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Add file_size_bytes column to document tables""" + + # Add to newsletter_archives + op.add_column('newsletter_archives', sa.Column('file_size_bytes', sa.Integer(), nullable=True)) + + # Add to financial_reports + op.add_column('financial_reports', sa.Column('file_size_bytes', sa.Integer(), nullable=True)) + + # Add to bylaws_documents + op.add_column('bylaws_documents', sa.Column('file_size_bytes', sa.Integer(), nullable=True)) + + +def downgrade() -> None: + """Remove file_size_bytes columns (rollback)""" + + op.drop_column('bylaws_documents', 'file_size_bytes') + op.drop_column('financial_reports', 'file_size_bytes') + op.drop_column('newsletter_archives', 'file_size_bytes') diff --git a/migrations/004_fix_all_permissions.sql b/migrations/004_fix_all_permissions.sql new file mode 100644 index 0000000..4124ff6 --- /dev/null +++ b/migrations/004_fix_all_permissions.sql @@ -0,0 +1,172 @@ +-- ============================================================================ +-- Fix All Permission Codes to Match Backend Code +-- This migration adds all missing permissions that the code actually checks for +-- ============================================================================ + +BEGIN; + +-- ============================================================================ +-- Delete old incorrect permissions and role mappings +-- ============================================================================ + +DELETE FROM role_permissions; +DELETE FROM permissions; + +-- ============================================================================ +-- Create ALL permissions that backend code actually checks for +-- ============================================================================ + +INSERT INTO permissions (id, code, name, description, module, created_at) +VALUES + -- Users Permissions + (gen_random_uuid(), 'users.view', 'View Users', 'View user list and profiles', 'users', NOW()), + (gen_random_uuid(), 'users.create', 'Create Users', 'Create new users', 'users', NOW()), + (gen_random_uuid(), 'users.edit', 'Edit Users', 'Edit user information', 'users', NOW()), + (gen_random_uuid(), 'users.approve', 'Approve Users', 'Approve pending memberships', 'users', NOW()), + (gen_random_uuid(), 'users.import', 'Import Users', 'Import users from CSV', 'users', NOW()), + (gen_random_uuid(), 'users.export', 'Export Users', 'Export users to CSV', 'users', NOW()), + (gen_random_uuid(), 'users.status', 'Change User Status', 'Update user status', 'users', NOW()), + (gen_random_uuid(), 'users.reset_password', 'Reset User Password', 'Reset user passwords', 'users', NOW()), + (gen_random_uuid(), 'users.resend_verification', 'Resend Verification', 'Resend email verification', 'users', NOW()), + + -- Events Permissions + (gen_random_uuid(), 'events.view', 'View Events', 'View event list', 'events', NOW()), + (gen_random_uuid(), 'events.create', 'Create Events', 'Create new events', 'events', NOW()), + (gen_random_uuid(), 'events.edit', 'Edit Events', 'Edit event information', 'events', NOW()), + (gen_random_uuid(), 'events.delete', 'Delete Events', 'Delete events', 'events', NOW()), + (gen_random_uuid(), 'events.rsvps', 'View RSVPs', 'View event RSVPs', 'events', NOW()), + (gen_random_uuid(), 'events.attendance', 'Manage Attendance', 'Mark attendance', 'events', NOW()), + + -- Gallery Permissions + (gen_random_uuid(), 'gallery.upload', 'Upload Photos', 'Upload event photos', 'gallery', NOW()), + (gen_random_uuid(), 'gallery.edit', 'Edit Gallery', 'Edit photo captions', 'gallery', NOW()), + (gen_random_uuid(), 'gallery.delete', 'Delete Photos', 'Delete event photos', 'gallery', NOW()), + + -- Subscriptions Permissions + (gen_random_uuid(), 'subscriptions.view', 'View Subscriptions', 'View user subscriptions', 'subscriptions', NOW()), + (gen_random_uuid(), 'subscriptions.plans', 'Manage Plans', 'Manage subscription plans', 'subscriptions', NOW()), + (gen_random_uuid(), 'subscriptions.edit', 'Edit Subscriptions', 'Edit user subscriptions', 'subscriptions', NOW()), + (gen_random_uuid(), 'subscriptions.cancel', 'Cancel Subscriptions', 'Cancel subscriptions', 'subscriptions', NOW()), + (gen_random_uuid(), 'subscriptions.activate', 'Activate Subscriptions', 'Manually activate subscriptions', 'subscriptions', NOW()), + (gen_random_uuid(), 'subscriptions.export', 'Export Subscriptions', 'Export subscription data', 'subscriptions', NOW()), + + -- Donations Permissions + (gen_random_uuid(), 'donations.view', 'View Donations', 'View donation records', 'donations', NOW()), + (gen_random_uuid(), 'donations.export', 'Export Donations', 'Export donation data', 'donations', NOW()), + + -- Financials Permissions (Financial Reports) + (gen_random_uuid(), 'financials.create', 'Create Financial Reports', 'Upload financial reports', 'financials', NOW()), + (gen_random_uuid(), 'financials.edit', 'Edit Financial Reports', 'Edit financial reports', 'financials', NOW()), + (gen_random_uuid(), 'financials.delete', 'Delete Financial Reports', 'Delete financial reports', 'financials', NOW()), + + -- Newsletters Permissions + (gen_random_uuid(), 'newsletters.create', 'Create Newsletters', 'Upload newsletter archives', 'newsletters', NOW()), + (gen_random_uuid(), 'newsletters.edit', 'Edit Newsletters', 'Edit newsletter archives', 'newsletters', NOW()), + (gen_random_uuid(), 'newsletters.delete', 'Delete Newsletters', 'Delete newsletter archives', 'newsletters', NOW()), + + -- Bylaws Permissions + (gen_random_uuid(), 'bylaws.create', 'Create Bylaws', 'Upload bylaws documents', 'bylaws', NOW()), + (gen_random_uuid(), 'bylaws.edit', 'Edit Bylaws', 'Edit bylaws documents', 'bylaws', NOW()), + (gen_random_uuid(), 'bylaws.delete', 'Delete Bylaws', 'Delete bylaws documents', 'bylaws', NOW()), + + -- Settings Permissions + (gen_random_uuid(), 'settings.storage', 'View Storage Usage', 'View storage usage statistics', 'settings', NOW()) +ON CONFLICT (code) DO NOTHING; + +-- ============================================================================ +-- Assign Permissions to Roles +-- ============================================================================ + +-- Guest Role: No permissions +-- (Members can only view their own data through different endpoints) + +-- Member Role: Basic viewing only +INSERT INTO role_permissions (id, role, role_id, permission_id, created_at) +SELECT + gen_random_uuid(), + 'member', + (SELECT id FROM roles WHERE code = 'member'), + p.id, + NOW() +FROM permissions p +WHERE p.code IN ( + 'events.view' +) +ON CONFLICT DO NOTHING; + +-- Admin Role: Full management except financial +INSERT INTO role_permissions (id, role, role_id, permission_id, created_at) +SELECT + gen_random_uuid(), + 'admin', + (SELECT id FROM roles WHERE code = 'admin'), + p.id, + NOW() +FROM permissions p +WHERE p.code IN ( + -- User Management + 'users.view', 'users.create', 'users.edit', 'users.approve', 'users.import', + 'users.export', 'users.status', 'users.reset_password', 'users.resend_verification', + + -- Event Management + 'events.view', 'events.create', 'events.edit', 'events.delete', 'events.rsvps', 'events.attendance', + + -- Gallery + 'gallery.upload', 'gallery.edit', 'gallery.delete', + + -- Content + 'newsletters.create', 'newsletters.edit', 'newsletters.delete', + 'bylaws.create', 'bylaws.edit', 'bylaws.delete', + + -- Settings + 'settings.storage' +) +ON CONFLICT DO NOTHING; + +-- Finance Role: Financial permissions + basic viewing +INSERT INTO role_permissions (id, role, role_id, permission_id, created_at) +SELECT + gen_random_uuid(), + 'finance', + (SELECT id FROM roles WHERE code = 'finance'), + p.id, + NOW() +FROM permissions p +WHERE p.code IN ( + -- Subscriptions & Donations + 'subscriptions.view', 'subscriptions.plans', 'subscriptions.edit', + 'subscriptions.cancel', 'subscriptions.activate', 'subscriptions.export', + 'donations.view', 'donations.export', + + -- Financial Reports + 'financials.create', 'financials.edit', 'financials.delete', + + -- Basic Access + 'users.view', + 'events.view' +) +ON CONFLICT DO NOTHING; + +-- Superadmin Role: ALL permissions +INSERT INTO role_permissions (id, role, role_id, permission_id, created_at) +SELECT + gen_random_uuid(), + 'superadmin', + (SELECT id FROM roles WHERE code = 'superadmin'), + p.id, + NOW() +FROM permissions p +ON CONFLICT DO NOTHING; + +COMMIT; + +\echo '✅ All permissions fixed!' +\echo '' +\echo 'Permission counts by role:' +\echo ' - Guest: 0' +\echo ' - Member: 1' +\echo ' - Admin: ~25' +\echo ' - Finance: ~13' +\echo ' - Superadmin: ALL (40 total)' +\echo '' +\echo 'Next: Restart backend with: pm2 restart membership-backend' -- 2.39.5