import { type PermissionsStore } from '@hcengineering/contact' import core, { type AnyAttribute, type Class, type Doc, type Permission, type Ref, type Space, type TypedSpace } from '@hcengineering/core' import { getMetadata } from '@hcengineering/platform' import { getClient } from '@hcengineering/presentation' export function canChangeAttribute ( attr: AnyAttribute, space: Ref, store: PermissionsStore, _class: Ref> ): boolean { const arePermissionsDisabled = getMetadata(core.metadata.DisablePermissions) ?? false if (arePermissionsDisabled) return true if (store.whitelist.has(space)) return true const forbiddenId = `${attr._id}_forbidden` as Ref const forbidden = store.ps[space]?.has(forbiddenId) if (forbidden) { return false } const allowedId = `${attr._id}_allowed` as Ref const allowed = store.ps[space]?.has(allowedId) if (allowed) { return true } const target = attr.attributeOf const forbiddenClId = `${target}_forbidden` as Ref const forbiddenCl = store.ps[space]?.has(forbiddenClId) if (forbiddenCl) { return false } const allowedClId = `${target}_allowed` as Ref const allowedCl = store.ps[space]?.has(allowedClId) if (allowedCl) { return true } return canChangeDoc(_class, space, store) } export function canChangeDoc (_class: Ref>, space: Ref, store: PermissionsStore): boolean { const arePermissionsDisabled = getMetadata(core.metadata.DisablePermissions) ?? false if (arePermissionsDisabled) return true if (store.whitelist.has(space)) return true if (store.ps[space] !== undefined) { const forbiddenClId = `${_class}_forbidden` as Ref const forbiddenCl = store.ps[space]?.has(forbiddenClId) if (forbiddenCl) { return false } const allowedClId = `${_class}_allowed` as Ref const allowedCl = store.ps[space]?.has(allowedClId) if (allowedCl) { return true } const client = getClient() const h = client.getHierarchy() const ancestors = h.getAncestors(_class) const permissions = client .getModel() .findAllSync(core.class.Permission, { txClass: { $in: [core.class.TxUpdateDoc, core.class.TxMixin] } }) for (const ancestor of ancestors) { const curr = permissions.filter( (p) => p.objectClass === ancestor && p.txMatch === undefined && p.txClass === (h.isMixin(ancestor) ? core.class.TxMixin : core.class.TxUpdateDoc) ) for (const permission of curr) { if (store.ps[space]?.has(permission._id)) { return permission.forbid !== true } } } } return !store.restrictedSpaces.has(space) } export function canRemoveDoc (_class: Ref>, space: Ref, store: PermissionsStore): boolean { const arePermissionsDisabled = getMetadata(core.metadata.DisablePermissions) ?? false if (arePermissionsDisabled) return true if (store.whitelist.has(space)) return true if (store.ps[space] !== undefined) { const client = getClient() const h = client.getHierarchy() const ancestors = h.getAncestors(_class) const permissions = client.getModel().findAllSync(core.class.Permission, { txClass: core.class.TxRemoveDoc }) for (const ancestor of ancestors) { const curr = permissions.filter((p) => p.objectClass === ancestor && p.txMatch === undefined) for (const permission of curr) { if (store.ps[space]?.has(permission._id)) { return permission.forbid !== true } } } } return !store.restrictedSpaces.has(space) } export function canCreateObject (_class: Ref>, space: Ref, store: PermissionsStore): boolean { const arePermissionsDisabled = getMetadata(core.metadata.DisablePermissions) ?? false if (arePermissionsDisabled) return true if (store.whitelist.has(space)) return true if (store.ps[space] !== undefined) { const client = getClient() const h = client.getHierarchy() const ancestors = h.getAncestors(_class) const permissions = client.getModel().findAllSync(core.class.Permission, { txClass: core.class.TxCreateDoc }) for (const ancestor of ancestors) { const curr = permissions.filter((p) => p.objectClass === ancestor && p.txMatch === undefined) for (const permission of curr) { if (store.ps[space]?.has(permission._id)) { return permission.forbid !== true } } } } return !store.restrictedSpaces.has(space) }