52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
|
|
// services/api/src/albums/assets.controller.ts —— /albums/{albumId}/assets
|
|||
|
|
// 端点(P1b Task 3)。方法名与契约 operationId 一一对应(initAlbumAssetUpload/
|
|||
|
|
// completeAlbumAssetUpload)。控制器级 SessionGuard:两端点全需认证。控制器只做
|
|||
|
|
// 认证用户与路径参数透传;权限与 HTTP 映射由 AssetsService 抛 ApiException
|
|||
|
|
// (404 ALBUM_NOT_FOUND / 403 AUTH_FORBIDDEN / 400 VALIDATION_FAILED 或
|
|||
|
|
// UPLOAD_VERIFY_FAILED)。
|
|||
|
|
import {
|
|||
|
|
Body,
|
|||
|
|
Controller,
|
|||
|
|
HttpCode,
|
|||
|
|
HttpStatus,
|
|||
|
|
Param,
|
|||
|
|
Post,
|
|||
|
|
Req,
|
|||
|
|
UseGuards,
|
|||
|
|
} from '@nestjs/common';
|
|||
|
|
import { AuthenticatedRequest, SessionGuard } from '../auth/session.guard';
|
|||
|
|
import { userOf } from './albums.controller';
|
|||
|
|
import { AssetInitRequestDto } from './dto';
|
|||
|
|
import {
|
|||
|
|
AssetsService,
|
|||
|
|
type AssetCompleteResponse,
|
|||
|
|
type AssetInitResponse,
|
|||
|
|
} from './assets.service';
|
|||
|
|
|
|||
|
|
@Controller('albums/:albumId/assets')
|
|||
|
|
@UseGuards(SessionGuard)
|
|||
|
|
export class AssetsController {
|
|||
|
|
constructor(private readonly assetsService: AssetsService) {}
|
|||
|
|
|
|||
|
|
/** 契约 201:会话行已建(每次 init 新行新键,无幂等键)。 */
|
|||
|
|
@Post()
|
|||
|
|
initAlbumAssetUpload(
|
|||
|
|
@Param('albumId') albumId: string,
|
|||
|
|
@Body() dto: AssetInitRequestDto,
|
|||
|
|
@Req() req: AuthenticatedRequest,
|
|||
|
|
): Promise<AssetInitResponse> {
|
|||
|
|
return this.assetsService.init(userOf(req), albumId, dto);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** 完成核验:幂等(已生效行现签新 URL 返回,即签名刷新入口)。 */
|
|||
|
|
@Post(':assetId/complete')
|
|||
|
|
@HttpCode(HttpStatus.OK)
|
|||
|
|
completeAlbumAssetUpload(
|
|||
|
|
@Param('albumId') albumId: string,
|
|||
|
|
@Param('assetId') assetId: string,
|
|||
|
|
@Req() req: AuthenticatedRequest,
|
|||
|
|
): Promise<AssetCompleteResponse> {
|
|||
|
|
return this.assetsService.complete(userOf(req), albumId, assetId);
|
|||
|
|
}
|
|||
|
|
}
|