288 lines
6.9 KiB
Markdown
288 lines
6.9 KiB
Markdown
# 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.
|
|
|
|
```bash
|
|
# 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.
|
|
|
|
```bash
|
|
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.
|
|
|
|
```bash
|
|
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.
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```sql
|
|
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:
|
|
```sql
|
|
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.
|