PublicApi: Add option to keep media to DELETE /notes/{note}

This adds a body to the route DELETE /notes/{note} of the public api to specify if the associated media uploads of the note should be kept or deleted.

Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
Philip Molares 2021-04-01 01:23:12 +02:00 committed by David Mehren
parent bd4231c1c5
commit 4640735d18
No known key found for this signature in database
GPG key ID: 185982BA4C42B7C3
2 changed files with 53 additions and 6 deletions

View file

@ -62,6 +62,7 @@ import {
} from '../../utils/descriptions'; } from '../../utils/descriptions';
import { MediaUploadDto } from '../../../media/media-upload.dto'; import { MediaUploadDto } from '../../../media/media-upload.dto';
import { MediaService } from '../../../media/media.service'; import { MediaService } from '../../../media/media.service';
import { NoteMediaDeletionDto } from '../../../notes/note.media-deletion.dto';
@ApiTags('notes') @ApiTags('notes')
@ApiSecurity('token') @ApiSecurity('token')
@ -172,12 +173,21 @@ export class NotesController {
async deleteNote( async deleteNote(
@Req() req: Request, @Req() req: Request,
@Param('noteIdOrAlias') noteIdOrAlias: string, @Param('noteIdOrAlias') noteIdOrAlias: string,
@Body() noteMediaDeletionDto: NoteMediaDeletionDto,
): Promise<void> { ): Promise<void> {
try { try {
const note = await this.noteService.getNoteByIdOrAlias(noteIdOrAlias); const note = await this.noteService.getNoteByIdOrAlias(noteIdOrAlias);
if (!this.permissionsService.isOwner(req.user, note)) { if (!this.permissionsService.isOwner(req.user, note)) {
throw new UnauthorizedException('Deleting note denied!'); throw new UnauthorizedException('Deleting note denied!');
} }
const mediaUploads = await this.mediaService.listUploadsByNote(note);
for (const mediaUpload of mediaUploads) {
if (!noteMediaDeletionDto.keepMedia) {
await this.mediaService.deleteFile(mediaUpload);
} else {
await this.mediaService.removeNoteFromMediaUpload(mediaUpload);
}
}
this.logger.debug('Deleting note: ' + noteIdOrAlias, 'deleteNote'); this.logger.debug('Deleting note: ' + noteIdOrAlias, 'deleteNote');
await this.noteService.deleteNote(note); await this.noteService.deleteNote(note);
this.logger.debug('Successfully deleted ' + noteIdOrAlias, 'deleteNote'); this.logger.debug('Successfully deleted ' + noteIdOrAlias, 'deleteNote');

View file

@ -38,6 +38,7 @@ describe('Notes', () => {
let content: string; let content: string;
let forbiddenNoteId: string; let forbiddenNoteId: string;
let uploadPath: string; let uploadPath: string;
let testImage: Buffer;
beforeAll(async () => { beforeAll(async () => {
const moduleRef = await Test.createTestingModule({ const moduleRef = await Test.createTestingModule({
@ -77,6 +78,7 @@ describe('Notes', () => {
user = await userService.createUser('hardcoded', 'Testy'); user = await userService.createUser('hardcoded', 'Testy');
user2 = await userService.createUser('hardcoded2', 'Max Mustermann'); user2 = await userService.createUser('hardcoded2', 'Max Mustermann');
content = 'This is a test note.'; content = 'This is a test note.';
testImage = await fs.readFile('test/public-api/fixtures/test.png');
}); });
it('POST /notes', async () => { it('POST /notes', async () => {
@ -149,12 +151,47 @@ describe('Notes', () => {
}); });
describe('DELETE /notes/{note}', () => { describe('DELETE /notes/{note}', () => {
it('works with an existing alias', async () => { describe('works', () => {
await notesService.createNote(content, 'test3', user); it('with an existing alias and keepMedia false', async () => {
await request(app.getHttpServer()).delete('/notes/test3').expect(204); const noteId = 'test3';
await expect(notesService.getNoteByIdOrAlias('test3')).rejects.toEqual( await notesService.createNote(content, noteId, user);
new NotInDBError("Note with id/alias 'test3' not found."), await mediaService.saveFile(testImage, user.userName, noteId);
await request(app.getHttpServer())
.delete(`/notes/${noteId}`)
.set('Content-Type', 'application/json')
.send({
keepMedia: false,
})
.expect(204);
await expect(notesService.getNoteByIdOrAlias(noteId)).rejects.toEqual(
new NotInDBError(`Note with id/alias '${noteId}' not found.`),
); );
expect(await mediaService.listUploadsByUser(user)).toHaveLength(0);
});
it('with an existing alias and keepMedia true', async () => {
const noteId = 'test3a';
await notesService.createNote(content, noteId, user);
const url = await mediaService.saveFile(
testImage,
user.userName,
noteId,
);
await request(app.getHttpServer())
.delete(`/notes/${noteId}`)
.set('Content-Type', 'application/json')
.send({
keepMedia: true,
})
.expect(204);
await expect(notesService.getNoteByIdOrAlias(noteId)).rejects.toEqual(
new NotInDBError(`Note with id/alias '${noteId}' not found.`),
);
expect(await mediaService.listUploadsByUser(user)).toHaveLength(1);
// Remove /upload/ from path as we just need the filename.
const fileName = url.replace('/uploads/', '');
// delete the file afterwards
await fs.unlink(join(uploadPath, fileName));
});
}); });
it('works with an existing alias with permissions', async () => { it('works with an existing alias with permissions', async () => {
const note = await notesService.createNote(content, 'test3', user); const note = await notesService.createNote(content, 'test3', user);