From f3ffc18aaed8b3b36c73829367c6db0c9961f9b7 Mon Sep 17 00:00:00 2001 From: biss Date: Thu, 23 Jul 2026 16:25:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20[Eis.Tools=20(line=201)](C?= =?UTF-8?q?:/Users/BI/Documents/EIS-dotnet/src/Eis.Tools/Program.cs:1)?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=20database=20init/reset/seed?= =?UTF-8?q?=E3=80=82=20=E6=95=B0=E6=8D=AE=E5=BA=93=E7=BB=B4=E6=8A=A4?= =?UTF-8?q?=E3=80=81=E5=AE=89=E5=85=A8=E6=A0=A1=E9=AA=8C=E5=92=8C=E4=BA=8B?= =?UTF-8?q?=E5=8A=A1=E9=80=BB=E8=BE=91=E4=BD=8D=E4=BA=8E=20[DatabaseMainte?= =?UTF-8?q?nanceService.cs=20(line=201)](C:/Users/BI/Documents/EIS-dotnet/?= =?UTF-8?q?src/Eis.Infrastructure/Data/DatabaseMaintenanceService.cs:1)?= =?UTF-8?q?=E3=80=82=20=E5=86=85=E7=BD=AE=E5=AE=8C=E6=95=B4=E6=BC=94?= =?UTF-8?q?=E7=A4=BA=E6=95=B0=E6=8D=AE=EF=BC=9A1200=20=E5=90=8D=E8=80=83?= =?UTF-8?q?=E7=94=9F=E3=80=8110800=20=E6=9D=A1=E6=88=90=E7=BB=A9=E3=80=812?= =?UTF-8?q?404=20=E6=9D=A1=E6=8B=9B=E7=94=9F=E8=AE=B0=E5=BD=95=E3=80=82=20?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A7=20import-test-data.mjs=20=E5=92=8C?= =?UTF-8?q?=20reset-dev-database.mjs=20=E8=BF=90=E8=A1=8C=E5=85=A5?= =?UTF-8?q?=E5=8F=A3=E3=80=82=20Docker=20=E9=95=9C=E5=83=8F=E5=90=8C?= =?UTF-8?q?=E6=97=B6=E5=8C=85=E5=90=AB=20Web=20=E5=92=8C=20/app/tools/Eis.?= =?UTF-8?q?Tools.dll=E3=80=82=20[package.json=20(line=2011)](C:/Users/BI/D?= =?UTF-8?q?ocuments/EIS-dotnet/package.json:11)=20=E5=8E=9F=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E5=91=BD=E4=BB=A4=E5=B7=B2=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E8=B0=83=E7=94=A8=20.NET=E3=80=82=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E5=8F=91=E5=B8=83=E8=84=9A=E6=9C=AC=EF=BC=9A?= =?UTF-8?q?[publish.ps1=20(line=201)](C:/Users/BI/Documents/EIS-dotnet/scr?= =?UTF-8?q?ipts/publish.ps1:1)=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 8 +- Eis.slnx | 1 + MIGRATION.md | 6 +- README.md | 65 +- package.json | 14 +- scripts/export-dotnet-demo-seed.mjs | 44 ++ scripts/import-test-data.mjs | 202 ------ scripts/publish.ps1 | 45 ++ scripts/reset-dev-database.mjs | 4 - scripts/smoke-dotnet-migration.ps1 | 20 +- .../AdminAdmissionService.Documents.cs | 4 +- .../AdminAdmissionService.Operations.cs | 7 +- .../Configuration/EnvironmentFile.cs | 6 +- .../Data/DatabaseInitializer.cs | 55 +- .../Data/DatabaseMaintenanceService.cs | 647 ++++++++++++++++++ .../Data/DatabaseOptions.cs | 18 + .../Data/demo-seed-operations.json.gz | Bin 0 -> 272242 bytes .../Eis.Infrastructure.csproj | 1 + src/Eis.Tools/Eis.Tools.csproj | 11 + src/Eis.Tools/Program.cs | 263 +++++++ src/Eis.Web/Program.cs | 1 + .../Data/DatabaseMaintenanceServiceTests.cs | 134 ++++ tests/system.test.mjs | 24 +- 23 files changed, 1299 insertions(+), 281 deletions(-) create mode 100644 scripts/export-dotnet-demo-seed.mjs delete mode 100644 scripts/import-test-data.mjs create mode 100644 scripts/publish.ps1 delete mode 100644 scripts/reset-dev-database.mjs rename src/{Eis.Web => Eis.Infrastructure}/Configuration/EnvironmentFile.cs (84%) create mode 100644 src/Eis.Infrastructure/Data/DatabaseMaintenanceService.cs create mode 100644 src/Eis.Infrastructure/Data/demo-seed-operations.json.gz create mode 100644 src/Eis.Tools/Eis.Tools.csproj create mode 100644 src/Eis.Tools/Program.cs create mode 100644 tests/Eis.Infrastructure.Tests/Data/DatabaseMaintenanceServiceTests.cs diff --git a/Dockerfile b/Dockerfile index b80855d..6a2734a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,9 @@ FROM mcr.microsoft.com/dotnet/sdk:10.0-bookworm-slim AS build WORKDIR /src COPY . . RUN dotnet restore src/Eis.Web/Eis.Web.csproj \ - && dotnet publish src/Eis.Web/Eis.Web.csproj --configuration Release --output /app/publish --no-restore + && dotnet restore src/Eis.Tools/Eis.Tools.csproj \ + && dotnet publish src/Eis.Web/Eis.Web.csproj --configuration Release --output /app/web --no-restore \ + && dotnet publish src/Eis.Tools/Eis.Tools.csproj --configuration Release --output /app/tools --no-restore FROM mcr.microsoft.com/dotnet/aspnet:10.0-bookworm-slim AS runtime @@ -11,7 +13,8 @@ WORKDIR /app RUN apt-get update \ && apt-get install --yes --no-install-recommends curl \ && rm -rf /var/lib/apt/lists/* -COPY --from=build --chown=$APP_UID:$APP_UID /app/publish . +COPY --from=build --chown=$APP_UID:$APP_UID /app/web /app/web +COPY --from=build --chown=$APP_UID:$APP_UID /app/tools /app/tools RUN mkdir -p /app/data \ && chown -R $APP_UID:$APP_UID /app/data @@ -24,6 +27,7 @@ EXPOSE 4173 VOLUME ["/app/data"] USER $APP_UID +WORKDIR /app/web HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD ["curl", "--fail", "--silent", "--show-error", "http://127.0.0.1:4173/health/live"] diff --git a/Eis.slnx b/Eis.slnx index 5bda0c2..0163606 100644 --- a/Eis.slnx +++ b/Eis.slnx @@ -3,6 +3,7 @@ + diff --git a/MIGRATION.md b/MIGRATION.md index 4650c18..7e6ca60 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -11,6 +11,7 @@ - [x] 指标资格、招生账户、志愿、计划、投档、录取、报到和退档 - [x] ClosedXML 文件导入导出、文书模板和 Redis/本机缓存 - [x] SQLite / MySQL 自动建库和基础配置初始化 +- [x] 可发布的 .NET 数据库重建与 1200 人演示数据导入工具 - [x] 容器入口切换及 Node.js 后端运行依赖移除 ## 本地运行 @@ -41,9 +42,10 @@ dotnet run --project .\src\Eis.Web\Eis.Web.csproj ```powershell dotnet test .\Eis.slnx -dotnet publish .\src\Eis.Web\Eis.Web.csproj -c Release +pwsh.exe -NoLogo -NoProfile -NonInteractive -File .\scripts\publish.ps1 +dotnet .\artifacts\publish\tools\Eis.Tools.dll database seed --sqlite --path .\artifacts\demo.sqlite --dry-run pwsh.exe -NoLogo -NoProfile -NonInteractive -File .\scripts\smoke-dotnet-native.ps1 docker compose up --build --detach ``` -`scripts/smoke-dotnet-native.ps1` 会发布并启动纯 .NET 产物,在操作系统临时目录创建一次性 SQLite 数据库,检查健康状态、首页、CKEditor、原生登录和未知 API 404 后清理。`scripts/smoke-dotnet-migration.ps1` 保留为迁移期 Node/.NET 行为对照工具,不属于生产启动链路。 +`Eis.Tools.dll` 提供 `database init/reset/seed`;破坏性命令要求 `--confirm-target`,SQLite 自动保留原库备份,MySQL 拒绝系统库和未显式强制覆盖的非演示业务数据。`scripts/smoke-dotnet-native.ps1` 会发布并启动纯 .NET 产物,在操作系统临时目录创建一次性 SQLite 数据库,检查健康状态、首页、CKEditor、原生登录和未知 API 404 后清理。`scripts/smoke-dotnet-migration.ps1` 保留为迁移期 Node/.NET 行为对照工具,不属于生产启动链路。 diff --git a/README.md b/README.md index deb46ab..32d4ebb 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,25 @@ dotnet run --project .\src\Eis.Web\Eis.Web.csproj 本地开发无需额外配置,首次运行会自动创建 `data/exam.sqlite` 和完整关系型数据库结构,但不会导入学校、考生、考试或报名测试数据。首次建库会写入系统基础配置、默认审批流程和一个超级管理员;账号、密码和显示名可通过 `INITIAL_ADMIN_USERNAME`、`INITIAL_ADMIN_PASSWORD`、`INITIAL_ADMIN_DISPLAY_NAME` 设置。当前数据库结构版本为 v20。 +统一发布 Web 和数据库工具: + +```powershell +pwsh.exe -NoLogo -NoProfile -NonInteractive -File .\scripts\publish.ps1 +``` + +发布结果分别位于 `artifacts/publish/web` 和 `artifacts/publish/tools`。服务器启动 Web: + +```powershell +dotnet .\artifacts\publish\web\Eis.Web.dll +``` + +数据库工具使用编译后的 `Eis.Tools.dll`,不需要源代码或 `dotnet run`: + +```powershell +dotnet .\artifacts\publish\tools\Eis.Tools.dll database init --sqlite --path .\data\exam.sqlite +dotnet .\artifacts\publish\tools\Eis.Tools.dll database seed --sqlite --path .\data\demo.sqlite --dry-run +``` + ### Docker 项目根目录包含生产镜像和 Docker Compose 配置。默认使用 SQLite,数据库保存在命名卷 `exam-information-data` 中,因此重建容器不会丢失数据。 @@ -131,7 +150,15 @@ docker compose logs --follow app docker build --tag hengzhun-exam-system:local . ``` -镜像仅包含 ASP.NET Core 10 运行时,默认监听 `0.0.0.0:4173`,以非 root 用户运行,并通过 `/health/live` 执行健康检查。需要连接 MySQL 或 Redis 时,用运行环境变量覆盖 `DATABASE_CLIENT`、`DATABASE_URL`/`MYSQL_*`、`REDIS_URL`;认证状态默认使用同一 Redis 服务的独立 DB 1,也可以通过 `REDIS_SESSION_DB` 或 `REDIS_SESSION_URL` 单独配置。此时 SQLite 数据卷可以移除。 +镜像包含 ASP.NET Core 10 Web 宿主和编译后的 `/app/tools/Eis.Tools.dll`,默认监听 `0.0.0.0:4173`,以非 root 用户运行,并通过 `/health/live` 执行健康检查。需要连接 MySQL 或 Redis 时,用运行环境变量覆盖 `DATABASE_CLIENT`、`DATABASE_URL`/`MYSQL_*`、`REDIS_URL`;认证状态默认使用同一 Redis 服务的独立 DB 1,也可以通过 `REDIS_SESSION_DB` 或 `REDIS_SESSION_URL` 单独配置。此时 SQLite 数据卷可以移除。 + +容器内执行数据库工具前应先停止 Web,SQLite 目标必须与命名卷路径完全一致: + +```powershell +docker compose stop app +docker compose run --rm --entrypoint dotnet app /app/tools/Eis.Tools.dll database seed --sqlite --path /app/data/exam.sqlite --confirm-target /app/data/exam.sqlite +docker compose up --detach app +``` #### Gitea Actions 自动发布到 Docker Hub 与 Gitea 软件包 @@ -165,7 +192,7 @@ git push origin v1.3.0-rc.1 首次成功推送后,容器镜像会出现在 `biss` 所有者的软件包列表。Gitea 的软件包归属于用户或组织,不会天然归属于某个仓库;打开该软件包的设置页面,将它关联到 `Exam-Information-System`,即可让它显示在此仓库的“软件包”页。之后可使用 `docker pull git.biss.click/biss/exam-information-system:latest` 拉取。 -应用会在空库上自动创建结构和基础配置。旧版 Node 数据重置、样例数据和地区快照构建脚本仍保留为开发维护工具,不会被生产镜像复制或执行;运行这些脚本前必须明确数据库目标,且不得对生产业务库执行。 +应用会在空库上自动创建结构和基础配置。测试数据导入和空库重建均由编译后的 `Eis.Tools.dll` 完成;旧 Node 导入入口已移除。演示数据包内置于 `Eis.Infrastructure.dll`,生产服务器不需要 Node.js。 ## 数据库配置 @@ -252,21 +279,25 @@ dotnet run --project .\src\Eis.Web\Eis.Web.csproj ### 导入服务器 MySQL 测试数据 -先停止正在运行的应用进程,确认服务器 `.env` 中已经设置 `DATABASE_CLIENT=mysql` 及完整 MySQL 连接参数,然后执行: +先停止正在运行的应用进程,确认服务器 `.env` 中已经设置 `DATABASE_CLIENT=mysql` 及完整 MySQL 连接参数。先预检并确认工具输出的数据库名: ```powershell -npm run seed-test-data:mysql +dotnet .\artifacts\publish\tools\Eis.Tools.dll database seed --mysql --dry-run ``` -脚本会读取 `.env`,校验当前连接的数据库名称、v15 表结构和已有数据。目标是新数据库时会自动建表并导入;目标只有首次启动生成的空业务结构时会在事务中替换为样例数据。若检测到学校、考生、考试、报名等业务数据,脚本默认拒绝覆盖。 - -仅在确认目标是可以完全覆盖的测试库时使用: +确认目标测试数据库名为 `exam_test` 后执行: ```powershell -npm run seed-test-data:mysql -- --force +dotnet .\artifacts\publish\tools\Eis.Tools.dll database seed --mysql --confirm-target exam_test ``` -强制模式会删除该 MySQL 数据库内现有应用数据并在同一事务中写入样例数据,但不会删除数据库或数据表。导入完成后再重新启动应用,避免导入期间出现并发写入或保留旧登录会话。不要对生产业务库执行此命令。本地需要明确使用 SQLite 时可运行 `npm run seed-test-data:sqlite`。 +工具会读取 `.env`,拒绝 MySQL 系统数据库,校验 v20 结构和已有数据,并在同一事务内清理、导入。若检测到无法识别为内置演示数据的业务记录,默认拒绝覆盖。仅在确认目标确实是可完全覆盖的测试库时追加: + +```powershell +dotnet .\artifacts\publish\tools\Eis.Tools.dll database seed --mysql --confirm-target exam_test --force +``` + +强制模式会删除该 MySQL 数据库内现有应用数据并在同一事务中写入样例数据,但不会删除数据库本身。MySQL 操作前应另行完成数据库备份;不要对生产业务库执行该命令。 ## 中考志愿填报与招生录取 @@ -307,20 +338,20 @@ npm run seed-test-data:mysql -- --force ## 测试结束后初始化系统 -先停止应用,然后运行以下命令。命令会读取 `.env` 并自动选择 SQLite 或 MySQL,删除样例学校、考生、考试、报名等业务数据,恢复系统基础配置和一个初始超级管理员: +先停止应用。SQLite 重建会自动生成带时间戳的原库备份,然后恢复系统基础配置和一个初始超级管理员: ```powershell -npm run initialize-system +dotnet .\artifacts\publish\tools\Eis.Tools.dll database reset --sqlite --path .\data\exam.sqlite --confirm-target .\data\exam.sqlite ``` -也可以明确指定数据库类型: +MySQL 应先执行 `--dry-run` 确认目标,再明确填写数据库名: ```powershell -npm run initialize-system:sqlite -npm run initialize-system:mysql +dotnet .\artifacts\publish\tools\Eis.Tools.dll database reset --mysql --dry-run +dotnet .\artifacts\publish\tools\Eis.Tools.dll database reset --mysql --confirm-target exam_test ``` -MySQL 模式会自动识别由本项目生成的批量样例数据并清理。若目标包含无法识别为样例数据的业务记录,命令会拒绝执行;只有明确确认目标可完全清空时才可运行 `npm run initialize-system:mysql -- --force`。初始化完成后,初始管理员账号由 `.env` 中的 `INITIAL_ADMIN_USERNAME`、`INITIAL_ADMIN_PASSWORD`、`INITIAL_ADMIN_DISPLAY_NAME` 决定,然后再重新启动应用。 +MySQL 模式会自动识别由本项目生成的批量演示数据;目标包含非演示业务记录时仍会拒绝,只有确认可覆盖时才能追加 `--force`。初始化管理员由 `.env` 中的 `INITIAL_ADMIN_USERNAME`、`INITIAL_ADMIN_PASSWORD`、`INITIAL_ADMIN_DISPLAY_NAME` 决定。 ## 自动化测试 @@ -340,13 +371,15 @@ Eis.slnx .NET 10 解决方案 src/Eis.Domain 领域模型与业务值 src/Eis.Application 应用服务契约 src/Eis.Infrastructure SQLite/MySQL、认证、缓存、Excel 与业务实现 +src/Eis.Tools 可独立发布的数据库初始化、重建和演示数据工具 src/Eis.Web ASP.NET Core 宿主、端点和发布静态资源 tests/Eis.Infrastructure.Tests xUnit 自动化测试 index.html / styles.css / app.js 前端入口、样式和控制器 src/client 公共、考生、管理及招生前端模块 src/database/schema.mjs 兼容 SQLite/MySQL 的 v20 建库定义 -scripts 迁移验证与旧版开发数据维护工具 +scripts/publish.ps1 Web 与数据库工具统一发布脚本 +scripts 迁移验证及演示数据包维护工具 server.mjs / src/routes 仅保留的旧 Node 行为对照源码 data/exam.sqlite 本地运行后生成的 SQLite 数据库 .env.example 开发与生产环境变量模板 diff --git a/package.json b/package.json index 69f9b02..f305f31 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,13 @@ "test": "dotnet test Eis.slnx", "test:legacy": "node tests/client-auth.test.mjs && node tests/api-dedup.test.mjs && node tests/cache.test.mjs && node tests/auth-state.test.mjs && node tests/state-cache.test.mjs && node tests/document-verification.test.mjs && node tests/admission.test.mjs && node tests/seed.test.mjs && node tests/system.test.mjs", "test:cache": "node tests/cache.test.mjs", - "reset-db": "node scripts/reset-dev-database.mjs", - "seed-test-data": "node scripts/import-test-data.mjs", - "seed-test-data:sqlite": "node scripts/import-test-data.mjs --sqlite", - "seed-test-data:mysql": "node scripts/import-test-data.mjs --mysql", - "initialize-system": "node scripts/import-test-data.mjs --empty", - "initialize-system:sqlite": "node scripts/import-test-data.mjs --empty --sqlite", - "initialize-system:mysql": "node scripts/import-test-data.mjs --empty --mysql" + "reset-db": "dotnet run --project src/Eis.Tools -- database reset", + "seed-test-data": "dotnet run --project src/Eis.Tools -- database seed", + "seed-test-data:sqlite": "dotnet run --project src/Eis.Tools -- database seed --sqlite", + "seed-test-data:mysql": "dotnet run --project src/Eis.Tools -- database seed --mysql", + "initialize-system": "dotnet run --project src/Eis.Tools -- database reset", + "initialize-system:sqlite": "dotnet run --project src/Eis.Tools -- database reset --sqlite", + "initialize-system:mysql": "dotnet run --project src/Eis.Tools -- database reset --mysql" }, "dependencies": { "ckeditor5": "^48.3.1", diff --git a/scripts/export-dotnet-demo-seed.mjs b/scripts/export-dotnet-demo-seed.mjs new file mode 100644 index 0000000..479aecc --- /dev/null +++ b/scripts/export-dotnet-demo-seed.mjs @@ -0,0 +1,44 @@ +import { pbkdf2Sync } from 'node:crypto'; +import { writeFile } from 'node:fs/promises'; +import { fileURLToPath } from 'node:url'; +import { dirname, join, resolve } from 'node:path'; +import { gzipSync } from 'node:zlib'; +import { buildSeedOperations } from '../database.mjs'; +import { createSeedDatabase } from '../src/data/seed.mjs'; + +const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const outputPath = join(root, 'src', 'Eis.Infrastructure', 'Data', 'demo-seed-operations.json.gz'); +const generatedAt = '2026-07-23T00:00:00.000Z'; +const deterministicSalt = 'eis-dotnet-demo-seed'; +const hashPassword = password => { + const hash = pbkdf2Sync(password, deterministicSalt, 120000, 32, 'sha256').toString('hex'); + return `${deterministicSalt}:${hash}`; +}; + +const database = createSeedDatabase({ + nowIso: () => generatedAt, + hashPassword +}); +database.meta.version = 20; +const operations = buildSeedOperations(database); +const payload = { + version: 1, + schemaVersion: 20, + generatedAt, + summary: { + schools: database.schools.length, + users: database.users.length, + candidates: database.candidateProfiles.length, + registrations: database.registrations.length, + results: database.results.length, + admissionRecords: database.admissionRecords.length, + firstRoundPreferences: database.admissionRecords.filter( + item => item.kind === 'preference' && Number(item.payload?.round || 1) === 1 + ).length, + operations: operations.length + }, + operations +}; +const compressed = gzipSync(Buffer.from(JSON.stringify(payload)), { level: 9 }); +await writeFile(outputPath, compressed); +console.log(JSON.stringify({ outputPath, compressedBytes: compressed.length, ...payload.summary })); diff --git a/scripts/import-test-data.mjs b/scripts/import-test-data.mjs deleted file mode 100644 index fb40c57..0000000 --- a/scripts/import-test-data.mjs +++ /dev/null @@ -1,202 +0,0 @@ -import { pbkdf2Sync, randomBytes } from 'node:crypto'; -import { existsSync } from 'node:fs'; -import { rm } from 'node:fs/promises'; -import { isAbsolute, join, relative, resolve } from 'node:path'; -import { loadEnvFile } from 'node:process'; -import { buildSeedOperations, createDatabase, relationalTables } from '../database.mjs'; -import { createBaseDatabase } from '../src/data/base.mjs'; -import { createSeedDatabase } from '../src/data/seed.mjs'; -import { CURRENT_SCHEMA_VERSION } from '../src/database/version.mjs'; - -const root = resolve(process.cwd()); -const envPath = join(root, '.env'); -if (existsSync(envPath)) loadEnvFile(envPath); - -const options = new Set(process.argv.slice(2)); -if (options.has('--mysql') && options.has('--sqlite')) throw new Error('不能同时指定 --mysql 和 --sqlite'); -const configuredClient = options.has('--mysql') ? 'mysql' : options.has('--sqlite') ? 'sqlite' : process.env.DATABASE_CLIENT; -const client = String(configuredClient || (process.env.NODE_ENV === 'production' ? 'mysql' : 'sqlite')).toLowerCase(); -if (!['sqlite', 'mysql'].includes(client)) throw new Error(`不支持的 DATABASE_CLIENT:${client}`); -process.env.DATABASE_CLIENT = client; -const force = options.has('--force'); -const initializeEmpty = options.has('--empty'); - -function hashPassword(password, salt = randomBytes(16).toString('hex')) { - const hash = pbkdf2Sync(password, salt, 120000, 32, 'sha256').toString('hex'); - return `${salt}:${hash}`; -} - -const createTargetState = () => initializeEmpty - ? createBaseDatabase({ - nowIso: () => new Date().toISOString(), - hashPassword, - initialAdmin: { - username: process.env.INITIAL_ADMIN_USERNAME, - password: process.env.INITIAL_ADMIN_PASSWORD, - displayName: process.env.INITIAL_ADMIN_DISPLAY_NAME - } - }) - : createSeedDatabase({ nowIso: () => new Date().toISOString(), hashPassword }); - -async function prepareSqlite() { - const databasePath = resolve(process.env.SQLITE_PATH || join(root, 'data', 'exam.sqlite')); - const relativePath = relative(root, databasePath); - if (!relativePath || relativePath.startsWith('..') || isAbsolute(relativePath)) { - throw new Error('拒绝覆盖工作区以外的 SQLite 数据库'); - } - await rm(databasePath, { force: true }); - await rm(`${databasePath}-shm`, { force: true }); - await rm(`${databasePath}-wal`, { force: true }); - process.env.SQLITE_PATH = databasePath; - return databasePath; -} - -function mysqlPoolOptions(mysql) { - if (process.env.DATABASE_URL) return mysql.createPool(process.env.DATABASE_URL); - if (!process.env.MYSQL_HOST || !process.env.MYSQL_USER || !process.env.MYSQL_DATABASE) { - throw new Error('MySQL 配置不完整:请在 .env 设置 DATABASE_URL,或 MYSQL_HOST、MYSQL_USER、MYSQL_DATABASE'); - } - return mysql.createPool({ - host: process.env.MYSQL_HOST, - port: Number(process.env.MYSQL_PORT || 3306), - user: process.env.MYSQL_USER, - password: process.env.MYSQL_PASSWORD || '', - database: process.env.MYSQL_DATABASE, - waitForConnections: true, - connectionLimit: 2, - charset: 'utf8mb4', - timezone: 'Z', - enableKeepAlive: true - }); -} - -const mysqlBusinessTables = [ - 'schools', 'school_classes', 'candidate_profiles', 'notices', 'exams', 'exam_subjects', - 'registrations', 'registration_subjects', 'exam_arrangement_plans', 'admit_cards', 'admit_card_subjects', - 'results', 'test_centers', 'test_rooms', 'center_change_requests', 'center_change_rooms', - 'candidate_account_batches', 'candidate_account_batch_items', 'workflow_instances', 'workflow_actions', 'admission_records', 'audit_logs' -]; - -async function prepareMysql() { - const { default: mysql } = await import('mysql2/promise'); - const pool = mysqlPoolOptions(mysql); - let connection; - try { - connection = await pool.getConnection(); - const [[databaseRow]] = await connection.query('SELECT DATABASE() AS name'); - const databaseName = String(databaseRow?.name || ''); - if (!databaseName || ['mysql', 'information_schema', 'performance_schema', 'sys'].includes(databaseName.toLowerCase())) { - throw new Error(`拒绝向系统数据库导入测试数据:${databaseName || '未选择数据库'}`); - } - - const [tableRows] = await connection.query(` - SELECT TABLE_NAME FROM information_schema.TABLES - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_TYPE = 'BASE TABLE' - `); - const existingTables = new Set(tableRows.map(row => row.TABLE_NAME)); - const existingAppTables = relationalTables.filter(table => existingTables.has(table)); - if (!existingAppTables.length) return { location: `MySQL database ${databaseName}`, initialized: false }; - if (existingAppTables.length !== relationalTables.length) { - const missing = relationalTables.filter(table => !existingTables.has(table)); - throw new Error(`MySQL 数据库结构不完整,缺少:${missing.join(', ')}。请先使用空数据库启动一次应用完成建表`); - } - - const [metadataRows] = await connection.query('SELECT schema_version FROM schema_metadata WHERE id = 1'); - if (Number(metadataRows[0]?.schema_version) !== CURRENT_SCHEMA_VERSION) { - throw new Error(`MySQL 数据库结构版本不是 v${CURRENT_SCHEMA_VERSION}(当前 ${metadataRows[0]?.schema_version ?? '未知'}),请先完成结构初始化`); - } - - const [examPartitionRows] = await connection.query( - 'SELECT candidates_table, admissions_table, results_table, centers_table FROM exam_data_partitions' - ); - const [schoolPartitionRows] = await connection.query('SELECT students_table FROM school_student_partitions'); - const dynamicPartitionTables = [ - ...examPartitionRows.flatMap(row => [row.candidates_table, row.admissions_table, row.results_table, row.centers_table]), - ...schoolPartitionRows.map(row => row.students_table) - ]; - if (dynamicPartitionTables.some(table => !/^[a-z][a-z0-9_]{0,63}$/.test(table))) { - throw new Error('分表登记中存在非法表名,拒绝替换测试数据'); - } - - const nonEmpty = []; - for (const table of mysqlBusinessTables) { - const [[row]] = await connection.query(`SELECT COUNT(*) AS count FROM \`${table}\``); - if (Number(row.count) > 0) nonEmpty.push(`${table}=${row.count}`); - } - const [[userRow]] = await connection.query('SELECT COUNT(*) AS count FROM users'); - if (Number(userRow.count) > 1) nonEmpty.push(`users=${userRow.count}`); - let recognizedTestData = false; - if (initializeEmpty && nonEmpty.length) { - const [[bulkUsers]] = await connection.query("SELECT COUNT(*) AS count FROM users WHERE id LIKE 'usr_bulk_%'"); - const [[testSchools]] = await connection.query("SELECT COUNT(*) AS count FROM schools WHERE id IN ('school_hz1', 'school_hz3', 'school_hz5', 'school_hz7', 'school_hz9')"); - recognizedTestData = Number(bulkUsers.count) >= 1100 && Number(testSchools.count) === 5; - } - if (nonEmpty.length && !force && !recognizedTestData) { - const forceCommand = initializeEmpty - ? 'npm run initialize-system:mysql -- --force' - : 'npm run seed-test-data:mysql -- --force'; - throw new Error( - `MySQL 数据库 ${databaseName} 已有业务数据(${nonEmpty.slice(0, 8).join(', ')}${nonEmpty.length > 8 ? ', ...' : ''})。` + - `如确认这是可覆盖的测试库,请运行 ${forceCommand}` - ); - } - if (nonEmpty.length) { - console.warn(`[${recognizedTestData ? 'test-data cleanup' : 'force'}] Replacing existing business data in MySQL database ${databaseName}`); - } else { - console.log(`Preparing empty MySQL database ${databaseName} for ${initializeEmpty ? 'system initialization' : 'test data'}`); - } - - const state = createTargetState(); - await connection.query('SET FOREIGN_KEY_CHECKS = 0'); - await connection.beginTransaction(); - try { - // 先移除考试,使归档成绩保护触发器在清理 results 时不再命中。 - const clearOrder = ['exams', ...[...relationalTables].reverse().filter(table => !['schema_metadata', 'exams'].includes(table))]; - for (const table of clearOrder) await connection.query(`DELETE FROM \`${table}\``); - for (const operation of buildSeedOperations(state)) await connection.execute(operation.sql, operation.params); - await connection.commit(); - } catch (error) { - await connection.rollback(); - throw error; - } finally { - await connection.query('SET FOREIGN_KEY_CHECKS = 1'); - } - for (const table of dynamicPartitionTables) await connection.query(`DROP TABLE IF EXISTS \`${table}\``); - return { location: `MySQL database ${databaseName}`, initialized: true }; - } finally { - connection?.release(); - await pool.end(); - } -} - -let location; -let mysqlAlreadyImported = false; -if (client === 'sqlite') { - location = await prepareSqlite(); -} else { - const prepared = await prepareMysql(); - location = prepared.location; - mysqlAlreadyImported = prepared.initialized; -} -const database = await createDatabase({ - root, - seed: createTargetState -}); -const state = await database.read(); -await database.close(); - -const pending = state.registrations.filter(item => item.status === 'pending').length; -const rejected = state.registrations.filter(item => item.status === 'rejected').length; -const unpaid = state.registrations.filter(item => item.status === 'approved' && item.paymentStatus === 'unpaid').length; -const paid = state.registrations.filter(item => item.status === 'approved' && item.paymentStatus === 'paid').length; -if (initializeEmpty) { - console.log(`Initialized empty system in ${location}${mysqlAlreadyImported ? ' (transactional replace)' : ''}`); - console.log(`${state.users.length} initial administrator, ${state.schools.length} schools, ${state.candidateProfiles.length} candidates, ${state.registrations.length} registrations`); -} else { - console.log(`Imported test data into ${location}${mysqlAlreadyImported ? ' (transactional replace)' : ''}`); - console.log(`${state.schools.filter(item => item.isSourceSchool).length} source schools, ${state.schools.filter(item => item.isAdmissionSchool).length} admission schools, ${state.candidateProfiles.length} candidates, ${state.registrations.length} registrations`); - console.log(`pending ${pending}, rejected ${rejected}, approved/unpaid ${unpaid}, approved/paid ${paid}`); - console.log(`${state.results.length} published subject scores, ${state.admissionRecords.filter(item => item.kind === 'preference' && Number(item.payload?.round || 1) === 1).length} first-round preferences`); - console.log(`arrangement plans ${state.arrangementPlans.length}, admit cards ${state.registrations.filter(item => item.admitCard).length}`); - console.log('all predefined test account passwords: 12345678'); -} diff --git a/scripts/publish.ps1 b/scripts/publish.ps1 new file mode 100644 index 0000000..06b515d --- /dev/null +++ b/scripts/publish.ps1 @@ -0,0 +1,45 @@ +[CmdletBinding()] +param( + [string]$OutputDirectory = (Join-Path $PSScriptRoot '..\artifacts\publish') +) + +$ErrorActionPreference = 'Stop' +$repositoryRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot '..')).Path +$publishRoot = [IO.Path]::GetFullPath( + $(if ([IO.Path]::IsPathRooted($OutputDirectory)) { + $OutputDirectory + } + else { + Join-Path $repositoryRoot $OutputDirectory + })) + +$projects = @( + @{ + Project = Join-Path $repositoryRoot 'src\Eis.Web\Eis.Web.csproj' + Output = Join-Path $publishRoot 'web' + }, + @{ + Project = Join-Path $repositoryRoot 'src\Eis.Tools\Eis.Tools.csproj' + Output = Join-Path $publishRoot 'tools' + } +) + +foreach ($item in $projects) { + $nativeArgs = @( + 'publish' + $item.Project + '--configuration' + 'Release' + '--output' + $item.Output + ) + & dotnet @nativeArgs + $exitCode = $LASTEXITCODE + if ($exitCode -ne 0) { + throw "dotnet publish 失败,退出码:$exitCode" + } +} + +Write-Host "Web 发布目录:$(Join-Path $publishRoot 'web')" +Write-Host "数据库工具目录:$(Join-Path $publishRoot 'tools')" +Write-Host "工具示例:dotnet $(Join-Path $publishRoot 'tools\Eis.Tools.dll') database seed --dry-run" diff --git a/scripts/reset-dev-database.mjs b/scripts/reset-dev-database.mjs deleted file mode 100644 index 9492a52..0000000 --- a/scripts/reset-dev-database.mjs +++ /dev/null @@ -1,4 +0,0 @@ -// Keep the historical reset-db entry point, but run the same guarded initializer used -// by initialize-system so SQLite, MySQL, .env loading and schema checks stay in sync. -if (!process.argv.slice(2).includes('--empty')) process.argv.push('--empty'); -await import('./import-test-data.mjs'); diff --git a/scripts/smoke-dotnet-migration.ps1 b/scripts/smoke-dotnet-migration.ps1 index ff1ebb7..8d161cc 100644 --- a/scripts/smoke-dotnet-migration.ps1 +++ b/scripts/smoke-dotnet-migration.ps1 @@ -245,7 +245,12 @@ try { TOTP_ENCRYPTION_KEY = 'migration-smoke-totp-key-32-characters-minimum' DOCUMENT_VERIFICATION_SECRET = 'migration-smoke-document-key-32-characters-minimum' } - $seedProcess = Start-TestProcess -FileName $nodeExecutable -ArgumentList @('scripts/import-test-data.mjs', '--sqlite') -Environment $nodeEnvironment + $seedProcess = Start-TestProcess -FileName $dotnetExecutable -ArgumentList @( + 'run', '--project', 'src/Eis.Tools', '--', + 'database', 'seed', '--sqlite', + '--path', $smokeDatabasePath, + '--confirm-target', $smokeDatabasePath + ) -Environment $nodeEnvironment if (-not $seedProcess.WaitForExit(30000)) { $seedProcess.Kill($true) throw 'Timed out while preparing the migration smoke-test database' @@ -404,6 +409,7 @@ try { if ($noticePayload.notice.title -ne 'ASP.NET Core 迁移冒烟通知' -or $noticePayload.notice.content -match ' item.Data["archivedAt"] is null) - .Select(item => (JsonNode)PublicExam(item)).ToArray()), + .Select(item => item.Data.DeepClone()).ToArray()), ["template"] = template, ["updatedAt"] = JsonValue.Create(record?.UpdatedAt) }); @@ -265,7 +265,7 @@ internal sealed partial class AdminAdmissionService var completed = data.Operational.Exams.Where(exam => Records(data, "setting", exam.Id).Any(setting => setting.Status == "completed") && placements.Any(item => Text(item["examId"]) == exam.Id && Text(item["status"]) == "final")) - .Select(item => (JsonNode)PublicExam(item)).ToArray(); + .Select(item => item.Data.DeepClone()).ToArray(); return Success(new JsonObject { ["ok"] = true, diff --git a/src/Eis.Infrastructure/Administration/AdminAdmissionService.Operations.cs b/src/Eis.Infrastructure/Administration/AdminAdmissionService.Operations.cs index 481252c..65f9514 100644 --- a/src/Eis.Infrastructure/Administration/AdminAdmissionService.Operations.cs +++ b/src/Eis.Infrastructure/Administration/AdminAdmissionService.Operations.cs @@ -32,7 +32,8 @@ internal sealed partial class AdminAdmissionService }).ToArray(); var home = await publicQueries.GetHomeAsync(cancellationToken); var notifications = (home["notices"] as JsonArray ?? []).OfType() - .Where(item => Text(item["schoolId"]).Length == 0 || Text(item["schoolId"]) == school.Id) + .Where(item => Text(item["sourceType"]).Length > 0 && + (Text(item["schoolId"]).Length == 0 || Text(item["schoolId"]) == school.Id)) .Take(6) .Select(item => { @@ -43,7 +44,7 @@ internal sealed partial class AdminAdmissionService var exams = data.Operational.Exams.Where(item => item.Data["archivedAt"] is null && Records(data, "setting", item.Id).Any(setting => Boolean(setting.Payload["enabled"]))) - .Select(item => (JsonNode)PublicExam(item)).ToArray(); + .Select(item => item.Data.DeepClone()).ToArray(); return Success(new JsonObject { ["ok"] = true, @@ -76,7 +77,7 @@ internal sealed partial class AdminAdmissionService ["school"] = SchoolJson(school), ["plans"] = new JsonArray(plans), ["exams"] = new JsonArray(data.Operational.Exams.Where(item => item.Data["archivedAt"] is null) - .Select(item => (JsonNode)PublicExam(item)).ToArray()), + .Select(item => item.Data.DeepClone()).ToArray()), ["sourceSchools"] = new JsonArray(data.Directory.Schools .Where(item => item.Active && item.IsSourceSchool) .Select(item => (JsonNode)SchoolJson(item)).ToArray()) diff --git a/src/Eis.Web/Configuration/EnvironmentFile.cs b/src/Eis.Infrastructure/Configuration/EnvironmentFile.cs similarity index 84% rename from src/Eis.Web/Configuration/EnvironmentFile.cs rename to src/Eis.Infrastructure/Configuration/EnvironmentFile.cs index b96f017..3e7a4a5 100644 --- a/src/Eis.Web/Configuration/EnvironmentFile.cs +++ b/src/Eis.Infrastructure/Configuration/EnvironmentFile.cs @@ -1,4 +1,4 @@ -namespace Eis.Web.Configuration; +namespace Eis.Infrastructure.Configuration; public static class EnvironmentFile { @@ -35,7 +35,9 @@ public static class EnvironmentFile } var value = line[(separator + 1)..].Trim(); - if (value.Length >= 2 && ((value[0] == '"' && value[^1] == '"') || (value[0] == '\'' && value[^1] == '\''))) + if (value.Length >= 2 && + ((value[0] == '"' && value[^1] == '"') || + (value[0] == '\'' && value[^1] == '\''))) { value = value[1..^1]; } diff --git a/src/Eis.Infrastructure/Data/DatabaseInitializer.cs b/src/Eis.Infrastructure/Data/DatabaseInitializer.cs index b8678b2..792cf6f 100644 --- a/src/Eis.Infrastructure/Data/DatabaseInitializer.cs +++ b/src/Eis.Infrastructure/Data/DatabaseInitializer.cs @@ -30,38 +30,41 @@ internal sealed partial class DatabaseInitializer( await ExecuteAsync(connection, match.Groups["sql"].Value, cancellationToken); } } - await SeedBaseStateAsync(connection, cancellationToken); + await SeedBaseStateAsync(connection, null, cancellationToken); } - private async Task SeedBaseStateAsync(DbConnection connection, CancellationToken cancellationToken) + internal async Task SeedBaseStateAsync( + DbConnection connection, + DbTransaction? transaction, + CancellationToken cancellationToken) { var now = DateTimeOffset.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss.fff'Z'", CultureInfo.InvariantCulture); - if (!await ExistsAsync(connection, "schema_metadata", cancellationToken)) + if (!await ExistsAsync(connection, transaction, "schema_metadata", cancellationToken)) { await ExecuteAsync(connection, """ INSERT INTO schema_metadata (id, schema_version, app_version, self_registration_enabled, created_at) VALUES (1, @version, @version, 0, @createdAt) """, - [("@version", SchemaVersion), ("@createdAt", now)], cancellationToken); + [("@version", SchemaVersion), ("@createdAt", now)], transaction, cancellationToken); } else { var version = await ScalarLongAsync(connection, - "SELECT schema_version FROM schema_metadata WHERE id = 1", cancellationToken); + "SELECT schema_version FROM schema_metadata WHERE id = 1", transaction, cancellationToken); if (version < SchemaVersion) { throw new InvalidOperationException( $"数据库结构版本为 {version},低于 ASP.NET Core 要求的 {SchemaVersion};请先备份并执行旧版本升级流程"); } } - if (!await ExistsAsync(connection, "organization", cancellationToken)) + if (!await ExistsAsync(connection, transaction, "organization", cancellationToken)) { await ExecuteAsync(connection, "INSERT INTO organization (id, name, code, phone, address) VALUES (1, @name, @code, '', '')", - [("@name", "考试服务平台"), ("@code", "EXAM-SERVICE")], cancellationToken); + [("@name", "考试服务平台"), ("@code", "EXAM-SERVICE")], transaction, cancellationToken); } - if (await ScalarLongAsync(connection, "SELECT COUNT(*) FROM users", cancellationToken) == 0) + if (await ScalarLongAsync(connection, "SELECT COUNT(*) FROM users", transaction, cancellationToken) == 0) { var username = Environment.GetEnvironmentVariable("INITIAL_ADMIN_USERNAME")?.Trim(); var password = Environment.GetEnvironmentVariable("INITIAL_ADMIN_PASSWORD") ?? "Admin123!"; @@ -80,25 +83,26 @@ internal sealed partial class DatabaseInitializer( ("@passwordHash", passwords.Hash(password)), ("@displayName", string.IsNullOrWhiteSpace(displayName) ? "系统管理员" : displayName), ("@createdAt", now) - ], cancellationToken); + ], transaction, cancellationToken); } - await SeedNumberRuleAsync(connection, now, cancellationToken); - await SeedAdmissionNumberRulesAsync(connection, now, cancellationToken); - await SeedWorkflowsAsync(connection, now, cancellationToken); + await SeedNumberRuleAsync(connection, transaction, now, cancellationToken); + await SeedAdmissionNumberRulesAsync(connection, transaction, now, cancellationToken); + await SeedWorkflowsAsync(connection, transaction, now, cancellationToken); } private static async Task SeedNumberRuleAsync( DbConnection connection, + DbTransaction? transaction, string now, CancellationToken cancellationToken) { - if (await ScalarLongAsync(connection, "SELECT COUNT(*) FROM number_rules", cancellationToken) > 0) return; + if (await ScalarLongAsync(connection, "SELECT COUNT(*) FROM number_rules", transaction, cancellationToken) > 0) return; await ExecuteAsync(connection, """ INSERT INTO number_rules (id, name, separator, active, created_by, updated_at) VALUES ('rule_default', @name, '-', 1, 'usr_admin', @updatedAt) """, - [("@name", "年度学校性别流水号"), ("@updatedAt", now)], cancellationToken); + [("@name", "年度学校性别流水号"), ("@updatedAt", now)], transaction, cancellationToken); var segments = new[] { ("segment_year", 1, "year", "", 4), @@ -116,16 +120,17 @@ internal sealed partial class DatabaseInitializer( [ ("@id", segment.Item1), ("@position", segment.Item2), ("@type", segment.Item3), ("@value", segment.Item4), ("@width", segment.Item5) - ], cancellationToken); + ], transaction, cancellationToken); } } private static async Task SeedAdmissionNumberRulesAsync( DbConnection connection, + DbTransaction? transaction, string now, CancellationToken cancellationToken) { - if (await ScalarLongAsync(connection, "SELECT COUNT(*) FROM admission_number_rules", cancellationToken) > 0) return; + if (await ScalarLongAsync(connection, "SELECT COUNT(*) FROM admission_number_rules", transaction, cancellationToken) > 0) return; var rules = new[] { new AdmissionRule("admit_rule_district_room_seat", "district_room_seat", "县区编号 + 考场号 + 座位号", @@ -159,16 +164,17 @@ internal sealed partial class DatabaseInitializer( ("@id", rule.Id), ("@code", rule.Code), ("@name", rule.Name), ("@description", rule.Description), ("@segments", segments), ("@example", rule.Example), ("@createdAt", now) - ], cancellationToken); + ], transaction, cancellationToken); } } private static async Task SeedWorkflowsAsync( DbConnection connection, + DbTransaction? transaction, string now, CancellationToken cancellationToken) { - if (await ScalarLongAsync(connection, "SELECT COUNT(*) FROM workflow_definitions", cancellationToken) > 0) return; + if (await ScalarLongAsync(connection, "SELECT COUNT(*) FROM workflow_definitions", transaction, cancellationToken) > 0) return; var workflows = new[] { new Workflow("workflow_profile", "profile_change", "考生信息修改审批", @@ -196,7 +202,7 @@ internal sealed partial class DatabaseInitializer( [ ("@id", workflow.Id), ("@type", workflow.Type), ("@name", workflow.Name), ("@updatedAt", now) - ], cancellationToken); + ], transaction, cancellationToken); for (var index = 0; index < workflow.Steps.Length; index++) { var step = workflow.Steps[index]; @@ -208,24 +214,27 @@ internal sealed partial class DatabaseInitializer( [ ("@id", step.Id), ("@workflowId", workflow.Id), ("@position", index + 1), ("@name", step.Name), ("@level", step.Level) - ], cancellationToken); + ], transaction, cancellationToken); } } } private static async Task ExistsAsync( DbConnection connection, + DbTransaction? transaction, string table, CancellationToken cancellationToken) => - await ScalarLongAsync(connection, $"SELECT COUNT(*) FROM {table}", cancellationToken) > 0; + await ScalarLongAsync(connection, $"SELECT COUNT(*) FROM {table}", transaction, cancellationToken) > 0; private static async Task ScalarLongAsync( DbConnection connection, string sql, + DbTransaction? transaction, CancellationToken cancellationToken) { await using var command = connection.CreateCommand(); command.CommandText = sql; + command.Transaction = transaction; return Convert.ToInt64(await command.ExecuteScalarAsync(cancellationToken), CultureInfo.InvariantCulture); } @@ -233,16 +242,18 @@ internal sealed partial class DatabaseInitializer( DbConnection connection, string sql, CancellationToken cancellationToken) => - ExecuteAsync(connection, sql, [], cancellationToken); + ExecuteAsync(connection, sql, [], null, cancellationToken); private static async Task ExecuteAsync( DbConnection connection, string sql, IReadOnlyList<(string Name, object Value)> values, + DbTransaction? transaction, CancellationToken cancellationToken) { await using var command = connection.CreateCommand(); command.CommandText = sql; + command.Transaction = transaction; foreach (var value in values) { var parameter = command.CreateParameter(); diff --git a/src/Eis.Infrastructure/Data/DatabaseMaintenanceService.cs b/src/Eis.Infrastructure/Data/DatabaseMaintenanceService.cs new file mode 100644 index 0000000..d29379e --- /dev/null +++ b/src/Eis.Infrastructure/Data/DatabaseMaintenanceService.cs @@ -0,0 +1,647 @@ +using System.Data.Common; +using System.Globalization; +using System.IO.Compression; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Text.RegularExpressions; +using Eis.Infrastructure.Authentication; + +namespace Eis.Infrastructure.Data; + +public enum DatabaseMaintenanceMode +{ + Init, + Reset, + Seed +} + +public sealed record DatabaseMaintenanceResult( + DatabaseMaintenanceMode Mode, + string Target, + bool DryRun, + string? BackupPath, + DemoSeedSummary? Summary); + +public sealed record DemoSeedSummary( + int Schools, + int Users, + int Candidates, + int Registrations, + int Results, + int AdmissionRecords, + int FirstRoundPreferences, + int Operations); + +public sealed partial class DatabaseMaintenanceService(DatabaseOptions options) +{ + private const int SchemaVersion = 20; + + private static readonly string[] RelationalTables = + [ + "schema_metadata", + "organization", + "schools", + "school_classes", + "school_student_partitions", + "users", + "candidate_profiles", + "notices", + "exams", + "exam_data_partitions", + "exam_subjects", + "registrations", + "registration_subjects", + "admission_number_rules", + "exam_arrangement_plans", + "admit_cards", + "admit_card_subjects", + "results", + "test_centers", + "test_rooms", + "center_change_requests", + "center_change_rooms", + "number_rules", + "number_rule_segments", + "candidate_account_batches", + "candidate_account_batch_items", + "workflow_definitions", + "workflow_steps", + "workflow_instances", + "workflow_actions", + "admission_records", + "audit_logs" + ]; + + private static readonly string[] BusinessTables = + [ + "schools", + "school_classes", + "candidate_profiles", + "notices", + "exams", + "exam_subjects", + "registrations", + "registration_subjects", + "exam_arrangement_plans", + "admit_cards", + "admit_card_subjects", + "results", + "test_centers", + "test_rooms", + "center_change_requests", + "center_change_rooms", + "candidate_account_batches", + "candidate_account_batch_items", + "workflow_instances", + "workflow_actions", + "admission_records", + "audit_logs" + ]; + + public async Task ExecuteAsync( + DatabaseMaintenanceMode mode, + string? confirmedTarget, + bool force, + bool dryRun, + CancellationToken cancellationToken) + { + ValidateTarget(); + if (mode is (DatabaseMaintenanceMode.Reset or DatabaseMaintenanceMode.Seed) && !dryRun) + { + RequireConfirmedTarget(confirmedTarget); + } + + if (dryRun) + { + if (options.Client == "mysql") + { + await ValidateMySqlDryRunAsync(force, cancellationToken); + } + return new DatabaseMaintenanceResult( + mode, + options.TargetDescription, + true, + null, + mode == DatabaseMaintenanceMode.Seed ? (await LoadDemoSeedAsync(cancellationToken)).Summary : null); + } + + if (mode == DatabaseMaintenanceMode.Init) + { + await CreateInitializer(options).InitializeAsync(cancellationToken); + return new DatabaseMaintenanceResult(mode, options.TargetDescription, false, null, null); + } + + return options.Client == "sqlite" + ? await ReplaceSqliteAsync(mode, cancellationToken) + : await ReplaceMySqlAsync(mode, force, cancellationToken); + } + + private async Task ReplaceSqliteAsync( + DatabaseMaintenanceMode mode, + CancellationToken cancellationToken) + { + var targetPath = options.SqlitePath + ?? throw new InvalidOperationException("SQLite 数据库路径不存在"); + var directory = Path.GetDirectoryName(targetPath) + ?? throw new InvalidOperationException("SQLite 数据库目录无效"); + Directory.CreateDirectory(directory); + var stagingPath = Path.Combine( + directory, + $".{Path.GetFileName(targetPath)}.staging-{Guid.NewGuid():N}"); + var stagingOptions = DatabaseOptions.CreateSqlite(stagingPath); + DemoSeedSummary? summary = null; + try + { + await CreateInitializer(stagingOptions).InitializeAsync(cancellationToken); + if (mode == DatabaseMaintenanceMode.Seed) + { + summary = await ImportDemoSeedAsync(stagingOptions, cancellationToken); + } + + await ValidateSqliteOutputAsync(stagingOptions, mode, cancellationToken); + string? backupPath = null; + if (File.Exists(targetPath)) + { + await CheckpointSqliteAsync(targetPath, cancellationToken); + backupPath = $"{targetPath}.backup-{DateTimeOffset.UtcNow:yyyyMMddTHHmmssfffZ}"; + File.Copy(targetPath, backupPath, overwrite: false); + } + + DeleteSqliteSidecars(targetPath); + File.Move(stagingPath, targetPath, overwrite: true); + return new DatabaseMaintenanceResult( + mode, + targetPath, + false, + backupPath, + summary); + } + finally + { + DeleteSqliteSidecars(stagingPath); + if (File.Exists(stagingPath)) + { + File.Delete(stagingPath); + } + } + } + + private async Task ReplaceMySqlAsync( + DatabaseMaintenanceMode mode, + bool force, + CancellationToken cancellationToken) + { + var initializer = CreateInitializer(options); + await initializer.InitializeAsync(cancellationToken); + var factory = new RelationalConnectionFactory(options); + await using var connection = await factory.OpenAsync(cancellationToken); + var nonEmpty = await FindNonEmptyBusinessTablesAsync(connection, cancellationToken); + var recognizedDemo = nonEmpty.Count > 0 && + await IsRecognizedDemoDatabaseAsync(connection, cancellationToken); + if (nonEmpty.Count > 0 && !force && !recognizedDemo) + { + throw new InvalidOperationException( + $"MySQL 数据库已有业务数据({string.Join(", ", nonEmpty.Take(8))}" + + $"{(nonEmpty.Count > 8 ? ", ..." : "")})。仅确认是可覆盖测试库时才可追加 --force"); + } + + var partitionTables = await ReadPartitionTablesAsync(connection, cancellationToken); + await ExecuteNonQueryAsync(connection, null, "SET FOREIGN_KEY_CHECKS = 0", [], cancellationToken); + DemoSeedSummary? summary = null; + try + { + await using var transaction = await connection.BeginTransactionAsync(cancellationToken); + try + { + await ClearApplicationDataAsync(connection, transaction, cancellationToken); + if (mode == DatabaseMaintenanceMode.Seed) + { + summary = await ImportDemoSeedAsync(connection, transaction, cancellationToken); + } + else + { + await initializer.SeedBaseStateAsync(connection, transaction, cancellationToken); + } + await transaction.CommitAsync(cancellationToken); + } + catch + { + await transaction.RollbackAsync(cancellationToken); + throw; + } + } + finally + { + await ExecuteNonQueryAsync(connection, null, "SET FOREIGN_KEY_CHECKS = 1", [], cancellationToken); + } + + foreach (var table in partitionTables) + { + await ExecuteNonQueryAsync( + connection, + null, + $"DROP TABLE IF EXISTS `{table}`", + [], + cancellationToken); + } + + return new DatabaseMaintenanceResult( + mode, + options.TargetDescription, + false, + null, + summary); + } + + private async Task ValidateMySqlDryRunAsync( + bool force, + CancellationToken cancellationToken) + { + var factory = new RelationalConnectionFactory(options); + await using var connection = await factory.OpenAsync(cancellationToken); + var existingTables = new HashSet(StringComparer.Ordinal); + await using (var command = connection.CreateCommand()) + { + command.CommandText = + """ + SELECT TABLE_NAME + FROM information_schema.TABLES + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_TYPE = 'BASE TABLE' + """; + await using var reader = await command.ExecuteReaderAsync(cancellationToken); + while (await reader.ReadAsync(cancellationToken)) + { + existingTables.Add(reader.GetString(0)); + } + } + + var applicationTables = RelationalTables.Where(existingTables.Contains).ToArray(); + if (applicationTables.Length == 0) + { + return; + } + if (applicationTables.Length != RelationalTables.Length) + { + var missing = RelationalTables.Where(item => !existingTables.Contains(item)); + throw new InvalidOperationException( + $"MySQL 数据库结构不完整,缺少:{string.Join(", ", missing)}"); + } + + var version = await ScalarLongAsync( + connection, + "SELECT schema_version FROM schema_metadata WHERE id = 1", + cancellationToken); + if (version != SchemaVersion) + { + throw new InvalidOperationException( + $"MySQL 数据库结构版本为 v{version},当前工具要求 v{SchemaVersion}"); + } + + var nonEmpty = await FindNonEmptyBusinessTablesAsync(connection, cancellationToken); + var recognizedDemo = nonEmpty.Count > 0 && + await IsRecognizedDemoDatabaseAsync(connection, cancellationToken); + if (nonEmpty.Count > 0 && !force && !recognizedDemo) + { + throw new InvalidOperationException( + $"MySQL 数据库已有业务数据({string.Join(", ", nonEmpty.Take(8))}" + + $"{(nonEmpty.Count > 8 ? ", ..." : "")})。预检拒绝覆盖;确认是测试库时追加 --force"); + } + } + + private async Task ImportDemoSeedAsync( + DatabaseOptions targetOptions, + CancellationToken cancellationToken) + { + var factory = new RelationalConnectionFactory(targetOptions); + await using var connection = await factory.OpenAsync(cancellationToken); + await ExecuteNonQueryAsync(connection, null, "PRAGMA foreign_keys = OFF", [], cancellationToken); + try + { + await using var transaction = await connection.BeginTransactionAsync(cancellationToken); + try + { + await ClearApplicationDataAsync(connection, transaction, cancellationToken); + var summary = await ImportDemoSeedAsync(connection, transaction, cancellationToken); + await transaction.CommitAsync(cancellationToken); + return summary; + } + catch + { + await transaction.RollbackAsync(cancellationToken); + throw; + } + } + finally + { + await ExecuteNonQueryAsync(connection, null, "PRAGMA foreign_keys = ON", [], cancellationToken); + } + } + + private static async Task ImportDemoSeedAsync( + DbConnection connection, + DbTransaction transaction, + CancellationToken cancellationToken) + { + var payload = await LoadDemoSeedAsync(cancellationToken); + if (payload.SchemaVersion != SchemaVersion) + { + throw new InvalidOperationException( + $"演示数据结构版本为 v{payload.SchemaVersion},当前程序要求 v{SchemaVersion}"); + } + + foreach (var operation in payload.Operations) + { + var values = operation.Parameters + .Select(JsonValue) + .ToArray(); + await ExecuteNonQueryAsync( + connection, + transaction, + RewriteParameters(operation.Sql, values.Length), + values, + cancellationToken); + } + return payload.Summary; + } + + private static async Task ClearApplicationDataAsync( + DbConnection connection, + DbTransaction transaction, + CancellationToken cancellationToken) + { + await ExecuteNonQueryAsync(connection, transaction, "DELETE FROM exams", [], cancellationToken); + foreach (var table in RelationalTables.Reverse() + .Where(item => item is not ("schema_metadata" or "exams"))) + { + await ExecuteNonQueryAsync( + connection, + transaction, + $"DELETE FROM `{table}`", + [], + cancellationToken); + } + } + + private static async Task ValidateSqliteOutputAsync( + DatabaseOptions targetOptions, + DatabaseMaintenanceMode mode, + CancellationToken cancellationToken) + { + var factory = new RelationalConnectionFactory(targetOptions); + await using var connection = await factory.OpenAsync(cancellationToken); + var version = await ScalarLongAsync( + connection, + "SELECT schema_version FROM schema_metadata WHERE id = 1", + cancellationToken); + var users = await ScalarLongAsync(connection, "SELECT COUNT(*) FROM users", cancellationToken); + if (version != SchemaVersion || users == 0) + { + throw new InvalidOperationException("生成的 SQLite 数据库未通过结构和账号校验"); + } + + if (mode == DatabaseMaintenanceMode.Seed) + { + var candidates = await ScalarLongAsync( + connection, + "SELECT COUNT(*) FROM candidate_profiles", + cancellationToken); + var results = await ScalarLongAsync(connection, "SELECT COUNT(*) FROM results", cancellationToken); + if (candidates != 1200 || results != 10800) + { + throw new InvalidOperationException( + $"演示数据校验失败:考生 {candidates},成绩 {results}"); + } + } + } + + private static async Task CheckpointSqliteAsync( + string targetPath, + CancellationToken cancellationToken) + { + var factory = new RelationalConnectionFactory(DatabaseOptions.CreateSqlite(targetPath)); + await using var connection = await factory.OpenAsync(cancellationToken); + await ExecuteNonQueryAsync( + connection, + null, + "PRAGMA wal_checkpoint(TRUNCATE)", + [], + cancellationToken); + } + + private static void DeleteSqliteSidecars(string path) + { + foreach (var suffix in new[] { "-wal", "-shm" }) + { + var sidecar = path + suffix; + if (File.Exists(sidecar)) + { + File.Delete(sidecar); + } + } + } + + private async Task> FindNonEmptyBusinessTablesAsync( + DbConnection connection, + CancellationToken cancellationToken) + { + var result = new List(); + foreach (var table in BusinessTables) + { + var count = await ScalarLongAsync( + connection, + $"SELECT COUNT(*) FROM `{table}`", + cancellationToken); + if (count > 0) + { + result.Add($"{table}={count}"); + } + } + + var users = await ScalarLongAsync(connection, "SELECT COUNT(*) FROM users", cancellationToken); + if (users > 1) + { + result.Add($"users={users}"); + } + return result; + } + + private static async Task IsRecognizedDemoDatabaseAsync( + DbConnection connection, + CancellationToken cancellationToken) + { + var users = await ScalarLongAsync( + connection, + "SELECT COUNT(*) FROM users WHERE id LIKE 'usr_bulk_%'", + cancellationToken); + var schools = await ScalarLongAsync( + connection, + """ + SELECT COUNT(*) FROM schools + WHERE id IN ('school_hz1', 'school_hz3', 'school_hz5', 'school_hz7', 'school_hz9') + """, + cancellationToken); + return users >= 1100 && schools == 5; + } + + private static async Task ReadPartitionTablesAsync( + DbConnection connection, + CancellationToken cancellationToken) + { + var tables = new List(); + await using (var command = connection.CreateCommand()) + { + command.CommandText = + "SELECT candidates_table, admissions_table, results_table, centers_table FROM exam_data_partitions"; + await using var reader = await command.ExecuteReaderAsync(cancellationToken); + while (await reader.ReadAsync(cancellationToken)) + { + for (var index = 0; index < 4; index++) + { + tables.Add(reader.GetString(index)); + } + } + } + await using (var command = connection.CreateCommand()) + { + command.CommandText = "SELECT students_table FROM school_student_partitions"; + await using var reader = await command.ExecuteReaderAsync(cancellationToken); + while (await reader.ReadAsync(cancellationToken)) + { + tables.Add(reader.GetString(0)); + } + } + + if (tables.Any(item => !PartitionTablePattern().IsMatch(item))) + { + throw new InvalidOperationException("分表登记中存在非法表名,拒绝替换数据库"); + } + return tables.Distinct(StringComparer.Ordinal).ToArray(); + } + + private void ValidateTarget() + { + if (options.Client == "sqlite" && string.IsNullOrWhiteSpace(options.SqlitePath)) + { + throw new InvalidOperationException("未指定 SQLite 数据库路径"); + } + if (options.Client == "mysql") + { + var name = options.MySqlDatabaseName?.Trim() ?? ""; + var normalized = name.ToLowerInvariant(); + if (normalized.Length == 0 || + normalized is "mysql" or "information_schema" or "performance_schema" or "sys") + { + throw new InvalidOperationException($"拒绝操作 MySQL 系统数据库:{name}"); + } + } + } + + private void RequireConfirmedTarget(string? confirmedTarget) + { + var expected = options.Client == "sqlite" + ? options.SqlitePath + : options.MySqlDatabaseName; + var comparison = options.Client == "sqlite" && OperatingSystem.IsWindows() + ? StringComparison.OrdinalIgnoreCase + : StringComparison.Ordinal; + if (string.IsNullOrWhiteSpace(confirmedTarget) || + !string.Equals(expected, confirmedTarget, comparison)) + { + throw new InvalidOperationException( + $"这是破坏性操作。请使用 --confirm-target \"{expected}\" 明确确认目标"); + } + } + + private static DatabaseInitializer CreateInitializer(DatabaseOptions targetOptions) => + new( + new RelationalConnectionFactory(targetOptions), + targetOptions, + new PasswordCompatibilityService()); + + private static async Task LoadDemoSeedAsync(CancellationToken cancellationToken) + { + var assembly = typeof(DatabaseMaintenanceService).Assembly; + var name = assembly.GetManifestResourceNames() + .Single(item => item.EndsWith("demo-seed-operations.json.gz", StringComparison.Ordinal)); + await using var source = assembly.GetManifestResourceStream(name) + ?? throw new InvalidOperationException("内置演示数据包不存在"); + await using var gzip = new GZipStream(source, CompressionMode.Decompress); + return await JsonSerializer.DeserializeAsync( + gzip, + new JsonSerializerOptions { PropertyNameCaseInsensitive = true }, + cancellationToken) + ?? throw new InvalidOperationException("内置演示数据包格式无效"); + } + + private static string RewriteParameters(string sql, int count) + { + var index = 0; + var rewritten = ParameterPattern().Replace(sql, _ => $"@p{index++}"); + if (index != count) + { + throw new InvalidOperationException( + $"演示数据 SQL 参数数量不匹配:预期 {index},实际 {count}"); + } + return rewritten; + } + + private static object JsonValue(JsonElement value) => + value.ValueKind switch + { + JsonValueKind.Null => DBNull.Value, + JsonValueKind.String => value.GetString() ?? "", + JsonValueKind.Number when value.TryGetInt64(out var integer) => integer, + JsonValueKind.Number => value.GetDouble(), + JsonValueKind.True => 1, + JsonValueKind.False => 0, + _ => value.GetRawText() + }; + + private static async Task ExecuteNonQueryAsync( + DbConnection connection, + DbTransaction? transaction, + string sql, + IReadOnlyList values, + CancellationToken cancellationToken) + { + await using var command = connection.CreateCommand(); + command.CommandText = sql; + command.Transaction = transaction; + for (var index = 0; index < values.Count; index++) + { + var parameter = command.CreateParameter(); + parameter.ParameterName = $"@p{index}"; + parameter.Value = values[index]; + command.Parameters.Add(parameter); + } + await command.ExecuteNonQueryAsync(cancellationToken); + } + + private static async Task ScalarLongAsync( + DbConnection connection, + string sql, + CancellationToken cancellationToken) + { + await using var command = connection.CreateCommand(); + command.CommandText = sql; + return Convert.ToInt64(await command.ExecuteScalarAsync(cancellationToken), CultureInfo.InvariantCulture); + } + + [GeneratedRegex(@"\?", RegexOptions.CultureInvariant)] + private static partial Regex ParameterPattern(); + + [GeneratedRegex(@"^[a-z][a-z0-9_]{0,63}$", RegexOptions.CultureInvariant)] + private static partial Regex PartitionTablePattern(); + + private sealed record DemoSeedPayload( + int Version, + int SchemaVersion, + string GeneratedAt, + DemoSeedSummary Summary, + DemoSeedOperation[] Operations); + + private sealed record DemoSeedOperation( + string Sql, + [property: JsonPropertyName("params")] JsonElement[] Parameters); +} diff --git a/src/Eis.Infrastructure/Data/DatabaseOptions.cs b/src/Eis.Infrastructure/Data/DatabaseOptions.cs index c843fb0..f16a265 100644 --- a/src/Eis.Infrastructure/Data/DatabaseOptions.cs +++ b/src/Eis.Infrastructure/Data/DatabaseOptions.cs @@ -17,9 +17,27 @@ public sealed class DatabaseOptions public string? MySqlConnectionString { get; } + public string TargetDescription => Client == "sqlite" + ? SqlitePath ?? "SQLite" + : $"MySQL database {MySqlDatabaseName}"; + + public string? MySqlDatabaseName => + Client == "mysql" && MySqlConnectionString is { Length: > 0 } connectionString + ? new MySqlConnectionStringBuilder(connectionString).Database + : null; + internal static DatabaseOptions CreateSqliteForTests(string path) => new("sqlite", Path.GetFullPath(path), null); + public static DatabaseOptions CreateSqlite(string path) => + new("sqlite", Path.GetFullPath(path), null); + + public static DatabaseOptions CreateMySqlFromEnvironment() => + new("mysql", null, BuildMySqlConnectionString()); + + public static DatabaseOptions CreateMySql(string connectionString) => + new("mysql", null, new MySqlConnectionStringBuilder(connectionString).ConnectionString); + public static DatabaseOptions FromEnvironment(string applicationRoot, bool production) { var client = (Environment.GetEnvironmentVariable("DATABASE_CLIENT") diff --git a/src/Eis.Infrastructure/Data/demo-seed-operations.json.gz b/src/Eis.Infrastructure/Data/demo-seed-operations.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..e2bfe317e2570f8759b1cd247966d446c5fd5ab3 GIT binary patch literal 272242 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 z

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

^qnhi0-HTN0jbFgmh$1eNukJPu5<7cRC?6s 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%0A{Qzh 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 + diff --git a/src/Eis.Tools/Eis.Tools.csproj b/src/Eis.Tools/Eis.Tools.csproj new file mode 100644 index 0000000..a018dea --- /dev/null +++ b/src/Eis.Tools/Eis.Tools.csproj @@ -0,0 +1,11 @@ + + + Exe + net10.0 + Eis.Tools + Eis.Tools + + + + + diff --git a/src/Eis.Tools/Program.cs b/src/Eis.Tools/Program.cs new file mode 100644 index 0000000..bd4ad8f --- /dev/null +++ b/src/Eis.Tools/Program.cs @@ -0,0 +1,263 @@ +using Eis.Infrastructure.Configuration; +using Eis.Infrastructure.Data; + +namespace Eis.Tools; + +internal static class Program +{ + public static async Task Main(string[] args) + { + try + { + var command = DatabaseToolCommand.Parse(args); + if (command.ShowHelp) + { + Console.WriteLine(DatabaseToolCommand.Usage); + return 0; + } + + var applicationRoot = command.ApplicationRoot ?? FindApplicationRoot(); + EnvironmentFile.Load(applicationRoot); + var options = BuildDatabaseOptions(command, applicationRoot); + if (command.Force && options.Client != "mysql") + { + throw new DatabaseToolUsageException("--force 只能用于 MySQL 测试数据库。"); + } + var confirmedTarget = NormalizeConfirmation(command.ConfirmedTarget, options, applicationRoot); + + Console.WriteLine($"命令:database {command.Mode.ToString().ToLowerInvariant()}"); + Console.WriteLine($"目标:{options.TargetDescription}"); + if (command.DryRun) + { + Console.WriteLine("模式:只预检,不写入数据库"); + } + + var service = new DatabaseMaintenanceService(options); + var result = await service.ExecuteAsync( + command.Mode, + confirmedTarget, + command.Force, + command.DryRun, + CancellationToken.None); + PrintResult(result); + return 0; + } + catch (DatabaseToolUsageException exception) + { + Console.Error.WriteLine(exception.Message); + Console.Error.WriteLine(); + Console.Error.WriteLine(DatabaseToolCommand.Usage); + return 2; + } + catch (Exception exception) + { + Console.Error.WriteLine($"数据库工具执行失败:{exception.Message}"); + return 1; + } + } + + private static DatabaseOptions BuildDatabaseOptions( + DatabaseToolCommand command, + string applicationRoot) + { + var client = command.Client ?? + Environment.GetEnvironmentVariable("DATABASE_CLIENT")?.Trim().ToLowerInvariant() ?? + "sqlite"; + return client switch + { + "sqlite" => DatabaseOptions.CreateSqlite(ResolveSqlitePath(command.SqlitePath, applicationRoot)), + "mysql" when command.SqlitePath is not null => + throw new DatabaseToolUsageException("--path 只能和 --sqlite 一起使用"), + "mysql" => DatabaseOptions.CreateMySqlFromEnvironment(), + _ => throw new DatabaseToolUsageException($"不支持的数据库类型:{client}") + }; + } + + private static string ResolveSqlitePath(string? configuredPath, string applicationRoot) + { + var path = configuredPath ?? + Environment.GetEnvironmentVariable("SQLITE_PATH") ?? + Path.Combine("data", "exam.sqlite"); + return Path.GetFullPath(Path.IsPathRooted(path) + ? path + : Path.Combine(applicationRoot, path)); + } + + private static string? NormalizeConfirmation( + string? confirmation, + DatabaseOptions options, + string applicationRoot) + { + if (confirmation is null || options.Client != "sqlite") + { + return confirmation; + } + return Path.GetFullPath(Path.IsPathRooted(confirmation) + ? confirmation + : Path.Combine(applicationRoot, confirmation)); + } + + private static string FindApplicationRoot() + { + foreach (var start in new[] { Directory.GetCurrentDirectory(), AppContext.BaseDirectory }) + { + var directory = new DirectoryInfo(Path.GetFullPath(start)); + while (directory is not null) + { + if (File.Exists(Path.Combine(directory.FullName, "Eis.slnx")) || + File.Exists(Path.Combine(directory.FullName, ".env"))) + { + return directory.FullName; + } + directory = directory.Parent; + } + } + return Path.GetFullPath(Directory.GetCurrentDirectory()); + } + + private static void PrintResult(DatabaseMaintenanceResult result) + { + if (result.DryRun) + { + Console.WriteLine("预检完成:未修改数据库。"); + } + else + { + Console.WriteLine(result.Mode switch + { + DatabaseMaintenanceMode.Init => "数据库结构和基础配置初始化完成。", + DatabaseMaintenanceMode.Reset => "数据库已重建为空业务系统。", + _ => "演示数据导入完成。" + }); + } + + if (result.BackupPath is not null) + { + Console.WriteLine($"原数据库备份:{result.BackupPath}"); + } + if (result.Summary is { } summary) + { + Console.WriteLine( + $"演示数据:学校 {summary.Schools},用户 {summary.Users},考生 {summary.Candidates}," + + $"报名 {summary.Registrations},成绩 {summary.Results},招生记录 {summary.AdmissionRecords}。"); + Console.WriteLine("预置测试账号密码:12345678"); + } + } +} + +internal sealed record DatabaseToolCommand( + DatabaseMaintenanceMode Mode, + string? Client, + string? SqlitePath, + string? ConfirmedTarget, + string? ApplicationRoot, + bool Force, + bool DryRun, + bool ShowHelp) +{ + public const string Usage = + """ + 用法: + dotnet Eis.Tools.dll database init [--sqlite|--mysql] [--path ] [--dry-run] + dotnet Eis.Tools.dll database reset [--sqlite|--mysql] [--path ] [--confirm-target <目标>] [--force] [--dry-run] + dotnet Eis.Tools.dll database seed [--sqlite|--mysql] [--path ] [--confirm-target <目标>] [--force] [--dry-run] + + 说明: + init 非破坏性建表和基础配置初始化。 + reset 重建为空业务库;SQLite 自动备份原文件。 + seed 导入内置的 1200 名考生演示数据;SQLite 自动备份原文件。 + + --confirm-target 对 SQLite 填写最终数据库路径,对 MySQL 填写数据库名。 + --force 仅在确认 MySQL 中已有非演示业务数据可覆盖时使用。 + --root 指定 .env 和相对 SQLite 路径的应用根目录。 + """; + + public static DatabaseToolCommand Parse(string[] args) + { + if (args.Length == 0 || args.Any(item => item is "-h" or "--help")) + { + return new( + DatabaseMaintenanceMode.Init, + null, + null, + null, + null, + false, + false, + true); + } + if (args.Length < 2 || !args[0].Equals("database", StringComparison.OrdinalIgnoreCase)) + { + throw new DatabaseToolUsageException("第一个参数必须是 database。"); + } + + var mode = args[1].ToLowerInvariant() switch + { + "init" => DatabaseMaintenanceMode.Init, + "reset" => DatabaseMaintenanceMode.Reset, + "seed" => DatabaseMaintenanceMode.Seed, + _ => throw new DatabaseToolUsageException($"不支持的 database 命令:{args[1]}") + }; + string? client = null; + string? path = null; + string? confirmation = null; + string? root = null; + var force = false; + var dryRun = false; + for (var index = 2; index < args.Length; index++) + { + switch (args[index]) + { + case "--sqlite": + SetClient(ref client, "sqlite"); + break; + case "--mysql": + SetClient(ref client, "mysql"); + break; + case "--path": + path = NextValue(args, ref index, "--path"); + break; + case "--confirm-target": + confirmation = NextValue(args, ref index, "--confirm-target"); + break; + case "--root": + root = Path.GetFullPath(NextValue(args, ref index, "--root")); + break; + case "--force": + force = true; + break; + case "--dry-run": + dryRun = true; + break; + default: + throw new DatabaseToolUsageException($"无法识别的参数:{args[index]}"); + } + } + + if (mode == DatabaseMaintenanceMode.Init && force) + { + throw new DatabaseToolUsageException("database init 不接受 --force。"); + } + return new(mode, client, path, confirmation, root, force, dryRun, false); + } + + private static void SetClient(ref string? current, string value) + { + if (current is not null && current != value) + { + throw new DatabaseToolUsageException("--sqlite 和 --mysql 不能同时使用。"); + } + current = value; + } + + private static string NextValue(string[] args, ref int index, string option) + { + if (++index >= args.Length || args[index].StartsWith("--", StringComparison.Ordinal)) + { + throw new DatabaseToolUsageException($"{option} 缺少参数值。"); + } + return args[index]; + } +} + +internal sealed class DatabaseToolUsageException(string message) : Exception(message); diff --git a/src/Eis.Web/Program.cs b/src/Eis.Web/Program.cs index 0060704..0b65346 100644 --- a/src/Eis.Web/Program.cs +++ b/src/Eis.Web/Program.cs @@ -2,6 +2,7 @@ using Eis.Infrastructure.Authentication; using Eis.Infrastructure.Administration; using Eis.Infrastructure.Candidate; using Eis.Infrastructure.Caching; +using Eis.Infrastructure.Configuration; using Eis.Application.Public; using Eis.Infrastructure; using Eis.Infrastructure.Data; diff --git a/tests/Eis.Infrastructure.Tests/Data/DatabaseMaintenanceServiceTests.cs b/tests/Eis.Infrastructure.Tests/Data/DatabaseMaintenanceServiceTests.cs new file mode 100644 index 0000000..ee72af7 --- /dev/null +++ b/tests/Eis.Infrastructure.Tests/Data/DatabaseMaintenanceServiceTests.cs @@ -0,0 +1,134 @@ +using Eis.Infrastructure.Data; +using Microsoft.Data.Sqlite; + +namespace Eis.Infrastructure.Tests.Data; + +public sealed class DatabaseMaintenanceServiceTests +{ + [Fact] + public async Task SeedAndReset_UseValidatedReplacementAndCreateBackups() + { + var root = Path.Combine(Path.GetTempPath(), $"eis-tools-{Guid.NewGuid():N}"); + var path = Path.Combine(root, "eis.sqlite"); + Directory.CreateDirectory(root); + try + { + var service = new DatabaseMaintenanceService(DatabaseOptions.CreateSqlite(path)); + await service.ExecuteAsync( + DatabaseMaintenanceMode.Init, + null, + force: false, + dryRun: false, + CancellationToken.None); + + var seed = await service.ExecuteAsync( + DatabaseMaintenanceMode.Seed, + path, + force: false, + dryRun: false, + CancellationToken.None); + Assert.NotNull(seed.BackupPath); + Assert.True(File.Exists(seed.BackupPath)); + Assert.Equal(1200, seed.Summary?.Candidates); + Assert.Equal(10800, seed.Summary?.Results); + Assert.Equal(1200, await ScalarAsync(path, "SELECT COUNT(*) FROM candidate_profiles")); + Assert.Equal(10800, await ScalarAsync(path, "SELECT COUNT(*) FROM results")); + + var reset = await service.ExecuteAsync( + DatabaseMaintenanceMode.Reset, + path, + force: false, + dryRun: false, + CancellationToken.None); + Assert.NotNull(reset.BackupPath); + Assert.True(File.Exists(reset.BackupPath)); + Assert.Equal(0, await ScalarAsync(path, "SELECT COUNT(*) FROM candidate_profiles")); + Assert.Equal(1, await ScalarAsync(path, "SELECT COUNT(*) FROM users")); + Assert.Equal(20, await ScalarAsync(path, + "SELECT schema_version FROM schema_metadata WHERE id = 1")); + } + finally + { + SqliteConnection.ClearAllPools(); + if (Directory.Exists(root)) + { + Directory.Delete(root, recursive: true); + } + } + } + + [Fact] + public async Task DestructiveCommand_RequiresExactTargetConfirmation() + { + var root = Path.Combine(Path.GetTempPath(), $"eis-tools-confirm-{Guid.NewGuid():N}"); + var path = Path.Combine(root, "eis.sqlite"); + try + { + var service = new DatabaseMaintenanceService(DatabaseOptions.CreateSqlite(path)); + var exception = await Assert.ThrowsAsync(() => + service.ExecuteAsync( + DatabaseMaintenanceMode.Seed, + path + ".wrong", + force: false, + dryRun: false, + CancellationToken.None)); + + Assert.Contains("--confirm-target", exception.Message); + Assert.False(File.Exists(path)); + } + finally + { + SqliteConnection.ClearAllPools(); + if (Directory.Exists(root)) + { + Directory.Delete(root, recursive: true); + } + } + } + + [Fact] + public async Task DryRun_ReportsSeedWithoutWritingDatabase() + { + var root = Path.Combine(Path.GetTempPath(), $"eis-tools-dry-{Guid.NewGuid():N}"); + var path = Path.Combine(root, "eis.sqlite"); + var service = new DatabaseMaintenanceService(DatabaseOptions.CreateSqlite(path)); + + var result = await service.ExecuteAsync( + DatabaseMaintenanceMode.Seed, + null, + force: false, + dryRun: true, + CancellationToken.None); + + Assert.True(result.DryRun); + Assert.Equal(1200, result.Summary?.Candidates); + Assert.False(File.Exists(path)); + } + + [Fact] + public async Task MySqlSystemDatabase_IsRejectedBeforeConnecting() + { + var options = DatabaseOptions.CreateMySql( + "Server=127.0.0.1;User ID=test;Database=mysql;Connection Timeout=1"); + var service = new DatabaseMaintenanceService(options); + + var exception = await Assert.ThrowsAsync(() => + service.ExecuteAsync( + DatabaseMaintenanceMode.Init, + null, + force: false, + dryRun: true, + CancellationToken.None)); + + Assert.Contains("系统数据库", exception.Message); + } + + private static async Task ScalarAsync(string path, string sql) + { + await using var connection = new SqliteConnection($"Data Source={path};Pooling=False"); + await connection.OpenAsync(); + await using var command = connection.CreateCommand(); + command.CommandText = sql; + return Convert.ToInt64(await command.ExecuteScalarAsync()); + } +} diff --git a/tests/system.test.mjs b/tests/system.test.mjs index dd4742c..66e26ee 100644 --- a/tests/system.test.mjs +++ b/tests/system.test.mjs @@ -53,19 +53,17 @@ assert.match(mysqlAdapterSource, /existingAppTables\.length && \(!hasSchemaMetad assert.match(mysqlAdapterSource, /\[\.\.\.mysqlTableNames\]\.reverse\(\)/, 'MySQL 半成品表应按外键依赖逆序清理'); const serverSource = await readFile(resolve(root, 'server.mjs'), 'utf8'); assert.doesNotMatch(serverSource, /src\/data\/seed\.mjs|createSeedDatabase/, '服务启动不得引用测试数据生成器'); -const testDataImportSource = await readFile(resolve(root, 'scripts', 'import-test-data.mjs'), 'utf8'); -assert.match(testDataImportSource, /loadEnvFile\(envPath\)/, '测试数据脚本应读取项目 .env'); -assert.match(testDataImportSource, /options\.has\('--mysql'\).*options\.has\('--sqlite'\)/, '测试数据脚本应支持显式选择 MySQL 或 SQLite'); -assert.doesNotMatch(testDataImportSource, /process\.env\.DATABASE_CLIENT\s*=\s*['"]sqlite['"]/, '测试数据脚本不得再强制使用 SQLite'); -assert.match(testDataImportSource, /nonEmpty\.length && !force/, 'MySQL 已有业务数据时应默认拒绝覆盖'); -assert.match(testDataImportSource, /SET FOREIGN_KEY_CHECKS = 0/, 'MySQL 样例数据替换应在受控外键环境中执行'); -assert.match(testDataImportSource, /beginTransaction\(\).*buildSeedOperations\(state\).*commit\(\)/s, 'MySQL 样例数据应在同一事务内清理并写入'); -assert.match(testDataImportSource, /initializeEmpty.*createBaseDatabase/s, '测试结束后应支持恢复空业务系统'); -assert.match(testDataImportSource, /recognizedTestData/, 'MySQL 初始化系统时应识别样例数据并保护非样例业务库'); -assert.match(testDataImportSource, /CURRENT_SCHEMA_VERSION/, '数据库导入脚本应复用统一的当前结构版本'); -const resetDatabaseSource = await readFile(resolve(root, 'scripts', 'reset-dev-database.mjs'), 'utf8'); -assert.match(resetDatabaseSource, /import\(['"]\.\/import-test-data\.mjs['"]\)/, '重置入口应复用统一的数据库初始化流程'); -assert.doesNotMatch(resetDatabaseSource, /DATABASE_CLIENT\s*=\s*['"]sqlite['"]/, '重置入口不得再强制使用 SQLite'); +const databaseToolSource = await readFile(resolve(root, 'src', 'Eis.Tools', 'Program.cs'), 'utf8'); +const databaseMaintenanceSource = await readFile(resolve(root, 'src', 'Eis.Infrastructure', 'Data', 'DatabaseMaintenanceService.cs'), 'utf8'); +assert.match(databaseToolSource, /EnvironmentFile\.Load\(applicationRoot\)/, '.NET 数据库工具应读取项目 .env'); +assert.match(databaseToolSource, /case "--sqlite".*case "--mysql"/s, '.NET 数据库工具应支持显式选择 MySQL 或 SQLite'); +assert.match(databaseToolSource, /--confirm-target/, '破坏性数据库命令必须精确确认目标'); +assert.match(databaseMaintenanceSource, /nonEmpty\.Count > 0 && !force/, 'MySQL 已有业务数据时应默认拒绝覆盖'); +assert.match(databaseMaintenanceSource, /SET FOREIGN_KEY_CHECKS = 0/, 'MySQL 样例数据替换应在受控外键环境中执行'); +assert.match(databaseMaintenanceSource, /BeginTransactionAsync.*ImportDemoSeedAsync.*CommitAsync/s, 'MySQL 样例数据应在同一事务内清理并写入'); +assert.match(databaseMaintenanceSource, /DatabaseMaintenanceMode\.Reset.*SeedBaseStateAsync/s, '测试结束后应支持恢复空业务系统'); +assert.match(databaseMaintenanceSource, /recognizedDemo/, 'MySQL 初始化系统时应识别样例数据并保护非样例业务库'); +assert.match(databaseMaintenanceSource, /SchemaVersion = 20/, '数据库导入工具应使用当前结构版本'); const baseState = createBaseDatabase({ nowIso: () => new Date().toISOString(), hashPassword: password => `test-${password}` }); assert.equal(baseState.meta.version, CURRENT_SCHEMA_VERSION, '空库初始状态必须使用当前结构版本'); assert.equal(baseState.schools.length, 0, '正常首次建库不得预置学校');