Files
membership-be/DEPLOYMENT_GUIDE.md
2025-12-16 20:03:50 +07:00

6.9 KiB

Deployment Guide - Dynamic RBAC System

This guide covers deploying the dynamic Role-Based Access Control (RBAC) system to your dev server.

Overview

The RBAC migration consists of 4 phases:

  • Phase 1: Add new database tables and columns (schema changes)
  • Phase 2: Seed system roles
  • Phase 3: Migrate existing data
  • Phase 4: System is fully operational with dynamic roles

Prerequisites

  • Database backup completed ✓
  • PostgreSQL access credentials
  • Python 3.8+ environment
  • All dependencies installed (pip install -r requirements.txt)

Step-by-Step Deployment

Step 1: Run Schema Migration (Phase 1)

This creates the new roles table and adds role_id columns to users and role_permissions tables.

# Connect to your database
psql -U <username> -d <database_name> -f migrations/006_add_dynamic_roles.sql

What this does:

  • Creates roles table
  • Adds role_id column to users (nullable)
  • Adds role_id column to role_permissions (nullable)
  • Legacy role enum columns remain for backward compatibility

Expected output:

Step 1 completed: roles table created
Step 2 completed: role_id column added to users table
Step 3 completed: role_id column added to role_permissions table
Migration 006 completed successfully!

Step 2: Seed System Roles (Phase 2)

This creates the 5 system roles: Superadmin, Admin, Finance, Member, Guest.

cd backend
python3 roles_seed.py

Expected output:

Starting roles seeding...
Created role: Superadmin (superadmin) - System role
Created role: Admin (admin) - System role
Created role: Finance (finance) - System role
Created role: Member (member) - System role
Created role: Guest (guest) - System role

Roles seeding completed!
Total roles created: 5

Step 3: Migrate Existing Users (Phase 3a)

This migrates all existing users from enum roles to the new dynamic role system.

python3 migrate_users_to_dynamic_roles.py

Expected output:

Starting user migration to dynamic roles...
Processing user: admin@loaf.org (superadmin)
  ✓ Mapped to role: Superadmin
Processing user: finance@loaf.org (finance)
  ✓ Mapped to role: Finance
...
User migration completed successfully!
Total users migrated: X

Step 4: Migrate Role Permissions (Phase 3b)

This migrates all existing role-permission mappings to use role_id.

python3 migrate_role_permissions_to_dynamic_roles.py

Expected output:

Starting role permissions migration to dynamic roles...
Migrating permissions for role: guest
  ✓ Migrated: events.view (X permissions)
Migrating permissions for role: member
  ✓ Migrated: events.create (X permissions)
...
Role permissions migration completed successfully!
Total role_permission records migrated: X

Step 5: Verify Migration

Run this verification script to ensure everything migrated correctly:

python3 verify_admin_account.py

Expected output:

================================================================================
VERIFYING admin@loaf.org ACCOUNT
================================================================================

✅ User found: Admin User
   Email: admin@loaf.org
   Status: UserStatus.active
   Email Verified: True

📋 Legacy Role (enum): superadmin
✅ Dynamic Role: Superadmin (code: superadmin)
   Role ID: <uuid>
   Is System Role: True

🔐 Checking Permissions:
   Total permissions assigned to role: 56

🎯 Access Check:
   ✅ User should have admin access (based on legacy enum)
   ✅ User should have admin access (based on dynamic role)

================================================================================
VERIFICATION COMPLETE
================================================================================

Step 6: Deploy Backend Code

# Pull latest code
git pull origin main

# Restart backend server
# (adjust based on your deployment method)
systemctl restart membership-backend
# OR
pm2 restart membership-backend
# OR
supervisorctl restart membership-backend

Step 7: Verify API Endpoints

Test the role management endpoints:

# Get all roles
curl -H "Authorization: Bearer <token>" \
  http://your-server/api/admin/roles

# Get all permissions
curl -H "Authorization: Bearer <token>" \
  http://your-server/api/admin/permissions

# Test export (the issue we just fixed)
curl -H "Authorization: Bearer <token>" \
  http://your-server/api/admin/users/export

Rollback Plan (If Needed)

If something goes wrong, you can rollback:

BEGIN;

-- Remove new columns
ALTER TABLE users DROP COLUMN IF EXISTS role_id;
ALTER TABLE role_permissions DROP COLUMN IF EXISTS role_id;

-- Drop roles table
DROP TABLE IF EXISTS roles CASCADE;

COMMIT;

Then restore from your backup if needed.


Post-Deployment Checklist

  • Schema migration completed without errors
  • System roles seeded (5 roles created)
  • All users migrated to dynamic roles
  • All role permissions migrated
  • Admin account verified
  • Backend server restarted
  • Export endpoint working (no 500 error)
  • Admin can view roles in UI (/admin/permissions)
  • Admin can create/edit roles
  • Admin can assign permissions to roles
  • Staff invitation uses dynamic roles

Troubleshooting

Issue: Migration script fails

Solution: Check your .env file has correct DATABASE_URL:

DATABASE_URL=postgresql://user:password@host:port/database

Issue: "role_id column already exists"

Solution: This is safe to ignore. The migration uses IF NOT EXISTS clauses.

Issue: "No roles found" when migrating users

Solution: Make sure you ran Step 2 (roles_seed.py) before Step 3.

Issue: Export still returns 500 error

Solution:

  1. Verify backend code is latest version
  2. Check server.py has export route BEFORE {user_id} route (around line 1965)
  3. Restart backend server

Issue: Permission denied errors

Solution: Make sure your database user has permissions:

GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO <username>;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO <username>;

Files Involved

Migration Files

  • migrations/006_add_dynamic_roles.sql - Schema changes
  • roles_seed.py - Seed system roles
  • migrate_users_to_dynamic_roles.py - Migrate user data
  • migrate_role_permissions_to_dynamic_roles.py - Migrate permission data
  • verify_admin_account.py - Verification script

Code Changes

  • server.py - Route reordering (export before {user_id})
  • auth.py - get_user_role_code() helper
  • models.py - Role model, role_id columns
  • Frontend: AdminRoles.js, InviteStaffDialog.js, AdminStaff.js, Navbar.js, Login.js

Support

If you encounter issues during deployment, check:

  1. Backend logs: tail -f /path/to/backend.log
  2. Database logs: Check PostgreSQL error logs
  3. Frontend console: Browser developer tools

For questions, refer to the CLAUDE.md file for system architecture details.