Initial commit of akmon project
This commit is contained in:
305
permission_manager.sql
Normal file
305
permission_manager.sql
Normal file
@@ -0,0 +1,305 @@
|
||||
-- =====================================================
|
||||
-- 消息系统权限模式管理器
|
||||
-- 在开发模式和生产模式之间快速切换
|
||||
-- =====================================================
|
||||
|
||||
-- 创建权限模式管理函数
|
||||
CREATE OR REPLACE FUNCTION public.get_permission_mode()
|
||||
RETURNS TABLE (
|
||||
mode TEXT,
|
||||
description TEXT,
|
||||
dev_policies INTEGER,
|
||||
normal_policies INTEGER,
|
||||
dev_functions INTEGER
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
AS $$
|
||||
DECLARE
|
||||
v_dev_policies INTEGER;
|
||||
v_normal_policies INTEGER;
|
||||
v_dev_functions INTEGER;
|
||||
v_mode TEXT;
|
||||
v_description TEXT;
|
||||
BEGIN
|
||||
-- 统计开发模式策略
|
||||
SELECT COUNT(*) INTO v_dev_policies
|
||||
FROM pg_policies
|
||||
WHERE schemaname = 'public'
|
||||
AND (policyname LIKE 'dev_%' OR policyname LIKE 'authenticated_full_%');
|
||||
|
||||
-- 统计正常模式策略
|
||||
SELECT COUNT(*) INTO v_normal_policies
|
||||
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')
|
||||
AND NOT (policyname LIKE 'dev_%' OR policyname LIKE 'authenticated_full_%');
|
||||
|
||||
-- 统计开发函数
|
||||
SELECT COUNT(*) INTO v_dev_functions
|
||||
FROM information_schema.routines
|
||||
WHERE routine_schema = 'public'
|
||||
AND routine_name LIKE 'dev_%';
|
||||
|
||||
-- 判断当前模式
|
||||
IF v_dev_policies > 0 THEN
|
||||
v_mode := '🔓 开发模式';
|
||||
v_description := '所有authenticated用户拥有完全权限';
|
||||
ELSIF v_normal_policies > 0 THEN
|
||||
v_mode := '🔒 生产模式';
|
||||
v_description := '基于角色的权限控制';
|
||||
ELSE
|
||||
v_mode := '❓ 未知模式';
|
||||
v_description := '权限策略可能未正确设置';
|
||||
END IF;
|
||||
|
||||
RETURN QUERY SELECT
|
||||
v_mode,
|
||||
v_description,
|
||||
v_dev_policies,
|
||||
v_normal_policies,
|
||||
v_dev_functions;
|
||||
END $$;
|
||||
|
||||
-- 权限策略详情查看函数
|
||||
CREATE OR REPLACE FUNCTION public.list_message_policies()
|
||||
RETURNS TABLE (
|
||||
table_name TEXT,
|
||||
policy_name TEXT,
|
||||
policy_type TEXT,
|
||||
policy_mode TEXT
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
AS $$
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT
|
||||
p.tablename::TEXT,
|
||||
p.policyname::TEXT,
|
||||
CASE
|
||||
WHEN p.cmd = 'r' THEN 'SELECT'
|
||||
WHEN p.cmd = 'a' THEN 'INSERT'
|
||||
WHEN p.cmd = 'w' THEN 'UPDATE'
|
||||
WHEN p.cmd = 'd' THEN 'DELETE'
|
||||
WHEN p.cmd = '*' THEN 'ALL'
|
||||
ELSE p.cmd::TEXT
|
||||
END as policy_type,
|
||||
CASE
|
||||
WHEN p.policyname LIKE 'dev_%' OR p.policyname LIKE 'authenticated_full_%' THEN '🔓 开发'
|
||||
ELSE '🔒 生产'
|
||||
END as policy_mode
|
||||
FROM pg_policies p
|
||||
WHERE p.schemaname = 'public'
|
||||
AND p.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')
|
||||
ORDER BY p.tablename, p.policyname;
|
||||
END $$;
|
||||
|
||||
-- 快速切换到开发模式
|
||||
CREATE OR REPLACE FUNCTION public.switch_to_dev_mode()
|
||||
RETURNS TEXT
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
AS $$
|
||||
DECLARE
|
||||
table_names TEXT[] := ARRAY[
|
||||
'ak_message_types', 'ak_messages', 'ak_message_recipients',
|
||||
'ak_message_groups', 'ak_message_group_members', 'ak_message_templates',
|
||||
'ak_user_message_preferences', 'ak_message_stats'
|
||||
];
|
||||
table_name TEXT;
|
||||
r RECORD;
|
||||
policy_count INTEGER := 0;
|
||||
BEGIN
|
||||
-- 清理现有策略
|
||||
FOREACH table_name IN ARRAY table_names LOOP
|
||||
FOR r IN
|
||||
SELECT policyname
|
||||
FROM pg_policies
|
||||
WHERE schemaname = 'public' AND tablename = table_name
|
||||
LOOP
|
||||
EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', r.policyname, table_name);
|
||||
END LOOP;
|
||||
|
||||
-- 创建开放策略
|
||||
EXECUTE format('
|
||||
CREATE POLICY "dev_open_access_%s" ON public.%I
|
||||
FOR ALL USING (auth.role() = ''authenticated'')
|
||||
WITH CHECK (auth.role() = ''authenticated'')
|
||||
', replace(table_name, 'ak_', ''), table_name);
|
||||
|
||||
policy_count := policy_count + 1;
|
||||
END LOOP;
|
||||
|
||||
RETURN format('🔓 已切换到开发模式,创建了 %s 个开放策略', policy_count);
|
||||
END $$;
|
||||
|
||||
-- 快速切换到生产模式
|
||||
CREATE OR REPLACE FUNCTION public.switch_to_prod_mode()
|
||||
RETURNS TEXT
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
AS $$
|
||||
DECLARE
|
||||
table_names TEXT[] := ARRAY[
|
||||
'ak_message_types', 'ak_messages', 'ak_message_recipients',
|
||||
'ak_message_groups', 'ak_message_group_members', 'ak_message_templates',
|
||||
'ak_user_message_preferences', 'ak_message_stats'
|
||||
];
|
||||
table_name TEXT;
|
||||
r RECORD;
|
||||
deleted_count INTEGER := 0;
|
||||
BEGIN
|
||||
-- 删除所有开发模式策略
|
||||
FOREACH table_name IN ARRAY table_names LOOP
|
||||
FOR r IN
|
||||
SELECT policyname
|
||||
FROM pg_policies
|
||||
WHERE schemaname = 'public'
|
||||
AND tablename = table_name
|
||||
AND (policyname LIKE 'dev_%' OR policyname LIKE 'authenticated_full_%')
|
||||
LOOP
|
||||
EXECUTE format('DROP POLICY IF EXISTS %I ON public.%I', r.policyname, table_name);
|
||||
deleted_count := deleted_count + 1;
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
|
||||
-- 这里应该运行完整的生产权限策略创建
|
||||
-- 为了简化,我们只清理开发策略
|
||||
-- 实际部署时需要运行 restore_normal_permissions.sql
|
||||
|
||||
RETURN format('🔒 已清理 %s 个开发策略,请运行 restore_normal_permissions.sql 完成生产模式设置', deleted_count);
|
||||
END $$;
|
||||
|
||||
-- 权限健康检查函数
|
||||
CREATE OR REPLACE FUNCTION public.check_permission_health()
|
||||
RETURNS TABLE (
|
||||
check_item TEXT,
|
||||
status TEXT,
|
||||
details TEXT,
|
||||
recommendation TEXT
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
AS $$
|
||||
DECLARE
|
||||
v_rls_enabled INTEGER;
|
||||
v_auth_functions INTEGER;
|
||||
v_role_functions INTEGER;
|
||||
v_conflicting_policies INTEGER;
|
||||
BEGIN
|
||||
-- 检查RLS是否启用
|
||||
SELECT COUNT(*) INTO v_rls_enabled
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON c.relnamespace = n.oid
|
||||
WHERE n.nspname = 'public'
|
||||
AND c.relname 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')
|
||||
AND c.relrowsecurity = true;
|
||||
|
||||
-- 检查认证相关函数
|
||||
SELECT COUNT(*) INTO v_auth_functions
|
||||
FROM information_schema.routines
|
||||
WHERE routine_schema = 'public'
|
||||
AND routine_name IN ('get_user_role', 'is_group_member');
|
||||
|
||||
-- 检查用户角色函数
|
||||
SELECT COUNT(*) INTO v_role_functions
|
||||
FROM information_schema.routines
|
||||
WHERE routine_schema = 'public'
|
||||
AND routine_name LIKE '%role%';
|
||||
|
||||
-- 检查冲突策略
|
||||
SELECT COUNT(*) INTO v_conflicting_policies
|
||||
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')
|
||||
GROUP BY tablename, cmd
|
||||
HAVING COUNT(*) > 3; -- 如果同一表同一操作有超过3个策略可能有问题
|
||||
|
||||
-- RLS启用检查
|
||||
RETURN QUERY SELECT
|
||||
'RLS启用状态'::TEXT,
|
||||
CASE WHEN v_rls_enabled >= 8 THEN '✅ 正常' ELSE '⚠️ 异常' END,
|
||||
format('%s/8 个表启用了RLS', v_rls_enabled),
|
||||
CASE WHEN v_rls_enabled < 8 THEN '运行完整部署脚本启用RLS' ELSE '无需操作' END;
|
||||
|
||||
-- 认证函数检查
|
||||
RETURN QUERY SELECT
|
||||
'认证函数'::TEXT,
|
||||
CASE WHEN v_auth_functions >= 2 THEN '✅ 正常' ELSE '⚠️ 缺失' END,
|
||||
format('找到 %s 个认证相关函数', v_auth_functions),
|
||||
CASE WHEN v_auth_functions < 2 THEN '运行 supabase_auth_complete_setup.sql' ELSE '无需操作' END;
|
||||
|
||||
-- 策略冲突检查
|
||||
RETURN QUERY SELECT
|
||||
'策略冲突'::TEXT,
|
||||
CASE WHEN v_conflicting_policies = 0 THEN '✅ 正常' ELSE '⚠️ 可能存在' END,
|
||||
format('发现 %s 个潜在冲突', v_conflicting_policies),
|
||||
CASE WHEN v_conflicting_policies > 0 THEN '检查并清理重复策略' ELSE '无需操作' END;
|
||||
|
||||
END $$;
|
||||
|
||||
-- =============================================================================
|
||||
-- 使用示例和说明
|
||||
-- =============================================================================
|
||||
|
||||
/*
|
||||
-- 使用示例:
|
||||
|
||||
-- 1. 查看当前权限模式
|
||||
SELECT * FROM public.get_permission_mode();
|
||||
|
||||
-- 2. 查看所有权限策略
|
||||
SELECT * FROM public.list_message_policies();
|
||||
|
||||
-- 3. 切换到开发模式
|
||||
SELECT public.switch_to_dev_mode();
|
||||
|
||||
-- 4. 切换到生产模式(仅清理,需要手动运行完整脚本)
|
||||
SELECT public.switch_to_prod_mode();
|
||||
|
||||
-- 5. 权限健康检查
|
||||
SELECT * FROM public.check_permission_health();
|
||||
|
||||
-- 6. 快速检查当前状态
|
||||
SELECT
|
||||
mode,
|
||||
description,
|
||||
CASE
|
||||
WHEN dev_policies > 0 THEN '⚠️ 开发环境权限'
|
||||
WHEN normal_policies > 0 THEN '✅ 生产环境权限'
|
||||
ELSE '❌ 权限未配置'
|
||||
END as security_level
|
||||
FROM public.get_permission_mode();
|
||||
*/
|
||||
|
||||
-- 创建权限管理视图(只读)
|
||||
CREATE OR REPLACE VIEW public.permission_dashboard AS
|
||||
SELECT
|
||||
pm.mode,
|
||||
pm.description,
|
||||
pm.dev_policies,
|
||||
pm.normal_policies,
|
||||
pm.dev_functions,
|
||||
CASE
|
||||
WHEN pm.dev_policies > 0 THEN '⚠️ 开发模式 - 权限开放'
|
||||
WHEN pm.normal_policies > 0 THEN '✅ 生产模式 - 权限受控'
|
||||
ELSE '❌ 未知模式 - 需要检查'
|
||||
END as security_status,
|
||||
NOW() as checked_at
|
||||
FROM public.get_permission_mode() pm;
|
||||
|
||||
-- 完成提示
|
||||
SELECT
|
||||
'🛠️ 权限管理器' as component,
|
||||
'已创建' as status,
|
||||
'get_permission_mode(), switch_to_dev_mode(), switch_to_prod_mode()' as functions,
|
||||
'permission_dashboard 视图可查看实时状态' as info;
|
||||
Reference in New Issue
Block a user