From 33f037d2c3a76096c3e2ff9f464231f902650b98 Mon Sep 17 00:00:00 2001 From: Kristina Fefelova Date: Wed, 21 Jan 2026 19:41:33 +0400 Subject: [PATCH] Allow guest update profile (avatar, name etc) Signed-off-by: Kristina Fefelova --- common/config/rush/pnpm-lock.yaml | 3 ++ .../server/packages/middleware/package.json | 1 + .../middleware/src/guestPermissions.ts | 32 ++++++++++++------- models/contact/src/index.ts | 3 +- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index db9763f98f3..52193c56b79 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -5005,6 +5005,9 @@ importers: '@hcengineering/analytics': specifier: workspace:^0.7.17 version: link:../../../core/packages/analytics + '@hcengineering/contact': + specifier: workspace:^0.7.0 + version: link:../../../../plugins/contact '@hcengineering/core': specifier: workspace:^0.7.24 version: link:../../../core/packages/core diff --git a/foundations/server/packages/middleware/package.json b/foundations/server/packages/middleware/package.json index 5e0993e37b4..08f1b540ea1 100644 --- a/foundations/server/packages/middleware/package.json +++ b/foundations/server/packages/middleware/package.json @@ -36,6 +36,7 @@ }, "dependencies": { "@hcengineering/core": "workspace:^0.7.24", + "@hcengineering/contact": "workspace:^0.7.0", "@hcengineering/platform": "workspace:^0.7.19", "@hcengineering/server-core": "workspace:^0.7.18", "@hcengineering/query": "workspace:^0.7.17", diff --git a/foundations/server/packages/middleware/src/guestPermissions.ts b/foundations/server/packages/middleware/src/guestPermissions.ts index 55fb936e0ca..13a2498807d 100644 --- a/foundations/server/packages/middleware/src/guestPermissions.ts +++ b/foundations/server/packages/middleware/src/guestPermissions.ts @@ -5,6 +5,7 @@ import { type TxMiddlewareResult } from '@hcengineering/server-core' import core, { + type Account, AccountRole, type Doc, hasAccountRole, @@ -19,6 +20,7 @@ import core, { type TxUpdateDoc } from '@hcengineering/core' import platform, { PlatformError, Severity, Status } from '@hcengineering/platform' +import contact, { type Person } from '@hcengineering/contact' export class GuestPermissionsMiddleware extends BaseMiddleware implements Middleware { static async create ( @@ -40,44 +42,44 @@ export class GuestPermissionsMiddleware extends BaseMiddleware implements Middle } for (const tx of txes) { - this.processTx(ctx, tx) + await this.processTx(ctx, tx) } return await this.provideTx(ctx, txes) } - private processTx (ctx: MeasureContext, tx: Tx): void { + private async processTx (ctx: MeasureContext, tx: Tx): Promise { const h = this.context.hierarchy if (tx._class === core.class.TxApplyIf) { const applyTx = tx as TxApplyIf for (const t of applyTx.txes) { - this.processTx(ctx, t) + await this.processTx(ctx, t) } return } if (TxProcessor.isExtendsCUD(tx._class)) { - const socialIds = ctx.contextData.account.socialIds + const { account } = ctx.contextData const cudTx = tx as TxCUD const isSpace = h.isDerived(cudTx.objectClass, core.class.Space) if (isSpace) { - if (this.isForbiddenSpaceTx(cudTx as TxCUD, socialIds)) { + if (await this.isForbiddenSpaceTx(ctx, cudTx as TxCUD, account)) { throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {})) } - } else if (cudTx.space !== core.space.DerivedTx && this.isForbiddenTx(cudTx, socialIds)) { + } else if (cudTx.space !== core.space.DerivedTx && (await this.isForbiddenTx(ctx, cudTx, account))) { throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {})) } } } - private isForbiddenTx (tx: TxCUD, socialIds: PersonId[]): boolean { + private async isForbiddenTx (ctx: MeasureContext, tx: TxCUD, account: Account): Promise { if (tx._class === core.class.TxMixin) return false - return !this.hasMixinAccessLevel(tx, socialIds) + return !(await this.hasMixinAccessLevel(ctx, tx, account)) } - private isForbiddenSpaceTx (tx: TxCUD, socialIds: PersonId[]): boolean { + private async isForbiddenSpaceTx (ctx: MeasureContext, tx: TxCUD, account: Account): Promise { if (tx._class === core.class.TxRemoveDoc) return true if (tx._class === core.class.TxCreateDoc) { - return !this.hasMixinAccessLevel(tx, socialIds) + return !(await this.hasMixinAccessLevel(ctx, tx, account)) } if (tx._class === core.class.TxUpdateDoc) { const updateTx = tx as TxUpdateDoc @@ -93,7 +95,7 @@ export class GuestPermissionsMiddleware extends BaseMiddleware implements Middle return false } - private hasMixinAccessLevel (tx: TxCUD, socialIds: PersonId[]): boolean { + private async hasMixinAccessLevel (ctx: MeasureContext, tx: TxCUD, account: Account): Promise { const h = this.context.hierarchy const accessLevelMixin = h.classHierarchyMixin(tx.objectClass, core.mixin.TxAccessLevel) if (accessLevelMixin === undefined) return false @@ -104,9 +106,15 @@ export class GuestPermissionsMiddleware extends BaseMiddleware implements Middle return accessLevelMixin.removeAccessLevel === AccountRole.Guest } if (tx._class === core.class.TxUpdateDoc) { - if (accessLevelMixin.isIdentity === true && socialIds.includes(tx.objectId as unknown as PersonId)) { + if (accessLevelMixin.isIdentity === true && account.socialIds.includes(tx.objectId as unknown as PersonId)) { return true } + if (accessLevelMixin.isIdentity === true && h.isDerived(tx.objectClass, contact.class.Person)) { + const person = (await this.findAll(ctx, tx.objectClass, { _id: tx.objectId }, { limit: 1 }))[0] as + | Person + | undefined + return person?.personUuid === account.uuid + } return accessLevelMixin.updateAccessLevel === AccountRole.Guest } return false diff --git a/models/contact/src/index.ts b/models/contact/src/index.ts index cc639f0501f..0cfeacf2dbd 100644 --- a/models/contact/src/index.ts +++ b/models/contact/src/index.ts @@ -325,7 +325,8 @@ export function createModel (builder: Builder): void { }) builder.mixin(contact.class.Person, core.class.Class, core.mixin.TxAccessLevel, { - createAccessLevel: AccountRole.Guest + createAccessLevel: AccountRole.Guest, + isIdentity: true }) builder.mixin(contact.class.SocialIdentity, core.class.Class, core.mixin.TxAccessLevel, {