Files
photo-live/services/api/src/albums/members.controller.ts
T

70 lines
2.0 KiB
TypeScript
Raw Normal View History

// services/api/src/albums/members.controller.ts —— /albums/{albumId}/members
// 端点(Task 17)。方法名与契约 operationId 一一对应(addAlbumMember/
// listAlbumMembers/removeAlbumMember)。控制器级 SessionGuard:三端点全需
2026-09-18 08:18:30 +08:00
// 认证。控制器只做认证用户透传 + 查询参数规整(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';
2026-09-18 08:18:30 +08:00
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<MemberResponse> {
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<MemberListResponse> {
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<void> {
return this.membersService.remove(userOf(req), albumId, userId);
}
}