refactor: remove try catches from controllers

This is handled by the ErrorExceptionMapping class

Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
Philip Molares 2022-01-17 10:48:33 +01:00
parent 2cd4f412e5
commit d142cbadeb
10 changed files with 133 additions and 424 deletions

View file

@ -9,7 +9,6 @@ import {
Controller,
Delete,
HttpCode,
NotFoundException,
Param,
Post,
Put,
@ -19,11 +18,7 @@ import {
import { ApiTags } from '@nestjs/swagger';
import {
AlreadyInDBError,
ForbiddenIdError,
NotInDBError,
PrimaryAliasDeletionForbiddenError,
} from '../../../errors/errors';
import { SessionGuard } from '../../../identity/session.guard';
import { ConsoleLoggerService } from '../../../logger/console-logger.service';
import { AliasCreateDto } from '../../../notes/alias-create.dto';
@ -49,32 +44,23 @@ export class AliasController {
) {
this.logger.setContext(AliasController.name);
}
@Post()
async addAlias(
@RequestUser() user: User,
@Body() newAliasDto: AliasCreateDto,
): Promise<AliasDto> {
try {
const note = await this.noteService.getNoteByIdOrAlias(
newAliasDto.noteIdOrAlias,
);
if (!(await this.permissionsService.isOwner(user, note))) {
throw new UnauthorizedException('Reading note denied!');
}
const updatedAlias = await this.aliasService.addAlias(
note,
newAliasDto.newAlias,
);
return this.aliasService.toAliasDto(updatedAlias, note);
} catch (e) {
if (e instanceof AlreadyInDBError) {
throw new BadRequestException(e.message);
}
if (e instanceof ForbiddenIdError) {
throw new BadRequestException(e.message);
}
throw e;
const note = await this.noteService.getNoteByIdOrAlias(
newAliasDto.noteIdOrAlias,
);
if (!(await this.permissionsService.isOwner(user, note))) {
throw new UnauthorizedException('Reading note denied!');
}
const updatedAlias = await this.aliasService.addAlias(
note,
newAliasDto.newAlias,
);
return this.aliasService.toAliasDto(updatedAlias, note);
}
@Put(':alias')
@ -88,25 +74,12 @@ export class AliasController {
`The field 'primaryAlias' must be set to 'true'.`,
);
}
try {
const note = await this.noteService.getNoteByIdOrAlias(alias);
if (!(await this.permissionsService.isOwner(user, note))) {
throw new UnauthorizedException('Reading note denied!');
}
const updatedAlias = await this.aliasService.makeAliasPrimary(
note,
alias,
);
return this.aliasService.toAliasDto(updatedAlias, note);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
if (e instanceof ForbiddenIdError) {
throw new BadRequestException(e.message);
}
throw e;
const note = await this.noteService.getNoteByIdOrAlias(alias);
if (!(await this.permissionsService.isOwner(user, note))) {
throw new UnauthorizedException('Reading note denied!');
}
const updatedAlias = await this.aliasService.makeAliasPrimary(note, alias);
return this.aliasService.toAliasDto(updatedAlias, note);
}
@Delete(':alias')
@ -115,24 +88,11 @@ export class AliasController {
@RequestUser() user: User,
@Param('alias') alias: string,
): Promise<void> {
try {
const note = await this.noteService.getNoteByIdOrAlias(alias);
if (!(await this.permissionsService.isOwner(user, note))) {
throw new UnauthorizedException('Reading note denied!');
}
await this.aliasService.removeAlias(note, alias);
return;
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
if (e instanceof PrimaryAliasDeletionForbiddenError) {
throw new BadRequestException(e.message);
}
if (e instanceof ForbiddenIdError) {
throw new BadRequestException(e.message);
}
throw e;
const note = await this.noteService.getNoteByIdOrAlias(alias);
if (!(await this.permissionsService.isOwner(user, note))) {
throw new UnauthorizedException('Reading note denied!');
}
await this.aliasService.removeAlias(note, alias);
return;
}
}

View file

@ -12,17 +12,12 @@ import {
Post,
Put,
Req,
UnauthorizedException,
UseGuards,
} from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Session } from 'express-session';
import {
AlreadyInDBError,
InvalidCredentialsError,
NoLocalIdentityError,
} from '../../../errors/errors';
import { AlreadyInDBError } from '../../../errors/errors';
import { IdentityService } from '../../../identity/identity.service';
import { LocalAuthGuard } from '../../../identity/local/local.strategy';
import { LoginDto } from '../../../identity/local/login.dto';
@ -62,6 +57,7 @@ export class AuthController {
);
return;
} catch (e) {
// This special handling can't be omitted since AlreadyInDBErrors get mapped to BadRequestException usually.
if (e instanceof AlreadyInDBError) {
throw new ConflictException(e.message);
}

View file

@ -1,15 +1,13 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import {
BadRequestException,
Body,
Controller,
Delete,
Get,
NotFoundException,
Post,
Put,
UseGuards,
@ -17,7 +15,6 @@ import {
} from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { ForbiddenIdError, NotInDBError } from '../../../../errors/errors';
import { HistoryEntryImportDto } from '../../../../history/history-entry-import.dto';
import { HistoryEntryUpdateDto } from '../../../../history/history-entry-update.dto';
import { HistoryEntryDto } from '../../../../history/history-entry.dto';
@ -43,19 +40,10 @@ export class HistoryController {
@Get()
async getHistory(@RequestUser() user: User): Promise<HistoryEntryDto[]> {
try {
const foundEntries = await this.historyService.getEntriesByUser(user);
return await Promise.all(
foundEntries.map((entry) =>
this.historyService.toHistoryEntryDto(entry),
),
);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
throw e;
}
const foundEntries = await this.historyService.getEntriesByUser(user);
return await Promise.all(
foundEntries.map((entry) => this.historyService.toHistoryEntryDto(entry)),
);
}
@Post()
@ -63,26 +51,12 @@ export class HistoryController {
@RequestUser() user: User,
@Body('history') history: HistoryEntryImportDto[],
): Promise<void> {
try {
await this.historyService.setHistory(user, history);
} catch (e) {
if (e instanceof NotInDBError || e instanceof ForbiddenIdError) {
throw new BadRequestException(e.message);
}
throw e;
}
await this.historyService.setHistory(user, history);
}
@Delete()
async deleteHistory(@RequestUser() user: User): Promise<void> {
try {
await this.historyService.deleteHistory(user);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
throw e;
}
await this.historyService.deleteHistory(user);
}
@Put(':noteIdOrAlias')
@ -92,19 +66,12 @@ export class HistoryController {
@RequestUser() user: User,
@Body() entryUpdateDto: HistoryEntryUpdateDto,
): Promise<HistoryEntryDto> {
try {
const newEntry = await this.historyService.updateHistoryEntry(
note,
user,
entryUpdateDto,
);
return await this.historyService.toHistoryEntryDto(newEntry);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
throw e;
}
const newEntry = await this.historyService.updateHistoryEntry(
note,
user,
entryUpdateDto,
);
return await this.historyService.toHistoryEntryDto(newEntry);
}
@Delete(':noteIdOrAlias')
@ -113,13 +80,6 @@ export class HistoryController {
@RequestNote() note: Note,
@RequestUser() user: User,
): Promise<void> {
try {
await this.historyService.deleteHistoryEntry(note, user);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
throw e;
}
await this.historyService.deleteHistoryEntry(note, user);
}
}

View file

@ -4,16 +4,12 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import {
BadRequestException,
Controller,
Delete,
Headers,
HttpCode,
InternalServerErrorException,
NotFoundException,
Param,
Post,
UnauthorizedException,
UploadedFile,
UseGuards,
UseInterceptors,
@ -30,12 +26,7 @@ import {
ApiUnauthorizedResponse,
} from '@nestjs/swagger';
import {
ClientError,
MediaBackendError,
NotInDBError,
PermissionError,
} from '../../../errors/errors';
import { PermissionError } from '../../../errors/errors';
import { SessionGuard } from '../../../identity/session.guard';
import { ConsoleLoggerService } from '../../../logger/console-logger.service';
import { MediaUploadUrlDto } from '../../../media/media-upload-url.dto';
@ -94,26 +85,14 @@ export class MediaController {
@Headers('HedgeDoc-Note') noteId: string,
@RequestUser() user: User,
): Promise<MediaUploadUrlDto> {
try {
// 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}'`,
'uploadMedia',
);
const url = await this.mediaService.saveFile(file.buffer, user, note);
return this.mediaService.toMediaUploadUrlDto(url);
} catch (e) {
if (e instanceof ClientError || e instanceof NotInDBError) {
throw new BadRequestException(e.message);
}
if (e instanceof MediaBackendError) {
throw new InternalServerErrorException(
'There was an error in the media backend',
);
}
throw e;
}
// 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}'`,
'uploadMedia',
);
const url = await this.mediaService.saveFile(file.buffer, user, note);
return this.mediaService.toMediaUploadUrlDto(url);
}
@Delete(':filename')
@ -125,37 +104,20 @@ export class MediaController {
@Param('filename') filename: string,
): Promise<void> {
const username = user.username;
try {
this.logger.debug(
`Deleting '${filename}' for user '${username}'`,
this.logger.debug(
`Deleting '${filename}' for user '${username}'`,
'deleteMedia',
);
const mediaUpload = await this.mediaService.findUploadByFilename(filename);
if ((await mediaUpload.user).username !== username) {
this.logger.warn(
`${username} tried to delete '${filename}', but is not the owner`,
'deleteMedia',
);
const mediaUpload = await this.mediaService.findUploadByFilename(
filename,
throw new PermissionError(
`File '${filename}' is not owned by '${username}'`,
);
if ((await mediaUpload.user).username !== username) {
this.logger.warn(
`${username} tried to delete '${filename}', but is not the owner`,
'deleteMedia',
);
throw new PermissionError(
`File '${filename}' is not owned by '${username}'`,
);
}
await this.mediaService.deleteFile(mediaUpload);
} catch (e) {
if (e instanceof PermissionError) {
throw new UnauthorizedException(e.message);
}
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
if (e instanceof MediaBackendError) {
throw new InternalServerErrorException(
'There was an error in the media backend',
);
}
throw e;
}
await this.mediaService.deleteFile(mediaUpload);
}
}

View file

@ -4,13 +4,11 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import {
BadRequestException,
Body,
Controller,
Delete,
Get,
HttpCode,
NotFoundException,
Param,
Post,
UseGuards,
@ -18,11 +16,6 @@ import {
} from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import {
AlreadyInDBError,
ForbiddenIdError,
NotInDBError,
} from '../../../errors/errors';
import { HistoryService } from '../../../history/history.service';
import { SessionGuard } from '../../../identity/session.guard';
import { ConsoleLoggerService } from '../../../logger/console-logger.service';
@ -91,7 +84,7 @@ export class NotesController {
@RequestUser() user: User,
@MarkdownBody() text: string,
): Promise<NoteDto> {
this.logger.debug('Got raw markdown:\n' + text);
this.logger.debug('Got raw markdown:\n' + text, 'createNote');
return await this.noteService.toNoteDto(
await this.noteService.createNote(text, user),
);
@ -107,19 +100,9 @@ export class NotesController {
@MarkdownBody() text: string,
): Promise<NoteDto> {
this.logger.debug('Got raw markdown:\n' + text, 'createNamedNote');
try {
return await this.noteService.toNoteDto(
await this.noteService.createNote(text, user, noteAlias),
);
} catch (e) {
if (e instanceof AlreadyInDBError) {
throw new BadRequestException(e.message);
}
if (e instanceof ForbiddenIdError) {
throw new BadRequestException(e.message);
}
throw e;
}
return await this.noteService.toNoteDto(
await this.noteService.createNote(text, user, noteAlias),
);
}
@Delete(':noteIdOrAlias')
@ -192,15 +175,8 @@ export class NotesController {
@RequestNote() note: Note,
@Param('revisionId') revisionId: number,
): Promise<RevisionDto> {
try {
return this.revisionsService.toRevisionDto(
await this.revisionsService.getRevision(note, revisionId),
);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
throw e;
}
return this.revisionsService.toRevisionDto(
await this.revisionsService.getRevision(note, revisionId),
);
}
}

View file

@ -9,7 +9,6 @@ import {
Delete,
Get,
HttpCode,
NotFoundException,
Param,
Post,
UnauthorizedException,
@ -20,7 +19,6 @@ import { ApiTags } from '@nestjs/swagger';
import { AuthTokenWithSecretDto } from '../../../auth/auth-token-with-secret.dto';
import { AuthTokenDto } from '../../../auth/auth-token.dto';
import { AuthService } from '../../../auth/auth.service';
import { NotInDBError } from '../../../errors/errors';
import { SessionGuard } from '../../../identity/session.guard';
import { ConsoleLoggerService } from '../../../logger/console-logger.service';
import { User } from '../../../users/user.entity';
@ -61,15 +59,9 @@ export class TokensController {
@Param('keyId') keyId: string,
): Promise<void> {
const tokens = await this.authService.getTokensByUser(user);
try {
for (const token of tokens) {
if (token.keyId == keyId) {
return await this.authService.removeToken(keyId);
}
}
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
for (const token of tokens) {
if (token.keyId == keyId) {
return await this.authService.removeToken(keyId);
}
}
throw new UnauthorizedException(

View file

@ -9,7 +9,6 @@ import {
Controller,
Delete,
HttpCode,
NotFoundException,
Param,
Post,
Put,
@ -24,12 +23,6 @@ import {
} from '@nestjs/swagger';
import { TokenAuthGuard } from '../../../auth/token.strategy';
import {
AlreadyInDBError,
ForbiddenIdError,
NotInDBError,
PrimaryAliasDeletionForbiddenError,
} from '../../../errors/errors';
import { ConsoleLoggerService } from '../../../logger/console-logger.service';
import { AliasCreateDto } from '../../../notes/alias-create.dto';
import { AliasUpdateDto } from '../../../notes/alias-update.dto';
@ -41,6 +34,7 @@ import { User } from '../../../users/user.entity';
import { FullApi } from '../../utils/fullapi-decorator';
import { RequestUser } from '../../utils/request-user.decorator';
@UseGuards(TokenAuthGuard)
@ApiTags('alias')
@ApiSecurity('token')
@Controller('alias')
@ -54,7 +48,6 @@ export class AliasController {
this.logger.setContext(AliasController.name);
}
@UseGuards(TokenAuthGuard)
@Post()
@ApiOkResponse({
description: 'The new alias',
@ -65,30 +58,19 @@ export class AliasController {
@RequestUser() user: User,
@Body() newAliasDto: AliasCreateDto,
): Promise<AliasDto> {
try {
const note = await this.noteService.getNoteByIdOrAlias(
newAliasDto.noteIdOrAlias,
);
if (!(await this.permissionsService.isOwner(user, note))) {
throw new UnauthorizedException('Reading note denied!');
}
const updatedAlias = await this.aliasService.addAlias(
note,
newAliasDto.newAlias,
);
return this.aliasService.toAliasDto(updatedAlias, note);
} catch (e) {
if (e instanceof AlreadyInDBError) {
throw new BadRequestException(e.message);
}
if (e instanceof ForbiddenIdError) {
throw new BadRequestException(e.message);
}
throw e;
const note = await this.noteService.getNoteByIdOrAlias(
newAliasDto.noteIdOrAlias,
);
if (!(await this.permissionsService.isOwner(user, note))) {
throw new UnauthorizedException('Reading note denied!');
}
const updatedAlias = await this.aliasService.addAlias(
note,
newAliasDto.newAlias,
);
return this.aliasService.toAliasDto(updatedAlias, note);
}
@UseGuards(TokenAuthGuard)
@Put(':alias')
@ApiOkResponse({
description: 'The updated alias',
@ -105,28 +87,14 @@ export class AliasController {
`The field 'primaryAlias' must be set to 'true'.`,
);
}
try {
const note = await this.noteService.getNoteByIdOrAlias(alias);
if (!(await this.permissionsService.isOwner(user, note))) {
throw new UnauthorizedException('Reading note denied!');
}
const updatedAlias = await this.aliasService.makeAliasPrimary(
note,
alias,
);
return this.aliasService.toAliasDto(updatedAlias, note);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
if (e instanceof ForbiddenIdError) {
throw new BadRequestException(e.message);
}
throw e;
const note = await this.noteService.getNoteByIdOrAlias(alias);
if (!(await this.permissionsService.isOwner(user, note))) {
throw new UnauthorizedException('Reading note denied!');
}
const updatedAlias = await this.aliasService.makeAliasPrimary(note, alias);
return this.aliasService.toAliasDto(updatedAlias, note);
}
@UseGuards(TokenAuthGuard)
@Delete(':alias')
@HttpCode(204)
@ApiNoContentResponse({
@ -137,23 +105,10 @@ export class AliasController {
@RequestUser() user: User,
@Param('alias') alias: string,
): Promise<void> {
try {
const note = await this.noteService.getNoteByIdOrAlias(alias);
if (!(await this.permissionsService.isOwner(user, note))) {
throw new UnauthorizedException('Reading note denied!');
}
await this.aliasService.removeAlias(note, alias);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
if (e instanceof PrimaryAliasDeletionForbiddenError) {
throw new BadRequestException(e.message);
}
if (e instanceof ForbiddenIdError) {
throw new BadRequestException(e.message);
}
throw e;
const note = await this.noteService.getNoteByIdOrAlias(alias);
if (!(await this.permissionsService.isOwner(user, note))) {
throw new UnauthorizedException('Reading note denied!');
}
await this.aliasService.removeAlias(note, alias);
}
}

View file

@ -46,6 +46,7 @@ import { GetNoteInterceptor } from '../../utils/get-note.interceptor';
import { RequestNote } from '../../utils/request-note.decorator';
import { RequestUser } from '../../utils/request-user.decorator';
@UseGuards(TokenAuthGuard)
@ApiTags('me')
@ApiSecurity('token')
@Controller('me')
@ -60,7 +61,6 @@ export class MeController {
this.logger.setContext(MeController.name);
}
@UseGuards(TokenAuthGuard)
@Get()
@ApiOkResponse({
description: 'The user information',
@ -71,7 +71,6 @@ export class MeController {
return this.usersService.toUserDto(user);
}
@UseGuards(TokenAuthGuard)
@Get('history')
@ApiOkResponse({
description: 'The history entries of the user',
@ -87,7 +86,6 @@ export class MeController {
}
@UseInterceptors(GetNoteInterceptor)
@UseGuards(TokenAuthGuard)
@Get('history/:noteIdOrAlias')
@ApiOkResponse({
description: 'The history entry of the user which points to the note',
@ -99,19 +97,11 @@ export class MeController {
@RequestUser() user: User,
@RequestNote() note: Note,
): Promise<HistoryEntryDto> {
try {
const foundEntry = await this.historyService.getEntryByNote(note, user);
return await this.historyService.toHistoryEntryDto(foundEntry);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
throw e;
}
const foundEntry = await this.historyService.getEntryByNote(note, user);
return await this.historyService.toHistoryEntryDto(foundEntry);
}
@UseInterceptors(GetNoteInterceptor)
@UseGuards(TokenAuthGuard)
@Put('history/:noteIdOrAlias')
@ApiOkResponse({
description: 'The updated history entry',
@ -125,24 +115,12 @@ export class MeController {
@Body() entryUpdateDto: HistoryEntryUpdateDto,
): Promise<HistoryEntryDto> {
// ToDo: Check if user is allowed to pin this history entry
try {
return await this.historyService.toHistoryEntryDto(
await this.historyService.updateHistoryEntry(
note,
user,
entryUpdateDto,
),
);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
throw e;
}
return await this.historyService.toHistoryEntryDto(
await this.historyService.updateHistoryEntry(note, user, entryUpdateDto),
);
}
@UseInterceptors(GetNoteInterceptor)
@UseGuards(TokenAuthGuard)
@Delete('history/:noteIdOrAlias')
@HttpCode(204)
@ApiNoContentResponse({ description: successfullyDeletedDescription })
@ -153,17 +131,9 @@ export class MeController {
@RequestNote() note: Note,
): Promise<void> {
// ToDo: Check if user is allowed to delete note
try {
await this.historyService.deleteHistoryEntry(note, user);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
throw e;
}
await this.historyService.deleteHistoryEntry(note, user);
}
@UseGuards(TokenAuthGuard)
@Get('notes')
@ApiOkResponse({
description: 'Metadata of all notes of the user',
@ -178,7 +148,6 @@ export class MeController {
);
}
@UseGuards(TokenAuthGuard)
@Get('media')
@ApiOkResponse({
description: 'All media uploads of the user',

View file

@ -4,16 +4,12 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import {
BadRequestException,
Controller,
Delete,
Headers,
HttpCode,
InternalServerErrorException,
NotFoundException,
Param,
Post,
UnauthorizedException,
UploadedFile,
UseGuards,
UseInterceptors,
@ -32,12 +28,7 @@ import {
} from '@nestjs/swagger';
import { TokenAuthGuard } from '../../../auth/token.strategy';
import {
ClientError,
MediaBackendError,
NotInDBError,
PermissionError,
} from '../../../errors/errors';
import { PermissionError } from '../../../errors/errors';
import { ConsoleLoggerService } from '../../../logger/console-logger.service';
import { MediaUploadUrlDto } from '../../../media/media-upload-url.dto';
import { MediaService } from '../../../media/media.service';
@ -53,6 +44,7 @@ import {
import { FullApi } from '../../utils/fullapi-decorator';
import { RequestUser } from '../../utils/request-user.decorator';
@UseGuards(TokenAuthGuard)
@ApiTags('media')
@ApiSecurity('token')
@Controller('media')
@ -65,7 +57,6 @@ export class MediaController {
this.logger.setContext(MediaController.name);
}
@UseGuards(TokenAuthGuard)
@Post()
@ApiConsumes('multipart/form-data')
@ApiBody({
@ -96,29 +87,16 @@ export class MediaController {
@UploadedFile() file: MulterFile,
@Headers('HedgeDoc-Note') noteId: string,
): Promise<MediaUploadUrlDto> {
try {
// 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}'`,
'uploadMedia',
);
const url = await this.mediaService.saveFile(file.buffer, user, note);
return this.mediaService.toMediaUploadUrlDto(url);
} catch (e) {
if (e instanceof ClientError || e instanceof NotInDBError) {
throw new BadRequestException(e.message);
}
if (e instanceof MediaBackendError) {
throw new InternalServerErrorException(
'There was an error in the media backend',
);
}
throw e;
}
// 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}'`,
'uploadMedia',
);
const url = await this.mediaService.saveFile(file.buffer, user, note);
return this.mediaService.toMediaUploadUrlDto(url);
}
@UseGuards(TokenAuthGuard)
@Delete(':filename')
@HttpCode(204)
@ApiNoContentResponse({ description: successfullyDeletedDescription })
@ -128,37 +106,20 @@ export class MediaController {
@Param('filename') filename: string,
): Promise<void> {
const username = user.username;
try {
this.logger.debug(
`Deleting '${filename}' for user '${username}'`,
this.logger.debug(
`Deleting '${filename}' for user '${username}'`,
'deleteMedia',
);
const mediaUpload = await this.mediaService.findUploadByFilename(filename);
if ((await mediaUpload.user).username !== username) {
this.logger.warn(
`${username} tried to delete '${filename}', but is not the owner`,
'deleteMedia',
);
const mediaUpload = await this.mediaService.findUploadByFilename(
filename,
throw new PermissionError(
`File '${filename}' is not owned by '${username}'`,
);
if ((await mediaUpload.user).username !== username) {
this.logger.warn(
`${username} tried to delete '${filename}', but is not the owner`,
'deleteMedia',
);
throw new PermissionError(
`File '${filename}' is not owned by '${username}'`,
);
}
await this.mediaService.deleteFile(mediaUpload);
} catch (e) {
if (e instanceof PermissionError) {
throw new UnauthorizedException(e.message);
}
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
if (e instanceof MediaBackendError) {
throw new InternalServerErrorException(
'There was an error in the media backend',
);
}
throw e;
}
await this.mediaService.deleteFile(mediaUpload);
}
}

View file

@ -11,7 +11,6 @@ import {
Get,
Header,
HttpCode,
NotFoundException,
Param,
Post,
Put,
@ -30,11 +29,6 @@ import {
} from '@nestjs/swagger';
import { TokenAuthGuard } from '../../../auth/token.strategy';
import {
AlreadyInDBError,
ForbiddenIdError,
NotInDBError,
} from '../../../errors/errors';
import { HistoryService } from '../../../history/history.service';
import { ConsoleLoggerService } from '../../../logger/console-logger.service';
import { MediaUploadDto } from '../../../media/media-upload.dto';
@ -66,6 +60,7 @@ import { PermissionsGuard } from '../../utils/permissions.guard';
import { RequestNote } from '../../utils/request-note.decorator';
import { RequestUser } from '../../utils/request-user.decorator';
@UseGuards(TokenAuthGuard)
@ApiTags('notes')
@ApiSecurity('token')
@Controller('notes')
@ -98,7 +93,7 @@ export class NotesController {
@UseInterceptors(GetNoteInterceptor)
@Permissions(Permission.READ)
@UseGuards(TokenAuthGuard, PermissionsGuard)
@UseGuards(PermissionsGuard)
@Get(':noteIdOrAlias')
@ApiOkResponse({
description: 'Get information about the newly created note',
@ -114,7 +109,7 @@ export class NotesController {
}
@Permissions(Permission.CREATE)
@UseGuards(TokenAuthGuard, PermissionsGuard)
@UseGuards(PermissionsGuard)
@Post(':noteAlias')
@HttpCode(201)
@ApiCreatedResponse({
@ -129,24 +124,14 @@ export class NotesController {
@MarkdownBody() text: string,
): Promise<NoteDto> {
this.logger.debug('Got raw markdown:\n' + text, 'createNamedNote');
try {
return await this.noteService.toNoteDto(
await this.noteService.createNote(text, user, noteAlias),
);
} catch (e) {
if (e instanceof AlreadyInDBError) {
throw new BadRequestException(e.message);
}
if (e instanceof ForbiddenIdError) {
throw new BadRequestException(e.message);
}
throw e;
}
return await this.noteService.toNoteDto(
await this.noteService.createNote(text, user, noteAlias),
);
}
@UseInterceptors(GetNoteInterceptor)
@Permissions(Permission.OWNER)
@UseGuards(TokenAuthGuard, PermissionsGuard)
@UseGuards(PermissionsGuard)
@Delete(':noteIdOrAlias')
@HttpCode(204)
@ApiNoContentResponse({ description: successfullyDeletedDescription })
@ -172,7 +157,7 @@ export class NotesController {
@UseInterceptors(GetNoteInterceptor)
@Permissions(Permission.WRITE)
@UseGuards(TokenAuthGuard, PermissionsGuard)
@UseGuards(PermissionsGuard)
@Put(':noteIdOrAlias')
@ApiOkResponse({
description: 'The new, changed note',
@ -192,7 +177,7 @@ export class NotesController {
@UseInterceptors(GetNoteInterceptor)
@Permissions(Permission.READ)
@UseGuards(TokenAuthGuard, PermissionsGuard)
@UseGuards(PermissionsGuard)
@Get(':noteIdOrAlias/content')
@ApiProduces('text/markdown')
@ApiOkResponse({
@ -209,7 +194,7 @@ export class NotesController {
@UseInterceptors(GetNoteInterceptor)
@Permissions(Permission.READ)
@UseGuards(TokenAuthGuard, PermissionsGuard)
@UseGuards(PermissionsGuard)
@Get(':noteIdOrAlias/metadata')
@ApiOkResponse({
description: 'The metadata of the note',
@ -225,7 +210,7 @@ export class NotesController {
@UseInterceptors(GetNoteInterceptor)
@Permissions(Permission.OWNER)
@UseGuards(TokenAuthGuard, PermissionsGuard)
@UseGuards(PermissionsGuard)
@Put(':noteIdOrAlias/metadata/permissions')
@ApiOkResponse({
description: 'The updated permissions of the note',
@ -244,7 +229,7 @@ export class NotesController {
@UseInterceptors(GetNoteInterceptor)
@Permissions(Permission.READ)
@UseGuards(TokenAuthGuard, PermissionsGuard)
@UseGuards(PermissionsGuard)
@Get(':noteIdOrAlias/revisions')
@ApiOkResponse({
description: 'Revisions of the note',
@ -266,7 +251,7 @@ export class NotesController {
@UseInterceptors(GetNoteInterceptor)
@Permissions(Permission.READ)
@UseGuards(TokenAuthGuard, PermissionsGuard)
@UseGuards(PermissionsGuard)
@Get(':noteIdOrAlias/revisions/:revisionId')
@ApiOkResponse({
description: 'Revision of the note for the given id or alias',
@ -278,21 +263,14 @@ export class NotesController {
@RequestNote() note: Note,
@Param('revisionId') revisionId: number,
): Promise<RevisionDto> {
try {
return this.revisionsService.toRevisionDto(
await this.revisionsService.getRevision(note, revisionId),
);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
throw e;
}
return this.revisionsService.toRevisionDto(
await this.revisionsService.getRevision(note, revisionId),
);
}
@UseInterceptors(GetNoteInterceptor)
@Permissions(Permission.READ)
@UseGuards(TokenAuthGuard, PermissionsGuard)
@UseGuards(PermissionsGuard)
@Get(':noteIdOrAlias/media')
@ApiOkResponse({
description: 'All media uploads of the note',