""" Permission Seeding Script This script populates the database with 60+ granular permissions for RBAC. Permissions are organized into 9 modules: users, events, subscriptions, financials, newsletters, bylaws, gallery, settings, and permissions. Usage: python permissions_seed.py Environment Variables: DATABASE_URL - PostgreSQL connection string """ import os import sys from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from database import Base from models import Permission, RolePermission, UserRole from dotenv import load_dotenv # Load environment variables load_dotenv() # Database connection DATABASE_URL = os.getenv("DATABASE_URL") if not DATABASE_URL: print("Error: DATABASE_URL environment variable not set") sys.exit(1) engine = create_engine(DATABASE_URL) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) # ============================================================ # Permission Definitions # ============================================================ PERMISSIONS = [ # ========== USERS MODULE ========== { "code": "users.view", "name": "View Users", "description": "View user list and user profiles", "module": "users" }, { "code": "users.create", "name": "Create Users", "description": "Create new users and send invitations", "module": "users" }, { "code": "users.edit", "name": "Edit Users", "description": "Edit user profiles and information", "module": "users" }, { "code": "users.delete", "name": "Delete Users", "description": "Delete user accounts", "module": "users" }, { "code": "users.status", "name": "Change User Status", "description": "Change user status (active, inactive, etc.)", "module": "users" }, { "code": "users.approve", "name": "Approve/Validate Users", "description": "Approve or validate user applications", "module": "users" }, { "code": "users.export", "name": "Export Users", "description": "Export user data to CSV", "module": "users" }, { "code": "users.import", "name": "Import Users", "description": "Import users from CSV", "module": "users" }, { "code": "users.reset_password", "name": "Reset User Password", "description": "Reset user passwords via email", "module": "users" }, { "code": "users.resend_verification", "name": "Resend Verification Email", "description": "Resend email verification links", "module": "users" }, # ========== EVENTS MODULE ========== { "code": "events.view", "name": "View Events", "description": "View event list and event details", "module": "events" }, { "code": "events.create", "name": "Create Events", "description": "Create new events", "module": "events" }, { "code": "events.edit", "name": "Edit Events", "description": "Edit existing events", "module": "events" }, { "code": "events.delete", "name": "Delete Events", "description": "Delete events", "module": "events" }, { "code": "events.publish", "name": "Publish Events", "description": "Publish or unpublish events", "module": "events" }, { "code": "events.attendance", "name": "Mark Event Attendance", "description": "Mark user attendance for events", "module": "events" }, { "code": "events.rsvps", "name": "View Event RSVPs", "description": "View and manage event RSVPs", "module": "events" }, { "code": "events.calendar_export", "name": "Export Event Calendar", "description": "Export events to iCal format", "module": "events" }, # ========== SUBSCRIPTIONS MODULE ========== { "code": "subscriptions.view", "name": "View Subscriptions", "description": "View subscription list and details", "module": "subscriptions" }, { "code": "subscriptions.create", "name": "Create Subscriptions", "description": "Create manual subscriptions for users", "module": "subscriptions" }, { "code": "subscriptions.edit", "name": "Edit Subscriptions", "description": "Edit subscription details", "module": "subscriptions" }, { "code": "subscriptions.cancel", "name": "Cancel Subscriptions", "description": "Cancel user subscriptions", "module": "subscriptions" }, { "code": "subscriptions.activate", "name": "Activate Subscriptions", "description": "Manually activate subscriptions", "module": "subscriptions" }, { "code": "subscriptions.plans", "name": "Manage Subscription Plans", "description": "Create and edit subscription plans", "module": "subscriptions" }, # ========== FINANCIALS MODULE ========== { "code": "financials.view", "name": "View Financial Reports", "description": "View financial reports and dashboards", "module": "financials" }, { "code": "financials.create", "name": "Create Financial Reports", "description": "Upload and create financial reports", "module": "financials" }, { "code": "financials.edit", "name": "Edit Financial Reports", "description": "Edit existing financial reports", "module": "financials" }, { "code": "financials.delete", "name": "Delete Financial Reports", "description": "Delete financial reports", "module": "financials" }, { "code": "financials.export", "name": "Export Financial Data", "description": "Export financial data to CSV/PDF", "module": "financials" }, { "code": "financials.payments", "name": "View Payment Details", "description": "View detailed payment information", "module": "financials" }, # ========== NEWSLETTERS MODULE ========== { "code": "newsletters.view", "name": "View Newsletters", "description": "View newsletter archives", "module": "newsletters" }, { "code": "newsletters.create", "name": "Create Newsletters", "description": "Upload and create newsletters", "module": "newsletters" }, { "code": "newsletters.edit", "name": "Edit Newsletters", "description": "Edit existing newsletters", "module": "newsletters" }, { "code": "newsletters.delete", "name": "Delete Newsletters", "description": "Delete newsletter archives", "module": "newsletters" }, { "code": "newsletters.send", "name": "Send Newsletters", "description": "Send newsletter emails to subscribers", "module": "newsletters" }, { "code": "newsletters.subscribers", "name": "Manage Newsletter Subscribers", "description": "View and manage newsletter subscribers", "module": "newsletters" }, # ========== BYLAWS MODULE ========== { "code": "bylaws.view", "name": "View Bylaws", "description": "View organization bylaws documents", "module": "bylaws" }, { "code": "bylaws.create", "name": "Create Bylaws", "description": "Upload new bylaws documents", "module": "bylaws" }, { "code": "bylaws.edit", "name": "Edit Bylaws", "description": "Edit existing bylaws documents", "module": "bylaws" }, { "code": "bylaws.delete", "name": "Delete Bylaws", "description": "Delete bylaws documents", "module": "bylaws" }, { "code": "bylaws.publish", "name": "Publish Bylaws", "description": "Mark bylaws as current/published version", "module": "bylaws" }, # ========== GALLERY MODULE ========== { "code": "gallery.view", "name": "View Event Gallery", "description": "View event gallery photos", "module": "gallery" }, { "code": "gallery.upload", "name": "Upload Photos", "description": "Upload photos to event galleries", "module": "gallery" }, { "code": "gallery.edit", "name": "Edit Photos", "description": "Edit photo captions and details", "module": "gallery" }, { "code": "gallery.delete", "name": "Delete Photos", "description": "Delete photos from galleries", "module": "gallery" }, { "code": "gallery.moderate", "name": "Moderate Gallery Content", "description": "Approve/reject uploaded photos", "module": "gallery" }, # ========== SETTINGS MODULE ========== { "code": "settings.view", "name": "View Settings", "description": "View application settings", "module": "settings" }, { "code": "settings.edit", "name": "Edit Settings", "description": "Edit application settings", "module": "settings" }, { "code": "settings.email_templates", "name": "Manage Email Templates", "description": "Edit email templates and notifications", "module": "settings" }, { "code": "settings.storage", "name": "Manage Storage", "description": "View and manage storage usage", "module": "settings" }, { "code": "settings.backup", "name": "Backup & Restore", "description": "Create and restore database backups", "module": "settings" }, { "code": "settings.logs", "name": "View System Logs", "description": "View application and audit logs", "module": "settings" }, # ========== PERMISSIONS MODULE (SUPERADMIN ONLY) ========== { "code": "permissions.view", "name": "View Permissions", "description": "View permission definitions and assignments", "module": "permissions" }, { "code": "permissions.assign", "name": "Assign Permissions", "description": "Assign permissions to roles (SUPERADMIN ONLY)", "module": "permissions" }, { "code": "permissions.manage_roles", "name": "Manage Roles", "description": "Create and manage user roles", "module": "permissions" }, { "code": "permissions.audit", "name": "View Permission Audit Log", "description": "View permission change audit logs", "module": "permissions" }, ] # Default permission assignments for each role DEFAULT_ROLE_PERMISSIONS = { UserRole.guest: [], # Guests have no admin permissions UserRole.member: [ # Members can view public content "events.view", "events.rsvps", "events.calendar_export", "newsletters.view", "bylaws.view", "gallery.view", ], UserRole.admin: [ # Admins have most permissions except RBAC management "users.view", "users.create", "users.edit", "users.status", "users.approve", "users.export", "users.import", "users.reset_password", "users.resend_verification", "events.view", "events.create", "events.edit", "events.delete", "events.publish", "events.attendance", "events.rsvps", "events.calendar_export", "subscriptions.view", "subscriptions.create", "subscriptions.edit", "subscriptions.cancel", "subscriptions.activate", "subscriptions.plans", "financials.view", "financials.create", "financials.edit", "financials.delete", "financials.export", "financials.payments", "newsletters.view", "newsletters.create", "newsletters.edit", "newsletters.delete", "newsletters.send", "newsletters.subscribers", "bylaws.view", "bylaws.create", "bylaws.edit", "bylaws.delete", "bylaws.publish", "gallery.view", "gallery.upload", "gallery.edit", "gallery.delete", "gallery.moderate", "settings.view", "settings.edit", "settings.email_templates", "settings.storage", "settings.logs", ], # Superadmin gets all permissions automatically in code, # so we don't need to explicitly assign them UserRole.superadmin: [] } def seed_permissions(): """Seed permissions and default role assignments""" db = SessionLocal() try: print("🌱 Starting permission seeding...") # Step 1: Clear existing permissions and role_permissions print("\nšŸ“¦ Clearing existing permissions and role assignments...") db.query(RolePermission).delete() db.query(Permission).delete() db.commit() print("āœ“ Cleared existing data") # Step 2: Create permissions print(f"\nšŸ“ Creating {len(PERMISSIONS)} permissions...") permission_map = {} # Map code to permission object for perm_data in PERMISSIONS: permission = Permission( code=perm_data["code"], name=perm_data["name"], description=perm_data["description"], module=perm_data["module"] ) db.add(permission) permission_map[perm_data["code"]] = permission db.commit() print(f"āœ“ Created {len(PERMISSIONS)} permissions") # Step 3: Assign default permissions to roles print("\nšŸ” Assigning default permissions to roles...") for role, permission_codes in DEFAULT_ROLE_PERMISSIONS.items(): if not permission_codes: print(f" • {role.value}: No default permissions (handled in code)") continue for code in permission_codes: if code not in permission_map: print(f" āš ļø Warning: Permission '{code}' not found for role {role.value}") continue role_permission = RolePermission( role=role, permission_id=permission_map[code].id ) db.add(role_permission) db.commit() print(f" āœ“ {role.value}: Assigned {len(permission_codes)} permissions") # Step 4: Summary print("\n" + "="*60) print("šŸ“Š Seeding Summary:") print("="*60) # Count permissions by module modules = {} for perm in PERMISSIONS: module = perm["module"] modules[module] = modules.get(module, 0) + 1 print("\nPermissions by module:") for module, count in sorted(modules.items()): print(f" • {module.capitalize()}: {count} permissions") print(f"\nTotal permissions: {len(PERMISSIONS)}") print("\nāœ… Permission seeding completed successfully!") except Exception as e: db.rollback() print(f"\nāŒ Error seeding permissions: {str(e)}") raise finally: db.close() if __name__ == "__main__": seed_permissions()