194 lines
7.1 KiB
SQL
194 lines
7.1 KiB
SQL
-- =====================================================
|
||
-- 完整清理脚本 - 解决所有冲突
|
||
-- 同时处理触发器、函数、策略冲突
|
||
-- =====================================================
|
||
|
||
-- 第一步:清理触发器
|
||
DO $$
|
||
BEGIN
|
||
RAISE NOTICE '🧹 第一步:清理触发器';
|
||
|
||
-- 删除用户角色相关触发器
|
||
DROP TRIGGER IF EXISTS trigger_update_user_roles_updated_at ON public.user_roles CASCADE;
|
||
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users CASCADE;
|
||
|
||
-- 删除可能存在的旧版本触发器
|
||
DROP TRIGGER IF EXISTS update_user_roles_updated_at ON public.user_roles CASCADE;
|
||
DROP TRIGGER IF EXISTS handle_new_user_trigger ON auth.users CASCADE;
|
||
|
||
RAISE NOTICE '✅ 触发器清理完成';
|
||
END $$;
|
||
|
||
-- 第二步:清理函数(处理参数名称冲突)
|
||
DO $$
|
||
BEGIN
|
||
RAISE NOTICE '🧹 第二步:清理函数(解决参数冲突)';
|
||
|
||
-- 删除所有可能冲突的函数(按依赖顺序)
|
||
DROP FUNCTION IF EXISTS public.batch_update_user_roles(JSONB, UUID) CASCADE;
|
||
DROP FUNCTION IF EXISTS public.batch_update_user_roles(JSONB) CASCADE;
|
||
DROP FUNCTION IF EXISTS public.update_user_role(UUID, TEXT, UUID, JSONB) CASCADE;
|
||
DROP FUNCTION IF EXISTS public.update_user_role(UUID, TEXT, UUID) CASCADE;
|
||
DROP FUNCTION IF EXISTS public.update_user_role(UUID, TEXT) CASCADE;
|
||
DROP FUNCTION IF EXISTS public.get_user_role(UUID) CASCADE;
|
||
DROP FUNCTION IF EXISTS public.get_user_role() CASCADE;
|
||
DROP FUNCTION IF EXISTS public.sync_user_role_metadata(UUID) CASCADE;
|
||
DROP FUNCTION IF EXISTS public.user_has_permission(TEXT, UUID) CASCADE;
|
||
DROP FUNCTION IF EXISTS public.can_access_resource(TEXT, UUID, TEXT, UUID) CASCADE;
|
||
DROP FUNCTION IF EXISTS public.update_user_roles_updated_at() CASCADE;
|
||
DROP FUNCTION IF EXISTS public.handle_new_user() CASCADE;
|
||
DROP FUNCTION IF EXISTS public.test_message_permissions(UUID) CASCADE;
|
||
DROP FUNCTION IF EXISTS public.test_deployment() CASCADE;
|
||
|
||
RAISE NOTICE '✅ 函数清理完成(解决参数名称冲突)';
|
||
END $$;
|
||
|
||
-- 第三步:清理策略
|
||
DO $$
|
||
DECLARE
|
||
r RECORD;
|
||
BEGIN
|
||
RAISE NOTICE '🧹 第三步:清理策略';
|
||
|
||
-- 清理 user_roles 表的所有策略
|
||
FOR r IN
|
||
SELECT policyname
|
||
FROM pg_policies
|
||
WHERE schemaname = 'public'
|
||
AND tablename = 'user_roles'
|
||
LOOP
|
||
EXECUTE format('DROP POLICY IF EXISTS %I ON public.user_roles', r.policyname);
|
||
RAISE NOTICE ' 删除策略: %', r.policyname;
|
||
END LOOP;
|
||
|
||
-- 清理消息相关表的策略
|
||
FOR r IN
|
||
SELECT schemaname, tablename, policyname
|
||
FROM pg_policies
|
||
WHERE schemaname = 'public'
|
||
AND tablename IN ('ak_messages', 'ak_message_recipients', 'ak_message_groups',
|
||
'ak_message_group_members', 'ak_message_templates',
|
||
'ak_user_message_preferences', 'ak_message_stats', 'ak_message_types')
|
||
LOOP
|
||
EXECUTE format('DROP POLICY IF EXISTS %I ON %I.%I',
|
||
r.policyname, r.schemaname, r.tablename);
|
||
RAISE NOTICE ' 删除策略: %.%', r.tablename, r.policyname;
|
||
END LOOP;
|
||
|
||
RAISE NOTICE '✅ 策略清理完成';
|
||
END $$;
|
||
|
||
-- 第四步:清理视图(如果存在冲突)
|
||
DO $$
|
||
DECLARE
|
||
r RECORD;
|
||
BEGIN
|
||
RAISE NOTICE '🧹 第四步:清理视图和错误策略';
|
||
|
||
-- 删除可能错误创建在视图上的策略
|
||
FOR r IN
|
||
SELECT schemaname, tablename, policyname
|
||
FROM pg_policies
|
||
WHERE schemaname = 'public'
|
||
AND tablename IN (
|
||
SELECT table_name
|
||
FROM information_schema.views
|
||
WHERE table_schema = 'public'
|
||
)
|
||
LOOP
|
||
BEGIN
|
||
EXECUTE format('DROP POLICY IF EXISTS %I ON %I.%I',
|
||
r.policyname, r.schemaname, r.tablename);
|
||
RAISE NOTICE ' 删除了视图上的错误策略: %.%', r.tablename, r.policyname;
|
||
EXCEPTION WHEN OTHERS THEN
|
||
RAISE NOTICE ' 无法删除策略: %.% (这是正常的)', r.tablename, r.policyname;
|
||
END;
|
||
END LOOP;
|
||
|
||
-- 重新创建视图
|
||
DROP VIEW IF EXISTS public.user_roles_with_email CASCADE;
|
||
DROP VIEW IF EXISTS public.user_roles_detailed CASCADE;
|
||
|
||
RAISE NOTICE '✅ 视图清理完成';
|
||
END $$;
|
||
|
||
-- 第五步:验证清理结果
|
||
DO $$
|
||
DECLARE
|
||
trigger_count INTEGER;
|
||
policy_count INTEGER;
|
||
function_count INTEGER;
|
||
BEGIN
|
||
RAISE NOTICE '🔍 第五步:验证清理结果';
|
||
|
||
-- 检查触发器
|
||
SELECT COUNT(*) INTO trigger_count
|
||
FROM information_schema.triggers
|
||
WHERE trigger_schema = 'public'
|
||
AND trigger_name IN ('trigger_update_user_roles_updated_at', 'on_auth_user_created');
|
||
|
||
-- 检查策略
|
||
SELECT COUNT(*) INTO policy_count
|
||
FROM pg_policies
|
||
WHERE schemaname = 'public'
|
||
AND tablename IN ('user_roles', 'ak_messages', 'ak_message_recipients');
|
||
|
||
-- 检查核心函数
|
||
SELECT COUNT(*) INTO function_count
|
||
FROM information_schema.routines
|
||
WHERE routine_schema = 'public'
|
||
AND routine_name IN ('get_user_role', 'user_has_permission', 'sync_user_role_metadata');
|
||
|
||
RAISE NOTICE '📊 清理统计:';
|
||
RAISE NOTICE ' - 剩余触发器: %', trigger_count;
|
||
RAISE NOTICE ' - 剩余策略: %', policy_count;
|
||
RAISE NOTICE ' - 核心函数: %', function_count;
|
||
|
||
IF trigger_count = 0 AND policy_count = 0 THEN
|
||
RAISE NOTICE '🎉 清理成功!可以安全地重新部署';
|
||
ELSE
|
||
RAISE NOTICE '⚠️ 部分组件仍存在,请检查是否需要进一步清理';
|
||
END IF;
|
||
END $$;
|
||
|
||
-- 第六步:重置RLS状态(确保表可以重新配置策略)
|
||
DO $$
|
||
DECLARE
|
||
table_record RECORD;
|
||
BEGIN
|
||
RAISE NOTICE '🔄 第六步:重置RLS状态';
|
||
|
||
-- 对所有相关表禁用然后重新启用RLS
|
||
FOR table_record IN
|
||
SELECT table_name
|
||
FROM information_schema.tables
|
||
WHERE table_schema = 'public'
|
||
AND table_name IN ('user_roles', 'ak_messages', 'ak_message_recipients', 'ak_message_groups',
|
||
'ak_message_group_members', 'ak_message_templates',
|
||
'ak_user_message_preferences', 'ak_message_stats', 'ak_message_types')
|
||
LOOP
|
||
EXECUTE format('ALTER TABLE public.%I DISABLE ROW LEVEL SECURITY', table_record.table_name);
|
||
EXECUTE format('ALTER TABLE public.%I ENABLE ROW LEVEL SECURITY', table_record.table_name);
|
||
RAISE NOTICE ' 重置RLS: %', table_record.table_name;
|
||
END LOOP;
|
||
|
||
RAISE NOTICE '✅ RLS状态重置完成';
|
||
END $$;
|
||
|
||
-- 完成消息
|
||
DO $$
|
||
BEGIN
|
||
RAISE NOTICE '🎉 完整清理完成!';
|
||
RAISE NOTICE '📋 下一步:';
|
||
RAISE NOTICE ' 1. 运行您的主要部署脚本';
|
||
RAISE NOTICE ' 2. 验证所有功能正常';
|
||
RAISE NOTICE ' 3. 测试权限和角色分配';
|
||
END $$;
|
||
|
||
-- 最终状态检查
|
||
SELECT
|
||
'🔧 清理完成' as status,
|
||
'系统已准备好重新部署' as message,
|
||
(SELECT COUNT(*) FROM pg_policies WHERE schemaname = 'public') as remaining_policies,
|
||
(SELECT COUNT(*) FROM information_schema.triggers WHERE trigger_schema = 'public') as remaining_triggers;
|