Merge pull request #993 from hedgedoc/publicApi/me

This commit is contained in:
David Mehren 2021-03-14 16:28:49 +01:00 committed by GitHub
commit b67ec817e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 217 additions and 49 deletions

View file

@ -59,6 +59,26 @@ export class MeController {
);
}
@UseGuards(TokenAuthGuard)
@Get('history/:note')
async getHistoryEntry(
@Req() req: Request,
@Param('note') note: string,
): Promise<HistoryEntryDto> {
try {
const foundEntry = await this.historyService.getEntryByNoteIdOrAlias(
note,
req.user,
);
return this.historyService.toHistoryEntryDto(foundEntry);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);
}
throw e;
}
}
@UseGuards(TokenAuthGuard)
@Put('history/:note')
async updateHistoryEntry(
@ -86,13 +106,13 @@ export class MeController {
@UseGuards(TokenAuthGuard)
@Delete('history/:note')
@HttpCode(204)
deleteHistoryEntry(
async deleteHistoryEntry(
@Req() req: Request,
@Param('note') note: string,
): Promise<void> {
// ToDo: Check if user is allowed to delete note
try {
return this.historyService.deleteHistoryEntry(note, req.user);
await this.historyService.deleteHistoryEntry(note, req.user);
} catch (e) {
if (e instanceof NotInDBError) {
throw new NotFoundException(e.message);

View file

@ -121,6 +121,32 @@ describe('HistoryService', () => {
});
});
describe('getEntryByNoteIdOrAlias', () => {
const user = {} as User;
const alias = 'alias';
describe('works', () => {
it('with history entry', async () => {
const note = Note.create(user, alias);
const historyEntry = HistoryEntry.create(user, note);
jest.spyOn(historyRepo, 'findOne').mockResolvedValueOnce(historyEntry);
jest.spyOn(noteRepo, 'findOne').mockResolvedValueOnce(note);
expect(await service.getEntryByNoteIdOrAlias(alias, user)).toEqual(
historyEntry,
);
});
});
describe('fails', () => {
it('with an non-existing note', async () => {
jest.spyOn(noteRepo, 'findOne').mockResolvedValueOnce(undefined);
try {
await service.getEntryByNoteIdOrAlias(alias, {} as User);
} catch (e) {
expect(e).toBeInstanceOf(NotInDBError);
}
});
});
});
describe('createOrUpdateHistoryEntry', () => {
describe('works', () => {
it('without an preexisting entry', async () => {
@ -231,10 +257,11 @@ describe('HistoryService', () => {
);
await service.deleteHistoryEntry(alias, user);
});
});
describe('fails', () => {
const user = {} as User;
const alias = 'alias';
it('without an entry', async () => {
const user = {} as User;
const alias = 'alias';
const note = Note.create(user, alias);
jest.spyOn(historyRepo, 'findOne').mockResolvedValueOnce(undefined);
jest.spyOn(noteRepo, 'findOne').mockResolvedValueOnce(note);
@ -244,6 +271,14 @@ describe('HistoryService', () => {
expect(e).toBeInstanceOf(NotInDBError);
}
});
it('without a note', async () => {
jest.spyOn(noteRepo, 'findOne').mockResolvedValueOnce(undefined);
try {
await service.getEntryByNoteIdOrAlias(alias, {} as User);
} catch (e) {
expect(e).toBeInstanceOf(NotInDBError);
}
});
});
});

View file

@ -29,6 +29,12 @@ export class HistoryService {
this.logger.setContext(HistoryService.name);
}
/**
* @async
* Get all entries of a user
* @param {User} user - the user the entries should be from
* @return {HistoryEntry[]} an array of history entries of the specified user
*/
async getEntriesByUser(user: User): Promise<HistoryEntry[]> {
return await this.historyEntryRepository.find({
where: { user: user },
@ -36,7 +42,15 @@ export class HistoryService {
});
}
private async getEntryByNoteIdOrAlias(
/**
* @async
* Get a history entry by the user and note, which is specified via id or alias
* @param {string} noteIdOrAlias - the id or alias specifying the note
* @param {User} user - the user that the note belongs to
* @throws {NotInDBError} the specified note does not exist
* @return {HistoryEntry} the requested history entry
*/
async getEntryByNoteIdOrAlias(
noteIdOrAlias: string,
user: User,
): Promise<HistoryEntry> {
@ -44,6 +58,13 @@ export class HistoryService {
return await this.getEntryByNote(note, user);
}
/**
* @async
* Get a history entry by the user and note
* @param {Note} note - the note that the history entry belongs to
* @param {User} user - the user that the history entry belongs to
* @return {HistoryEntry} the requested history entry
*/
private async getEntryByNote(note: Note, user: User): Promise<HistoryEntry> {
return await this.historyEntryRepository.findOne({
where: {
@ -54,6 +75,13 @@ export class HistoryService {
});
}
/**
* @async
* Create or update a history entry by the user and note. If the entry is merely updated the updatedAt date is set to the current date.
* @param {Note} note - the note that the history entry belongs to
* @param {User} user - the user that the history entry belongs to
* @return {HistoryEntry} the requested history entry
*/
async createOrUpdateHistoryEntry(
note: Note,
user: User,
@ -67,6 +95,14 @@ export class HistoryService {
return await this.historyEntryRepository.save(entry);
}
/**
* @async
* Update a history entry identified by the user and a note id or alias
* @param {string} noteIdOrAlias - the note that the history entry belongs to
* @param {User} user - the user that the history entry belongs to
* @param {HistoryEntryUpdateDto} updateDto - the change that should be applied to the history entry
* @return {HistoryEntry} the requested history entry
*/
async updateHistoryEntry(
noteIdOrAlias: string,
user: User,
@ -82,6 +118,13 @@ export class HistoryService {
return await this.historyEntryRepository.save(entry);
}
/**
* @async
* Delete the history entry identified by the user and a note id or alias
* @param {string} noteIdOrAlias - the note that the history entry belongs to
* @param {User} user - the user that the history entry belongs to
* @throws {NotInDBError} the specified history entry does not exist
*/
async deleteHistoryEntry(noteIdOrAlias: string, user: User): Promise<void> {
const entry = await this.getEntryByNoteIdOrAlias(noteIdOrAlias, user);
if (!entry) {
@ -93,6 +136,11 @@ export class HistoryService {
return;
}
/**
* Build HistoryEntryDto from a history entry.
* @param {HistoryEntry} entry - the history entry to use
* @return {HistoryEntryDto} the built HistoryEntryDto
*/
toHistoryEntryDto(entry: HistoryEntry): HistoryEntryDto {
return {
identifier: entry.note.alias ? entry.note.alias : entry.note.id,