-- Migration: Migrate roles, permissions, user_roles, and role_permissions to UUID -- Date: 2025-01-27 -- Reference: GO-004, GO-001, GO-005, GO-006 -- -- This migration converts all RBAC tables from BIGINT to UUID to align with the models -- and ensure consistency with the rest of the application. CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- ========================================== -- TABLE: roles -- ========================================== DO $$ BEGIN -- Check if roles table exists and has BIGINT ID IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'roles') THEN IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'roles' AND column_name = 'id' AND data_type = 'bigint') THEN RAISE NOTICE 'Migrating roles.id from BIGINT to UUID'; -- Add UUID column ALTER TABLE roles ADD COLUMN IF NOT EXISTS id_uuid UUID DEFAULT gen_random_uuid(); -- Update role_permissions to use UUID (temporary mapping) ALTER TABLE role_permissions ADD COLUMN IF NOT EXISTS role_id_uuid UUID; UPDATE role_permissions rp SET role_id_uuid = r.id_uuid FROM roles r WHERE rp.role_id = r.id; -- Update user_roles to use UUID (temporary mapping) ALTER TABLE user_roles ADD COLUMN IF NOT EXISTS role_id_uuid UUID; UPDATE user_roles ur SET role_id_uuid = r.id_uuid FROM roles r WHERE ur.role_id = r.id; -- Drop foreign key constraints ALTER TABLE role_permissions DROP CONSTRAINT IF EXISTS role_permissions_role_id_fkey; ALTER TABLE user_roles DROP CONSTRAINT IF EXISTS user_roles_role_id_fkey; -- Drop old ID column and rename UUID column ALTER TABLE roles DROP CONSTRAINT IF EXISTS roles_pkey; ALTER TABLE roles DROP COLUMN id; ALTER TABLE roles RENAME COLUMN id_uuid TO id; ALTER TABLE roles ADD PRIMARY KEY (id); -- Update role_permissions ALTER TABLE role_permissions DROP COLUMN role_id; ALTER TABLE role_permissions RENAME COLUMN role_id_uuid TO role_id; ALTER TABLE role_permissions ADD CONSTRAINT role_permissions_role_id_fkey FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE; -- Update user_roles ALTER TABLE user_roles DROP COLUMN role_id; ALTER TABLE user_roles RENAME COLUMN role_id_uuid TO role_id; ALTER TABLE user_roles ADD CONSTRAINT user_roles_role_id_fkey FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE; END IF; END IF; END $$; -- ========================================== -- TABLE: permissions -- ========================================== DO $$ BEGIN -- Check if permissions table exists and has BIGINT ID IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'permissions') THEN IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'permissions' AND column_name = 'id' AND data_type = 'bigint') THEN RAISE NOTICE 'Migrating permissions.id from BIGINT to UUID'; -- Add UUID column ALTER TABLE permissions ADD COLUMN IF NOT EXISTS id_uuid UUID DEFAULT gen_random_uuid(); -- Update role_permissions to use UUID (temporary mapping) ALTER TABLE role_permissions ADD COLUMN IF NOT EXISTS permission_id_uuid UUID; UPDATE role_permissions rp SET permission_id_uuid = p.id_uuid FROM permissions p WHERE rp.permission_id = p.id; -- Drop foreign key constraint ALTER TABLE role_permissions DROP CONSTRAINT IF EXISTS role_permissions_permission_id_fkey; -- Drop old ID column and rename UUID column ALTER TABLE permissions DROP CONSTRAINT IF EXISTS permissions_pkey; ALTER TABLE permissions DROP COLUMN id; ALTER TABLE permissions RENAME COLUMN id_uuid TO id; ALTER TABLE permissions ADD PRIMARY KEY (id); -- Update role_permissions ALTER TABLE role_permissions DROP COLUMN permission_id; ALTER TABLE role_permissions RENAME COLUMN permission_id_uuid TO permission_id; ALTER TABLE role_permissions ADD CONSTRAINT role_permissions_permission_id_fkey FOREIGN KEY (permission_id) REFERENCES permissions(id) ON DELETE CASCADE; -- Recreate composite primary key ALTER TABLE role_permissions DROP CONSTRAINT IF EXISTS role_permissions_pkey; ALTER TABLE role_permissions ADD PRIMARY KEY (role_id, permission_id); END IF; END IF; END $$; -- ========================================== -- TABLE: user_roles -- ========================================== DO $$ BEGIN -- Check if user_roles table exists and has BIGINT ID IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'user_roles') THEN IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'user_roles' AND column_name = 'id' AND data_type = 'bigint') THEN RAISE NOTICE 'Migrating user_roles.id from BIGINT to UUID'; -- Add UUID column ALTER TABLE user_roles ADD COLUMN IF NOT EXISTS id_uuid UUID DEFAULT gen_random_uuid(); -- Drop old ID column and rename UUID column ALTER TABLE user_roles DROP CONSTRAINT IF EXISTS user_roles_pkey; ALTER TABLE user_roles DROP COLUMN id; ALTER TABLE user_roles RENAME COLUMN id_uuid TO id; ALTER TABLE user_roles ADD PRIMARY KEY (id); END IF; -- Ensure user_id is UUID (should already be done by migration 047, but double-check) IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'user_roles' AND column_name = 'user_id' AND data_type = 'bigint') THEN RAISE NOTICE 'user_roles.user_id is still BIGINT, should have been migrated by 047. This is unexpected.'; END IF; -- Ensure assigned_by is UUID if it exists IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'user_roles' AND column_name = 'assigned_by' AND data_type = 'bigint') THEN RAISE NOTICE 'Migrating user_roles.assigned_by from BIGINT to UUID'; ALTER TABLE user_roles ADD COLUMN IF NOT EXISTS assigned_by_uuid UUID; UPDATE user_roles ur SET assigned_by_uuid = u.id FROM users u WHERE ur.assigned_by = u.id::bigint AND u.id IS NOT NULL; ALTER TABLE user_roles DROP COLUMN assigned_by; ALTER TABLE user_roles RENAME COLUMN assigned_by_uuid TO assigned_by; END IF; END IF; END $$; -- ========================================== -- INDEXES -- ========================================== -- Recreate indexes if they don't exist CREATE INDEX IF NOT EXISTS idx_user_roles_user_id ON user_roles(user_id); CREATE INDEX IF NOT EXISTS idx_user_roles_role_id ON user_roles(role_id); CREATE INDEX IF NOT EXISTS idx_role_permissions_role_id ON role_permissions(role_id); CREATE INDEX IF NOT EXISTS idx_role_permissions_permission_id ON role_permissions(permission_id); -- ========================================== -- COMMENTS -- ========================================== COMMENT ON TABLE roles IS 'System roles for RBAC (migrated to UUID)'; COMMENT ON TABLE permissions IS 'System permissions for RBAC (migrated to UUID)'; COMMENT ON TABLE user_roles IS 'User role assignments (migrated to UUID)'; COMMENT ON TABLE role_permissions IS 'Role permission mappings (migrated to UUID)';