From 3b6666d252e70bdfdecbe56ae0989a5c8b8a3b8d Mon Sep 17 00:00:00 2001 From: Kristina Date: Fri, 11 Jul 2025 21:57:11 +0400 Subject: [PATCH] Adjust notifications for readonly guest (#87) Signed-off-by: Kristina Fefelova --- packages/server/src/middleware/permissions.ts | 15 ++++++++++++++- .../server/src/notification/notification.ts | 17 +++++++++++------ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/server/src/middleware/permissions.ts b/packages/server/src/middleware/permissions.ts index 54b4e8b52d..9d9e565794 100644 --- a/packages/server/src/middleware/permissions.ts +++ b/packages/server/src/middleware/permissions.ts @@ -21,7 +21,7 @@ import { NotificationEventType, type SessionData } from '@hcengineering/communication-sdk-types' -import { systemAccountUuid } from '@hcengineering/core' +import { AccountRole, systemAccountUuid } from '@hcengineering/core' import type { AccountID, SocialID } from '@hcengineering/communication-types' import { ApiError } from '../error' @@ -40,6 +40,8 @@ export class PermissionsMiddleware extends BaseMiddleware implements Middleware async event (session: SessionData, event: Enriched, derived: boolean): Promise { if (derived) return await this.provideEvent(session, event, derived) + this.notAnonymousAccount(session) + switch (event.type) { case MessageEventType.CreateMessage: this.checkSocialId(session, event.socialId) @@ -96,8 +98,19 @@ export class PermissionsMiddleware extends BaseMiddleware implements Middleware } } + private notAnonymousAccount (session: SessionData): void { + if (this.isAnonymousAccount(session)) { + throw ApiError.forbidden('anonymous account is not allowed') + } + } + private isSystemAccount (session: SessionData): boolean { const account = session.account return systemAccountUuid === account.uuid } + + private isAnonymousAccount (session: SessionData): boolean { + const account = session.account + return account.role === AccountRole.ReadOnlyGuest + } } diff --git a/packages/server/src/notification/notification.ts b/packages/server/src/notification/notification.ts index f02620d9de..0ce78b8cd5 100644 --- a/packages/server/src/notification/notification.ts +++ b/packages/server/src/notification/notification.ts @@ -34,14 +34,16 @@ import { type SocialID, SortingOrder } from '@hcengineering/communication-types' +import { markdownToMarkup } from '@hcengineering/text-markdown' +import { jsonToMarkup, markupToText } from '@hcengineering/text-core' +import { readOnlyGuestAccountUuid } from '@hcengineering/core' import type { Enriched, TriggerCtx } from '../types' import { findAccount } from '../utils' import { findMessage, getNameBySocialID } from '../triggers/utils' -import { markdownToMarkup } from '@hcengineering/text-markdown' -import { jsonToMarkup, markupToText } from '@hcengineering/text-core' const BATCH_SIZE = 500 +const maxDate = new Date('9999-12-31T23:59:59Z') export async function notify (ctx: TriggerCtx, event: Enriched): Promise { switch (event.type) { @@ -191,7 +193,7 @@ async function notifyReaction ( blobId, date, content, - read: false + read: messageAccount === readOnlyGuestAccountUuid }) if ((context?.lastNotify?.getTime() ?? date.getTime()) < date.getTime()) { @@ -294,6 +296,7 @@ async function processCollaborator ( const text = markupToText(jsonToMarkup(markdownToMarkup(markdown))) const shortText = text.slice(0, 100) + const isRead = collaborator === readOnlyGuestAccountUuid result.push({ type: NotificationEventType.CreateNotification, notificationType: NotificationType.Message, @@ -308,7 +311,7 @@ async function processCollaborator ( title: cardTitle, shortText: shortText.length < text.length ? shortText + '...' : text }, - read: date.getTime() < (context?.lastView?.getTime() ?? 0) + read: isRead || date.getTime() < (context?.lastView?.getTime() ?? 0) }) return result } @@ -325,7 +328,8 @@ async function createOrUpdateContext ( events: Event[] }> { if (context == null) { - const contextId = await createContext(ctx, collaborator, cardId, date, isOwn ? date : undefined, date) + const lastView = collaborator === readOnlyGuestAccountUuid ? maxDate : isOwn ? date : undefined + const contextId = await createContext(ctx, collaborator, cardId, date, lastView, date) return { contextId, @@ -334,7 +338,8 @@ async function createOrUpdateContext ( } const lastUpdate = context.lastUpdate == null || date > context.lastUpdate ? date : context.lastUpdate - const lastView = isOwn && isContextRead(context) ? date : undefined + const lastView = + collaborator === readOnlyGuestAccountUuid ? maxDate : isOwn && isContextRead(context) ? date : undefined return { contextId: context.id,