Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions plugins/card-resources/src/components/CardAttributes.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
<script lang="ts">
import { Card } from '@hcengineering/card'
import { PermissionsStore } from '@hcengineering/contact'
import { checkMyPermission, permissionsStore } from '@hcengineering/contact-resources'
import core, { AnyAttribute, Class, Doc, Permission, Ref, toRank, TypedSpace } from '@hcengineering/core'
import { canChangeAttribute, permissionsStore } from '@hcengineering/contact-resources'
import core, { AnyAttribute, Class, Doc, Ref, toRank, TypedSpace } from '@hcengineering/core'
import {
AttributeBarEditor,
createQuery,
Expand Down Expand Up @@ -57,9 +57,8 @@
updateKeys(_class, ignoreKeys, to)
})

function checkForbiddenPermission (attr: AnyAttribute, permissionsStore: PermissionsStore): boolean {
const _id = `${attr._id}_forbidden` as Ref<Permission>
return checkMyPermission(_id, object.space as Ref<TypedSpace>, permissionsStore)
function canChange (attr: AnyAttribute, permissionsStore: PermissionsStore): boolean {
return canChangeAttribute(attr, object.space as Ref<TypedSpace>, permissionsStore)
}
</script>

Expand All @@ -70,7 +69,7 @@
{_class}
{object}
{showHeader}
readonly={readonly || checkForbiddenPermission(key.attr, $permissionsStore)}
readonly={readonly || !canChange(key.attr, $permissionsStore)}
withIcon
on:update
/>
Expand Down
6 changes: 4 additions & 2 deletions plugins/card-resources/src/components/EditCardNew.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -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<Card>
export let readonly: boolean = false
Expand Down Expand Up @@ -152,6 +153,7 @@
})

$: _readonly = (readonly || doc?.readonly) ?? false
$: updatePermissionForbidden = doc && !canChangeDoc(doc?._class, doc?.space, $permissionsStore)
</script>

<FocusHandler {manager} />
Expand Down Expand Up @@ -179,7 +181,7 @@
<svelte:fragment slot="title">
<ParentNamesPresenter value={doc} maxWidth={'12rem'} compact={!expandedParents} />
<div class="title flex-row-center">
{#if !_readonly}
{#if !_readonly && !updatePermissionForbidden}
<EditBox
focusIndex={1}
bind:value={title}
Expand Down Expand Up @@ -267,7 +269,7 @@
card: doc
}}
/>
<TagsEditor {doc} {dropdownTags} id={'cardHeader-tags'} />
<TagsEditor {doc} {dropdownTags} readonly={_readonly} id={'cardHeader-tags'} />
<slot name="extra" />
</svelte:fragment>

