110 lines
4.4 KiB
Markdown
110 lines
4.4 KiB
Markdown
# CMS Service
|
||
|
||
内容管理系统(CMS)微服务,遵循 DDD 分层(api/application/domain/infrastructure),并与 IAM 服务集成实现“认证 + 租户隔离 + 权限裁决”:
|
||
|
||
- 认证/租户隔离:复用 [auth-kit](file:///home/shay/project/backend/auth-kit/README.md) 中间件(JWT 验签 + `X-Tenant-ID` 一致性校验)
|
||
- 权限裁决:通过 iam-client 调用 IAM `POST /authorize/check`(CMS 不内置 RBAC 聚合逻辑)
|
||
|
||
## 技术栈
|
||
|
||
- Rust:edition 2024 / Tokio
|
||
- Web:Axum
|
||
- DB:PostgreSQL / SQLx(启动时自动运行 migrations)
|
||
- 文档:utoipa + Scalar(`GET /scalar`)
|
||
- 观测:tracing + `common-telemetry`
|
||
- 鉴权集成:
|
||
- JWT:RS256(优先 JWKS 拉取,或配置静态公钥 PEM)
|
||
- RBAC:由 IAM 统一裁决
|
||
|
||
## 项目结构
|
||
|
||
DDD 分层目录:
|
||
|
||
- [src/api](file:///home/shay/project/backend/cms-service/src/api):HTTP 层(路由/handlers/中间件/OpenAPI)
|
||
- [src/application](file:///home/shay/project/backend/cms-service/src/application):应用服务编排(面向用例)
|
||
- [src/domain](file:///home/shay/project/backend/cms-service/src/domain):领域模型(实体/DTO)
|
||
- [src/infrastructure](file:///home/shay/project/backend/cms-service/src/infrastructure):基础设施(DB、repositories、iam-client)
|
||
|
||
关键入口文件:
|
||
|
||
- [main.rs](file:///home/shay/project/backend/cms-service/src/main.rs):配置加载、Telemetry、DB 连接、迁移、JWT/Tenant 中间件挂载
|
||
- [api/mod.rs](file:///home/shay/project/backend/cms-service/src/api/mod.rs):路由组装(`/v1`、`/scalar`、`/healthz`)
|
||
- [docs/API.md](file:///home/shay/project/backend/cms-service/docs/API.md):接口概览与权限点
|
||
|
||
## 快速开始(本地开发)
|
||
|
||
1. 复制并修改环境变量:
|
||
- `cp .env.example .env`
|
||
2. 准备 PostgreSQL 并配置 `DATABASE_URL`
|
||
3. 启动服务(会自动运行 migrations):
|
||
- `cargo run`
|
||
|
||
## 文档
|
||
|
||
- Scalar:`GET /scalar`
|
||
- 健康检查:`GET /healthz`
|
||
|
||
## API(v1)
|
||
|
||
资源入口:
|
||
|
||
- 栏目:`/v1/columns`
|
||
- 标签/分类:`/v1/tags`
|
||
- 媒体库:`/v1/media`
|
||
- 文章:`/v1/articles`
|
||
|
||
更完整的接口清单与权限点见: [docs/API.md](file:///home/shay/project/backend/cms-service/docs/API.md)
|
||
|
||
## 鉴权与租户隔离
|
||
|
||
- 必须携带:
|
||
- `Authorization: Bearer <access_token>`
|
||
- `X-Tenant-ID: <tenant_uuid>`(与 token 内 tenant_id 不一致将被拒绝)
|
||
- CMS 侧 JWT 校验基于 IAM 的公钥:
|
||
- 优先读 `JWT_PUBLIC_KEY_PEM`(静态公钥,无需访问 IAM)
|
||
- 否则读取 `IAM_JWKS_URL`(未配置则默认 `IAM_BASE_URL + /.well-known/jwks.json`)
|
||
- 权限校验由 IAM 统一裁决(CMS 侧仅通过 iam-client 调用 IAM `/authorize/check`)。
|
||
|
||
## 配置项(环境变量)
|
||
|
||
基础:
|
||
|
||
- `DATABASE_URL`:PostgreSQL 连接串(必填)
|
||
- `PORT`:监听端口(默认 3100)
|
||
- `SERVICE_NAME` / `LOG_LEVEL` / `LOG_TO_FILE` / `LOG_DIR` / `LOG_FILE_NAME`:日志与 Telemetry
|
||
|
||
IAM 集成:
|
||
|
||
- `IAM_BASE_URL`:IAM 服务地址(默认 `http://localhost:3000`)
|
||
- `IAM_JWKS_URL`:JWKS 地址(可选;未配置时使用 `IAM_BASE_URL + /.well-known/jwks.json`)
|
||
- `JWT_PUBLIC_KEY_PEM`:静态公钥 PEM(可选;配置后不走 JWKS 拉取)
|
||
- `IAM_TIMEOUT_MS`:调用 IAM 超时(默认 2000ms)
|
||
- `IAM_CACHE_TTL_SECONDS`:鉴权结果缓存 TTL(默认 10s)
|
||
- `IAM_STALE_IF_ERROR_SECONDS`:IAM 不可用时使用 stale cache 的窗口(默认 60s)
|
||
- `IAM_CACHE_MAX_ENTRIES`:缓存最大条目数(默认 50000,超过会清空)
|
||
|
||
示例配置见: [.env.example](file:///home/shay/project/backend/cms-service/.env.example)
|
||
|
||
## 与 IAM 的对接约束
|
||
|
||
CMS 运行时依赖 IAM 提供以下能力:
|
||
|
||
- 公钥发布:`GET /.well-known/jwks.json`(用于 RS256 验签;若使用 `JWT_PUBLIC_KEY_PEM` 可不依赖此端点)
|
||
- 权限裁决:`POST /authorize/check`(由 iam-client 调用;用于 `cms:*` 权限点校验)
|
||
|
||
## 数据库迁移
|
||
|
||
- 迁移文件目录: [migrations](file:///home/shay/project/backend/cms-service/migrations)
|
||
- 启动时自动执行:见 [db::run_migrations](file:///home/shay/project/backend/cms-service/src/infrastructure/db/mod.rs#L14-L16)
|
||
- 运维脚本(migrate/verify/rollback):见 [scripts/db/README.md](file:///home/shay/project/backend/cms-service/scripts/db/README.md)
|
||
|
||
## 测试
|
||
|
||
```bash
|
||
cargo test
|
||
```
|
||
|
||
当前包含:
|
||
|
||
- iam-client 缓存/降级测试: [iam_client_cache.rs](file:///home/shay/project/backend/cms-service/tests/iam_client_cache.rs)
|