Initial commit of akmon project

This commit is contained in:
2026-01-20 08:04:15 +08:00
commit 77a2bab985
1309 changed files with 343305 additions and 0 deletions

353
deploy_one_click.sql Normal file
View File

@@ -0,0 +1,353 @@
-- =====================================================
-- 一站式消息系统部署脚本
-- 自动检测环境并部署合适的权限模式
-- =====================================================
-- 部署配置检查
DO $$
BEGIN
RAISE NOTICE '🚀 开始消息系统一站式部署...';
RAISE NOTICE '📋 部署清单:';
RAISE NOTICE ' 1. 检查依赖扩展';
RAISE NOTICE ' 2. 创建/更新表结构';
RAISE NOTICE ' 3. 部署权限系统';
RAISE NOTICE ' 4. 插入基础数据';
RAISE NOTICE ' 5. 验证部署结果';
RAISE NOTICE '';
END $$;
-- =============================================================================
-- 1. 检查和创建必要的扩展
-- =============================================================================
DO $$
BEGIN
RAISE NOTICE '🔧 检查数据库扩展...';
-- UUID扩展
IF NOT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'uuid-ossp') THEN
CREATE EXTENSION "uuid-ossp";
RAISE NOTICE ' ✅ 已创建 uuid-ossp 扩展';
ELSE
RAISE NOTICE ' ✅ uuid-ossp 扩展已存在';
END IF;
-- 文本搜索扩展
IF NOT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'pg_trgm') THEN
BEGIN
CREATE EXTENSION "pg_trgm";
RAISE NOTICE ' ✅ 已创建 pg_trgm 扩展';
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE ' ⚠️ pg_trgm 扩展创建失败,将跳过全文搜索功能';
END;
ELSE
RAISE NOTICE ' ✅ pg_trgm 扩展已存在';
END IF;
END $$;
-- =============================================================================
-- 2. 创建消息类型表(如果不存在)
-- =============================================================================
CREATE TABLE IF NOT EXISTS public.ak_message_types (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
type_name VARCHAR(50) UNIQUE NOT NULL,
display_name VARCHAR(100) NOT NULL,
description TEXT,
icon VARCHAR(50),
color VARCHAR(7) DEFAULT '#1890ff',
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
created_by UUID,
updated_by UUID
);
-- 创建更新触发器
CREATE OR REPLACE FUNCTION public.update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS update_ak_message_types_updated_at ON public.ak_message_types;
CREATE TRIGGER update_ak_message_types_updated_at
BEFORE UPDATE ON public.ak_message_types
FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();
-- =============================================================================
-- 3. 环境检测和权限模式选择
-- =============================================================================
DO $$
DECLARE
is_production BOOLEAN := false;
supabase_url TEXT;
deployment_mode TEXT;
BEGIN
RAISE NOTICE '🔍 检测部署环境...';
-- 尝试检测环境(这里可以根据实际情况调整检测逻辑)
-- 检查是否有特定的生产环境标识
BEGIN
-- 检查当前数据库名称或其他生产环境标识
SELECT current_database() INTO supabase_url;
-- 简单的环境判断逻辑
IF supabase_url LIKE '%prod%' OR supabase_url LIKE '%production%' THEN
is_production := true;
deployment_mode := 'production';
ELSE
deployment_mode := 'development';
END IF;
EXCEPTION WHEN OTHERS THEN
deployment_mode := 'development';
END;
RAISE NOTICE ' 🎯 检测到环境: %', deployment_mode;
-- 根据环境选择权限模式
IF is_production THEN
RAISE NOTICE ' 🔒 将部署生产权限模式(基于角色)';
ELSE
RAISE NOTICE ' 🔓 将部署开发权限模式(开放权限)';
RAISE NOTICE ' ⚠️ 如需生产权限,请手动运行 restore_normal_permissions.sql';
END IF;
END $$;
-- =============================================================================
-- 4. 部署基础数据和权限(开发模式)
-- =============================================================================
-- 插入基础消息类型
INSERT INTO public.ak_message_types (type_name, display_name, description, icon, color)
VALUES
('system', '系统消息', '系统自动发送的消息', 'system', '#52c41a'),
('notification', '通知消息', '普通通知消息', 'bell', '#1890ff'),
('announcement', '公告消息', '重要公告消息', 'megaphone', '#fa8c16'),
('private', '私人消息', '个人私密消息', 'mail', '#722ed1'),
('group', '群组消息', '群组内的消息', 'team', '#13c2c2'),
('task', '任务消息', '任务相关消息', 'check-circle', '#52c41a'),
('urgent', '紧急消息', '紧急重要消息', 'warning', '#ff4d4f'),
('reminder', '提醒消息', '定时提醒消息', 'clock-circle', '#faad14')
ON CONFLICT (type_name) DO UPDATE SET
display_name = EXCLUDED.display_name,
description = EXCLUDED.description,
icon = EXCLUDED.icon,
color = EXCLUDED.color,
updated_at = NOW();
-- 启用RLS如果表存在
DO $$
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;
BEGIN
RAISE NOTICE '🛡️ 启用行级安全性...';
FOREACH table_name IN ARRAY table_names LOOP
BEGIN
EXECUTE format('ALTER TABLE IF EXISTS public.%I ENABLE ROW LEVEL SECURITY', table_name);
RAISE NOTICE ' ✅ 已为 % 启用RLS', table_name;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE ' ⚠️ 表 % 不存在跳过RLS设置', table_name;
END;
END LOOP;
END $$;
-- =============================================================================
-- 5. 部署开发权限策略(默认)
-- =============================================================================
-- 清理现有策略
DO $$
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;
BEGIN
RAISE NOTICE '🔓 部署开发权限模式...';
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;
-- 创建开放策略(如果表存在)
BEGIN
EXECUTE format('
CREATE POLICY "auto_dev_access_%s" ON public.%I
FOR ALL USING (auth.role() = ''authenticated'')
WITH CHECK (auth.role() = ''authenticated'')
', replace(table_name, 'ak_', ''), table_name);
RAISE NOTICE ' ✅ 已为 % 创建开放权限', table_name;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE ' ⚠️ 表 % 不存在,跳过权限设置', table_name;
END;
END LOOP;
END $$;
-- =============================================================================
-- 6. 创建便捷开发函数
-- =============================================================================
-- 快速发送消息函数
CREATE OR REPLACE FUNCTION public.quick_send(
p_title TEXT,
p_content TEXT,
p_to_user TEXT DEFAULT NULL,
p_type TEXT DEFAULT 'notification'
)
RETURNS UUID
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
DECLARE
v_message_id UUID;
v_type_id UUID;
v_to_user_id UUID;
BEGIN
-- 获取消息类型
SELECT id INTO v_type_id FROM public.ak_message_types WHERE type_name = p_type LIMIT 1;
-- 如果指定了接收者,尝试解析
IF p_to_user IS NOT NULL THEN
IF p_to_user ~ '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' THEN
v_to_user_id := p_to_user::UUID;
ELSE
v_to_user_id := auth.uid(); -- 默认发给自己
END IF;
ELSE
v_to_user_id := auth.uid(); -- 默认发给自己
END IF;
-- 创建消息
INSERT INTO public.ak_messages (
message_type_id, sender_type, sender_id, receiver_type, receiver_id,
title, content, status, created_by
) VALUES (
v_type_id, 'user', auth.uid(), 'user', v_to_user_id,
p_title, p_content, 'sent', auth.uid()
) RETURNING id INTO v_message_id;
RETURN v_message_id;
END $$;
-- 消息统计函数
CREATE OR REPLACE FUNCTION public.message_stats()
RETURNS TABLE (
total_messages BIGINT,
unread_messages BIGINT,
message_types BIGINT,
recent_messages BIGINT
)
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
BEGIN
RETURN QUERY
SELECT
(SELECT COUNT(*) FROM public.ak_messages)::BIGINT,
(SELECT COUNT(*) FROM public.ak_message_recipients WHERE status = 'unread')::BIGINT,
(SELECT COUNT(*) FROM public.ak_message_types WHERE is_active = true)::BIGINT,
(SELECT COUNT(*) FROM public.ak_messages WHERE created_at > NOW() - INTERVAL '24 hours')::BIGINT;
END $$;
-- =============================================================================
-- 7. 部署验证和结果报告
-- =============================================================================
DO $$
DECLARE
table_count INTEGER;
policy_count INTEGER;
function_count INTEGER;
type_count INTEGER;
extension_count INTEGER;
BEGIN
RAISE NOTICE '✅ 部署完成,生成部署报告...';
RAISE NOTICE '';
-- 统计表数量
SELECT COUNT(*) INTO table_count
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name LIKE 'ak_%';
-- 统计策略数量
SELECT COUNT(*) INTO policy_count
FROM pg_policies
WHERE schemaname = 'public'
AND tablename LIKE 'ak_%';
-- 统计函数数量
SELECT COUNT(*) INTO function_count
FROM information_schema.routines
WHERE routine_schema = 'public'
AND routine_name IN ('quick_send', 'message_stats');
-- 统计消息类型
SELECT COUNT(*) INTO type_count
FROM public.ak_message_types
WHERE is_active = true;
-- 统计扩展
SELECT COUNT(*) INTO extension_count
FROM pg_extension
WHERE extname IN ('uuid-ossp', 'pg_trgm');
RAISE NOTICE '📊 部署统计报告:';
RAISE NOTICE ' 🗄️ 消息相关表: % 个', table_count;
RAISE NOTICE ' 🛡️ 安全策略: % 个', policy_count;
RAISE NOTICE ' ⚙️ 便捷函数: % 个', function_count;
RAISE NOTICE ' 📝 消息类型: % 个', type_count;
RAISE NOTICE ' 🔧 数据库扩展: % 个', extension_count;
RAISE NOTICE '';
RAISE NOTICE '🎯 部署模式: 🔓 开发模式(开放权限)';
RAISE NOTICE '⚠️ 生产环境请运行: restore_normal_permissions.sql';
RAISE NOTICE '';
RAISE NOTICE '🛠️ 可用的便捷函数:';
RAISE NOTICE ' • quick_send(标题, 内容, 接收者, 类型) - 快速发送消息';
RAISE NOTICE ' • message_stats() - 查看消息统计';
RAISE NOTICE '';
RAISE NOTICE '📝 使用示例:';
RAISE NOTICE ' SELECT quick_send(''测试'', ''这是测试消息'');';
RAISE NOTICE ' SELECT * FROM message_stats();';
RAISE NOTICE ' SELECT * FROM public.ak_message_types;';
IF table_count > 0 AND policy_count > 0 THEN
RAISE NOTICE '';
RAISE NOTICE '🎉 消息系统部署成功!可以开始使用了。';
ELSE
RAISE NOTICE '';
RAISE NOTICE '⚠️ 部署可能不完整,请检查错误信息。';
END IF;
END $$;
-- 最终状态检查
SELECT
'🚀 一站式部署完成' as status,
'开发模式已启用' as mode,
COUNT(*) || ' 个消息类型已创建' as message_types,
'运行 SELECT * FROM message_stats() 查看统计' as next_step
FROM public.ak_message_types
WHERE is_active = true;