Expand Down
22 changes: 18 additions & 4 deletions plugins/card-resources/src/components/EditCardOld.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -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<Card>
export let readonly: boolean = false
Expand Down Expand Up @@ -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<void> {
Expand Down Expand Up @@ -161,14 +163,20 @@

<div class="container">
<div class="title flex-row-center">
<EditBox focusIndex={1} bind:value={title} placeholder={card.string.Card} on:blur={(evt) => saveTitle(evt)} />
<EditBox
focusIndex={1}
bind:value={title}
disabled={_readonly || updatePermissionForbidden}
placeholder={card.string.Card}
on:blur={(evt) => saveTitle(evt)}
/>
</div>

<TagsEditor {doc} />
<TagsEditor {doc} readonly={_readonly} />

<CardAttributeEditor value={doc} {mixins} readonly={_readonly} ignoreKeys={['title', 'content', 'parent']} />

<Content {doc} readonly={_readonly} bind:content />
<Content {doc} readonly={_readonly || updatePermissionForbidden} bind:content />
</div>

<ComponentExtensions
Expand All @@ -181,7 +189,13 @@
<Childs object={doc} readonly={_readonly} />
<RelationsEditor object={doc} readonly={_readonly} />

<Attachments objectId={doc._id} _class={doc._class} space={doc.space} attachments={doc.attachments ?? 0} />
<Attachments
objectId={doc._id}
_class={doc._class}
space={doc.space}
readonly={_readonly}
attachments={doc.attachments ?? 0}
/>

<svelte:fragment slot="utils">
{#if !_readonly}
Expand Down
3 changes: 1 addition & 2 deletions plugins/card-resources/src/components/TagAttributes.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
-->
<script lang="ts">
import { Card, Tag } from '@hcengineering/card'
import { AccountRole, getCurrentAccount, hasAccountRole } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import setting, { settingId } from '@hcengineering/setting'
import {
Button,
Chevron,
ExpandCollapse,
getColorNumberByText,
getCurrentResolvedLocation,
getPlatformColorDef,
IconAdd,
Expand All @@ -31,7 +31,6 @@
tooltip
} from '@hcengineering/ui'
import CardAttributes from './CardAttributes.svelte'
import { AccountRole, getCurrentAccount, hasAccountRole } from '@hcengineering/core'

export let value: Card
export let tag: Tag
Expand Down
6 changes: 4 additions & 2 deletions plugins/card-resources/src/components/TagsEditor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
export let doc: Card
export let dropdownTags: boolean = false
export let id: string | undefined = undefined
export let readonly: boolean = false

const client = getClient()
const hierarchy = client.getHierarchy()
Expand Down Expand Up @@ -131,15 +132,16 @@
/>
{:else}
{#each activeTags as mixin}
{@const removable = isRemoveable(mixin._id, activeTags) && !checkRemovePermission($permissionsStore)}
{@const removable =
!readonly && isRemoveable(mixin._id, activeTags) && !checkRemovePermission($permissionsStore)}
<CardTagColored
labelIntl={mixin.label}
color={mixin.background ?? 0}
{removable}
on:remove={() => removeTag(mixin._id)}
/>
{/each}
{#if dropdownItems.length > 0 && !checkAddPermission($permissionsStore)}
{#if !readonly && dropdownItems.length > 0 && !checkAddPermission($permissionsStore)}
<CircleButton id={id ? `${id}-add` : undefined} icon={IconAdd} size={'small'} ghost on:click={add} />
{/if}
{/if}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import Content from '../Content.svelte'
import { CardSectionAction } from '../../types'
import { canChangeDoc, permissionsStore } from '@hcengineering/contact-resources'

export let readonly: boolean = false
export let doc: Card
Expand All @@ -42,11 +43,20 @@
onMount(() => {
dispatch('action', { id: 'toc', toc: [] })
})

$: updatePermissionForbidden = doc && !canChangeDoc(doc?._class, doc?.space, $permissionsStore)
</script>

{#if contentDiv != null}
<div class="content" class:hidden>
<Content {doc} {readonly} content={contentDiv} showToc={false} on:loaded on:headings={handleHeadings} />
<Content
{doc}
readonly={readonly || updatePermissionForbidden}
content={contentDiv}
showToc={false}
on:loaded
on:headings={handleHeadings}
/>
</div>
{/if}

Expand Down
61 changes: 60 additions & 1 deletion plugins/contact-resources/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {
import core, {
type AccountUuid,
type AggregateValue,
type AnyAttribute,
type Class,
type Client,
type Doc,
Expand Down Expand Up @@ -670,6 +671,58 @@ export function checkMyPermission (_id: Ref<Permission>, space: Ref<TypedSpace>,
return (store.whitelist.has(space) || store.ps[space]?.has(_id)) ?? false
}

export function canChangeAttribute (
attr: AnyAttribute,
space: Ref<TypedSpace>,
store: PermissionsStore,
_class?: Ref<Class<Doc>>
): 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<Permission>
const forbidden = store.ps[space]?.has(forbiddenId)
if (forbidden) {
return false
}
const allowedId = `${attr._id}_allowed` as Ref<Permission>
const allowed = store.ps[space]?.has(allowedId)
if (allowed) {
return true
}

return canChangeDoc(_class ?? attr.attributeOf, space, store)
}

export function canChangeDoc (_class: Ref<Class<Doc>>, space: Ref<Space>, 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<Permission>,
space: Ref<TypedSpace>,
Expand All @@ -686,6 +739,7 @@ export const permissionsStore = derived(
[spacesStore, employeeRefByAccountUuidStore],
([spaces, personRefByAccount]) => {
const whitelistedSpaces = new Set<Ref<Space>>()
const restrictedSpaces = new Set<Ref<Space>>()
const permissionsBySpace: PermissionsBySpace = {}
const employeesByPermission: PersonsByPermission = {}
const membersBySpace: MembersBySpace = {}
Expand All @@ -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

Expand Down Expand Up @@ -740,7 +798,8 @@ export const permissionsStore = derived(
ps: permissionsBySpace,
ap: employeesByPermission,
ms: membersBySpace,
whitelist: whitelistedSpaces
whitelist: whitelistedSpaces,
restrictedSpaces
}
}
)
Expand Down
1 change: 1 addition & 0 deletions plugins/contact/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export interface PermissionsStore {
ap: PersonsByPermission
ms: MembersBySpace
whitelist: Set<Ref<Space>>
restrictedSpaces: Set<Ref<Space>>
}

export type UserProfile = Card & { person: Ref<Person> }
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
)
Expand Down
Loading