-- ===================================================================================== -- 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; $$;