209 lines
5.8 KiB
Markdown
209 lines
5.8 KiB
Markdown
# 用户认证相关 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. **检查前端页面**
|
||
- 个人中心页面是否能正常显示用户信息
|