From ce016bf93389a20e331ec1cc64cbf918b7bebc9f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 10 May 2024 13:51:58 +0200 Subject: [PATCH] add recycle bin conditions for media + document root access --- .../models/menu-item.model.ts | 7 +++-- .../allow-document-recycle-bin.condition.ts | 25 ++++++++++++++++++ .../documents/recycle-bin/manifests.ts | 6 +++++ .../recycle-bin/menu-item/manifests.ts | 5 ++++ .../allow-media-recycle-bin.condition.ts | 25 ++++++++++++++++++ .../media/media/recycle-bin/manifests.ts | 6 +++++ .../media/recycle-bin/menu-item/manifests.ts | 5 ++++ .../user/current-user/current-user.context.ts | 2 ++ .../current-user.server.data-source.ts | 26 ++++++++++--------- .../src/packages/user/current-user/types.ts | 24 +++++++++-------- 10 files changed, 106 insertions(+), 25 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/allow-document-recycle-bin.condition.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/allow-media-recycle-bin.condition.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/menu-item.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/menu-item.model.ts index 3efd308a9a..05eeb81b78 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/menu-item.model.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/menu-item.model.ts @@ -1,7 +1,10 @@ import type { UmbMenuItemElement } from '../interfaces/menu-item-element.interface.js'; -import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api'; +import type { ConditionTypes } from '../conditions/types.js'; +import type { ManifestWithDynamicConditions, ManifestElement } from '@umbraco-cms/backoffice/extension-api'; -export interface ManifestMenuItem extends ManifestElement { +export interface ManifestMenuItem + extends ManifestElement, + ManifestWithDynamicConditions { type: 'menuItem'; meta: MetaMenuItem; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/allow-document-recycle-bin.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/allow-document-recycle-bin.condition.ts new file mode 100644 index 0000000000..bdd03fd190 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/allow-document-recycle-bin.condition.ts @@ -0,0 +1,25 @@ +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { + UmbConditionConfigBase, + UmbConditionControllerArguments, + UmbExtensionCondition, +} from '@umbraco-cms/backoffice/extension-api'; +import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user'; + +export class UmbAllowDocumentRecycleBinCurrentUserCondition + extends UmbConditionBase + implements UmbExtensionCondition +{ + constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { + super(host, args); + + this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { + this.observe(context.hasDocumentRootAccess, (hasAccess) => { + this.permitted = hasAccess === true; + }); + }); + } +} + +export { UmbAllowDocumentRecycleBinCurrentUserCondition as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts index a97b720238..af9255f13c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts @@ -5,6 +5,12 @@ import { manifests as treeManifests } from './tree/manifests.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ + { + type: 'condition', + name: 'Allow Document Recycle Bin Current User Condition', + alias: 'Umb.Condition.CurrentUser.AllowDocumentRecycleBin', + api: () => import('./allow-document-recycle-bin.condition.js'), + }, ...entityActionManifests, ...menuItemManifests, ...repositoryManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu-item/manifests.ts index 27ade54b9d..fb27a67276 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu-item/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu-item/manifests.ts @@ -14,6 +14,11 @@ const menuItem: ManifestMenuItemTreeKind = { icon: 'icon-trash', menus: [UMB_CONTENT_MENU_ALIAS], }, + conditions: [ + { + alias: 'Umb.Condition.CurrentUser.AllowDocumentRecycleBin', + }, + ], }; export const manifests: Array = [menuItem]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/allow-media-recycle-bin.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/allow-media-recycle-bin.condition.ts new file mode 100644 index 0000000000..ca5f74bda2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/allow-media-recycle-bin.condition.ts @@ -0,0 +1,25 @@ +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { + UmbConditionConfigBase, + UmbConditionControllerArguments, + UmbExtensionCondition, +} from '@umbraco-cms/backoffice/extension-api'; +import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user'; + +export class UmbAllowMediaRecycleBinCurrentUserCondition + extends UmbConditionBase + implements UmbExtensionCondition +{ + constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { + super(host, args); + + this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { + this.observe(context.hasMediaRootAccess, (hasAccess) => { + this.permitted = hasAccess === true; + }); + }); + } +} + +export { UmbAllowMediaRecycleBinCurrentUserCondition as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/manifests.ts index a97b720238..8cf3e41fb1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/manifests.ts @@ -5,6 +5,12 @@ import { manifests as treeManifests } from './tree/manifests.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ + { + type: 'condition', + name: 'Allow Media Recycle Bin Current User Condition', + alias: 'Umb.Condition.CurrentUser.AllowMediaRecycleBin', + api: () => import('./allow-media-recycle-bin.condition.js'), + }, ...entityActionManifests, ...menuItemManifests, ...repositoryManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu-item/manifests.ts index dda0653c7f..8155c5c801 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu-item/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu-item/manifests.ts @@ -14,6 +14,11 @@ const menuItem: ManifestMenuItemTreeKind = { icon: 'icon-trash', menus: [UMB_MEDIA_MENU_ALIAS], }, + conditions: [ + { + alias: 'Umb.Condition.CurrentUser.AllowMediaRecycleBin', + }, + ], }; export const manifests: Array = [menuItem]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts index 2faa82b6ff..69e0d1cd18 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts @@ -14,6 +14,8 @@ export class UmbCurrentUserContext extends UmbContextBase readonly unique = this.#currentUser.asObservablePart((user) => user?.unique); readonly languageIsoCode = this.#currentUser.asObservablePart((user) => user?.languageIsoCode); + readonly hasDocumentRootAccess = this.#currentUser.asObservablePart((user) => user?.hasDocumentRootAccess); + readonly hasMediaRootAccess = this.#currentUser.asObservablePart((user) => user?.hasMediaRootAccess); #authContext?: typeof UMB_AUTH_CONTEXT.TYPE; #currentUserRepository = new UmbCurrentUserRepository(this); diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.server.data-source.ts index 46bfc12a3c..60ec6d51c4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.server.data-source.ts @@ -30,20 +30,22 @@ export class UmbCurrentUserServerDataSource { if (data) { const user: UmbCurrentUserModel = { - unique: data.id, - email: data.email, - userName: data.userName, - name: data.name, - languageIsoCode: data.languageIsoCode || 'en-us', // TODO: make global variable - documentStartNodeUniques: data.documentStartNodeIds, - mediaStartNodeUniques: data.mediaStartNodeIds, - avatarUrls: data.avatarUrls, - languages: data.languages, - hasAccessToAllLanguages: data.hasAccessToAllLanguages, - fallbackPermissions: data.fallbackPermissions, - permissions: data.permissions, allowedSections: data.allowedSections, + avatarUrls: data.avatarUrls, + documentStartNodeUniques: data.documentStartNodeIds, + email: data.email, + fallbackPermissions: data.fallbackPermissions, + hasAccessToAllLanguages: data.hasAccessToAllLanguages, + hasDocumentRootAccess: data.hasDocumentRootAccess, + hasMediaRootAccess: data.hasMediaRootAccess, isAdmin: data.isAdmin, + languageIsoCode: data.languageIsoCode || 'en-us', // TODO: make global variable + languages: data.languages, + mediaStartNodeUniques: data.mediaStartNodeIds, + name: data.name, + permissions: data.permissions, + unique: data.id, + userName: data.userName, }; return { data: user }; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts index ba8898ade5..e480087911 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts @@ -7,20 +7,22 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; export interface UmbCurrentUserModel { - unique: string; - email: string; - userName: string; - name: string; - languageIsoCode: string; - documentStartNodeUniques: Array; - mediaStartNodeUniques: Array; - avatarUrls: Array; - languages: Array; - hasAccessToAllLanguages: boolean; allowedSections: Array; + avatarUrls: Array; + documentStartNodeUniques: Array; + email: string; fallbackPermissions: Array; - permissions: Array; + hasAccessToAllLanguages: boolean; + hasDocumentRootAccess: boolean; + hasMediaRootAccess: boolean; isAdmin: boolean; + languageIsoCode: string; + languages: Array; + mediaStartNodeUniques: Array; + name: string; + permissions: Array; + unique: string; + userName: string; } export type UmbCurrentUserMfaProviderModel = UserTwoFactorProviderModel;