Files
photo-live/services/api/src/auth/dto.ts
T
浅念 31ba03de11 feat(api): password change endpoint and source device id on uploads
P3 Task 3 契约增补批次(单一事实来源 openapi.yaml + cn 实现 + e2e):

- POST /v1/auth/password-change(operationId changePassword,需求 4.1 的
  P1 契约缺口补齐):Bearer + {oldPassword 1-128, newPassword 8-128} → 204;
  旧密码错误 401 AUTH_INVALID_CREDENTIALS;成功后事务内更新 argon2 哈希、
  撤销该用户除当前会话外的全部其他会话(当前会话保留,本人不下线)、写
  审计 auth.password_change。
- sourceDeviceId(A19 设备来源语义):UploadInitRequest 可选 8-64 位设备
  标识;upload_sessions 落列(VARCHAR(64) utf8mb4_0900_bin,可空,存量
  行 NULL 兼容);GET /uploads 条目回显;幂等重放不比对(first-writer,
  首次落库值不随重放漂移)。
- e2e:auth 增 4 例(未认证 401 / 新密码过短 400 / 旧密码错误 401 且会话
  无副作用 / 成功后他端会话撤销当前保留 + 新旧密码登录裁决 + 审计);
  uploads 增 1 例(携带落库回显、换设备重放保留首值、缺省 null、长度
  越界 400)。api e2e 179 → 184;contracts gen/redocly/单测、worker、
  sync 门全绿。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-19 00:59:39 +08:00

37 lines
1.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// services/api/src/auth/dto.ts —— auth 端点入参 DTO(Task 13;Task 3/P3 增补
// password-change)。Nest 约定用 class-validator + class-transformer(非 zod):
// 装饰器元数据供全局 ValidationPipe(app-cn.module 经 APP_PIPE 注册)校验,
// 失败抛 BadRequestException,由全局过滤器映射 400 VALIDATION_FAILED(契约各
// auth 端点的 '400' 响应)。字段约束对齐契约 LoginRequest:account/password
// 均为非空字符串;契约未定义长度上限(users.account 列宽 64 由入库侧保证,
// 超长账号查无此人不构成枚举面)。PasswordChangeRequest(P3 Task 3 契约增补):
// oldPassword 1-128、newPassword 8-128。
import {
IsNotEmpty,
IsString,
MaxLength,
MinLength,
} from 'class-validator';
export class LoginRequestDto {
@IsString()
@IsNotEmpty()
account!: string;
@IsString()
@IsNotEmpty()
password!: string;
}
export class PasswordChangeRequestDto {
@IsString()
@IsNotEmpty()
@MaxLength(128)
oldPassword!: string;
@IsString()
@MinLength(8)
@MaxLength(128)
newPassword!: string;
}