diff --git a/src/api/private/media/media.controller.ts b/src/api/private/media/media.controller.ts index 58c715b11..bcb05a0a3 100644 --- a/src/api/private/media/media.controller.ts +++ b/src/api/private/media/media.controller.ts @@ -6,7 +6,6 @@ import { Controller, Delete, - Headers, Param, Post, UploadedFile, @@ -25,7 +24,9 @@ import { MulterFile } from '../../../media/multer-file.interface'; import { Note } from '../../../notes/note.entity'; import { NotesService } from '../../../notes/notes.service'; import { User } from '../../../users/user.entity'; +import { NoteHeaderInterceptor } from '../../utils/note-header.interceptor'; import { OpenApi } from '../../utils/openapi.decorator'; +import { RequestNote } from '../../utils/request-note.decorator'; import { RequestUser } from '../../utils/request-user.decorator'; @UseGuards(SessionGuard) @@ -59,6 +60,7 @@ export class MediaController { description: 'ID or alias of the parent note', }) @UseInterceptors(FileInterceptor('file')) + @UseInterceptors(NoteHeaderInterceptor) @OpenApi( { code: 201, @@ -72,13 +74,11 @@ export class MediaController { ) async uploadMedia( @UploadedFile() file: MulterFile, - @Headers('HedgeDoc-Note') noteId: string, + @RequestNote() note: Note, @RequestUser() user: User, ): Promise { - // TODO: Move getting the Note object into a decorator - const note: Note = await this.noteService.getNoteByIdOrAlias(noteId); this.logger.debug( - `Recieved filename '${file.originalname}' for note '${noteId}' from user '${user.username}'`, + `Recieved filename '${file.originalname}' for note '${note.id}' from user '${user.username}'`, 'uploadMedia', ); const upload = await this.mediaService.saveFile(file.buffer, user, note); diff --git a/src/api/public/media/media.controller.ts b/src/api/public/media/media.controller.ts index e426908fe..0fbd1a151 100644 --- a/src/api/public/media/media.controller.ts +++ b/src/api/public/media/media.controller.ts @@ -6,7 +6,6 @@ import { Controller, Delete, - Headers, Param, Post, UploadedFile, @@ -31,7 +30,9 @@ import { MulterFile } from '../../../media/multer-file.interface'; import { Note } from '../../../notes/note.entity'; import { NotesService } from '../../../notes/notes.service'; import { User } from '../../../users/user.entity'; +import { NoteHeaderInterceptor } from '../../utils/note-header.interceptor'; import { OpenApi } from '../../utils/openapi.decorator'; +import { RequestNote } from '../../utils/request-note.decorator'; import { RequestUser } from '../../utils/request-user.decorator'; @UseGuards(TokenAuthGuard) @@ -77,15 +78,14 @@ export class MediaController { 500, ) @UseInterceptors(FileInterceptor('file')) + @UseInterceptors(NoteHeaderInterceptor) async uploadMedia( @RequestUser() user: User, @UploadedFile() file: MulterFile, - @Headers('HedgeDoc-Note') noteId: string, + @RequestNote() note: Note, ): Promise { - // TODO: Move getting the Note object into a decorator - const note: Note = await this.noteService.getNoteByIdOrAlias(noteId); this.logger.debug( - `Recieved filename '${file.originalname}' for note '${noteId}' from user '${user.username}'`, + `Recieved filename '${file.originalname}' for note '${note.id}' from user '${user.username}'`, 'uploadMedia', ); const upload = await this.mediaService.saveFile(file.buffer, user, note); diff --git a/src/api/utils/note-header.interceptor.ts b/src/api/utils/note-header.interceptor.ts new file mode 100644 index 000000000..6fc53d615 --- /dev/null +++ b/src/api/utils/note-header.interceptor.ts @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +import { + CallHandler, + ExecutionContext, + Injectable, + NestInterceptor, +} from '@nestjs/common'; +import { Request } from 'express'; +import { Observable } from 'rxjs'; + +import { Note } from '../../notes/note.entity'; +import { NotesService } from '../../notes/notes.service'; + +/** + * Saves the note identified by the `HedgeDoc-Note` header + * under the `note` property of the request object. + */ +@Injectable() +export class NoteHeaderInterceptor implements NestInterceptor { + constructor(private noteService: NotesService) {} + + async intercept( + context: ExecutionContext, + next: CallHandler, + ): Promise> { + const request: Request & { + note: Note; + } = context.switchToHttp().getRequest(); + const noteId: string = request.headers['hedgedoc-note'] as string; + request.note = await this.noteService.getNoteByIdOrAlias(noteId); + return next.handle(); + } +}