mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-12 02:11:57 +00:00
Fix notifications query (#8644)
Some checks are pending
CI / test (push) Blocked by required conditions
CI / build (push) Waiting to run
CI / svelte-check (push) Blocked by required conditions
CI / formatting (push) Blocked by required conditions
CI / uitest (push) Waiting to run
CI / uitest-pg (push) Waiting to run
CI / uitest-qms (push) Waiting to run
CI / uitest-workspaces (push) Waiting to run
CI / docker-build (push) Blocked by required conditions
CI / dist-build (push) Blocked by required conditions
Some checks are pending
CI / test (push) Blocked by required conditions
CI / build (push) Waiting to run
CI / svelte-check (push) Blocked by required conditions
CI / formatting (push) Blocked by required conditions
CI / uitest (push) Waiting to run
CI / uitest-pg (push) Waiting to run
CI / uitest-qms (push) Waiting to run
CI / uitest-workspaces (push) Waiting to run
CI / docker-build (push) Blocked by required conditions
CI / dist-build (push) Blocked by required conditions
Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
parent
cf65de4725
commit
5423aa5047
@ -18,7 +18,7 @@ import activity, { ActivityMessage, DocUpdateMessage } from '@hcengineering/acti
|
|||||||
import chunter, { ChatMessage } from '@hcengineering/chunter'
|
import chunter, { ChatMessage } from '@hcengineering/chunter'
|
||||||
import contact, { Employee, type Person } from '@hcengineering/contact'
|
import contact, { Employee, type Person } from '@hcengineering/contact'
|
||||||
import core, {
|
import core, {
|
||||||
PersonId,
|
AccountUuid,
|
||||||
AnyAttribute,
|
AnyAttribute,
|
||||||
ArrOf,
|
ArrOf,
|
||||||
AttachedDoc,
|
AttachedDoc,
|
||||||
@ -30,6 +30,8 @@ import core, {
|
|||||||
DocumentUpdate,
|
DocumentUpdate,
|
||||||
MeasureContext,
|
MeasureContext,
|
||||||
MixinUpdate,
|
MixinUpdate,
|
||||||
|
notEmpty,
|
||||||
|
PersonId,
|
||||||
Ref,
|
Ref,
|
||||||
RefTo,
|
RefTo,
|
||||||
SortingOrder,
|
SortingOrder,
|
||||||
@ -41,11 +43,7 @@ import core, {
|
|||||||
TxMixin,
|
TxMixin,
|
||||||
TxProcessor,
|
TxProcessor,
|
||||||
TxRemoveDoc,
|
TxRemoveDoc,
|
||||||
TxUpdateDoc,
|
TxUpdateDoc
|
||||||
AccountUuid,
|
|
||||||
notEmpty,
|
|
||||||
generateId,
|
|
||||||
toIdMap
|
|
||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
import notification, {
|
import notification, {
|
||||||
ActivityInboxNotification,
|
ActivityInboxNotification,
|
||||||
@ -78,21 +76,21 @@ import {
|
|||||||
createPullCollaboratorsTx,
|
createPullCollaboratorsTx,
|
||||||
createPushCollaboratorsTx,
|
createPushCollaboratorsTx,
|
||||||
getHTMLPresenter,
|
getHTMLPresenter,
|
||||||
|
getNotificationContent,
|
||||||
getNotificationLink,
|
getNotificationLink,
|
||||||
getNotificationProviderControl,
|
getNotificationProviderControl,
|
||||||
getObjectSpace,
|
getObjectSpace,
|
||||||
getTextPresenter,
|
|
||||||
getReceiversInfo,
|
getReceiversInfo,
|
||||||
|
getSenderInfo,
|
||||||
|
getTextPresenter,
|
||||||
isAllowed,
|
isAllowed,
|
||||||
isMixinTx,
|
isMixinTx,
|
||||||
isShouldNotifyTx,
|
isShouldNotifyTx,
|
||||||
isUserEmployeeInFieldValueTypeMatch,
|
isUserEmployeeInFieldValueTypeMatch,
|
||||||
messageToMarkup,
|
messageToMarkup,
|
||||||
replaceAll,
|
|
||||||
updateNotifyContextsSpace,
|
|
||||||
type NotificationProviderControl,
|
type NotificationProviderControl,
|
||||||
getNotificationContent,
|
replaceAll,
|
||||||
getSenderInfo
|
updateNotifyContextsSpace
|
||||||
} from './utils'
|
} from './utils'
|
||||||
import { PushNotificationsHandler } from './push'
|
import { PushNotificationsHandler } from './push'
|
||||||
|
|
||||||
@ -564,11 +562,6 @@ async function createNotifyContext (
|
|||||||
contextsCache.contexts.set(cacheKey, createTx.objectId)
|
contextsCache.contexts.set(cacheKey, createTx.objectId)
|
||||||
control.cache.set(ContextsCacheKey, contextsCache)
|
control.cache.set(ContextsCacheKey, contextsCache)
|
||||||
await ctx.with('apply', {}, () => control.apply(control.ctx, [createTx]))
|
await ctx.with('apply', {}, () => control.apply(control.ctx, [createTx]))
|
||||||
control.ctx.contextData.broadcast.targets['docNotifyContext' + createTx._id] = (it) => {
|
|
||||||
if (it._id === createTx._id) {
|
|
||||||
return [receiver.account]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return createTx.objectId
|
return createTx.objectId
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -668,12 +661,6 @@ async function updateContextsTimestamp (
|
|||||||
})
|
})
|
||||||
|
|
||||||
res.push(updateTx)
|
res.push(updateTx)
|
||||||
|
|
||||||
control.ctx.contextData.broadcast.targets['docNotifyContext' + updateTx._id] = (it) => {
|
|
||||||
if (it._id === updateTx._id) {
|
|
||||||
return [context.user]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.length > 0) {
|
if (res.length > 0) {
|
||||||
@ -700,12 +687,6 @@ async function removeContexts (
|
|||||||
const removeTx = control.txFactory.createTxRemoveDoc(context._class, context.space, context._id)
|
const removeTx = control.txFactory.createTxRemoveDoc(context._class, context.space, context._id)
|
||||||
|
|
||||||
res.push(removeTx)
|
res.push(removeTx)
|
||||||
|
|
||||||
control.ctx.contextData.broadcast.targets['docNotifyContext' + removeTx._id] = (it) => {
|
|
||||||
if (it._id === removeTx._id) {
|
|
||||||
return [context.user]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await control.apply(control.ctx, res)
|
await control.apply(control.ctx, res)
|
||||||
@ -815,13 +796,7 @@ export async function createCollabDocInfo (
|
|||||||
docMessages,
|
docMessages,
|
||||||
settings
|
settings
|
||||||
)
|
)
|
||||||
const ids = new Set(targetRes.map((it) => it._id))
|
|
||||||
const id = generateId() as string
|
|
||||||
control.ctx.contextData.broadcast.targets[id] = (it) => {
|
|
||||||
if (ids.has(it._id)) {
|
|
||||||
return [receiver.account]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res = res.concat(targetRes)
|
res = res.concat(targetRes)
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
@ -1448,41 +1423,6 @@ export async function OnAttributeUpdate (txes: Tx[], control: TriggerControl): P
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async function applyUserTxes (ctx: MeasureContext, control: TriggerControl, txes: Tx[]): Promise<Tx[]> {
|
|
||||||
const map: Map<AccountUuid, Tx[]> = new Map<AccountUuid, Tx[]>()
|
|
||||||
const res: Tx[] = []
|
|
||||||
|
|
||||||
for (const tx of txes) {
|
|
||||||
const ttx = tx as TxCUD<Doc>
|
|
||||||
if (
|
|
||||||
control.hierarchy.isDerived(ttx.objectClass, notification.class.InboxNotification) &&
|
|
||||||
ttx._class === core.class.TxCreateDoc
|
|
||||||
) {
|
|
||||||
const notification = TxProcessor.createDoc2Doc(ttx as TxCreateDoc<InboxNotification>)
|
|
||||||
|
|
||||||
if (map.has(notification.user)) {
|
|
||||||
map.get(notification.user)?.push(tx)
|
|
||||||
} else {
|
|
||||||
map.set(notification.user, [tx])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.push(tx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [user, txs] of map.entries()) {
|
|
||||||
await control.apply(ctx, txs)
|
|
||||||
const m1 = toIdMap(txs)
|
|
||||||
control.ctx.contextData.broadcast.targets.docNotifyContext = (it) => {
|
|
||||||
if (m1.has(it._id)) {
|
|
||||||
return [user]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateCollaborators (
|
async function updateCollaborators (
|
||||||
ctx: MeasureContext,
|
ctx: MeasureContext,
|
||||||
control: TriggerControl,
|
control: TriggerControl,
|
||||||
@ -1565,19 +1505,16 @@ export async function createCollaboratorNotifications (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tx.attachedTo !== undefined && !ignoreCollection) {
|
if (tx.attachedTo !== undefined && !ignoreCollection) {
|
||||||
const res = await ctx.with('collectionCollabDoc', {}, (ctx) =>
|
return await ctx.with('collectionCollabDoc', {}, (ctx) =>
|
||||||
collectionCollabDoc(ctx, tx as TxCUD<AttachedDoc>, control, activityMessages, cache, true)
|
collectionCollabDoc(ctx, tx as TxCUD<AttachedDoc>, control, activityMessages, cache, true)
|
||||||
)
|
)
|
||||||
return await applyUserTxes(ctx, control, res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (tx._class) {
|
switch (tx._class) {
|
||||||
case core.class.TxCreateDoc: {
|
case core.class.TxCreateDoc: {
|
||||||
const res = await ctx.with('createCollaboratorDoc', {}, (ctx) =>
|
return await ctx.with('createCollaboratorDoc', {}, (ctx) =>
|
||||||
createCollaboratorDoc(ctx, tx as TxCreateDoc<Doc>, control, activityMessages, cache)
|
createCollaboratorDoc(ctx, tx as TxCreateDoc<Doc>, control, activityMessages, cache)
|
||||||
)
|
)
|
||||||
|
|
||||||
return await applyUserTxes(ctx, control, res)
|
|
||||||
}
|
}
|
||||||
case core.class.TxUpdateDoc:
|
case core.class.TxUpdateDoc:
|
||||||
case core.class.TxMixin: {
|
case core.class.TxMixin: {
|
||||||
@ -1596,7 +1533,7 @@ export async function createCollaboratorNotifications (
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return await applyUserTxes(ctx, control, res)
|
return res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
"@hcengineering/platform": "^0.6.11",
|
"@hcengineering/platform": "^0.6.11",
|
||||||
"@hcengineering/server-core": "^0.6.1",
|
"@hcengineering/server-core": "^0.6.1",
|
||||||
"@hcengineering/server-preference": "^0.6.0",
|
"@hcengineering/server-preference": "^0.6.0",
|
||||||
"@hcengineering/server-notification": "^0.6.1",
|
|
||||||
"@hcengineering/query": "^0.6.12",
|
"@hcengineering/query": "^0.6.12",
|
||||||
"@hcengineering/analytics": "^0.6.0",
|
"@hcengineering/analytics": "^0.6.0",
|
||||||
"fast-equals": "^5.2.2"
|
"fast-equals": "^5.2.2"
|
||||||
|
@ -28,7 +28,6 @@ export * from './lookup'
|
|||||||
export * from './lowLevel'
|
export * from './lowLevel'
|
||||||
export * from './model'
|
export * from './model'
|
||||||
export * from './modified'
|
export * from './modified'
|
||||||
export * from './notifications'
|
|
||||||
export * from './private'
|
export * from './private'
|
||||||
export * from './queryJoin'
|
export * from './queryJoin'
|
||||||
export * from './spacePermissions'
|
export * from './spacePermissions'
|
||||||
|
@ -1,99 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright © 2024 Hardcore Engineering Inc.
|
|
||||||
//
|
|
||||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License. You may
|
|
||||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
|
|
||||||
import core, {
|
|
||||||
Doc,
|
|
||||||
MeasureContext,
|
|
||||||
Tx,
|
|
||||||
TxCUD,
|
|
||||||
TxProcessor,
|
|
||||||
type SessionData,
|
|
||||||
TxApplyIf,
|
|
||||||
systemAccountUuid,
|
|
||||||
AccountUuid
|
|
||||||
} from '@hcengineering/core'
|
|
||||||
import platform, { PlatformError, Severity, Status } from '@hcengineering/platform'
|
|
||||||
import { BaseMiddleware, Middleware, TxMiddlewareResult, type PipelineContext } from '@hcengineering/server-core'
|
|
||||||
import { DOMAIN_USER_NOTIFY, DOMAIN_NOTIFICATION, DOMAIN_DOC_NOTIFY } from '@hcengineering/server-notification'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export class NotificationsMiddleware extends BaseMiddleware implements Middleware {
|
|
||||||
private readonly targetDomains = [DOMAIN_USER_NOTIFY, DOMAIN_NOTIFICATION, DOMAIN_DOC_NOTIFY]
|
|
||||||
|
|
||||||
private constructor (context: PipelineContext, next?: Middleware) {
|
|
||||||
super(context, next)
|
|
||||||
}
|
|
||||||
|
|
||||||
static async create (
|
|
||||||
ctx: MeasureContext,
|
|
||||||
context: PipelineContext,
|
|
||||||
next: Middleware | undefined
|
|
||||||
): Promise<NotificationsMiddleware> {
|
|
||||||
return new NotificationsMiddleware(context, next)
|
|
||||||
}
|
|
||||||
|
|
||||||
isTargetDomain (tx: Tx): boolean {
|
|
||||||
if (TxProcessor.isExtendsCUD(tx._class)) {
|
|
||||||
const txCUD = tx as TxCUD<Doc>
|
|
||||||
const domain = this.context.hierarchy.getDomain(txCUD.objectClass)
|
|
||||||
return this.targetDomains.includes(domain)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
processTx (ctx: MeasureContext<SessionData>, tx: Tx): void {
|
|
||||||
let target: AccountUuid[] | undefined
|
|
||||||
if (this.isTargetDomain(tx)) {
|
|
||||||
const account = ctx.contextData.account
|
|
||||||
if (!account.socialIds.includes(tx.modifiedBy) && account.uuid !== systemAccountUuid) {
|
|
||||||
throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {}))
|
|
||||||
}
|
|
||||||
const modifiedByAccount = ctx.contextData.socialStringsToUsers.get(tx.modifiedBy)
|
|
||||||
target = [account.uuid, systemAccountUuid]
|
|
||||||
if (modifiedByAccount !== undefined && !target.includes(modifiedByAccount)) {
|
|
||||||
target.push(modifiedByAccount)
|
|
||||||
}
|
|
||||||
ctx.contextData.broadcast.targets['checkDomain' + account.uuid] = (tx) => {
|
|
||||||
if (this.isTargetDomain(tx)) {
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tx (ctx: MeasureContext<SessionData>, txes: Tx[]): Promise<TxMiddlewareResult> {
|
|
||||||
for (const tx of txes) {
|
|
||||||
if (this.context.hierarchy.isDerived(tx._class, core.class.TxApplyIf)) {
|
|
||||||
for (const ttx of (tx as TxApplyIf).txes) {
|
|
||||||
this.processTx(ctx, ttx)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.processTx(ctx, tx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.provideTx(ctx, txes)
|
|
||||||
}
|
|
||||||
|
|
||||||
isAvailable (ctx: MeasureContext<SessionData>, doc: Doc): boolean {
|
|
||||||
const domain = this.context.hierarchy.getDomain(doc._class)
|
|
||||||
if (!this.targetDomains.includes(domain)) return true
|
|
||||||
const account = ctx.contextData.account
|
|
||||||
const socialStrings = account.socialIds
|
|
||||||
return (doc.createdBy !== undefined && socialStrings.includes(doc.createdBy)) || account.uuid === systemAccountUuid
|
|
||||||
}
|
|
||||||
}
|
|
@ -30,7 +30,6 @@ import {
|
|||||||
MarkDerivedEntryMiddleware,
|
MarkDerivedEntryMiddleware,
|
||||||
ModelMiddleware,
|
ModelMiddleware,
|
||||||
ModifiedMiddleware,
|
ModifiedMiddleware,
|
||||||
NotificationsMiddleware,
|
|
||||||
PluginConfigurationMiddleware,
|
PluginConfigurationMiddleware,
|
||||||
PrivateMiddleware,
|
PrivateMiddleware,
|
||||||
QueryJoinMiddleware,
|
QueryJoinMiddleware,
|
||||||
@ -122,7 +121,6 @@ export function createServerPipeline (
|
|||||||
ModifiedMiddleware.create,
|
ModifiedMiddleware.create,
|
||||||
PluginConfigurationMiddleware.create,
|
PluginConfigurationMiddleware.create,
|
||||||
PrivateMiddleware.create,
|
PrivateMiddleware.create,
|
||||||
NotificationsMiddleware.create,
|
|
||||||
(ctx: MeasureContext, context: PipelineContext, next?: Middleware) =>
|
(ctx: MeasureContext, context: PipelineContext, next?: Middleware) =>
|
||||||
SpaceSecurityMiddleware.create(opt.adapterSecurity ?? false, ctx, context, next),
|
SpaceSecurityMiddleware.create(opt.adapterSecurity ?? false, ctx, context, next),
|
||||||
SpacePermissionsMiddleware.create,
|
SpacePermissionsMiddleware.create,
|
||||||
|
Loading…
Reference in New Issue
Block a user