2026-09-17 22:16:16 +08:00
|
|
|
|
// 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 的
|
2026-09-17 22:16:16 +08:00
|
|
|
|
// 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';
|
2026-09-17 22:16:16 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|