From b79afafa7745749f9490eaa72b4c885ef08e8143 Mon Sep 17 00:00:00 2001 From: Victor Ilyushchenko Date: Sat, 17 May 2025 00:58:25 +0300 Subject: [PATCH 1/3] EQMS-1302: fixed RBAC bypass for space / team related wizards and popups (develop port) (#8979) Signed-off-by: Victor Ilyushchenko --- plugins/contact-resources/src/utils.ts | 17 ++++++++++ plugins/contact/src/types.ts | 2 ++ .../src/components/TeamPopup.svelte | 14 ++++---- .../create-doc/steps/LocationStep.svelte | 10 +++--- .../src/components/document/DocTeam.svelte | 32 +++++++++---------- .../popups/TransferDocumentPopup.svelte | 10 +++--- .../src/utils.ts | 4 ++- 7 files changed, 55 insertions(+), 34 deletions(-) diff --git a/plugins/contact-resources/src/utils.ts b/plugins/contact-resources/src/utils.ts index 68dc0ea085..b76931500e 100644 --- a/plugins/contact-resources/src/utils.ts +++ b/plugins/contact-resources/src/utils.ts @@ -32,6 +32,7 @@ import { type PermissionsStore, type Person, type PersonsByPermission, + type MembersBySpace, type SocialIdentity } from '@hcengineering/contact' import core, { @@ -732,19 +733,33 @@ export async function resolveLocationData (loc: Location): Promise } export function checkMyPermission (_id: Ref, space: Ref, store: PermissionsStore): boolean { + const arePermissionsDisabled = getMetadata(core.metadata.DisablePermissions) ?? false + if (arePermissionsDisabled) return true return (store.whitelist.has(space) || store.ps[space]?.has(_id)) ?? false } +export function getPermittedPersons ( + _id: Ref, + space: Ref, + store: PermissionsStore +): Array> { + const arePermissionsDisabled = getMetadata(core.metadata.DisablePermissions) ?? false + if (arePermissionsDisabled) return Array.from(store.ms[space] ?? []) + return store.whitelist.has(space) ? Array.from(store.ms[space] ?? []) : Array.from(store.ap[space]?.[_id] ?? []) +} + const spacesStore = writable([]) export const permissionsStore = derived([spacesStore, personRefByAccountUuidStore], ([spaces, personRefByAccount]) => { const whitelistedSpaces = new Set>() const permissionsBySpace: PermissionsBySpace = {} const employeesByPermission: PersonsByPermission = {} + const membersBySpace: MembersBySpace = {} const client = getClient() const hierarchy = client.getHierarchy() for (const s of spaces) { + membersBySpace[s._id] = new Set(s.members.map((m) => personRefByAccount.get(m)).filter(notEmpty)) if (hierarchy.isDerived(s._class, core.class.TypedSpace)) { const type = client.getModel().findAllSync(core.class.SpaceType, { _id: (s as TypedSpace).type })[0] const mixin = type?.targetClass @@ -790,6 +805,7 @@ export const permissionsStore = derived([spacesStore, personRefByAccountUuidStor return { ps: permissionsBySpace, ap: employeesByPermission, + ms: membersBySpace, whitelist: whitelistedSpaces } }) @@ -815,6 +831,7 @@ spaceTypesQuery.query(core.class.SpaceType, {}, (types) => { projection: { _id: 1, type: 1, + members: 1, ...targetClasses } as any } diff --git a/plugins/contact/src/types.ts b/plugins/contact/src/types.ts index 334fb0f0d6..6196244546 100644 --- a/plugins/contact/src/types.ts +++ b/plugins/contact/src/types.ts @@ -52,9 +52,11 @@ export const AVATAR_COLORS: ColorDefinition[] = [ export type PermissionsBySpace = Record, Set>> export type PersonsByPermission = Record, Record, Set>>> +export type MembersBySpace = Record, Set>> export interface PermissionsStore { ps: PermissionsBySpace ap: PersonsByPermission + ms: MembersBySpace whitelist: Set> } diff --git a/plugins/controlled-documents-resources/src/components/TeamPopup.svelte b/plugins/controlled-documents-resources/src/components/TeamPopup.svelte index 359d76e06c..7a653492de 100644 --- a/plugins/controlled-documents-resources/src/components/TeamPopup.svelte +++ b/plugins/controlled-documents-resources/src/components/TeamPopup.svelte @@ -4,18 +4,18 @@ // -->