数据库文档编写,开发规范文档,数据库接入
This commit is contained in:
159
docs/sql/05_rls_permissions_matrix.md
Normal file
159
docs/sql/05_rls_permissions_matrix.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# 05 RLS 权限矩阵(Supabase 行级安全)
|
||||
|
||||
本节整理 `complete_mall_database.sql` 中的 RLS(Row 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`)有索引
|
||||
Reference in New Issue
Block a user