Commit Graph

2 Commits

Author SHA1 Message Date
hailin 510a890b33 fix(mining-admin): 修复审计日志 IP 地址记录为内网 IP 的问题,补全全操作的 IP 审计
【根本原因】
- main.ts 缺少 `app.set('trust proxy', 1)`,Express 在 Nginx/Kong 代理后 req.ip
  返回的是代理服务器内网 IP(127.0.0.1),而非真实客户端 IP。
- Nginx 已正确设置 X-Forwarded-For / X-Real-IP,但后端从未读取这些 header。

【修复内容】

1. main.ts
   - 新增 `app.set('trust proxy', 1)`,使 Express 信任 Nginx 第一跳的
     X-Forwarded-For,req.ip 从此返回真实客户端 IP。

2. shared/utils/get-client-ip.ts(新建工具函数)
   - 优先读取 X-Forwarded-For(取逗号分隔的第一个 IP,支持多跳代理)
   - 其次读取 X-Real-IP
   - 兜底使用 req.ip
   - 全服务统一使用此函数,避免各处重复逻辑。

3. auth.controller.ts / auth.service.ts
   - LOGIN:将 req.ip 改为 getClientIp(req)(已记录 IP,修正来源)
   - LOGOUT:之前完全不记录 IP/UA,现在补全传入并存入审计日志。

4. config.service.ts / config.controller.ts
   - setConfig / deleteConfig 新增 ipAddress / userAgent 可选参数。
   - 新增 recordAuditLog 通用方法,供 Controller 记录任意审计事件。
   - 所有写操作(setTransferEnabled、setP2pTransferFee、setConfig、
     deleteConfig)均传入真实 IP 和 UA。
   - activateMining / deactivateMining 之前完全无审计日志,
     现补录 ACTIVATE / DEACTIVATE 类型的 MINING 审计条目。

5. capability-admin.service.ts / capability.controller.ts
   - setCapability / setCapabilities / writeAuditLog 均新增
     ipAddress / userAgent 参数,Controller 层传入真实 IP。

6. pre-planting-restriction.service.ts / controller
   - unlockRestriction 新增 ipAddress / userAgent 参数并写入审计日志。

7. manual-mining.service.ts / controller
   - execute 新增 ipAddress / userAgent 参数并写入审计日志。

8. batch-mining.service.ts / controller
   - execute 新增 ipAddress / userAgent 参数并写入审计日志
     (upload-execute 和 execute 两个入口均已更新)。

【影响范围】
- 仅 mining-admin-service,无数据库 Schema 变更(ipAddress/userAgent 字段已存在)。
- 所有现有接口签名向后兼容(新增参数均为可选)。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 22:32:29 -07:00
hailin ac3adfc90a feat(pre-planting): 新增预种积分股卖出限制(方案B纯新增)
限制仅有预种份数(未合并成棵)的用户卖出积分股,
直到用户完成首次预种合并后方可卖出。

=== 改动范围(全部 2.0 系统,纯新增)===

contribution-service:
- prisma/pre-planting/schema.prisma: 新增 PrePlantingSellRestrictionOverride 模型
- migrations/20260304000000: 对应建表 SQL
- src/pre-planting/application/services/sell-restriction.service.ts: 核心判断逻辑
  isRestricted = has_pre_planting_marker AND !has_real_tree AND !admin_override
- src/api/controllers/pre-planting-restriction.controller.ts: 暴露内部接口
  GET  /api/v2/pre-planting/sell-restriction/:accountSequence (@Public)
  POST /api/v2/pre-planting/sell-restriction/:accountSequence/unlock (@Public)
- src/api/api.module.ts: 注册新 controller 和 SellRestrictionService

trading-service:
- src/application/services/sell-restriction.service.ts: HTTP + Redis 缓存(TTL 60s)
  fail-open:contribution-service 不可用时允许卖出,保障业务连续性
- src/application/services/order.service.ts: 卖单前增加限制检查(4行)
- src/application/application.module.ts: 注册 TradingSellRestrictionService

mining-admin-service:
- src/application/services/pre-planting-restriction.service.ts: 代理接口 + 审计日志
  每次管理员解除操作均写入 AuditLog,保证严格可追溯性
- src/api/controllers/pre-planting-restriction.controller.ts:
  GET  /pre-planting-restriction/:accountSequence
  POST /pre-planting-restriction/:accountSequence/unlock
- api.module.ts / application.module.ts: 注册新服务和接口

mining-admin-web:
- users.api.ts: 新增 getPrePlantingRestriction / unlockPrePlantingRestriction
- use-users.ts: 新增 usePrePlantingRestriction / useUnlockPrePlantingRestriction hooks
- users/[accountSequence]/page.tsx: 受限时在基本信息卡显示红色警告 + 解除按钮

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 05:04:57 -08:00