import { Body, Controller, Delete, ForbiddenException, Get, Headers, Param, Post } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { ApiBearerAuth, ApiBody, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger'; import { firstValueFrom } from 'rxjs'; import { map } from 'rxjs/operators'; import { CoreGrpcService } from '../core-grpc.service'; import { getAuthorizedUserId } from '../document-access'; import { UpsertAddressDto } from '../dto/addresses.dto'; @ApiTags('Адреса') @ApiBearerAuth() @Controller('addresses/users/:userId') export class AddressesController { constructor( private readonly core: CoreGrpcService, private readonly jwt: JwtService ) {} private async assertSelfAccess(authorization: string | undefined, userId: string) { const requesterId = await getAuthorizedUserId(this.jwt, this.core, authorization); if (requesterId !== userId) { throw new ForbiddenException('Можно управлять только своими адресами'); } return requesterId; } @Get() @ApiOperation({ summary: 'Список адресов пользователя' }) @ApiParam({ name: 'userId', description: 'ID пользователя' }) async list(@Headers('authorization') authorization: string | undefined, @Param('userId') userId: string) { await this.assertSelfAccess(authorization, userId); return firstValueFrom( this.core.addresses.ListAddresses({ userId }).pipe( map((response) => { const payload = response as { addresses?: unknown[] }; return { addresses: payload.addresses ?? [] }; }) ) ); } @Post() @ApiOperation({ summary: 'Создать или обновить адрес' }) @ApiParam({ name: 'userId', description: 'ID пользователя' }) @ApiBody({ type: UpsertAddressDto }) async upsert( @Headers('authorization') authorization: string | undefined, @Param('userId') userId: string, @Body() dto: UpsertAddressDto ) { await this.assertSelfAccess(authorization, userId); return firstValueFrom(this.core.addresses.UpsertAddress({ userId, ...dto })); } @Delete(':addressId') @ApiOperation({ summary: 'Удалить адрес' }) @ApiParam({ name: 'userId', description: 'ID пользователя' }) @ApiParam({ name: 'addressId', description: 'ID адреса' }) @ApiResponse({ status: 200, description: 'Адрес удалён' }) async delete( @Headers('authorization') authorization: string | undefined, @Param('userId') userId: string, @Param('addressId') addressId: string ) { await this.assertSelfAccess(authorization, userId); return firstValueFrom(this.core.addresses.DeleteAddress({ userId, addressId })); } }