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