Прикрепите идентификатор пользователя из токена доступа с помощью DTO - PullRequest
3 голосов
/ 02 августа 2020

Я создаю конечную точку POST для создания нового объекта. Я также создал схему для mon goose с полем userId (для подключения этого объекта к указанному пользователю) и DTO, который я использую в моем методе POST.

@UseGuards(JwtAuthGuard)
@Post("/")
createAction(@Request() req, @Body() createActionDto: CreateActionDto) {
    return this.actionService.createAction(req?.user?.userId, createActionDto);
}

DTO:

import { IsString, IsNumber, IsUrl } from 'class-validator';

export class CreateActionDto {
    userId: string;

    @IsString()
    name: string;

    @IsNumber()
    timeStart: number;
}

Схема:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

@Schema()
export class Action extends Document {
    @Prop()
    userId: string;

    @Prop()
    name: string;

    @Prop()
    timeStart: number;
}

export const ActionSchema = SchemaFactory.createForClass(Action)

В свойстве req у меня есть userId. Как лучше всего создать объект и прикрепить userId, извлеченный из токена?

Должен ли я передать req в службу, а в свойстве userId в DTO установить свойство следующим образом?:

@Injectable()
export class ActionService {
    constructor(
        @InjectModel(Action.name) private actionModel: Model<Action>,
    ) { }

    async createAction(req: string, createActionDto: CreateActionDto) {
        createActionDto.userId = req.user.userId

        // ... save to mongoose createActionDto
    }
}

Это правильное решение или есть другой, лучший способ справиться с ним?

1 Ответ

2 голосов
/ 02 августа 2020

Лично я бы установил userId в контроллере, чтобы не передавать его:

@UseGuards(JwtAuthGuard)
@Post("/")
createAction(@Request() req, @Body() createActionDto: CreateActionDto) {
    createActionDto.userId = req?.user?.userId;
    return this.actionService.createAction(createActionDto);
}

Если у вас много разных контроллеров и DTO, требующих userId, вы также можете определите перехватчик и сделайте это там, чтобы уменьшить дублирование:

@Injectable()
export class SetUserIdInterceptor implements NestInterceptor {
  public intercept(_context: ExecutionContext, $next: CallHandler): Observable<any> {    
   const request: any = _context.switchToHttp().getRequest(); //instead of any you could also define a super-class for all DTOs that require the `userId`-property    
   request.body?.userId = req?.user?.userId;
   return $next;
  }
}

Затем вы можете использовать этот перехватчик на своем маршруте следующим образом:

@UseGuards(JwtAuthGuard)
@Post("/")
@UseInterceptors(SetUserIdInterceptor)
createAction(@Body() createActionDto: CreateActionDto) {
    return this.actionService.createAction(createActionDto)
}
...