fix(server): only send comment mention notification when comment author is doc owner (#13033)
close AF-2711 #### PR Dependency Tree * **PR #13033** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Added an end-to-end test to verify that mention notifications are correctly sent when replying to a comment authored by the document owner. * **Refactor** * Improved the notification logic to streamline how mention and owner notifications are sent, reducing redundancy and ensuring correct recipients. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -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 => {
|
e2e('should create reply work when user is Commenter', async t => {
|
||||||
const docId = randomUUID();
|
const docId = randomUUID();
|
||||||
await app.create(Mockers.DocUser, {
|
await app.create(Mockers.DocUser, {
|
||||||
|
|||||||
@@ -374,14 +374,33 @@ export class CommentResolver {
|
|||||||
mentions?: string[],
|
mentions?: string[],
|
||||||
reply?: Reply
|
reply?: Reply
|
||||||
) {
|
) {
|
||||||
// send comment notification to doc owners
|
const mentionUserIds = new Set(mentions);
|
||||||
const owner = await this.models.docUser.getOwner(
|
// send comment mention notification to comment author on reply
|
||||||
comment.workspaceId,
|
if (reply) {
|
||||||
comment.docId
|
mentionUserIds.add(comment.userId);
|
||||||
);
|
}
|
||||||
if (owner && owner.userId !== sender.id) {
|
|
||||||
|
// 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', {
|
await this.queue.add('notification.sendComment', {
|
||||||
userId: owner.userId,
|
isMention: true,
|
||||||
|
userId: mentionUserId,
|
||||||
body: {
|
body: {
|
||||||
workspaceId: comment.workspaceId,
|
workspaceId: comment.workspaceId,
|
||||||
createdByUserId: sender.id,
|
createdByUserId: sender.id,
|
||||||
@@ -396,16 +415,24 @@ export class CommentResolver {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// send comment mention notification to comment author on reply
|
// send comment notification to doc owners
|
||||||
if (reply && comment.userId !== sender.id) {
|
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', {
|
await this.queue.add('notification.sendComment', {
|
||||||
isMention: true,
|
userId: owner.userId,
|
||||||
userId: comment.userId,
|
|
||||||
body: {
|
body: {
|
||||||
workspaceId: comment.workspaceId,
|
workspaceId: comment.workspaceId,
|
||||||
createdByUserId: sender.id,
|
createdByUserId: sender.id,
|
||||||
commentId: comment.id,
|
commentId: comment.id,
|
||||||
replyId: reply.id,
|
replyId: reply?.id,
|
||||||
doc: {
|
doc: {
|
||||||
id: comment.docId,
|
id: comment.docId,
|
||||||
title: docTitle,
|
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(
|
private async assertPermission(
|
||||||
|
|||||||
Reference in New Issue
Block a user