refactor: extract "extract note from request" logic into separate function

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2023-05-19 13:32:56 +02:00
parent 65fb110a1e
commit ab5aebc9c4
3 changed files with 125 additions and 10 deletions

View file

@ -0,0 +1,87 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Mock } from 'ts-mockery';
import { Note } from '../../notes/note.entity';
import { NotesService } from '../../notes/notes.service';
import { extractNoteFromRequest } from './extract-note-from-request';
import { CompleteRequest } from './request.type';
describe('extract note from request', () => {
const mockNoteIdOrAlias1 = 'mockNoteIdOrAlias1';
const mockNoteIdOrAlias2 = 'mockNoteIdOrAlias2';
const mockNote1 = Mock.of<Note>({ id: 1 });
const mockNote2 = Mock.of<Note>({ id: 2 });
let notesService: NotesService;
beforeEach(() => {
notesService = Mock.of<NotesService>({
getNoteByIdOrAlias: async (id) => {
if (id === mockNoteIdOrAlias1) {
return mockNote1;
} else if (id === mockNoteIdOrAlias2) {
return mockNote2;
} else {
throw new Error('unknown note id');
}
},
});
});
function createRequest(
parameterValue: string | undefined,
headerValue: string | string[] | undefined,
): CompleteRequest {
return Mock.of<CompleteRequest>({
params: parameterValue
? {
noteIdOrAlias: parameterValue,
}
: {},
headers: headerValue
? {
// eslint-disable-next-line @typescript-eslint/naming-convention
'hedgedoc-note': headerValue,
}
: {},
});
}
it('will return undefined if no id is present', async () => {
const request = createRequest(undefined, undefined);
expect(await extractNoteFromRequest(request, notesService)).toBe(undefined);
});
it('can extract an id from parameters', async () => {
const request = createRequest(mockNoteIdOrAlias1, undefined);
expect(await extractNoteFromRequest(request, notesService)).toBe(mockNote1);
});
it('can extract an id from headers if no parameter is given', async () => {
const request = createRequest(undefined, mockNoteIdOrAlias1);
expect(await extractNoteFromRequest(request, notesService)).toBe(mockNote1);
});
it('can extract the first id from multiple id headers', async () => {
const request = createRequest(undefined, [
mockNoteIdOrAlias1,
mockNoteIdOrAlias2,
]);
expect(await extractNoteFromRequest(request, notesService)).toBe(mockNote1);
});
it('will return undefined if no parameter and empty id header array', async () => {
const request = createRequest(undefined, []);
expect(await extractNoteFromRequest(request, notesService)).toBe(undefined);
});
it('will prefer the parameter over the header', async () => {
const request = createRequest(mockNoteIdOrAlias1, mockNoteIdOrAlias2);
expect(await extractNoteFromRequest(request, notesService)).toBe(mockNote1);
});
});

View file

@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { isArray } from 'class-validator';
import { Note } from '../../notes/note.entity';
import { NotesService } from '../../notes/notes.service';
import { CompleteRequest } from './request.type';
export async function extractNoteFromRequest(
request: CompleteRequest,
noteService: NotesService,
): Promise<Note | undefined> {
const noteIdOrAlias = extractNoteIdOrAlias(request);
if (noteIdOrAlias === undefined) {
return undefined;
}
return await noteService.getNoteByIdOrAlias(noteIdOrAlias);
}
function extractNoteIdOrAlias(request: CompleteRequest): string | undefined {
const noteIdOrAlias =
request.params['noteIdOrAlias'] || request.headers['hedgedoc-note'];
if (noteIdOrAlias === undefined) {
return undefined;
} else if (isArray(noteIdOrAlias)) {
return noteIdOrAlias[0];
} else {
return noteIdOrAlias;
}
}

View file

@ -11,8 +11,8 @@ import {
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { Note } from '../../notes/note.entity';
import { NotesService } from '../../notes/notes.service';
import { extractNoteFromRequest } from './extract-note-from-request';
import { CompleteRequest } from './request.type';
/**
@ -28,15 +28,10 @@ export class GetNoteInterceptor implements NestInterceptor {
next: CallHandler,
): Promise<Observable<T>> {
const request: CompleteRequest = context.switchToHttp().getRequest();
const noteIdOrAlias = request.params['noteIdOrAlias'];
request.note = await getNote(this.noteService, noteIdOrAlias);
const note = await extractNoteFromRequest(request, this.noteService);
if (note !== undefined) {
request.note = note;
}
return next.handle();
}
}
export async function getNote(
noteService: NotesService,
noteIdOrAlias: string,
): Promise<Note> {
return await noteService.getNoteByIdOrAlias(noteIdOrAlias);
}