From 4d0205a61fb261608515726142fba983a06b74ff Mon Sep 17 00:00:00 2001 From: David Mehren Date: Mon, 24 May 2021 21:58:44 +0200 Subject: [PATCH] NotesService: Implement getAuthorUsers This reimplements logic to get all Users that ever edited a note and fixes the empty `editedBy` property of `toNoteMetadataDto` introduced in 81cc092e. Signed-off-by: David Mehren --- src/notes/notes.module.ts | 2 ++ src/notes/notes.service.spec.ts | 32 +++++++++++++++++++++++++++++++- src/notes/notes.service.ts | 19 ++++++++++++++++++- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/notes/notes.module.ts b/src/notes/notes.module.ts index 728f92ef3..1d7656b90 100644 --- a/src/notes/notes.module.ts +++ b/src/notes/notes.module.ts @@ -12,6 +12,7 @@ import { LoggerModule } from '../logger/logger.module'; import { NoteGroupPermission } from '../permissions/note-group-permission.entity'; import { NoteUserPermission } from '../permissions/note-user-permission.entity'; import { RevisionsModule } from '../revisions/revisions.module'; +import { User } from '../users/user.entity'; import { UsersModule } from '../users/users.module'; import { Note } from './note.entity'; import { NotesService } from './notes.service'; @@ -24,6 +25,7 @@ import { Tag } from './tag.entity'; Tag, NoteGroupPermission, NoteUserPermission, + User, ]), forwardRef(() => RevisionsModule), UsersModule, diff --git a/src/notes/notes.service.spec.ts b/src/notes/notes.service.spec.ts index 716b302cd..667522593 100644 --- a/src/notes/notes.service.spec.ts +++ b/src/notes/notes.service.spec.ts @@ -46,6 +46,12 @@ describe('NotesService', () => { let forbiddenNoteId: string; beforeEach(async () => { + /** + * We need to have *one* userRepo for both the providers array and + * the overrideProvider call, as otherwise we have two instances + * and the mock of createQueryBuilder replaces the wrong one + * **/ + userRepo = new Repository(); const module: TestingModule = await Test.createTestingModule({ providers: [ NotesService, @@ -57,6 +63,10 @@ describe('NotesService', () => { provide: getRepositoryToken(Tag), useClass: Repository, }, + { + provide: getRepositoryToken(User), + useValue: userRepo, + }, ], imports: [ ConfigModule.forRoot({ @@ -74,7 +84,7 @@ describe('NotesService', () => { .overrideProvider(getRepositoryToken(Tag)) .useClass(Repository) .overrideProvider(getRepositoryToken(User)) - .useClass(Repository) + .useValue(userRepo) .overrideProvider(getRepositoryToken(AuthToken)) .useValue({}) .overrideProvider(getRepositoryToken(Identity)) @@ -688,6 +698,16 @@ describe('NotesService', () => { ]; revisions[0].createdAt = new Date(1549312452000); jest.spyOn(revisionRepo, 'findOne').mockResolvedValue(revisions[0]); + const createQueryBuilder = { + innerJoin: () => createQueryBuilder, + where: () => createQueryBuilder, + getMany: () => [user], + }; + jest + .spyOn(userRepo, 'createQueryBuilder') + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + .mockImplementation(() => createQueryBuilder); note.publicId = 'testId'; note.alias = 'testAlias'; note.title = 'testTitle'; @@ -777,6 +797,16 @@ describe('NotesService', () => { .spyOn(revisionRepo, 'findOne') .mockResolvedValue(revisions[0]) .mockResolvedValue(revisions[0]); + const createQueryBuilder = { + innerJoin: () => createQueryBuilder, + where: () => createQueryBuilder, + getMany: () => [user], + }; + jest + .spyOn(userRepo, 'createQueryBuilder') + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + .mockImplementation(() => createQueryBuilder); note.publicId = 'testId'; note.alias = 'testAlias'; note.title = 'testTitle'; diff --git a/src/notes/notes.service.ts b/src/notes/notes.service.ts index b5a34cc7b..048bb4fc5 100644 --- a/src/notes/notes.service.ts +++ b/src/notes/notes.service.ts @@ -41,6 +41,7 @@ export class NotesService { private readonly logger: ConsoleLoggerService, @InjectRepository(Note) private noteRepository: Repository, @InjectRepository(Tag) private tagRepository: Repository, + @InjectRepository(User) private userRepository: Repository, @Inject(UsersService) private usersService: UsersService, @Inject(GroupsService) private groupsService: GroupsService, @Inject(forwardRef(() => RevisionsService)) @@ -188,6 +189,22 @@ export class NotesService { return note; } + /** + * @async + * Get all users that ever appeared as an author for the given note + * @param note The note to search authors for + */ + async getAuthorUsers(note: Note): Promise { + return await this.userRepository + .createQueryBuilder('user') + .innerJoin('user.authors', 'author') + .innerJoin('author.authorships', 'authorship') + .innerJoin('authorship.revisions', 'revision') + .innerJoin('revision.note', 'note') + .where('note.id = :id', { id: note.id }) + .getMany(); + } + /** * Check if the provided note id or alias is not forbidden * @param noteIdOrAlias - the alias or id in question @@ -358,7 +375,7 @@ export class NotesService { title: note.title ?? '', createTime: (await this.getFirstRevision(note)).createdAt, description: note.description ?? '', - editedBy: [], // TODO temporary placeholder, + editedBy: (await this.getAuthorUsers(note)).map((user) => user.userName), permissions: this.toNotePermissionsDto(note), tags: this.toTagList(note), updateTime: (await this.getLatestRevision(note)).createdAt,