diff --git a/packages/backend/server/src/__tests__/e2e/comment/resolver.spec.ts b/packages/backend/server/src/__tests__/e2e/comment/resolver.spec.ts index f23d293feb..406371b163 100644 --- a/packages/backend/server/src/__tests__/e2e/comment/resolver.spec.ts +++ b/packages/backend/server/src/__tests__/e2e/comment/resolver.spec.ts @@ -744,6 +744,62 @@ e2e( } ); +e2e( + 'should create reply and send comment mention notification to comment author only when author is doc owner', + async t => { + const docId = randomUUID(); + await app.create(Mockers.DocUser, { + workspaceId: teamWorkspace.id, + docId, + userId: member.id, + type: DocRole.Owner, + }); + + await app.login(member); + const createResult = await app.gql({ + query: createCommentMutation, + variables: { + input: { + workspaceId: teamWorkspace.id, + docId, + docMode: DocMode.page, + docTitle: 'test', + content: { + type: 'paragraph', + content: [{ type: 'text', text: 'test' }], + }, + }, + }, + }); + + await app.login(owner); + const count = app.queue.count('notification.sendComment'); + const result = await app.gql({ + query: createReplyMutation, + variables: { + input: { + commentId: createResult.createComment.id, + docMode: DocMode.page, + docTitle: 'test', + content: { + type: 'paragraph', + content: [{ type: 'text', text: 'test' }], + }, + }, + }, + }); + + t.truthy(result.createReply.id); + t.is(result.createReply.commentId, createResult.createComment.id); + t.is(app.queue.count('notification.sendComment'), count + 1); + const notification = app.queue.last('notification.sendComment'); + t.is(notification.name, 'notification.sendComment'); + t.is(notification.payload.userId, member.id); + t.is(notification.payload.body.replyId, result.createReply.id); + t.is(notification.payload.isMention, true); + } +); + e2e('should create reply work when user is Commenter', async t => { const docId = randomUUID(); await app.create(Mockers.DocUser, { diff --git a/packages/backend/server/src/core/comment/resolver.ts b/packages/backend/server/src/core/comment/resolver.ts index 389585ffe6..620f1fb72f 100644 --- a/packages/backend/server/src/core/comment/resolver.ts +++ b/packages/backend/server/src/core/comment/resolver.ts @@ -374,14 +374,33 @@ export class CommentResolver { mentions?: string[], reply?: Reply ) { - // send comment notification to doc owners - const owner = await this.models.docUser.getOwner( - comment.workspaceId, - comment.docId - ); - if (owner && owner.userId !== sender.id) { + const mentionUserIds = new Set(mentions); + // send comment mention notification to comment author on reply + if (reply) { + mentionUserIds.add(comment.userId); + } + + // send comment mention notification to mentioned users + for (const mentionUserId of mentionUserIds) { + // skip if the mention user is the sender + if (mentionUserId === sender.id) { + continue; + } + + // check if the mention user has Doc.Comments.Read permission + const hasPermission = await this.ac + .user(mentionUserId) + .workspace(comment.workspaceId) + .doc(comment.docId) + .can('Doc.Comments.Read'); + + if (!hasPermission) { + continue; + } + await this.queue.add('notification.sendComment', { - userId: owner.userId, + isMention: true, + userId: mentionUserId, body: { workspaceId: comment.workspaceId, createdByUserId: sender.id, @@ -396,16 +415,24 @@ export class CommentResolver { }); } - // send comment mention notification to comment author on reply - if (reply && comment.userId !== sender.id) { + // send comment notification to doc owners + const owner = await this.models.docUser.getOwner( + comment.workspaceId, + comment.docId + ); + // if the owner is not in the mention user ids, send comment notification to the owner + if ( + owner && + owner.userId !== sender.id && + !mentionUserIds.has(owner.userId) + ) { await this.queue.add('notification.sendComment', { - isMention: true, - userId: comment.userId, + userId: owner.userId, body: { workspaceId: comment.workspaceId, createdByUserId: sender.id, commentId: comment.id, - replyId: reply.id, + replyId: reply?.id, doc: { id: comment.docId, title: docTitle, @@ -414,47 +441,6 @@ export class CommentResolver { }, }); } - - // send comment mention notification to mentioned users - if (mentions) { - for (const mentionUserId of mentions) { - // skip if the mention user is the doc owner or the comment author - if ( - mentionUserId === owner?.userId || - mentionUserId === sender.id || - mentionUserId === comment.userId - ) { - continue; - } - - // check if the mention user has Doc.Comments.Read permission - const hasPermission = await this.ac - .user(mentionUserId) - .workspace(comment.workspaceId) - .doc(comment.docId) - .can('Doc.Comments.Read'); - - if (!hasPermission) { - continue; - } - - await this.queue.add('notification.sendComment', { - isMention: true, - userId: mentionUserId, - body: { - workspaceId: comment.workspaceId, - createdByUserId: sender.id, - commentId: comment.id, - replyId: reply?.id, - doc: { - id: comment.docId, - title: docTitle, - mode: docMode, - }, - }, - }); - } - } } private async assertPermission(