// services/api/src/albums/members.controller.ts —— /albums/{albumId}/members // 端点(Task 17)。方法名与契约 operationId 一一对应(addAlbumMember/ // listAlbumMembers/removeAlbumMember)。控制器级 SessionGuard:三端点全需 // 认证。控制器只做认证用户透传 + 查询参数规整(shared/pagination 的 // parseLimit/parseCursor,同一契约 bounds/游标语义);权限与 HTTP 映射由 // MembersService 抛 ApiException(404 ALBUM_NOT_FOUND / 403 AUTH_FORBIDDEN / // 409 MEMBER_CONFLICT)。 import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Query, Req, UseGuards, } from '@nestjs/common'; import { AuthenticatedRequest, SessionGuard } from '../auth/session.guard'; import { userOf } from './albums.controller'; import { parseCursor, parseLimit } from '../shared/pagination'; import { MemberAddRequestDto } from './dto'; import { type MemberListResponse, type MemberResponse, MembersService, } from './members.service'; @Controller('albums/:albumId/members') @UseGuards(SessionGuard) export class MembersController { constructor(private readonly membersService: MembersService) {} @Post() addAlbumMember( @Param('albumId') albumId: string, @Body() dto: MemberAddRequestDto, @Req() req: AuthenticatedRequest, ): Promise { return this.membersService.add(userOf(req), albumId, dto); } @Get() listAlbumMembers( @Param('albumId') albumId: string, @Query('cursor') cursor: string | undefined, @Query('limit') limit: string | undefined, @Req() req: AuthenticatedRequest, ): Promise { return this.membersService.list( userOf(req), albumId, parseCursor(cursor), parseLimit(limit), ); } @Delete(':userId') @HttpCode(HttpStatus.NO_CONTENT) removeAlbumMember( @Param('albumId') albumId: string, @Param('userId') userId: string, @Req() req: AuthenticatedRequest, ): Promise { return this.membersService.remove(userOf(req), albumId, userId); } }