From cf1e8b284fcf12e82570c4b0f31a9f56d8149b3e Mon Sep 17 00:00:00 2001 From: Ruslan Bayandinov <45530296+wazsone@users.noreply.github.com> Date: Wed, 3 May 2023 18:03:36 +0400 Subject: [PATCH] [TSK-779] Use txMatch (#3101) Signed-off-by: Ruslan Bayandinov --- models/server-attachment/package.json | 1 + models/server-attachment/src/index.ts | 8 ++- models/server-contact/src/index.ts | 12 ++++- models/server-gmail/package.json | 1 + models/server-gmail/src/index.ts | 8 ++- models/server-hr/src/index.ts | 35 +++++++++++-- models/server-notification/src/index.ts | 12 ++++- models/server-telegram/package.json | 3 +- models/server-telegram/src/index.ts | 8 ++- models/server-tracker/src/index.ts | 6 ++- .../attachment-resources/src/index.ts | 14 +---- server-plugins/contact-resources/src/index.ts | 16 ------ server-plugins/gmail-resources/src/index.ts | 9 +--- server-plugins/hr-resources/src/index.ts | 45 ++-------------- .../notification-resources/src/index.ts | 7 +-- .../telegram-resources/src/index.ts | 14 +---- server-plugins/tracker-resources/src/index.ts | 7 +-- server/core/src/storage.ts | 2 +- server/core/src/triggers.ts | 52 ++++++++++++++++++- 19 files changed, 143 insertions(+), 117 deletions(-) diff --git a/models/server-attachment/package.json b/models/server-attachment/package.json index 8e254c90dd..b43b56fb2c 100644 --- a/models/server-attachment/package.json +++ b/models/server-attachment/package.json @@ -25,6 +25,7 @@ "@rushstack/heft": "^0.47.9" }, "dependencies": { + "@hcengineering/attachment": "^0.6.4", "@hcengineering/core": "^0.6.23", "@hcengineering/model": "^0.6.2", "@hcengineering/platform": "^0.6.8", diff --git a/models/server-attachment/src/index.ts b/models/server-attachment/src/index.ts index ed17071381..67ac40abc4 100644 --- a/models/server-attachment/src/index.ts +++ b/models/server-attachment/src/index.ts @@ -16,6 +16,7 @@ import { Builder } from '@hcengineering/model' +import attachment from '@hcengineering/attachment' import core from '@hcengineering/core' import serverAttachment from '@hcengineering/server-attachment' import serverCore from '@hcengineering/server-core' @@ -24,6 +25,11 @@ export { serverAttachmentId } from '@hcengineering/server-attachment' export function createModel (builder: Builder): void { builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverAttachment.trigger.OnAttachmentDelete + trigger: serverAttachment.trigger.OnAttachmentDelete, + txMatch: { + _class: core.class.TxCollectionCUD, + 'tx.objectClass': attachment.class.Attachment, + 'tx._class': core.class.TxRemoveDoc + } }) } diff --git a/models/server-contact/src/index.ts b/models/server-contact/src/index.ts index 5a4729d2f9..54e35744b3 100644 --- a/models/server-contact/src/index.ts +++ b/models/server-contact/src/index.ts @@ -41,11 +41,19 @@ export function createModel (builder: Builder): void { }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverContact.trigger.OnContactDelete + trigger: serverContact.trigger.OnContactDelete, + txMatch: { + objectClass: contact.class.Contact, + _class: core.class.TxRemoveDoc + } }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverContact.trigger.OnChannelUpdate + trigger: serverContact.trigger.OnChannelUpdate, + txMatch: { + objectClass: contact.class.Channel, + _class: core.class.TxUpdateDoc + } }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { diff --git a/models/server-gmail/package.json b/models/server-gmail/package.json index 08444f01f8..b75d56471f 100644 --- a/models/server-gmail/package.json +++ b/models/server-gmail/package.json @@ -26,6 +26,7 @@ }, "dependencies": { "@hcengineering/core": "^0.6.23", + "@hcengineering/gmail": "^0.6.8", "@hcengineering/model": "^0.6.2", "@hcengineering/contact": "^0.6.14", "@hcengineering/platform": "^0.6.8", diff --git a/models/server-gmail/src/index.ts b/models/server-gmail/src/index.ts index b5b2e19b87..287ae35ac8 100644 --- a/models/server-gmail/src/index.ts +++ b/models/server-gmail/src/index.ts @@ -17,6 +17,7 @@ import { Builder } from '@hcengineering/model' import contact from '@hcengineering/contact' import core, { Class, Doc } from '@hcengineering/core' +import gmail from '@hcengineering/gmail' import serverCore, { ObjectDDParticipant } from '@hcengineering/server-core' import serverGmail from '@hcengineering/server-gmail' export { serverGmailId } from '@hcengineering/server-gmail' @@ -32,6 +33,11 @@ export function createModel (builder: Builder): void { ) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverGmail.trigger.OnMessageCreate + trigger: serverGmail.trigger.OnMessageCreate, + txMatch: { + _class: core.class.TxCollectionCUD, + 'tx.objectClass': gmail.class.Message, + 'tx._class': core.class.TxCreateDoc + } }) } diff --git a/models/server-hr/src/index.ts b/models/server-hr/src/index.ts index 4b404d6fab..7721310161 100644 --- a/models/server-hr/src/index.ts +++ b/models/server-hr/src/index.ts @@ -25,23 +25,48 @@ export { serverHrId } from '@hcengineering/server-hr' export function createModel (builder: Builder): void { builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverHr.trigger.OnDepartmentStaff + trigger: serverHr.trigger.OnDepartmentStaff, + txMatch: { + _class: core.class.TxCollectionCUD, + 'tx.objectClass': hr.mixin.Staff, + 'tx._class': core.class.TxMixin + } }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverHr.trigger.OnRequestCreate + trigger: serverHr.trigger.OnRequestCreate, + txMatch: { + _class: core.class.TxCollectionCUD, + 'tx.objectClass': hr.class.Request, + 'tx._class': core.class.TxCreateDoc + } }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverHr.trigger.OnRequestUpdate + trigger: serverHr.trigger.OnRequestUpdate, + txMatch: { + _class: core.class.TxCollectionCUD, + 'tx.objectClass': hr.class.Request, + 'tx._class': core.class.TxUpdateDoc + } }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverHr.trigger.OnRequestRemove + trigger: serverHr.trigger.OnRequestRemove, + txMatch: { + _class: core.class.TxCollectionCUD, + 'tx.objectClass': hr.class.Request, + 'tx._class': core.class.TxRemoveDoc + } }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverHr.trigger.OnPublicHolidayCreate + trigger: serverHr.trigger.OnPublicHolidayCreate, + txMatch: { + _class: core.class.TxCollectionCUD, + 'tx.objectClass': hr.class.PublicHoliday, + 'tx._class': core.class.TxCreateDoc + } }) builder.mixin(hr.class.Request, core.class.Class, serverNotification.mixin.HTMLPresenter, { diff --git a/models/server-notification/src/index.ts b/models/server-notification/src/index.ts index 928402609b..86ab76bac6 100644 --- a/models/server-notification/src/index.ts +++ b/models/server-notification/src/index.ts @@ -60,10 +60,18 @@ export function createModel (builder: Builder): void { }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverNotification.trigger.OnAttributeCreate + trigger: serverNotification.trigger.OnAttributeCreate, + txMatch: { + objectClass: core.class.Attribute, + _class: core.class.TxCreateDoc + } }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverNotification.trigger.OnAttributeUpdate + trigger: serverNotification.trigger.OnAttributeUpdate, + txMatch: { + objectClass: core.class.Attribute, + _class: core.class.TxUpdateDoc + } }) } diff --git a/models/server-telegram/package.json b/models/server-telegram/package.json index 5d664c3aa6..17bed990e8 100644 --- a/models/server-telegram/package.json +++ b/models/server-telegram/package.json @@ -30,6 +30,7 @@ "@hcengineering/contact": "^0.6.14", "@hcengineering/platform": "^0.6.8", "@hcengineering/server-telegram": "^0.6.0", - "@hcengineering/server-core": "^0.6.1" + "@hcengineering/server-core": "^0.6.1", + "@hcengineering/telegram": "^0.6.7" } } diff --git a/models/server-telegram/src/index.ts b/models/server-telegram/src/index.ts index deaa44e2dc..32f7787983 100644 --- a/models/server-telegram/src/index.ts +++ b/models/server-telegram/src/index.ts @@ -19,6 +19,7 @@ import contact from '@hcengineering/contact' import core, { Class, Doc } from '@hcengineering/core' import serverCore, { ObjectDDParticipant } from '@hcengineering/server-core' import serverTelegram from '@hcengineering/server-telegram' +import telegram from '@hcengineering/telegram' export { serverTelegramId } from '@hcengineering/server-telegram' @@ -33,6 +34,11 @@ export function createModel (builder: Builder): void { ) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverTelegram.trigger.OnMessageCreate + trigger: serverTelegram.trigger.OnMessageCreate, + txMatch: { + _class: core.class.TxCollectionCUD, + 'tx.objectClass': telegram.class.Message, + 'tx._class': core.class.TxCreateDoc + } }) } diff --git a/models/server-tracker/src/index.ts b/models/server-tracker/src/index.ts index 2a8c7ddef0..559f416be0 100644 --- a/models/server-tracker/src/index.ts +++ b/models/server-tracker/src/index.ts @@ -37,7 +37,11 @@ export function createModel (builder: Builder): void { }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverTracker.trigger.OnComponentRemove + trigger: serverTracker.trigger.OnComponentRemove, + txMatch: { + _class: core.class.TxCollectionCUD, + 'tx._class': core.class.TxCreateDoc + } }) builder.mixin( diff --git a/server-plugins/attachment-resources/src/index.ts b/server-plugins/attachment-resources/src/index.ts index c1493613cb..53d46c64c3 100644 --- a/server-plugins/attachment-resources/src/index.ts +++ b/server-plugins/attachment-resources/src/index.ts @@ -15,9 +15,8 @@ // import type { Attachment } from '@hcengineering/attachment' -import attachment from '@hcengineering/attachment' import type { Doc, Ref, Tx, TxRemoveDoc } from '@hcengineering/core' -import core, { TxProcessor } from '@hcengineering/core' +import { TxProcessor } from '@hcengineering/core' import type { TriggerControl } from '@hcengineering/server-core' /** @@ -27,16 +26,7 @@ export async function OnAttachmentDelete ( tx: Tx, { findAll, hierarchy, fulltextFx, storageFx, removedMap }: TriggerControl ): Promise { - const actualTx = TxProcessor.extractTx(tx) - if (actualTx._class !== core.class.TxRemoveDoc) { - return [] - } - - const rmTx = actualTx as TxRemoveDoc - - if (!hierarchy.isDerived(rmTx.objectClass, attachment.class.Attachment)) { - return [] - } + const rmTx = TxProcessor.extractTx(tx) as TxRemoveDoc // Obtain document being deleted. const attach = removedMap.get(rmTx.objectId) as Attachment diff --git a/server-plugins/contact-resources/src/index.ts b/server-plugins/contact-resources/src/index.ts index c681c63665..2317715f0c 100644 --- a/server-plugins/contact-resources/src/index.ts +++ b/server-plugins/contact-resources/src/index.ts @@ -51,16 +51,8 @@ export async function OnContactDelete ( tx: Tx, { findAll, hierarchy, storageFx, removedMap, txFactory }: TriggerControl ): Promise { - if (tx._class !== core.class.TxRemoveDoc) { - return [] - } - const rmTx = tx as TxRemoveDoc - if (!hierarchy.isDerived(rmTx.objectClass, contact.class.Contact)) { - return [] - } - const removeContact = removedMap.get(rmTx.objectId) as Contact if (removeContact === undefined) { return [] @@ -322,16 +314,8 @@ export async function OnEmployeeUpdate (tx: Tx, control: TriggerControl): Promis * @public */ export async function OnChannelUpdate (tx: Tx, control: TriggerControl): Promise { - if (tx._class !== core.class.TxUpdateDoc) { - return [] - } - const uTx = tx as TxUpdateDoc - if (!control.hierarchy.isDerived(uTx.objectClass, contact.class.Channel)) { - return [] - } - const result: Tx[] = [] if (uTx.operations.$inc?.items !== undefined) { diff --git a/server-plugins/gmail-resources/src/index.ts b/server-plugins/gmail-resources/src/index.ts index 1b5c6bbdd2..b74c010c88 100644 --- a/server-plugins/gmail-resources/src/index.ts +++ b/server-plugins/gmail-resources/src/index.ts @@ -14,7 +14,7 @@ // import contact, { Channel } from '@hcengineering/contact' -import core, { +import { Class, Doc, DocumentQuery, @@ -57,16 +57,9 @@ export async function FindMessages ( */ export async function OnMessageCreate (tx: Tx, control: TriggerControl): Promise { const res: Tx[] = [] - const actualTx = TxProcessor.extractTx(tx) - if (actualTx._class !== core.class.TxCreateDoc) { - return [] - } const createTx = tx as TxCreateDoc - if (!control.hierarchy.isDerived(createTx.objectClass, gmail.class.Message)) { - return [] - } const message = TxProcessor.createDoc2Doc(createTx) const channel = (await control.findAll(contact.class.Channel, { _id: message.attachedTo }, { limit: 1 }))[0] diff --git a/server-plugins/hr-resources/src/index.ts b/server-plugins/hr-resources/src/index.ts index 5d7aeea3d7..3a8c5aef60 100644 --- a/server-plugins/hr-resources/src/index.ts +++ b/server-plugins/hr-resources/src/index.ts @@ -116,14 +116,7 @@ function getTxes ( * @public */ export async function OnDepartmentStaff (tx: Tx, control: TriggerControl): Promise { - const actualTx = TxProcessor.extractTx(tx) - if (core.class.TxMixin !== actualTx._class) { - return [] - } - const ctx = actualTx as TxMixin - if (ctx.mixin !== hr.mixin.Staff) { - return [] - } + const ctx = TxProcessor.extractTx(tx) as TxMixin const targetAccount = ( await control.modelDb.findAll(contact.class.EmployeeAccount, { @@ -252,14 +245,7 @@ async function getEmailNotification ( * @public */ export async function OnRequestCreate (tx: Tx, control: TriggerControl): Promise { - const actualTx = TxProcessor.extractTx(tx) - if (core.class.TxCreateDoc !== actualTx._class) { - return [] - } - const ctx = actualTx as TxCreateDoc - if (ctx.objectClass !== hr.class.Request) { - return [] - } + const ctx = TxProcessor.extractTx(tx) as TxCreateDoc const sender = await getEmployeeAccountById(ctx.modifiedBy, control) if (sender === undefined) return [] @@ -279,14 +265,7 @@ export async function OnRequestCreate (tx: Tx, control: TriggerControl): Promise * @public */ export async function OnRequestUpdate (tx: Tx, control: TriggerControl): Promise { - const actualTx = TxProcessor.extractTx(tx) - if (core.class.TxUpdateDoc !== actualTx._class) { - return [] - } - const ctx = actualTx as TxUpdateDoc - if (ctx.objectClass !== hr.class.Request) { - return [] - } + const ctx = TxProcessor.extractTx(tx) as TxUpdateDoc const sender = await getEmployeeAccountById(ctx.modifiedBy, control) if (sender === undefined) return [] @@ -307,14 +286,7 @@ export async function OnRequestUpdate (tx: Tx, control: TriggerControl): Promise * @public */ export async function OnRequestRemove (tx: Tx, control: TriggerControl): Promise { - const actualTx = TxProcessor.extractTx(tx) - if (core.class.TxRemoveDoc !== actualTx._class) { - return [] - } - const ctx = actualTx as TxCreateDoc - if (ctx.objectClass !== hr.class.Request) { - return [] - } + const ctx = TxProcessor.extractTx(tx) as TxCreateDoc const sender = await getEmployeeAccountById(ctx.modifiedBy, control) if (sender === undefined) return [] @@ -371,14 +343,7 @@ export async function RequestTextPresenter (doc: Doc, control: TriggerControl): * @public */ export async function OnPublicHolidayCreate (tx: Tx, control: TriggerControl): Promise { - const actualTx = TxProcessor.extractTx(tx) - if (core.class.TxCreateDoc !== actualTx._class) { - return [] - } - const ctx = actualTx as TxCreateDoc - if (ctx.objectClass !== hr.class.PublicHoliday) { - return [] - } + const ctx = TxProcessor.extractTx(tx) as TxCreateDoc const sender = await getEmployeeAccountById(ctx.modifiedBy, control) if (sender === undefined) return [] diff --git a/server-plugins/notification-resources/src/index.ts b/server-plugins/notification-resources/src/index.ts index 172fec3249..87e13a665e 100644 --- a/server-plugins/notification-resources/src/index.ts +++ b/server-plugins/notification-resources/src/index.ts @@ -756,10 +756,7 @@ export async function isUserEmployeeInFieldValue ( * @public */ export async function OnAttributeCreate (tx: Tx, control: TriggerControl): Promise { - if (tx._class !== core.class.TxCreateDoc) return [] - const ctx = tx as TxCreateDoc - if (ctx.objectClass !== core.class.Attribute) return [] - const attribute = TxProcessor.createDoc2Doc(ctx) + const attribute = TxProcessor.createDoc2Doc(tx as TxCreateDoc) const group = ( await control.modelDb.findAll(notification.class.NotificationGroup, { objectClass: attribute.attributeOf }) )[0] @@ -795,9 +792,7 @@ export async function OnAttributeCreate (tx: Tx, control: TriggerControl): Promi * @public */ export async function OnAttributeUpdate (tx: Tx, control: TriggerControl): Promise { - if (tx._class !== core.class.TxUpdateDoc) return [] const ctx = tx as TxUpdateDoc - if (ctx.objectClass !== core.class.Attribute) return [] if (ctx.operations.hidden === undefined) return [] const type = (await control.findAll(notification.class.NotificationType, { attribute: ctx.objectId }))[0] if (type === undefined) return [] diff --git a/server-plugins/telegram-resources/src/index.ts b/server-plugins/telegram-resources/src/index.ts index 3373fabb31..396e1c2c6c 100644 --- a/server-plugins/telegram-resources/src/index.ts +++ b/server-plugins/telegram-resources/src/index.ts @@ -14,7 +14,7 @@ // import contact, { Channel } from '@hcengineering/contact' -import core, { +import { Class, Doc, DocumentQuery, @@ -57,18 +57,8 @@ export async function FindMessages ( */ export async function OnMessageCreate (tx: Tx, control: TriggerControl): Promise { const res: Tx[] = [] - const actualTx = TxProcessor.extractTx(tx) - if (actualTx._class !== core.class.TxCreateDoc) { - return [] - } - - const createTx = tx as TxCreateDoc - - if (!control.hierarchy.isDerived(createTx.objectClass, telegram.class.Message)) { - return [] - } - const message = TxProcessor.createDoc2Doc(createTx) + const message = TxProcessor.createDoc2Doc(tx as TxCreateDoc) const channel = (await control.findAll(contact.class.Channel, { _id: message.attachedTo }, { limit: 1 }))[0] if (channel !== undefined) { if (channel.lastMessage === undefined || channel.lastMessage < message.sendOn) { diff --git a/server-plugins/tracker-resources/src/index.ts b/server-plugins/tracker-resources/src/index.ts index 584a4f696c..ff54a9bbba 100644 --- a/server-plugins/tracker-resources/src/index.ts +++ b/server-plugins/tracker-resources/src/index.ts @@ -73,12 +73,7 @@ export async function issueTextPresenter (doc: Doc, control: TriggerControl): Pr * @public */ export async function OnComponentRemove (tx: Tx, control: TriggerControl): Promise { - const actualTx = TxProcessor.extractTx(tx) - if (actualTx._class !== core.class.TxRemoveDoc) { - return [] - } - - const ctx = actualTx as TxUpdateDoc + const ctx = TxProcessor.extractTx(tx) as TxUpdateDoc const issues = await control.findAll(tracker.class.Issue, { component: ctx.objectId diff --git a/server/core/src/storage.ts b/server/core/src/storage.ts index 87da098e95..f5be827542 100644 --- a/server/core/src/storage.ts +++ b/server/core/src/storage.ts @@ -762,7 +762,7 @@ export async function createServerStorage ( options: ServerStorageOptions ): Promise { const hierarchy = new Hierarchy() - const triggers = new Triggers() + const triggers = new Triggers(hierarchy) const adapters = new Map() const modelDb = new ModelDb(hierarchy) diff --git a/server/core/src/triggers.ts b/server/core/src/triggers.ts index d4cb4e650e..f57b99ced7 100644 --- a/server/core/src/triggers.ts +++ b/server/core/src/triggers.ts @@ -24,7 +24,10 @@ import core, { AttachedDoc, DocumentQuery, matchQuery, - TxFactory + TxFactory, + Hierarchy, + Class, + Obj } from '@hcengineering/core' import { getResource } from '@hcengineering/platform' @@ -38,6 +41,8 @@ import serverCore from './plugin' export class Triggers { private readonly triggers: [DocumentQuery | undefined, TriggerFunc][] = [] + constructor (protected readonly hierarchy: Hierarchy) {} + async tx (tx: Tx): Promise { if (tx._class === core.class.TxCollectionCUD) { tx = (tx as TxCollectionCUD).tx @@ -56,9 +61,52 @@ export class Triggers { async apply (account: Ref, tx: Tx, ctrl: Omit): Promise { const control = { ...ctrl, txFactory: new TxFactory(account, true) } const derived = this.triggers - .filter(([query]) => query === undefined || matchQuery([tx], query, core.class.Tx, control.hierarchy).length > 0) + .filter(([query]) => { + if (query === undefined) { + return true + } + this.addDerived(query, 'objectClass') + this.addDerived(query, 'tx.objectClass') + return matchQuery([tx], query, core.class.Tx, control.hierarchy).length > 0 + }) .map(([, trigger]) => trigger(tx, control)) const result = await Promise.all(derived) return result.flatMap((x) => x) } + + private addDerived (q: DocumentQuery, key: string): void { + if (q[key] === undefined) { + return + } + if (typeof q[key] === 'string') { + const descendants = this.hierarchy.getDescendants(q[key]) + q[key] = { + $in: [...(q[key].$in ?? []), ...descendants] + } + } else { + if (Array.isArray(q[key].$in)) { + const oldIn = q[key].$in + const newIn = new Set(oldIn) + q[key].$in.forEach((element: Ref>) => { + const descendants = this.hierarchy.getDescendants(element) + descendants.forEach((d) => newIn.add(d)) + }) + q[key].$in = Array.from(newIn.values()) + } + if (Array.isArray(q[key].$nin)) { + const oldNin = q[key].$nin + const newNin = new Set(oldNin) + q[key].$nin.forEach((element: Ref>) => { + const descendants = this.hierarchy.getDescendants(element) + descendants.forEach((d) => newNin.add(d)) + }) + q[key].$nin = Array.from(newNin.values()) + } + if (q[key].$ne !== undefined) { + const descendants = this.hierarchy.getDescendants(q[key].$ne) + delete q[key].$ne + q[key].$nin = [...(q[key].$nin ?? []), ...descendants] + } + } + } }