Merge origin/main into huangzhenbao-admin

This commit is contained in:
2026-02-04 08:50:46 +08:00
233 changed files with 58165 additions and 12361 deletions

View File

@@ -0,0 +1,159 @@
# 05 RLS 权限矩阵Supabase 行级安全)
本节整理 `complete_mall_database.sql` 中的 RLSRow Level Security启用范围与策略意图并给出“角色 ×× 操作”的矩阵化视角,便于前后端对齐。
> 说明:该库采用 Supabase 模式,常用 `auth.uid()` 获取当前登录用户的 auth id并通过 `ak_users.auth_id` 映射到业务用户 `ak_users.id`。
---
## 1. RLS 设计目标
- **默认拒绝**:启用 RLS 后,如果没有策略,访问会被拒绝。
- **数据隔离优先**:用户私有数据只能访问自己的行。
- **商家/用户双视角**:订单可被“买家”和“卖家”访问。
- **公共可见数据受限**:商品仅公开上架数据。
---
## 2. 启用 RLS 的表(来自 `complete_mall_database.sql`
脚本显式启用 RLS
- `ml_user_profiles`
- `ml_user_addresses`
- `ml_shopping_cart`
- `ml_user_favorites`
- `ml_browse_history`
- `ml_user_coupons`
- `ml_orders`
- `ml_products`
> 备注:其他表(如 `ml_categories/ml_brands/ml_shops/ml_order_items` 等)在该脚本片段中未显式启用 RLS。
---
## 3. 核心策略模式pattern
### 3.1 “归属自己”的通用模式
对用户私有表(档案、地址、购物车、收藏、浏览、券)使用类似逻辑:
- `SELECT/UPDATE/DELETE`:要求当前 `auth.uid()` 对应到该行的 `user_id`
- `INSERT`:要求插入行的 `user_id` 也属于当前 `auth.uid()`
概念表达(伪 SQL
```sql
-- 伪表达:当前登录者只能操作 user_id 属于自己的行
auth.uid() = (select auth_id from ak_users where id = <row.user_id>)
```
价值:
- 前端直连 DB 时,**就算请求参数伪造 user_id**,也无法读写别人的行。
### 3.2 “订单:买家/卖家都可访问”模式
订单 SELECT 策略允许 `auth.uid()` 属于 `user_id``merchant_id`
```sql
auth.uid() in (
select auth_id from ak_users where id in (user_id, merchant_id)
)
```
价值:
- 买家能看自己的订单
- 商家能看自己店铺相关订单(在当前“单商家订单模型”下成立)
### 3.3 “商品:公开上架,商家管理自己的”模式
- `SELECT`:仅 `status = 1` 的商品可见
- `INSERT/UPDATE/DELETE`:要求 `merchant_id` 属于当前登录商家
---
## 4. 权限矩阵(建议口径)
> 说明:此矩阵从业务语义出发描述“期望权限”。实际是否满足,还取决于:
> - 是否启用 RLS
> - 是否存在相应策略
> - `ak_users` 中角色定义与 `auth_id` 映射是否正确
### 4.1 角色定义
- **Customer消费者**:普通用户
- **Merchant商家**:拥有商品与订单管理权限
- **Admin管理员**:平台管理(通常需要 service role 或额外策略)
### 4.2 表级矩阵(读/写)
#### `ml_user_profiles`
- Customer
- **SELECT**:仅本人
- **INSERT/UPDATE/DELETE**:仅本人
- Merchant
- 同 Customer如果商家也是用户
- Admin
- 建议:通过 service role 或单独策略可读全量
#### `ml_user_addresses`
- Customer
- **SELECT/INSERT/UPDATE/DELETE**:仅本人
#### `ml_shopping_cart`
- Customer
- **SELECT/INSERT/UPDATE/DELETE**:仅本人
#### `ml_user_favorites` / `ml_browse_history` / `ml_user_coupons`
- Customer
- **SELECT/INSERT/UPDATE/DELETE**:仅本人
#### `ml_orders`
- Customer
- **SELECT/INSERT/UPDATE/DELETE**:仅自己的订单
- Merchant
- **SELECT/INSERT/UPDATE/DELETE**:仅 `merchant_id` 为自己的订单
- Admin
- 建议service role 或独立策略全量访问
#### `ml_products`
- Public / Customer
- **SELECT**:仅上架(`status=1`
- Merchant
- **SELECT**:至少能看上架;更合理的做法是:商家能看自己所有状态商品(当前策略是否支持需核对)
- **INSERT/UPDATE/DELETE**:仅自己的商品
---
## 5. 关键前提与性能建议
### 5.1 `ak_users.auth_id` 的唯一性与索引
由于策略频繁执行子查询:
```sql
select auth_id from ak_users where id = ...
```
建议:
- 确保 `ak_users.id` 为主键(已有)
- 确保 `ak_users.auth_id` 存在且唯一(建议唯一索引)
### 5.2 RLS 子查询的成本
RLS 每次查询都要执行策略表达式。若策略中大量子查询,可能带来性能压力。
可选优化方向:
- 在业务表冗余 `auth_id`(空间换性能)
- 使用 `security definer` 函数封装策略逻辑(需谨慎)
- 确保常用过滤字段(`user_id/merchant_id/status`)有索引