Commit Graph

4 Commits

Author SHA1 Message Date
hailin 97f8b7339f fix(auth): LOGIN 能力禁用后强制下线已登录用户
## 问题
管理员在后台禁用用户的 LOGIN 能力后,该用户仍然可以正常使用 mining-app。
原因是 LOGIN 检查只在登录/刷新 token 时执行,已持有有效 JWT(7天有效期)
的用户不会被影响,直到 token 过期才会被拦截。

## 修复

### 后端 - JwtAuthGuard (auth-service)
- 在 JWT 验证通过后,增加 LOGIN 能力实时检查
- 调用 CapabilityService.isCapabilityEnabled() 查询 Redis 缓存
- LOGIN 被禁用时返回 403 ForbiddenException("您的账户已被限制登录")
- 采用 fail-open 策略:Redis/DB 查询失败时放行,不影响正常用户
- 每次认证请求多一次 Redis GET(<1ms),对当前用户规模无性能影响

### 前端 - mining-app API Client
- 新增 onLoginDisabled 全局回调(类似现有的 onUnauthorized)
- Dio 拦截器检测 403 响应中包含"限制登录"关键词时触发回调
- 回调执行:清除用户状态 + 跳转登录页(与 401 处理一致)

## 影响范围
- 所有使用 @UseGuards(JwtAuthGuard) 的端点都会实时检查 LOGIN 能力
- 管理员禁用 LOGIN 后,用户下一次 API 请求即被拦截并强制下线
- 不影响公开端点(登录、注册等不经过 JwtAuthGuard 的接口)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 05:01:37 -08:00
hailin 21fc55fb01 fix(capability): auth-service CapabilityGuard 类型修复 string → Capability
isCapabilityEnabled 参数需要 Capability 枚举类型,添加 as Capability 类型断言

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 22:29:20 -08:00
hailin 55cfc96464 feat(capability): 实现用户能力权限控制系统(Capability-based Permission)
借鉴 Stripe Capability 模型,实现 13 项细粒度用户功能权限控制:
LOGIN, TRADING, C2C, TRANSFER_IN/OUT, P2P_SEND/RECEIVE,
MINING_CLAIM, KYC, PROFILE_EDIT, VIEW_ASSET/TEAM/RECORDS

## 架构设计
- auth-service 为能力数据唯一写入点(DB + Redis DB14 缓存)
- 下游服务通过独立 ioredis 客户端直连 Redis DB14 检查能力(~1ms)
- 默认全部开启(fail-open):无缓存/Redis 故障 = 允许通行
- Guard 执行顺序:JwtAuthGuard → CapabilityGuard

## Phase 1: auth-service 核心
- Prisma Schema: UserCapability + CapabilityLog 两张表
- Domain: Capability 枚举, CapabilityMap 类型, Repository 接口
- Infrastructure: PrismaCapabilityRepository(含 $transaction 原子操作)
- Application: CapabilityService(Redis 缓存优先 → DB fallback → 写回 Redis TTL 1h)
- Scheduler: 每 60 秒扫描到期限制自动恢复(Redis 分布式锁防重复)
- API: GET /auth/user/capabilities (JWT), Internal CRUD API (服务间)
- 登录/refreshToken 均增加 LOGIN 能力检查

## Phase 2: 下游 CapabilityGuard
- trading-service: 14 个端点标注(TRADING/C2C/TRANSFER/P2P_SEND/VIEW_ASSET)
- contribution-service: 3 个端点标注(VIEW_RECORDS/VIEW_TEAM)
- mining-service: Guard 注册 + JwtAuthGuard accountSequence 兼容修复
- auth-service: KYC 端点标注(controller 级别 UseGuards)

## Phase 3: mining-admin-service
- CapabilityAdminService: 代理 auth-service internal API + 本地 AuditLog
- CapabilityController: Admin CRUD + 批量设置 + 变更日志查询

## Phase 4: mining-admin-web
- capability-management.tsx: 分组 Switch 开关 + 禁用 Dialog(原因+到期时间)+ 变更日志分页
- React Query hooks: useCapabilities/useSetCapability/useCapabilityLogs
- 用户详情页新增"权限管理"Tab

## Phase 5: mining-app (Flutter)
- CapabilityMap 数据模型 + ForbiddenException 异常类
- api_client.dart: 403 响应适配 ExceptionFilter 包装格式
- capabilitiesProvider: 登录后获取能力列表,fail-open 降级

## 审计修复
- CRITICAL: users.api.ts capability 方法移入 usersApi 对象内部
- P0: Flutter 403 解析路径适配 {error:{code,message}} 实际格式
- P0: 批量接口 operatorId 提升到 body 顶层匹配 auth-service 契约
- P1: mining-service JwtAuthGuard accountSequence fallback payload.sub
- P1: refreshCache 加 try/catch 防止 Redis 故障导致 500
- P1: processExpiredRestrictions 改用 upsertWithLog 事务方法
- P1: C2C upload-proof 补加 @RequireCapability('C2C')
- HIGH: internal.controller.ts 新增 capability 枚举校验
- HIGH: admin capability.controller.ts adminId fallback + query params 类型修复
- MEDIUM: setCapability 改用 $transaction 保证 upsert+log 原子性

## 部署注意
- 需运行: cd auth-service && npx prisma migrate dev --name add_user_capabilities
- 需配置: mining-admin-service .env AUTH_SERVICE_URL=http://auth-service:3010

## 待后续处理(P2)
- P2P_RECEIVE 需在业务逻辑层检查(收款方无主动请求)
- MINING_CLAIM/PROFILE_EDIT 待对应端点实现后标注
- getCapabilities 返回 Map 转 Array 丢失 reason/expiresAt 详细字段

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 22:19:56 -08:00
hailin f7278b6196 feat(auth-service): 添加用户认证服务2.0
实现完整的用户认证服务,支持1.0用户迁移和2.0新用户注册:

功能特性:
- 用户注册(生成V2格式accountSequence: 15位)
- 密码登录(支持V1迁移用户和V2用户)
- V1用户首次登录自动迁移到2.0系统
- 短信验证码发送/验证(注册/登录/重置密码/更换手机号)
- 密码管理(重置密码、修改密码)
- KYC实名认证(提交/审核资料)
- JWT认证(Access Token + Refresh Token)

技术架构:
- DDD六边形架构(Domain/Application/Infrastructure/API)
- Prisma ORM + PostgreSQL
- CDC消费者同步1.0用户数据
- Outbox模式发布领域事件
- NestJS ThrottlerModule限流

数据模型:
- User: 2.0用户表(含KYC字段)
- SyncedLegacyUser: CDC同步的1.0用户(只读)
- RefreshToken: 刷新令牌
- SmsVerification: 短信验证码
- DailySequenceCounter: 每日序号计数器
- OutboxEvent: 发件箱事件

AccountSequence格式:
- V1: D + YYMMDD + 5位序号 = 12字符
- V2: D + YYMMDD + 8位序号 = 15字符

服务端口:3024
数据库:rwa_auth

同时更新deploy-mining.sh添加auth-service支持。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 18:50:59 -08:00