From cec2cc4f372bf070e63346b138687ad3659dc883 Mon Sep 17 00:00:00 2001 From: Denis Bykhov <bykhov.denis@gmail.com> Date: Fri, 22 Sep 2023 12:10:35 +0600 Subject: [PATCH] Fix comments notifications (#3732) Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> --- models/notification/src/index.ts | 1 + models/tracker/src/index.ts | 1 + plugins/notification/src/index.ts | 2 + .../notification-resources/src/index.ts | 39 ++++++++++++------- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/models/notification/src/index.ts b/models/notification/src/index.ts index c32bc01f6c..e7d83d5caa 100644 --- a/models/notification/src/index.ts +++ b/models/notification/src/index.ts @@ -109,6 +109,7 @@ export class TNotificationType extends TDoc implements NotificationType { objectClass!: Ref<Class<Doc>> hidden!: boolean templates?: NotificationTemplate + onlyOwn?: boolean } @Model(notification.class.NotificationGroup, core.class.Doc, DOMAIN_MODEL) diff --git a/models/tracker/src/index.ts b/models/tracker/src/index.ts index e091619f7d..20b969c39c 100644 --- a/models/tracker/src/index.ts +++ b/models/tracker/src/index.ts @@ -1990,6 +1990,7 @@ export function createModel (builder: Builder): void { field: 'assignee', txClasses: [core.class.TxCreateDoc, core.class.TxUpdateDoc], objectClass: tracker.class.Issue, + onlyOwn: true, templates: { textTemplate: '{doc} was assigned to you by {sender}', htmlTemplate: '<p>{doc} was assigned to you by {sender}</p>', diff --git a/plugins/notification/src/index.ts b/plugins/notification/src/index.ts index e0c53c3944..b51e9832fa 100644 --- a/plugins/notification/src/index.ts +++ b/plugins/notification/src/index.ts @@ -109,6 +109,8 @@ export interface NotificationType extends Doc { group: Ref<NotificationGroup> txClasses: Ref<Class<Tx>>[] objectClass: Ref<Class<Doc>> + // not allowed to parent doc + onlyOwn?: boolean // check parent doc class attachedToClass?: Ref<Class<Doc>> // use for update/mixin txes diff --git a/server-plugins/notification-resources/src/index.ts b/server-plugins/notification-resources/src/index.ts index 0ffb87d78b..dacf7c47ff 100644 --- a/server-plugins/notification-resources/src/index.ts +++ b/server-plugins/notification-resources/src/index.ts @@ -95,7 +95,7 @@ export async function OnBacklinkCreate (tx: Tx, control: TriggerControl): Promis res.push(collabTx) } const actualTx = TxProcessor.extractTx(tx) as TxCUD<Doc> - res = res.concat(await createCollabDocInfo([receiver._id], control, actualTx, tx as TxCUD<Doc>, doc)) + res = res.concat(await createCollabDocInfo([receiver._id], control, actualTx, tx as TxCUD<Doc>, doc, true)) } return res } @@ -360,9 +360,16 @@ function fieldUpdated (field: string, ops: DocumentUpdate<Doc> | MixinUpdate<Doc return false } -function isTypeMatched (control: TriggerControl, type: NotificationType, tx: TxCUD<Doc>, originTx: TxCUD<Doc>): boolean { +function isTypeMatched ( + control: TriggerControl, + type: NotificationType, + tx: TxCUD<Doc>, + originTx: TxCUD<Doc>, + isOwn: boolean +): boolean { const h = control.hierarchy const targetClass = h.getBaseClass(type.objectClass) + if (type.onlyOwn === true && !isOwn) return false if (!type.txClasses.includes(tx._class)) return false if (!control.hierarchy.isDerived(h.getBaseClass(tx.objectClass), targetClass)) return false if (originTx._class === core.class.TxCollectionCUD && type.attachedToClass !== undefined) { @@ -389,14 +396,15 @@ async function getMatchedTypes ( control: TriggerControl, tx: TxCUD<Doc>, originTx: TxCUD<Doc>, - isSpace: boolean = false + isOwn: boolean, + isSpace: boolean ): Promise<NotificationType[]> { const allTypes = (await control.modelDb.findAll(notification.class.NotificationType, {})).filter((p) => isSpace ? p.spaceSubscribe === true : p.spaceSubscribe !== true ) const filtered: NotificationType[] = [] for (const type of allTypes) { - if (isTypeMatched(control, type, tx, originTx)) { + if (isTypeMatched(control, type, tx, originTx, isOwn)) { filtered.push(type) } } @@ -414,11 +422,12 @@ async function isShouldNotify ( originTx: TxCUD<Doc>, object: Doc, user: Ref<Account>, + isOwn: boolean, isSpace: boolean ): Promise<NotifyResult> { let allowed = false const emailTypes: NotificationType[] = [] - const types = await getMatchedTypes(control, tx, originTx, isSpace) + const types = await getMatchedTypes(control, tx, originTx, isOwn, isSpace) for (const type of types) { if (type.allowedForAuthor !== true && tx.modifiedBy === user) continue if (control.hierarchy.hasMixin(type, serverNotification.mixin.TypeMatch)) { @@ -502,10 +511,11 @@ async function getNotificationTxes ( originTx: TxCUD<Doc>, target: Ref<Account>, docUpdates: DocUpdates[], + isOwn: boolean, isSpace: boolean ): Promise<Tx[]> { const res: Tx[] = [] - const allowed = await isShouldNotify(control, tx, originTx, object, target, isSpace) + const allowed = await isShouldNotify(control, tx, originTx, object, target, isOwn, isSpace) if (allowed.allowed) { pushNotification(control, res, target, object, originTx, docUpdates) } @@ -537,6 +547,7 @@ async function createCollabDocInfo ( tx: TxCUD<Doc>, originTx: TxCUD<Doc>, object: Doc, + isOwn: boolean, isSpace: boolean = false ): Promise<Tx[]> { let res: Tx[] = [] @@ -544,7 +555,7 @@ async function createCollabDocInfo ( const targets = new Set(collaborators) const docUpdates = await control.findAll(notification.class.DocUpdates, { attachedTo: object._id }) for (const target of targets) { - res = res.concat(await getNotificationTxes(control, object, tx, originTx, target, docUpdates, isSpace)) + res = res.concat(await getNotificationTxes(control, object, tx, originTx, target, docUpdates, isOwn, isSpace)) } return res } @@ -584,7 +595,7 @@ async function getSpaceCollabTxes ( if (mixin !== undefined) { const collabs = control.hierarchy.as<Doc, Collaborators>(space, notification.mixin.Collaborators) if (collabs.collaborators !== undefined) { - return await createCollabDocInfo(collabs.collaborators, control, tx, originTx, doc, true) + return await createCollabDocInfo(collabs.collaborators, control, tx, originTx, doc, false, true) } } return [] @@ -606,7 +617,7 @@ export async function createCollaboratorDoc ( const collaborators = await getDocCollaborators(doc, mixin, control) const mixinTx = getMixinTx(tx, control, collaborators) - const notificationTxes = await createCollabDocInfo(collaborators, control, tx, originTx, doc) + const notificationTxes = await createCollabDocInfo(collaborators, control, tx, originTx, doc, true) res.push(mixinTx) res.push(...notificationTxes) } @@ -697,14 +708,14 @@ async function updateCollaboratorsMixin ( } async function collectionCollabDoc (tx: TxCollectionCUD<Doc, AttachedDoc>, control: TriggerControl): Promise<Tx[]> { - const actualTx = TxProcessor.extractTx(tx) - let res = await collaboratorDocHandler(actualTx as TxCUD<Doc>, control, tx) + const actualTx = TxProcessor.extractTx(tx) as TxCUD<Doc> + let res = await collaboratorDocHandler(actualTx, control, tx) if ([core.class.TxCreateDoc, core.class.TxRemoveDoc].includes(actualTx._class)) { const doc = (await control.findAll(tx.objectClass, { _id: tx.objectId }, { limit: 1 }))[0] if (doc !== undefined) { if (control.hierarchy.hasMixin(doc, notification.mixin.Collaborators)) { const collabMixin = control.hierarchy.as(doc, notification.mixin.Collaborators) - res = res.concat(await createCollabDocInfo(collabMixin.collaborators, control, tx, tx, doc)) + res = res.concat(await createCollabDocInfo(collabMixin.collaborators, control, actualTx, tx, doc, false)) } } } @@ -808,12 +819,12 @@ async function updateCollaboratorDoc ( ) } res = res.concat( - await createCollabDocInfo([...collabMixin.collaborators, ...newCollaborators], control, tx, originTx, doc) + await createCollabDocInfo([...collabMixin.collaborators, ...newCollaborators], control, tx, originTx, doc, true) ) } else { const collaborators = await getDocCollaborators(doc, mixin, control) res.push(getMixinTx(tx, control, collaborators)) - res = res.concat(await createCollabDocInfo(collaborators, control, tx, originTx, doc)) + res = res.concat(await createCollabDocInfo(collaborators, control, tx, originTx, doc, true)) } res = res.concat(await getSpaceCollabTxes(control, doc, tx, originTx))