# 用户认证相关 SQL 文件说明 > 本目录包含用户登录/注册相关的数据库表结构和触发器。 ## 📁 文件说明 ### 1. `USER_AUTH_SCHEMA.sql` ⭐ **第一步** 创建用户认证相关的表结构: - **`ak_users`** - 业务用户资料表(与 `auth.users` 关联) - **`users`** - 轻量用户表(用于统计) - **`user_sessions`** - 用户会话表(用于在线统计) - **RLS 策略** - 行级安全策略 - **触发器** - 自动更新 `updated_at` 字段 - **RPC 函数** - `upsert_user_profile`(用于创建/更新用户资料,绕过 RLS) **执行顺序**:首次部署时执行 **执行方式**:在 Supabase Dashboard 的 SQL Editor 中执行 --- ### 2. `USER_AUTH_TRIGGER.sql` ⭐ **第二步(推荐)** 创建数据库触发器,在 `auth.users` 表插入新用户时自动创建 `ak_users` 记录。 **优点**: - 完全自动化,无需前端处理 - 即使邮箱验证开启也能正常工作 - 不依赖前端 token **执行顺序**:在 `USER_AUTH_SCHEMA.sql` 之后执行 **执行方式**:在 Supabase Dashboard 的 SQL Editor 中执行(需要 superuser 权限,Dashboard 默认有) **注意**:如果无法创建触发器(权限问题),可以跳过此文件,使用 RPC 函数方案。 --- ### 3. `USER_AUTH_TEST_DATA.sql`(可选) 插入测试用户数据,用于开发和测试。 **执行顺序**:在表结构创建后执行 --- ## 🚀 快速部署 ### 方式一:使用触发器(推荐) 1. **执行表结构** ```sql -- 在 Supabase Dashboard 执行 -- 复制 pages/user/test/USER_AUTH_SCHEMA.sql 的内容并执行 ``` 2. **创建触发器** ```sql -- 在 Supabase Dashboard 执行 -- 复制 pages/user/test/USER_AUTH_TRIGGER.sql 的内容并执行 ``` 3. **验证** ```sql -- 检查函数是否存在 SELECT * FROM pg_proc WHERE proname = 'upsert_user_profile'; -- 检查触发器是否存在(如果执行了 USER_AUTH_TRIGGER.sql) SELECT * FROM pg_trigger WHERE tgname = 'on_auth_user_created'; ``` ### 方式二:仅使用 RPC 函数(如果触发器无法创建) 1. **执行表结构** ```sql -- 在 Supabase Dashboard 执行 -- 复制 pages/user/test/USER_AUTH_SCHEMA.sql 的内容并执行 ``` 2. **验证 RPC 函数** ```sql -- 检查函数是否存在 SELECT * FROM pg_proc WHERE proname = 'upsert_user_profile'; ``` --- ## 🔧 工作原理 ### 方案一:数据库触发器(推荐) 1. 用户注册 → Supabase Auth 在 `auth.users` 表中创建记录 2. 数据库触发器自动执行 → 在 `ak_users` 表中创建对应记录 3. 前端无需处理 → 用户资料自动创建 ### 方案二:RPC 函数 1. 用户注册 → 前端获取 user 对象 2. 前端调用 `ensureUserProfile()` → 内部调用 `upsert_user_profile` RPC 函数 3. RPC 函数使用 `SECURITY DEFINER` → 绕过 RLS 策略,创建用户资料 --- ## ⚠️ 重要说明 ### RLS 策略 `ak_users` 表已启用 RLS,策略如下: - **SELECT**:用户只能查看自己的资料(`auth.uid() = id`) - **INSERT**:用户只能插入自己的资料(`auth.uid() = id`) - **UPDATE**:用户只能更新自己的资料(`auth.uid() = id`) ### 注册时的问题 注册时,如果邮箱验证未开启,Supabase 会返回 session,此时有 token,可以直接插入。 如果邮箱验证已开启,注册后没有 session,此时没有 token,`auth.uid()` 返回 `null`,RLS 策略会阻止插入。 **解决方案**: 1. ✅ 使用数据库触发器(自动创建,无需 token) 2. ✅ 使用 `SECURITY DEFINER` RPC 函数(绕过 RLS) 3. ⚠️ 用户登录后自动创建(在 `getCurrentUser` 中处理) --- ## 🔍 验证和测试 ### 测试注册流程 1. **注册新用户** - 在前端注册页面输入邮箱和密码 - 点击注册 2. **检查数据库** ```sql -- 检查 auth.users 表中是否有新用户 SELECT id, email, created_at FROM auth.users ORDER BY created_at DESC LIMIT 5; -- 检查 ak_users 表中是否有对应记录 SELECT id, email, username, created_at FROM ak_users ORDER BY created_at DESC LIMIT 5; ``` 3. **如果 ak_users 中没有记录** - 检查是否执行了 `USER_AUTH_TRIGGER.sql` - 检查触发器是否创建成功 - 检查 RPC 函数是否创建成功 - 查看浏览器控制台的错误信息 --- ## 📚 相关文件 - `pages/user/register.uvue` - 注册页面 - `pages/user/login.uvue` - 登录页面 - `utils/sapi.uts` - `ensureUserProfile` 函数 - `utils/store.uts` - `getCurrentUser` 函数(登录后自动创建资料) --- ## 🐛 故障排查 ### 问题:注册后 `ak_users` 表中没有记录 **可能原因**: 1. 未执行 `USER_AUTH_SCHEMA.sql`(RPC 函数不存在) 2. 未执行 `USER_AUTH_TRIGGER.sql`(触发器不存在) 3. RLS 策略阻止插入(没有 token) 4. 邮箱验证已开启,注册后没有 session **解决方案**: 1. 执行 `USER_AUTH_SCHEMA.sql` 创建 RPC 函数 2. 执行 `USER_AUTH_TRIGGER.sql` 创建触发器(推荐) 3. 或者等待用户登录后自动创建(在 `getCurrentUser` 中处理) ### 问题:RPC 函数调用失败 **检查**: ```sql -- 检查函数是否存在 SELECT proname, prosrc FROM pg_proc WHERE proname = 'upsert_user_profile'; -- 检查权限 SELECT grantee, privilege_type FROM information_schema.routine_privileges WHERE routine_name = 'upsert_user_profile'; ``` **解决**:重新执行 `USER_AUTH_SCHEMA.sql` 中的函数创建部分。 --- ## ✅ 下一步 执行完 SQL 文件后: 1. **测试注册功能** - 在前端注册新用户 - 检查 `ak_users` 表中是否有新记录 2. **测试登录功能** - 使用注册的账号登录 - 检查是否能正常获取用户资料 3. **检查前端页面** - 个人中心页面是否能正常显示用户信息