2026-09-17 22:05:36 +08:00
|
|
|
|
// services/api/src/albums/albums.controller.ts —— /albums 端点(Task 15;Task 16
|
|
|
|
|
|
// 增补 updateAlbum)。方法名与契约 operationId 一一对应(createAlbum/
|
|
|
|
|
|
// listAlbums/getAlbum/updateAlbum)。控制器级 SessionGuard:四端点全需认证
|
2026-09-17 21:51:50 +08:00
|
|
|
|
// (契约均有 bearerAuth、无 security: [] 例外)。职责仅剩:
|
|
|
|
|
|
// · 透传认证用户(req.user,守卫挂载);
|
2026-09-18 08:18:30 +08:00
|
|
|
|
// · 查询参数规整(limit 1..100 整数、cursor 长度)经 shared/pagination
|
|
|
|
|
|
// (P1a 终审修缮③迁出本控制器),非法 → 400 VALIDATION_FAILED;
|
2026-09-17 21:51:50 +08:00
|
|
|
|
// · 权限/可见性→HTTP 映射交由服务层抛 ApiException(404 ALBUM_NOT_FOUND)。
|
|
|
|
|
|
import {
|
|
|
|
|
|
Body,
|
|
|
|
|
|
Controller,
|
2026-09-23 10:13:08 +08:00
|
|
|
|
Delete,
|
2026-09-17 21:51:50 +08:00
|
|
|
|
Get,
|
2026-09-23 10:13:08 +08:00
|
|
|
|
HttpCode,
|
2026-09-17 21:51:50 +08:00
|
|
|
|
HttpStatus,
|
|
|
|
|
|
Param,
|
2026-09-17 22:05:36 +08:00
|
|
|
|
Patch,
|
2026-09-17 21:51:50 +08:00
|
|
|
|
Post,
|
|
|
|
|
|
Query,
|
|
|
|
|
|
Req,
|
|
|
|
|
|
UseGuards,
|
|
|
|
|
|
} from '@nestjs/common';
|
|
|
|
|
|
import { ErrorCodes } from '@photo/contracts';
|
|
|
|
|
|
import { ApiException } from '../api-exception';
|
|
|
|
|
|
import type { AuthUser } from '../auth/session.guard';
|
|
|
|
|
|
import { AuthenticatedRequest, SessionGuard } from '../auth/session.guard';
|
2026-09-18 08:18:30 +08:00
|
|
|
|
import { parseCursor, parseLimit } from '../shared/pagination';
|
2026-09-17 21:51:50 +08:00
|
|
|
|
import {
|
|
|
|
|
|
type AlbumListResponse,
|
|
|
|
|
|
type AlbumResponse,
|
|
|
|
|
|
AlbumsService,
|
|
|
|
|
|
} from './albums.service';
|
2026-09-17 22:05:36 +08:00
|
|
|
|
import { AlbumCreateRequestDto, AlbumUpdateRequestDto } from './dto';
|
2026-09-17 21:51:50 +08:00
|
|
|
|
|
2026-09-17 22:05:36 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 守卫放行后提取 req.user;防御性兜底(守卫未挂载属装配错误,按未认证拒绝)。
|
2026-09-18 08:18:30 +08:00
|
|
|
|
* members/categories/photos/uploads 控制器复用同一判定,导出。
|
2026-09-17 22:05:36 +08:00
|
|
|
|
*/
|
|
|
|
|
|
export function userOf(req: AuthenticatedRequest): AuthUser {
|
2026-09-17 21:51:50 +08:00
|
|
|
|
if (req.user === undefined) {
|
|
|
|
|
|
throw new ApiException(
|
|
|
|
|
|
ErrorCodes.AUTH_TOKEN_EXPIRED,
|
|
|
|
|
|
'Session token is missing, invalid, or expired',
|
|
|
|
|
|
HttpStatus.UNAUTHORIZED,
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
return req.user;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Controller('albums')
|
|
|
|
|
|
@UseGuards(SessionGuard)
|
|
|
|
|
|
export class AlbumsController {
|
|
|
|
|
|
constructor(private readonly albumsService: AlbumsService) {}
|
|
|
|
|
|
|
|
|
|
|
|
@Post()
|
|
|
|
|
|
createAlbum(
|
|
|
|
|
|
@Body() dto: AlbumCreateRequestDto,
|
|
|
|
|
|
@Req() req: AuthenticatedRequest,
|
|
|
|
|
|
): Promise<AlbumResponse> {
|
|
|
|
|
|
return this.albumsService.create(userOf(req).id, dto);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Get()
|
|
|
|
|
|
listAlbums(
|
|
|
|
|
|
@Query('cursor') cursor: string | undefined,
|
|
|
|
|
|
@Query('limit') limit: string | undefined,
|
|
|
|
|
|
@Req() req: AuthenticatedRequest,
|
|
|
|
|
|
): Promise<AlbumListResponse> {
|
|
|
|
|
|
return this.albumsService.list(
|
|
|
|
|
|
userOf(req),
|
|
|
|
|
|
parseCursor(cursor),
|
|
|
|
|
|
parseLimit(limit),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Get(':albumId')
|
|
|
|
|
|
getAlbum(
|
|
|
|
|
|
@Param('albumId') albumId: string,
|
|
|
|
|
|
@Req() req: AuthenticatedRequest,
|
|
|
|
|
|
): Promise<AlbumResponse> {
|
|
|
|
|
|
return this.albumsService.get(userOf(req), albumId);
|
|
|
|
|
|
}
|
2026-09-17 22:05:36 +08:00
|
|
|
|
|
2026-09-23 10:13:08 +08:00
|
|
|
|
@Delete(':albumId')
|
|
|
|
|
|
@HttpCode(HttpStatus.NO_CONTENT)
|
|
|
|
|
|
deleteAlbum(
|
|
|
|
|
|
@Param('albumId') albumId: string,
|
|
|
|
|
|
@Req() req: AuthenticatedRequest,
|
|
|
|
|
|
): Promise<void> {
|
|
|
|
|
|
return this.albumsService.softDelete(userOf(req), albumId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-17 22:05:36 +08:00
|
|
|
|
@Patch(':albumId')
|
|
|
|
|
|
updateAlbum(
|
|
|
|
|
|
@Param('albumId') albumId: string,
|
|
|
|
|
|
@Body() dto: AlbumUpdateRequestDto,
|
|
|
|
|
|
@Req() req: AuthenticatedRequest,
|
|
|
|
|
|
): Promise<AlbumResponse> {
|
|
|
|
|
|
return this.albumsService.update(userOf(req), albumId, dto);
|
|
|
|
|
|
}
|
2026-09-17 21:51:50 +08:00
|
|
|
|
}
|