- Remove outdated development plan from `development-plan.md`. - Update `operations.md` to include details on authorization cache configuration. - Revise `quickstart.md` for clarity on local development setup and database initialization. - Delete redundant `redis-authorization-cache.md`. - Add new `tenant-provisioning.md` to document the process of setting up a tenant from an empty database.
This commit is contained in:
@@ -1,47 +1,61 @@
|
||||
# 空数据库到租户建站
|
||||
# 本地开发快速上手
|
||||
|
||||
本页记录 Development 环境从全新 PostgreSQL 数据库完成平台管理员、租户、Owner 激活、网站发布和学生端访问的真实流程。数据库迁移只由 `Tiku.DbMigrator` 执行,API 不会自动更新 Schema。
|
||||
本页用于日常开发:初始化依赖、迁移数据库、启动 API/Worker/平台前端并完成基础验证。若要从空数据库验收“创建租户 → Owner 激活 → 发布站点”的完整流程,请改看[空数据库到租户建站验收](tenant-provisioning.md)。
|
||||
|
||||
## 1. 准备环境
|
||||
## 前置依赖
|
||||
|
||||
需要 .NET 10、Node.js 24+、npm 11+、PostgreSQL、Redis,以及 `psql`、`createdb`、`dropdb`。
|
||||
- .NET 10 SDK
|
||||
- Node.js 24+、npm 11+
|
||||
- PostgreSQL
|
||||
- Redis(Development 可不配置;涉及分布式缓存、频控或完整验收时应启动)
|
||||
|
||||
```bash
|
||||
dotnet --version
|
||||
node --version
|
||||
npm --version
|
||||
pg_isready -h 127.0.0.1 -p 5432
|
||||
redis-cli -h 127.0.0.1 -p 6379 ping
|
||||
```
|
||||
|
||||
首次拉取代码后安装依赖:
|
||||
首次拉取代码后恢复依赖:
|
||||
|
||||
```bash
|
||||
dotnet restore TIKU-BACKEND.slnx
|
||||
npm --prefix Tiku.PlatformAdmin.Web install
|
||||
npm --prefix /path/to/tiku-saas-web install
|
||||
```
|
||||
|
||||
## 2. 创建空数据库
|
||||
## 配置数据库
|
||||
|
||||
以下操作只针对本地数据库 `tiku`。如果它已经包含需要保留的数据,请先备份,不要执行清理命令。
|
||||
Development 未配置连接串时,默认使用当前系统用户连接本机 `tiku` 数据库:
|
||||
|
||||
```text
|
||||
Host=localhost;Database=tiku;Username=<当前系统用户>
|
||||
```
|
||||
|
||||
首次使用可创建数据库:
|
||||
|
||||
```bash
|
||||
dropdb --if-exists -h 127.0.0.1 -U <数据库用户> tiku
|
||||
createdb -h 127.0.0.1 -U <数据库用户> tiku
|
||||
```
|
||||
|
||||
Development 未配置连接串时默认使用当前系统用户连接本机 `tiku`。其他用户或端口应显式设置:
|
||||
使用其他地址、端口或账号时,通过环境变量覆盖:
|
||||
|
||||
```bash
|
||||
export ConnectionStrings__Database='Host=127.0.0.1;Port=5432;Database=tiku;Username=<数据库用户>;Password=<本地密码>'
|
||||
```
|
||||
|
||||
不要把连接串、密码或 Token 写入 `appsettings*.json`、README 或 Git。
|
||||
不要把连接串、密码、Token 或私钥写入仓库。
|
||||
|
||||
## 3. 初始化目录、starter 套餐和首个平台账号
|
||||
## 迁移与初始化
|
||||
|
||||
先设置一次性 Bootstrap 参数,再执行生产式空库初始化:
|
||||
API 不执行 Migration。数据库结构、内置权限/菜单目录和 `starter` 套餐统一由 `Tiku.DbMigrator` 初始化:
|
||||
|
||||
```bash
|
||||
ASPNETCORE_ENVIRONMENT=Development dotnet run --project Tiku.DbMigrator
|
||||
```
|
||||
|
||||
默认 Development seed 会在尚无平台角色绑定时创建 `admin@tiku.local`、演示租户和演示运营数据;随机临时密码只在首次创建时输出,首次登录必须改密。
|
||||
|
||||
若需要不含演示数据的空库,使用显式 Bootstrap 流程,不要运行默认 Development seed:
|
||||
|
||||
```bash
|
||||
export ASPNETCORE_ENVIRONMENT=Development
|
||||
@@ -54,157 +68,69 @@ dotnet run --project Tiku.DbMigrator -- \
|
||||
--bootstrap-platform-admin
|
||||
```
|
||||
|
||||
该命令按固定顺序执行:
|
||||
完整空库验收步骤见[空数据库到租户建站验收](tenant-provisioning.md)。
|
||||
|
||||
1. EF Core Migration;
|
||||
2. Feature、Permission、菜单和额度目录;
|
||||
3. 内置 `starter` 套餐及其已发布版本;
|
||||
4. 可选的平台超级管理员 Bootstrap。
|
||||
## 启动运行时
|
||||
|
||||
`starter` 是零元、CNY、已发布的建站基础套餐,包含 `core.backoffice` 和 `marketing.site_content`。首个平台账号使用临时密码,首次登录必须改密。
|
||||
|
||||
清除 Bootstrap 密码并再运行一次 Migrator,确认日常重复执行不会创建演示租户或重复目录:
|
||||
启动 API:
|
||||
|
||||
```bash
|
||||
unset TIKU_BOOTSTRAP_PLATFORM_ADMIN_PASSWORD
|
||||
unset TIKU_BOOTSTRAP_PLATFORM_ADMIN_EMAIL
|
||||
unset TIKU_BOOTSTRAP_PLATFORM_ADMIN_NAME
|
||||
|
||||
dotnet run --project Tiku.DbMigrator -- --skip-development-seed
|
||||
ASPNETCORE_ENVIRONMENT=Development dotnet run --project Tiku.Api --launch-profile http
|
||||
```
|
||||
|
||||
Migration 需要 `citext`、`ltree` 和 `pg_trgm` 扩展。执行用户必须可以创建这些扩展,或由数据库管理员预先安装。
|
||||
|
||||
## 4. 启动真实服务
|
||||
|
||||
确保 Redis 已运行,然后从后端仓库启动 API:
|
||||
|
||||
```bash
|
||||
export ASPNETCORE_ENVIRONMENT=Development
|
||||
export ConnectionStrings__Redis='localhost:6379,abortConnect=false'
|
||||
dotnet run --project Tiku.Api --launch-profile http
|
||||
```
|
||||
|
||||
API 在 Development 会同时拉起平台管理端 Vite 服务:
|
||||
`Tiku.Api.csproj` 的 SPA Proxy 会在 Development 启动 `Tiku.PlatformAdmin.Web` 的 Vite 服务。默认入口:
|
||||
|
||||
- 平台管理端:<http://localhost:5173>
|
||||
- API:<http://localhost:5090>
|
||||
- Scalar:<http://localhost:5090/scalar/v1>
|
||||
- OpenAPI:<http://localhost:5090/openapi/v1.json>
|
||||
- Liveness:<http://localhost:5090/api/health>
|
||||
- Readiness:<http://localhost:5090/api/health/ready>
|
||||
|
||||
不要使用 `http://localhost:5090/platform-admin/` 作为开发入口;该路径受 API 授权保护,未登录访问返回 401。
|
||||
|
||||
在 `tiku-saas-web` 仓库另开终端,使用真实 API 模式启动租户前端:
|
||||
后台循环不在 API 内运行。需要处理域名、订阅、任务队列、授权缓存失效或商业账务时,另开终端启动 Worker:
|
||||
|
||||
```bash
|
||||
VITE_DATA_MODE=api \
|
||||
VITE_DEV_API_TARGET='http://localhost:5090' \
|
||||
npm run dev -- --host 0.0.0.0 --port 5180
|
||||
ASPNETCORE_ENVIRONMENT=Development dotnet run --project Tiku.Worker
|
||||
```
|
||||
|
||||
浏览器始终请求同源 `/api`,Vite 只在服务端把它代理到 `VITE_DEV_API_TARGET`。代理保留原始 Host,因此 `school.localhost` 能由后端解析到正确租户。
|
||||
|
||||
## 5. 浏览器建站流程
|
||||
|
||||
### 5.1 平台首次登录
|
||||
|
||||
1. 打开 <http://localhost:5173>;
|
||||
2. 使用 Bootstrap 邮箱和临时密码登录;
|
||||
3. 按页面要求设置新密码;
|
||||
4. 进入“租户管理”。
|
||||
|
||||
### 5.2 创建租户和本地域名
|
||||
|
||||
点击“新建租户”,至少填写:
|
||||
|
||||
- 租户短编码,例如 `school`;
|
||||
- 租户名称;
|
||||
- 主域名 `school.localhost`;
|
||||
- Owner 姓名;
|
||||
- Owner 邮箱或手机号。
|
||||
|
||||
不选择套餐时,后端自动使用 `starter` 和默认试用天数。Development 配置只对精确的 `localhost` 或 `*.localhost` 启用 DNS/TLS 旁路,通常数秒内显示“DNS 与 TLS 已激活”。其他域名仍走真实 DNS 和网关流程。
|
||||
|
||||
### 5.3 签发并消费 Owner 链接
|
||||
|
||||
1. 域名 Active 后点击“领取激活链接”;
|
||||
2. 填写审计原因并确认;
|
||||
3. 立即保存弹窗中的一次性链接;
|
||||
4. 用完整链接打开 `http://school.localhost:5180/activate/...#token=...`;
|
||||
5. Owner 设置密码后自动进入 `/manage/onboarding`。
|
||||
|
||||
Token 只在签发成功弹窗显示一次。租户前端读入 Fragment 后立即清除地址栏;后端消费后不能重放。平台管理员看不到 Owner 密码,也不需要审批 Owner 激活。
|
||||
|
||||
### 5.4 配置并发布
|
||||
|
||||
向导依次完成:品牌信息、模板、主题样式、页面模块、桌面/移动预览、发布上线。保存草稿不会影响学生端;发布成功后 Runtime 读取已发布配置。
|
||||
|
||||
打开或刷新 <http://school.localhost:5180/>,应看到新的品牌、导航、主题和首页模块。退出租户后台后,可在 <http://school.localhost:5180/manage/login> 使用 Owner 账号重新登录。
|
||||
|
||||
## 6. 预期状态
|
||||
|
||||
| 阶段 | 预期状态 |
|
||||
| --- | --- |
|
||||
| 刚创建域名 | `pending` |
|
||||
| Development 后台任务处理完成 | 域名 `active` |
|
||||
| Owner 尚未领取链接 | `ready_to_issue` |
|
||||
| 链接签发 | `issued` |
|
||||
| Owner 激活并登录 | 进入 `/manage/onboarding` |
|
||||
| 草稿完成但未发布 | `ready_to_launch` |
|
||||
| 发布完成 | 学生端显示已发布配置 |
|
||||
|
||||
## 7. 常见问题
|
||||
|
||||
### `.localhost` 一直 Pending
|
||||
|
||||
确认 API 使用 `ASPNETCORE_ENVIRONMENT=Development`,并加载:
|
||||
|
||||
```json
|
||||
{
|
||||
"TenantDomains": {
|
||||
"PollSeconds": 2,
|
||||
"EnableDevelopmentLocalhostBypass": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
API 日志应出现 `Processed ... pending Development tenant domains`。非 Development 环境启用该旁路会在启动时失败。
|
||||
|
||||
### 激活页只出现 OPTIONS,没有 POST
|
||||
|
||||
不要把 API 地址配置为浏览器请求 Base URL。租户前端真实模式必须使用同源 `/api`,开发代理目标使用:
|
||||
如需 Redis,API 与 Worker 应使用同一实例:
|
||||
|
||||
```bash
|
||||
VITE_DEV_API_TARGET=http://localhost:5090
|
||||
export ConnectionStrings__Redis='localhost:6379,abortConnect=false'
|
||||
```
|
||||
|
||||
确保旧的 `VITE_API_BASE_URL` 未注入进程,并重启 Vite。
|
||||
## 验证修改
|
||||
|
||||
### 激活失败后地址栏已没有 Token
|
||||
```bash
|
||||
dotnet build TIKU-BACKEND.slnx --no-restore
|
||||
dotnet test TIKU-BACKEND.slnx --no-build
|
||||
dotnet format TIKU-BACKEND.slnx --verify-no-changes --no-restore
|
||||
npm --prefix Tiku.PlatformAdmin.Web run check
|
||||
dotnet ef migrations has-pending-model-changes \
|
||||
--project Tiku.Infrastructure \
|
||||
--startup-project Tiku.DbMigrator \
|
||||
--no-build
|
||||
git diff --check
|
||||
```
|
||||
|
||||
如果后端尚未消费 Token,可重新打开平台最初交付的完整链接。已经消费、过期或丢失明文时,必须由平台撤销并重新签发,不能从数据库或日志恢复。
|
||||
PostgreSQL 特有的 Migration、事务、约束和租户隔离行为必须由真实 PostgreSQL 集成测试验证,EF InMemory 不能替代。接口、DTO 和错误响应以当前运行时 OpenAPI/Scalar 为准。
|
||||
|
||||
### 发布后旧标签仍显示筹备页
|
||||
## 常见问题
|
||||
|
||||
草稿与已发布配置相互隔离。确认向导显示发布成功后,刷新学生端标签,让它重新请求 Runtime Bootstrap。
|
||||
### API 报数据库不可用
|
||||
|
||||
### Cookie 没有建立
|
||||
确认 PostgreSQL 已启动、数据库存在,并核对 `ConnectionStrings__Database` 或 `DATABASE_URL`。非 Development 环境没有本地默认连接串。
|
||||
|
||||
必须通过 `school.localhost:5180` 访问激活和后台,不能改用 `localhost:5180` 或把 `tenantId` 填进请求。浏览器 Session 使用 Secure/HttpOnly Cookie,写请求使用 CSRF 双提交 Token,前端不得降级保存 JWT。
|
||||
### 找不到平台管理员临时密码
|
||||
|
||||
默认 Development seed 和显式 Bootstrap 都只在创建账号时输出一次临时密码,后续运行不会重放。不要从日志或数据库恢复明文;应通过受控流程重置,或在确认无需保留本地数据后重建开发数据库。
|
||||
|
||||
### Readiness 返回 503
|
||||
|
||||
确认 PostgreSQL 和 Redis 均可访问。匿名 readiness 只返回总体状态;依赖详情需要具有 `platform:operations:view` 权限的平台账号。
|
||||
`/api/health/ready` 会检查 PostgreSQL 和已配置的 Redis。先验证数据库连接;配置 Redis 后还需确认 Redis 可访问。匿名响应不会暴露依赖详情。
|
||||
|
||||
## 8. 清理
|
||||
### API 启动了但后台任务不执行
|
||||
|
||||
先停止 API、平台 Vite 和租户 Vite,再只删除明确的本地数据库:
|
||||
Production 和常规 Development 都需要独立运行 `Tiku.Worker`。Development 仅额外在 API 中注册本地域名生命周期旁路,不代表 API 承载全部 Worker 循环。
|
||||
|
||||
```bash
|
||||
dropdb -h 127.0.0.1 -U <数据库用户> tiku
|
||||
```
|
||||
|
||||
该操作不可恢复,会删除本轮创建的平台账号、租户、Session、草稿和发布配置。
|
||||
|
||||
更多配置见[配置与后台任务](operations.md),安全边界见[认证、授权与租户隔离](architecture/security-and-tenancy.md)。
|
||||
下一步可阅读[系统架构与业务边界](architecture/overview.md)、[认证、授权与租户隔离](architecture/security-and-tenancy.md)和[配置与后台任务](operations.md)。
|
||||
|
||||
Reference in New Issue
Block a user