10 KiB
Database Migrations
This folder contains SQL migration scripts for the membership platform.
Running the Sprint 1-3 Migration
The sprint_1_2_3_migration.sql file adds all necessary columns and tables for the Members Only features (Sprints 1, 2, and 3).
Prerequisites
- PostgreSQL installed and running
- Database created (e.g.,
membership_db) - Database connection credentials from your
.envfile
Option 1: Using psql command line
# Navigate to the migrations directory
cd /Users/andika/Documents/Works/Koncept\ Kit/KKN/membership-website/backend/migrations
# Run the migration (replace with your database credentials)
psql -U your_username -d membership_db -f sprint_1_2_3_migration.sql
# Or if you have a connection string
psql "postgresql://user:password@localhost:5432/membership_db" -f sprint_1_2_3_migration.sql
Option 2: Using pgAdmin or another GUI tool
- Open pgAdmin and connect to your database
- Open the Query Tool
- Load the
sprint_1_2_3_migration.sqlfile - Execute the script
Option 3: Using Python script
cd /Users/andika/Documents/Works/Koncept\ Kit/KKN/membership-website/backend
# Run the migration using Python
python3 -c "
import psycopg2
import os
from dotenv import load_dotenv
load_dotenv()
DATABASE_URL = os.getenv('DATABASE_URL')
conn = psycopg2.connect(DATABASE_URL)
cur = conn.cursor()
with open('migrations/sprint_1_2_3_migration.sql', 'r') as f:
sql = f.read()
cur.execute(sql)
conn.commit()
cur.close()
conn.close()
print('Migration completed successfully!')
"
What Gets Added
Users Table:
profile_photo_url- Stores Cloudflare R2 URL for profile photossocial_media_facebook- Facebook profile/page URLsocial_media_instagram- Instagram handle or URLsocial_media_twitter- Twitter/X handle or URLsocial_media_linkedin- LinkedIn profile URL
Events Table:
microsoft_calendar_id- Microsoft Calendar event ID for syncingmicrosoft_calendar_sync_enabled- Boolean flag for sync status
New Tables:
event_galleries- Stores event photos with captionsnewsletter_archives- Stores newsletter documentsfinancial_reports- Stores annual financial reportsbylaws_documents- Stores organization bylawsstorage_usage- Tracks Cloudflare R2 storage usage
Verification
After running the migration, verify it worked:
-- Check users table columns
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'users'
AND column_name IN ('profile_photo_url', 'social_media_facebook');
-- Check new tables exist
SELECT table_name
FROM information_schema.tables
WHERE table_name IN ('event_galleries', 'storage_usage');
-- Check storage_usage has initial record
SELECT * FROM storage_usage;
Troubleshooting
Error: "relation does not exist"
- Make sure you're connected to the correct database
- Verify the
usersandeventstables exist first
Error: "column already exists"
- This is safe to ignore - the script uses
IF NOT EXISTSclauses
Error: "permission denied"
- Make sure your database user has ALTER TABLE privileges
- You may need to run as a superuser or database owner
Rollback (if needed)
If you need to undo the migration:
-- Remove new columns from users
ALTER TABLE users DROP COLUMN IF EXISTS profile_photo_url;
ALTER TABLE users DROP COLUMN IF EXISTS social_media_facebook;
ALTER TABLE users DROP COLUMN IF EXISTS social_media_instagram;
ALTER TABLE users DROP COLUMN IF EXISTS social_media_twitter;
ALTER TABLE users DROP COLUMN IF EXISTS social_media_linkedin;
-- Remove new columns from events
ALTER TABLE events DROP COLUMN IF EXISTS microsoft_calendar_id;
ALTER TABLE events DROP COLUMN IF EXISTS microsoft_calendar_sync_enabled;
-- Remove new tables
DROP TABLE IF EXISTS event_galleries;
DROP TABLE IF EXISTS newsletter_archives;
DROP TABLE IF EXISTS financial_reports;
DROP TABLE IF EXISTS bylaws_documents;
DROP TABLE IF EXISTS storage_usage;
Running Phase 1-4.5 Migrations (December 2025)
These migrations add features from client feedback phases 1-4.5:
- Member Since field for imported users
- Approval → Validation terminology update
- Terms of Service acceptance tracking
- Reminder email tracking for admin dashboard
Quick Start
Run all migrations at once:
cd backend/migrations
psql $DATABASE_URL -f run_all_migrations.sql
Individual Migration Files
The migrations are numbered in the order they should be run:
- 001_add_member_since_field.sql - Adds editable
member_sincefield for imported users - 002_rename_approval_to_validation.sql - Updates terminology from "approval" to "validation"
- 003_add_tos_acceptance.sql - Adds Terms of Service acceptance tracking
- 004_add_reminder_tracking_fields.sql - Adds reminder email tracking for admin dashboard
Run Individual Migrations
cd backend/migrations
# Run migrations one by one
psql $DATABASE_URL -f 001_add_member_since_field.sql
psql $DATABASE_URL -f 002_rename_approval_to_validation.sql
psql $DATABASE_URL -f 003_add_tos_acceptance.sql
psql $DATABASE_URL -f 004_add_reminder_tracking_fields.sql
Using psql Interactive Mode
# Connect to your database
psql $DATABASE_URL
# Inside psql, run:
\i backend/migrations/001_add_member_since_field.sql
\i backend/migrations/002_rename_approval_to_validation.sql
\i backend/migrations/003_add_tos_acceptance.sql
\i backend/migrations/004_add_reminder_tracking_fields.sql
What Each Migration Adds
Migration 001 - Member Since Field:
- Adds
member_sincecolumn (nullable timestamp) - Backfills active members with their
created_atdate - Allows admins to edit dates for imported users
Migration 002 - Approval → Validation Terminology:
- Updates
pending_approval→pending_validation - Updates
pre_approved→pre_validated - Aligns database with client's terminology requirements
Migration 003 - ToS Acceptance:
- Adds
accepts_tosboolean field (default false) - Adds
tos_accepted_attimestamp field - Backfills existing users as having accepted ToS
Migration 004 - Reminder Tracking:
- Adds 8 fields to track reminder emails:
email_verification_reminders_sent+last_email_verification_reminder_atevent_attendance_reminders_sent+last_event_attendance_reminder_atpayment_reminders_sent+last_payment_reminder_atrenewal_reminders_sent+last_renewal_reminder_at
- Enables admin dashboard to show users needing personal outreach
Verification
After running migrations, verify they completed successfully:
-- Check if new columns exist
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'users'
AND column_name IN (
'member_since',
'accepts_tos',
'tos_accepted_at',
'email_verification_reminders_sent',
'last_email_verification_reminder_at',
'event_attendance_reminders_sent',
'last_event_attendance_reminder_at',
'payment_reminders_sent',
'last_payment_reminder_at',
'renewal_reminders_sent',
'last_renewal_reminder_at'
)
ORDER BY column_name;
-- Check status values were updated
SELECT status, COUNT(*)
FROM users
GROUP BY status;
Rollback Phase 1-4.5 Migrations (If Needed)
-- Rollback 004: Remove reminder tracking fields
ALTER TABLE users
DROP COLUMN IF EXISTS email_verification_reminders_sent,
DROP COLUMN IF EXISTS last_email_verification_reminder_at,
DROP COLUMN IF EXISTS event_attendance_reminders_sent,
DROP COLUMN IF EXISTS last_event_attendance_reminder_at,
DROP COLUMN IF EXISTS payment_reminders_sent,
DROP COLUMN IF EXISTS last_payment_reminder_at,
DROP COLUMN IF EXISTS renewal_reminders_sent,
DROP COLUMN IF EXISTS last_renewal_reminder_at;
-- Rollback 003: Remove ToS fields
ALTER TABLE users
DROP COLUMN IF EXISTS accepts_tos,
DROP COLUMN IF EXISTS tos_accepted_at;
-- Rollback 002: Revert validation to approval
UPDATE users SET status = 'pending_approval' WHERE status = 'pending_validation';
UPDATE users SET status = 'pre_approved' WHERE status = 'pre_validated';
-- Rollback 001: Remove member_since field
ALTER TABLE users DROP COLUMN IF EXISTS member_since;
Running Phase RBAC Migration (December 2025)
This migration adds RBAC permission management, user invitations, and CSV import tracking capabilities.
Quick Start
cd backend/migrations
psql $DATABASE_URL -f 005_add_rbac_and_invitations.sql
What This Migration Adds
UserRole Enum Update:
- Adds
superadminrole to UserRole enum
New Tables:
- permissions - Granular permission definitions (60+ permissions)
- role_permissions - Junction table linking roles to permissions
- user_invitations - Email-based invitation tracking with tokens
- import_jobs - CSV import job tracking with error logging
New Enum Types:
invitationstatus(pending, accepted, expired, revoked)importjobstatus(processing, completed, failed, partial)
Verification
After running the migration, verify it completed successfully:
-- Check if superadmin role exists
SELECT enumlabel FROM pg_enum
WHERE enumtypid = 'userrole'::regtype
ORDER BY enumlabel;
-- Check if new tables exist
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name IN ('permissions', 'role_permissions', 'user_invitations', 'import_jobs')
ORDER BY table_name;
-- Check table structures
\d permissions
\d role_permissions
\d user_invitations
\d import_jobs
Next Steps After Migration
- Seed Permissions: Run
permissions_seed.pyto populate default permissions - Upgrade Admin to Superadmin: Update existing admin users to superadmin role
- Assign Permissions: Configure permissions for admin, member, and guest roles
Rollback (If Needed)
-- Remove all RBAC tables and enums
DROP TABLE IF EXISTS import_jobs CASCADE;
DROP TABLE IF EXISTS user_invitations CASCADE;
DROP TABLE IF EXISTS role_permissions CASCADE;
DROP TABLE IF EXISTS permissions CASCADE;
DROP TYPE IF EXISTS importjobstatus;
DROP TYPE IF EXISTS invitationstatus;
-- Note: Cannot remove 'superadmin' from UserRole enum without recreating
-- the entire enum. Only rollback if no users have the superadmin role.