Files
medical-mall/docs/sql/30_rpc/auth/handle_new_user_v2.sql
2026-02-05 10:11:09 +08:00

77 lines
2.5 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- =====================================================================================
-- Trigger Function: handle_new_user
-- Version: v2
-- Purpose: auth.users 新用户创建后,同步写入 public.ak_users权威用户表并保持 user_roles 兼容写入
-- Security: SECURITY DEFINER + 固定 search_path
-- Depends:
-- - public.ak_users(auth_id,email,username,role)
-- - public.user_roles(user_id,role,created_by) (如存在)
-- Notes:
-- - 角色权威口径为 public.ak_users.role
-- - user_roles 为历史/兼容表:存在则写入,不存在则跳过
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
user_role TEXT := 'customer';
user_email TEXT := NEW.email;
user_name TEXT;
has_user_roles BOOLEAN := FALSE;
BEGIN
-- 1) 基于邮箱规则分配默认角色(可按需调整)
IF user_email ILIKE '%@teacher.%' OR user_email ILIKE '%@edu.%' THEN
user_role := 'teacher';
ELSIF user_email ILIKE '%@admin.%' THEN
user_role := 'admin';
END IF;
-- 2) 默认 username取邮箱 @ 前缀
IF user_email IS NOT NULL AND POSITION('@' IN user_email) > 1 THEN
user_name := SPLIT_PART(user_email, '@', 1);
ELSE
user_name := 'user';
END IF;
-- 3) 写入 ak_users权威
-- 使用 ON CONFLICT 确保幂等:同一 auth_id 只会有一条记录
INSERT INTO public.ak_users (auth_id, email, username, role)
VALUES (NEW.id, user_email, user_name, user_role)
ON CONFLICT (auth_id)
DO UPDATE SET
email = COALESCE(EXCLUDED.email, public.ak_users.email),
username = COALESCE(EXCLUDED.username, public.ak_users.username),
role = COALESCE(public.ak_users.role, EXCLUDED.role),
updated_at = now();
-- 4) 兼容写入 user_roles如果表存在
SELECT EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_schema='public'
AND table_name='user_roles'
) INTO has_user_roles;
IF has_user_roles THEN
BEGIN
INSERT INTO public.user_roles (user_id, role, created_by)
VALUES (NEW.id, user_role, NEW.id);
EXCEPTION WHEN unique_violation THEN
-- 忽略重复
NULL;
END;
END IF;
-- 5) 更新 auth.users 元数据(可选保留)
UPDATE auth.users
SET raw_user_meta_data = COALESCE(raw_user_meta_data, '{}'::jsonb) || jsonb_build_object('user_role', user_role)
WHERE id = NEW.id;
RETURN NEW;
END;
$$;