diff --git a/src/notes/note.entity.ts b/src/notes/note.entity.ts index 1adcef9cb..538af568b 100644 --- a/src/notes/note.entity.ts +++ b/src/notes/note.entity.ts @@ -39,9 +39,14 @@ export class Note { @OneToMany( (_) => NoteGroupPermission, (groupPermission) => groupPermission.note, + { cascade: true }, // This ensures that embedded NoteGroupPermissions are automatically saved to the database ) groupPermissions: NoteGroupPermission[]; - @OneToMany((_) => NoteUserPermission, (userPermission) => userPermission.note) + @OneToMany( + (_) => NoteUserPermission, + (userPermission) => userPermission.note, + { cascade: true }, // This ensures that embedded NoteUserPermission are automatically saved to the database + ) userPermissions: NoteUserPermission[]; @Column({ nullable: false, diff --git a/src/notes/notes.service.ts b/src/notes/notes.service.ts index a1b1ecfdf..b21dba99c 100644 --- a/src/notes/notes.service.ts +++ b/src/notes/notes.service.ts @@ -183,7 +183,9 @@ export class NotesService { 'authorColors', 'owner', 'groupPermissions', + 'groupPermissions.group', 'userPermissions', + 'userPermissions.user', 'tags', ], }); @@ -224,6 +226,8 @@ export class NotesService { //TODO: Calculate patch revisions.push(Revision.create(noteContent, noteContent)); note.revisions = Promise.resolve(revisions); + note.userPermissions = []; + note.groupPermissions = []; return await this.noteRepository.save(note); } @@ -270,6 +274,7 @@ export class NotesService { user, newUserPermission.canEdit, ); + createdPermission.note = note; note.userPermissions.push(createdPermission); } @@ -282,6 +287,7 @@ export class NotesService { group, newGroupPermission.canEdit, ); + createdPermission.note = note; note.groupPermissions.push(createdPermission); } diff --git a/src/permissions/note-group-permission.entity.ts b/src/permissions/note-group-permission.entity.ts index d1e94112c..364c2991d 100644 --- a/src/permissions/note-group-permission.entity.ts +++ b/src/permissions/note-group-permission.entity.ts @@ -10,10 +10,16 @@ import { Note } from '../notes/note.entity'; @Entity() export class NoteGroupPermission { - @ManyToOne((_) => Group, { primary: true }) + @ManyToOne((_) => Group, { + primary: true, + onDelete: 'CASCADE', // This deletes the NoteGroupPermission, when the associated Group is deleted + }) group: Group; - @ManyToOne((_) => Note, (note) => note.groupPermissions, { primary: true }) + @ManyToOne((_) => Note, (note) => note.groupPermissions, { + primary: true, + onDelete: 'CASCADE', // This deletes the NoteGroupPermission, when the associated Note is deleted + }) note: Note; @Column() diff --git a/src/permissions/note-user-permission.entity.ts b/src/permissions/note-user-permission.entity.ts index 0bad0d41d..06e94d0af 100644 --- a/src/permissions/note-user-permission.entity.ts +++ b/src/permissions/note-user-permission.entity.ts @@ -10,10 +10,16 @@ import { User } from '../users/user.entity'; @Entity() export class NoteUserPermission { - @ManyToOne((_) => User, { primary: true }) + @ManyToOne((_) => User, { + primary: true, + onDelete: 'CASCADE', // This deletes the NoteUserPermission, when the associated Note is deleted + }) user: User; - @ManyToOne((_) => Note, (note) => note.userPermissions, { primary: true }) + @ManyToOne((_) => Note, (note) => note.userPermissions, { + primary: true, + onDelete: 'CASCADE', // This deletes the NoteUserPermission, when the associated Note is deleted + }) note: Note; @Column() diff --git a/test/public-api/notes.e2e-spec.ts b/test/public-api/notes.e2e-spec.ts index dcabd4dd5..63c5e661d 100644 --- a/test/public-api/notes.e2e-spec.ts +++ b/test/public-api/notes.e2e-spec.ts @@ -26,6 +26,7 @@ import { User } from '../../src/users/user.entity'; import { UsersModule } from '../../src/users/users.module'; import { promises as fs } from 'fs'; import { MediaService } from '../../src/media/media.service'; +import { NotePermissionsUpdateDto } from '../../src/notes/note-permissions.dto'; import { join } from 'path'; describe('Notes', () => { @@ -155,6 +156,31 @@ describe('Notes', () => { new NotInDBError("Note with id/alias 'test3' not found."), ); }); + it('works with an existing alias with permissions', async () => { + const note = await notesService.createNote(content, 'test3', user); + const updateNotePermission = new NotePermissionsUpdateDto(); + updateNotePermission.sharedToUsers = [ + { + username: user.userName, + canEdit: true, + }, + ]; + updateNotePermission.sharedToGroups = []; + await notesService.updateNotePermissions(note, updateNotePermission); + const updatedNote = await notesService.getNoteByIdOrAlias(note.alias); + expect(updatedNote.userPermissions).toHaveLength(1); + expect(updatedNote.userPermissions[0].canEdit).toEqual( + updateNotePermission.sharedToUsers[0].canEdit, + ); + expect(updatedNote.userPermissions[0].user.userName).toEqual( + user.userName, + ); + expect(updatedNote.groupPermissions).toHaveLength(0); + await request(app.getHttpServer()).delete('/notes/test3').expect(204); + await expect(notesService.getNoteByIdOrAlias('test3')).rejects.toEqual( + new NotInDBError("Note with id/alias 'test3' not found."), + ); + }); it('fails with a forbidden alias', async () => { await request(app.getHttpServer()) .delete(`/notes/${forbiddenNoteId}`)