feat: 多租户数据权限 + 数据库连接修正
- adminPool 连服务器本地 5432 sbrain_admin (SCRAM 认证) - tenantPool/pool 连 FRP 隧道 15432 bill_query (trust 认证) - query() 自动注入 store_code 数据权限 (store/regional 角色) - 区域经理 region 字段存储逗号分隔的 store_code 列表 - /overview 和 /overview/daily 对 scoped 用户从 bill_fact 聚合 - tenant_users.region 扩展为 VARCHAR(500) - deploy.sh .env 增加 ADMIN_DB_* 配置 - run.md 更新数据库连接架构说明 - 新增海淀区区域经理用户 (21 家海淀区门店)
This commit is contained in:
@@ -2,43 +2,81 @@
|
||||
|
||||
## 登录账号
|
||||
|
||||
| 用户名 | 密码 | 角色 |
|
||||
|--------|------|------|
|
||||
| 总部管理员 | 123 | hq |
|
||||
| 区域经理 | 123 | regional |
|
||||
| 潘家园店长 | 123 | store |
|
||||
| 商品部 | 123 | dept |
|
||||
### 平台管理员
|
||||
|
||||
## 架构(2026-08-02 更新:SaaS + 本地数据库)
|
||||
| 用户名 | 密码 | 角色 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| 平台管理员 | 123 | platform_admin | 管理所有租户,登录后进入平台管理后台 |
|
||||
|
||||
### 租户用户(存储在服务器 sbrain_admin 数据库)
|
||||
|
||||
| 用户名 | 密码 | 角色 | 租户 |
|
||||
|--------|------|------|------|
|
||||
| 总部管理员 | 123 | hq | tenant_a(西部马华) |
|
||||
|
||||
> 租户管理员(hq)登录后可在系统内创建区域经理、店长、商品部等角色用户。
|
||||
> 密码使用 bcrypt 加密存储。
|
||||
|
||||
## 架构(2026-08-02 更新:SaaS 多租户)
|
||||
|
||||
```
|
||||
浏览器 → https://dm.all8ai.top
|
||||
→ Nginx(服务器) → /api/ → 127.0.0.1:9333 (服务器后端, pm2管理)
|
||||
→ frp隧道 127.0.0.1:15432 → 本机PostgreSQL:5432
|
||||
→ 服务器本地 PostgreSQL:5432 → sbrain_admin(平台库:租户配置、用户认证)
|
||||
→ frp隧道 127.0.0.1:15432 → 本机PostgreSQL:5432 → bill_query(租户业务库)
|
||||
```
|
||||
|
||||
- **前端**:服务器 Nginx 静态文件 `/var/www/dm.all8ai.top`
|
||||
- **后端**:服务器 `/opt/sbrain-server`,pm2 管理,端口 9333
|
||||
- **数据库**:本机 PostgreSQL 15,端口 5432,数据库 bill_query
|
||||
- **frp 隧道**:暴露 PostgreSQL(5432→15432),服务器后端通过 15432 连接本机数据库
|
||||
### 数据库连接(重要)
|
||||
|
||||
后端连接两个不同的数据库,走不同端口:
|
||||
|
||||
| 连接池 | 目标数据库 | 连接地址 | 认证方式 | 配置来源 |
|
||||
|--------|-----------|---------|---------|---------|
|
||||
| `adminPool` | `sbrain_admin`(平台库) | `127.0.0.1:5432`(服务器本地 PG) | scram-sha-256(用户 `sbrain_admin`,密码 `sbrain2026`) | `.env` 中 `ADMIN_DB_*` |
|
||||
| `tenantPool` | `bill_query`(业务库) | `127.0.0.1:15432`(FRP 隧道 → 本机 PG) | trust(用户 `freedak`,无需密码) | `tenant_configs.db_port=15432` |
|
||||
| `pool` | `bill_query`(业务库) | `127.0.0.1:15432`(FRP 隧道 → 本机 PG) | trust(用户 `freedak`,无需密码) | `.env` 中 `DB_*` |
|
||||
|
||||
> ⚠️ `tenant_configs` 表中 `db_port` 必须为 `15432`(FRP 隧道),`db_password` 为 NULL(trust 认证)。
|
||||
> ⚠️ `adminPool` 连接服务器本地 5432,需要 `ADMIN_DB_PASSWORD=sbrain2026`。
|
||||
|
||||
### 数据库分布
|
||||
|
||||
| 数据库 | 位置 | 存储内容 |
|
||||
|--------|------|---------|
|
||||
| `sbrain_admin` | 服务器本地 PostgreSQL(5432) | 平台管理员、租户配置(tenant_configs)、所有租户用户(tenant_users) |
|
||||
| `bill_query` | 本机 PostgreSQL(通过 frp 暴露为 15432) | 租户业务数据(销售、任务、成本分析等) |
|
||||
|
||||
### 多租户数据隔离
|
||||
|
||||
- **认证流程**:用户登录 → 查 `sbrain_admin.tenant_users` → bcrypt 验证 → JWT 含 `tenantId`
|
||||
- **数据隔离**:业务请求 → `tenantDbMiddleware` 根据 JWT 中的 `tenantId` 查 `tenant_configs` 获取该租户数据库连接信息 → `AsyncLocalStorage` 设置租户连接池 → 所有 `query()` 自动走对应租户数据库
|
||||
- **租户用户管理**:平台管理员为租户创建管理员(hq),租户管理员在系统内创建区域经理/店长/商品部等用户,均存储在 `sbrain_admin.tenant_users` 表中,通过 `tenant_id` 字段区分
|
||||
|
||||
### 关键文件
|
||||
|
||||
| 文件 | 职责 |
|
||||
|------|------|
|
||||
| `server/src/config/tenant-db.ts` | 租户连接池缓存 + AsyncLocalStorage |
|
||||
| `server/src/config/admin-pool.ts` | 平台库连接池(通过 `ADMIN_DB_*` 环境变量配置) |
|
||||
| `server/src/config/database.ts` | 主业务库连接池 + 全局 `query()` 函数(自动注入数据权限) |
|
||||
| `server/src/middleware/tenant-db.ts` | 根据 JWT tenantId 动态切换数据库 + 注入用户 scope |
|
||||
| `server/src/middleware/data-scope.ts` | 数据权限工具函数(`getDataScope` / `scopeStoreFilter`) |
|
||||
| `server/src/routes/auth.ts` | 租户用户登录(查 tenant_users + bcrypt) |
|
||||
| `server/src/routes/admin.ts` | 平台管理 API + 租户内用户管理 API |
|
||||
| `server/sql/11_tenant_management.sql` | 平台数据库建表 SQL |
|
||||
|
||||
## 部署流程
|
||||
|
||||
### 前端部署
|
||||
### 一键部署(前端+后端)
|
||||
|
||||
```bash
|
||||
bash deploy.sh
|
||||
bash deploy.sh # 全量部署(后端+前端)
|
||||
bash deploy.sh server # 只部署后端
|
||||
bash deploy.sh front # 只部署前端
|
||||
```
|
||||
|
||||
构建前端 + scp 上传到服务器 `/var/www/dm.all8ai.top`。
|
||||
|
||||
### 后端部署
|
||||
|
||||
```bash
|
||||
bash deploy-server.sh
|
||||
```
|
||||
|
||||
rsync 同步代码到服务器 `/opt/sbrain-server` + npm install + pm2 重启。
|
||||
- 后端:rsync 同步到服务器 `/opt/sbrain-server` + npm install + pm2 重启
|
||||
- 前端:构建 + scp 上传到服务器 `/var/www/dm.all8ai.top`
|
||||
|
||||
### 本机 frp 隧道(launchd 系统级服务)
|
||||
|
||||
@@ -123,11 +161,19 @@ ssh ubuntu@152.136.182.184 'cat /opt/sbrain-server/.env'
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 本机 PostgreSQL 端口 5432 被 Homebrew PostgreSQL 占用,数据库 `bill_query` 在本地
|
||||
- frp 隧道将远程 15432 映射到本地 5432,服务器后端通过 15432 连接本机数据库
|
||||
- **平台库 `sbrain_admin` 在服务器本地 PostgreSQL(5432)**,业务库 `bill_query` 在本机 PostgreSQL(通过 frp 暴露为 15432)
|
||||
- `adminPool` 连服务器本地 5432 的 `sbrain_admin`(SCRAM 认证,用户 `sbrain_admin`,密码 `sbrain2026`)
|
||||
- `tenantPool` / `pool` 连 FRP 隧道 15432 的 `bill_query`(trust 认证,用户 `freedak`,无需密码)
|
||||
- `tenant_configs` 表中 `db_port` 必须为 `15432`,`db_password` 为 NULL(trust 认证)
|
||||
- `pg` 库在 `password` 为空字符串时会触发 SCRAM 认证失败,因此 `admin-pool.ts`、`database.ts`、`tenant-db.ts` 中空密码时不传 `password` 参数
|
||||
- `deploy.sh` 每次部署会覆盖服务器 `.env`,其中包含 `ADMIN_DB_*` 配置(`ADMIN_DB_PORT=5432`,`ADMIN_DB_PASSWORD=sbrain2026`),修改 `.env` 配置必须同步修改 `deploy.sh`
|
||||
- 租户用户统一存储在 `sbrain_admin.tenant_users` 表,通过 `tenant_id` 区分租户
|
||||
- `tenant_users.region` 字段为 `VARCHAR(500)`,区域经理的 `region` 存储逗号分隔的 `store_code` 列表(如 `0010,0011,0014`)
|
||||
- 密码使用 bcrypt 加密,平台管理员密码目前仍为明文(后续可改)
|
||||
- 本机只需运行 frpc(launchd 自启),后端已部署到服务器
|
||||
- 修改后端代码后执行 `bash deploy-server.sh` 部署到服务器
|
||||
- 修改前端代码后执行 `bash deploy.sh` 部署到服务器
|
||||
- 修改后端代码后执行 `bash deploy.sh server` 部署到服务器
|
||||
- 修改前端代码后执行 `bash deploy.sh front` 部署到服务器
|
||||
- 全量部署执行 `bash deploy.sh`(后端+前端)
|
||||
- `server/.env`(本机开发用)中 `DB_PORT=5432` 连接本地数据库,不要改为 5433
|
||||
- 服务器 `/opt/sbrain-server/.env` 中 `DB_PORT=15432` 连接 frp 隧道端口
|
||||
- frpc 断开后线上前端 API 会失效,需重新启动 frpc
|
||||
|
||||
Reference in New Issue
Block a user