fix: restore enterprise application lists
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { SmsConfigService } from './sms-config.service';
|
||||
|
||||
function createPrismaMock() {
|
||||
@@ -240,7 +241,12 @@ describe('SmsConfigService', () => {
|
||||
expect(prisma.smsApplication.findMany).toHaveBeenCalledWith(expect.objectContaining({
|
||||
where: expect.objectContaining({ status: 'active', tenant: { name: { contains: '租户' } }, name: { contains: '应用' } }),
|
||||
include: { tenant: true, ipAllowlist: true, httpConfig: true },
|
||||
omit: { secretHash: true },
|
||||
}));
|
||||
const applicationModel = Prisma.dmmf.datamodel.models.find((model) => model.name === 'SmsApplication');
|
||||
const applicationFields = new Set(applicationModel?.fields.map((field) => field.name));
|
||||
const omittedFields = Object.keys(prisma.smsApplication.findMany.mock.calls[0][0].omit);
|
||||
expect(omittedFields.every((field) => applicationFields.has(field))).toBe(true);
|
||||
expect(prisma.smsApplication.findMany.mock.calls[0][0]).not.toHaveProperty('take');
|
||||
expect(prisma.smsMessageRecord.groupBy).toHaveBeenCalledWith(expect.objectContaining({
|
||||
by: ['applicationId', 'status'],
|
||||
|
||||
@@ -213,7 +213,6 @@ export class SmsConfigService implements OnModuleInit, OnModuleDestroy {
|
||||
},
|
||||
omit: {
|
||||
secretHash: true,
|
||||
passwordCipher: true,
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
...(query.page && query.pageSize ? {
|
||||
|
||||
@@ -1809,3 +1809,9 @@
|
||||
- 企业应用和签名等下拉框使用轻量选项接口,不得为了选择器加载连接、资料、报备任务等完整关联对象。
|
||||
- 分页排序字段应有数据库索引;Nginx 对 JSON、JavaScript、CSS、CSV、文本和 SVG 响应启用 gzip,降低传输与解析等待。
|
||||
- 通道组本轮按用户明确要求排除,保留现状,后续如数据规模扩大再单独改造。
|
||||
|
||||
## 企业应用列表字段安全约束(2026-07-29)
|
||||
|
||||
- 企业应用列表及分页接口只能在 Prisma 查询中引用 `SmsApplication` 模型真实存在的字段;接口入参或响应别名(例如 `passwordCipher`)不得作为数据库 `select`、`omit` 或筛选字段。
|
||||
- 企业应用列表必须排除真实敏感字段 `secretHash`,不得通过列表接口返回应用接入密码;密码只允许在既有受控的专用参数接口中按权限读取。
|
||||
- 企业应用黑名单等页面加载筛选项时应使用轻量企业应用选项接口,避免依赖包含连接状态和统计信息的完整企业应用列表。
|
||||
|
||||
@@ -4009,3 +4009,11 @@ npm run verify:phase8
|
||||
1. 应用分页索引 migration。
|
||||
2. 对短信、任务、报备、应用、签名、模板、通道、上行和充值分页 SQL 执行计划进行检查。
|
||||
3. 携带 `Accept-Encoding: gzip` 请求大于 1KB 的 JSON,验证响应 `Content-Encoding: gzip`。
|
||||
|
||||
## 2026-07-29 企业应用列表 Prisma 字段回归用例
|
||||
|
||||
| 用例编号 | 场景 | 预期结果 |
|
||||
| --- | --- | --- |
|
||||
| TC-APP-LIST-001 | 运营端打开企业应用列表并请求分页接口 | Prisma 查询仅排除真实存在的 `secretHash`;接口 HTTP 200,不因 DTO 字段 `passwordCipher` 触发 Prisma 校验错误 |
|
||||
| TC-APP-LIST-002 | 运营端打开企业应用黑名单并加载企业应用筛选项 | 黑名单及筛选项均从真实后端返回;企业应用加载不触发 HTTP 500,列表响应不包含 `secretHash` |
|
||||
| TC-APP-LIST-003 | 校验企业应用列表 Prisma `omit` 字段 | 所有 `omit` 键都存在于当前生成客户端的 `SmsApplication` DMMF 模型,模型字段变更或错误别名会使回归测试失败 |
|
||||
|
||||
@@ -2688,3 +2688,13 @@ git diff --check
|
||||
- 发布后真实`OperationsService`在与问题复现相同的`2026-07-27`至`2026-07-28`范围查询第一页25条:总数443,当前页46条提交、90条回执、25条下游投递,序列化后约110139字节,真实PostgreSQL查询及对象构造耗时约171.4ms;原全量响应约4.47MB,体积下降约97.6%。Nginx对Vite的`text/javascript`资源真实返回`Content-Encoding: gzip`,不是仅写配置未生效。
|
||||
- API、Gateway、Nginx、PostgreSQL、MinIO和Redis均active,`12026/17890/8090/3000/6379/5432/9000`监听;内外健康接口、首页、运营端和客户端均HTTP 200,公网CMPP 17890可连接。Redis Stream消费者1、`pending=0`、`lag=0`,API/Gateway近10分钟error级journal为0。
|
||||
- 4条active供应商通道均为`connected 1/1`;最近120秒活跃下游客户连接为0。本轮未发送、重投或补发真实短信,未修改通道账号、密码、启停状态、企业余额或客户连接。
|
||||
|
||||
## 2026-07-29 企业应用列表 Prisma 字段回归修复(发布前)
|
||||
|
||||
- 预生产企业应用页面和企业应用黑名单页面 HTTP 500 已定位为列表查询 `omit` 错误引用 DTO/响应别名 `passwordCipher`;真实 `SmsApplication` 模型只保存敏感字段 `secretHash`,Prisma 7.9.0 在执行 SQL 前抛出 `PrismaClientValidationError`。
|
||||
- 企业应用列表查询已移除不存在的 `passwordCipher`,继续明确排除真实敏感字段 `secretHash`。企业应用黑名单改为调用轻量企业应用选项接口,不再为了筛选项加载连接状态、统计及完整关联;本次修复不修改企业、应用、黑名单、通道、余额或短信数据。
|
||||
- 新增回归断言:企业应用查询的 `omit` 必须等于 `{ secretHash: true }`,且每个排除字段都必须存在于当前生成 Prisma Client 的 `SmsApplication` DMMF 模型,避免 Mock 测试再次接受不存在的数据库字段。
|
||||
- 代码检查确认短信入库和通道路由不会调用手机号段页面分页接口:运营商直接读取启用的 `PhoneCarrierRule`,省份通过唯一索引 `PhoneSegment.prefix` 逐级精确查询;本次页面列表错误不影响号码段识别链路。
|
||||
- Node.js v24.14.0 下短信配置定向 1 suite / 62 tests、API 全量 26 suites / 367 tests 全部通过;Prisma format、validate、generate、API TypeScript 正式构建、前端 TypeScript/Vite 生产构建、Gateway `go test ./...` 与 `go vet ./...`、依赖安全门禁和 `git diff --check` 均通过。Jest 仅保留既有强制结束异步句柄提示,Vite 仅保留既有大 chunk 体积事实。
|
||||
- 发布前使用预生产真实 Prisma Client 和 PostgreSQL 只读执行 `SmsApplication.findMany(... omit: { secretHash: true })` 成功返回 10 条企业应用,结果中 `secretHash` 泄漏计数为 0;未写入或修改预生产数据。
|
||||
- 既有 `api/tsconfig.build.tsbuildinfo`、`tsconfig.tsbuildinfo`、`outputs/` 和空文件 `=` 继续作为构建或临时产物保留,不纳入提交。
|
||||
|
||||
@@ -33,7 +33,7 @@ export function AdminEnterpriseBlacklistPage() {
|
||||
Promise.all([
|
||||
adminApi.listEnterpriseBlacklist(filters),
|
||||
adminApi.listTenants(),
|
||||
adminApi.listEnterpriseApplications(),
|
||||
adminApi.listEnterpriseApplicationOptions(),
|
||||
])
|
||||
.then(([blacklist, tenantItems, applicationItems]) => {
|
||||
setItems(blacklist as EnterpriseBlacklistItem[]);
|
||||
|
||||
Reference in New Issue
Block a user