veza/veza-backend-api/migrations/062_migrate_roles_permissions_to_uuid.sql
2025-12-03 20:29:37 +01:00

164 lines
7.7 KiB
SQL

-- 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)';