diff --git a/plugins/card-resources/src/components/CardAttributes.svelte b/plugins/card-resources/src/components/CardAttributes.svelte index 78c2d100fe6..de71079ac26 100644 --- a/plugins/card-resources/src/components/CardAttributes.svelte +++ b/plugins/card-resources/src/components/CardAttributes.svelte @@ -15,8 +15,8 @@ @@ -70,7 +69,7 @@ {_class} {object} {showHeader} - readonly={readonly || checkForbiddenPermission(key.attr, $permissionsStore)} + readonly={readonly || !canChange(key.attr, $permissionsStore)} withIcon on:update /> diff --git a/plugins/card-resources/src/components/EditCardNew.svelte b/plugins/card-resources/src/components/EditCardNew.svelte index e19146c9b08..837686acd72 100644 --- a/plugins/card-resources/src/components/EditCardNew.svelte +++ b/plugins/card-resources/src/components/EditCardNew.svelte @@ -49,6 +49,7 @@ import ParentNamesPresenter from './ParentNamesPresenter.svelte' import { openCardInSidebar } from '../utils' import { afterUpdate } from 'svelte' + import { canChangeDoc, permissionsStore } from '@hcengineering/contact-resources' export let _id: Ref export let readonly: boolean = false @@ -152,6 +153,7 @@ }) $: _readonly = (readonly || doc?.readonly) ?? false + $: updatePermissionForbidden = doc && !canChangeDoc(doc?._class, doc?.space, $permissionsStore) @@ -179,7 +181,7 @@
- {#if !_readonly} + {#if !_readonly && !updatePermissionForbidden} - + diff --git a/plugins/card-resources/src/components/EditCardOld.svelte b/plugins/card-resources/src/components/EditCardOld.svelte index 7cf8cdbc39a..0b34b4ba4b7 100644 --- a/plugins/card-resources/src/components/EditCardOld.svelte +++ b/plugins/card-resources/src/components/EditCardOld.svelte @@ -42,6 +42,7 @@ import Childs from './Childs.svelte' import Content from './Content.svelte' import TagsEditor from './TagsEditor.svelte' + import { canChangeDoc, permissionsStore } from '@hcengineering/contact-resources' export let _id: Ref export let readonly: boolean = false @@ -87,6 +88,7 @@ }) $: _readonly = (readonly || doc?.readonly) ?? false + $: updatePermissionForbidden = doc && !canChangeDoc(doc?._class, doc?.space, $permissionsStore) $: canSave = title.trim().length > 0 && !_readonly async function saveTitle (ev: Event): Promise { @@ -161,14 +163,20 @@
- saveTitle(evt)} /> + saveTitle(evt)} + />
- + - +
- + {#if !_readonly} diff --git a/plugins/card-resources/src/components/TagAttributes.svelte b/plugins/card-resources/src/components/TagAttributes.svelte index f1917a45905..74271af45ae 100644 --- a/plugins/card-resources/src/components/TagAttributes.svelte +++ b/plugins/card-resources/src/components/TagAttributes.svelte @@ -14,13 +14,13 @@ --> {#if contentDiv != null}
- +
{/if} diff --git a/plugins/contact-resources/src/utils.ts b/plugins/contact-resources/src/utils.ts index 967117fe85e..2945a942b96 100644 --- a/plugins/contact-resources/src/utils.ts +++ b/plugins/contact-resources/src/utils.ts @@ -53,6 +53,7 @@ import { import core, { type AccountUuid, type AggregateValue, + type AnyAttribute, type Class, type Client, type Doc, @@ -670,6 +671,58 @@ export function checkMyPermission (_id: Ref, space: Ref, return (store.whitelist.has(space) || store.ps[space]?.has(_id)) ?? false } +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 + } + + return canChangeDoc(_class ?? attr.attributeOf, 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 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 getPermittedPersons ( _id: Ref, space: Ref, @@ -686,6 +739,7 @@ export const permissionsStore = derived( [spacesStore, employeeRefByAccountUuidStore], ([spaces, personRefByAccount]) => { const whitelistedSpaces = new Set>() + const restrictedSpaces = new Set>() const permissionsBySpace: PermissionsBySpace = {} const employeesByPermission: PersonsByPermission = {} const membersBySpace: MembersBySpace = {} @@ -695,6 +749,10 @@ export const permissionsStore = derived( 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 typedSpace = s as TypedSpace + if (typedSpace.restricted === true) { + restrictedSpaces.add(s._id) + } const type = client.getModel().findAllSync(core.class.SpaceType, { _id: (s as TypedSpace).type })[0] const mixin = type?.targetClass @@ -740,7 +798,8 @@ export const permissionsStore = derived( ps: permissionsBySpace, ap: employeesByPermission, ms: membersBySpace, - whitelist: whitelistedSpaces + whitelist: whitelistedSpaces, + restrictedSpaces } } ) diff --git a/plugins/contact/src/types.ts b/plugins/contact/src/types.ts index 61962445463..c5fa89b182a 100644 --- a/plugins/contact/src/types.ts +++ b/plugins/contact/src/types.ts @@ -58,6 +58,7 @@ export interface PermissionsStore { ap: PersonsByPermission ms: MembersBySpace whitelist: Set> + restrictedSpaces: Set> } export type UserProfile = Card & { person: Ref } diff --git a/plugins/process-resources/src/components/ProcessesHeaderExtension.svelte b/plugins/process-resources/src/components/ProcessesHeaderExtension.svelte index eb094826f4e..c549313f386 100644 --- a/plugins/process-resources/src/components/ProcessesHeaderExtension.svelte +++ b/plugins/process-resources/src/components/ProcessesHeaderExtension.svelte @@ -27,14 +27,13 @@ let todos: ProcessToDo[] = [] const executionQuery = createQuery() - executionQuery.query( + $: executionQuery.query( process.class.Execution, { card: card._id, status: { $ne: ExecutionStatus.Cancelled } }, (res) => { - console.log(res) docs = res } )