From ce016bf93389a20e331ec1cc64cbf918b7bebc9f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 10 May 2024 13:51:58 +0200 Subject: [PATCH 01/13] 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; From 72a83370f346a6679dae0f4e33f5b15750f123ef Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 10 May 2024 15:14:36 +0200 Subject: [PATCH 02/13] move extension components --- src/Umbraco.Web.UI.Client/src/packages/core/components/index.ts | 2 -- src/Umbraco.Web.UI.Client/src/packages/core/entry-point.ts | 1 + .../components/extension-slot/extension-slot.element.ts | 2 +- .../components/extension-slot/extension-slot.test.ts | 0 .../{ => extension-registry}/components/extension-slot/index.ts | 0 .../extension-with-api-slot/extension-with-api-slot.element.ts | 2 +- .../extension-with-api-slot/extension-with-api-slot.test.ts | 0 .../components/extension-with-api-slot/index.ts | 0 .../src/packages/core/extension-registry/components/index.ts | 2 ++ .../src/packages/core/property/property/property.element.ts | 2 +- 10 files changed, 6 insertions(+), 5 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/core/{ => extension-registry}/components/extension-slot/extension-slot.element.ts (98%) rename src/Umbraco.Web.UI.Client/src/packages/core/{ => extension-registry}/components/extension-slot/extension-slot.test.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{ => extension-registry}/components/extension-slot/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{ => extension-registry}/components/extension-with-api-slot/extension-with-api-slot.element.ts (98%) rename src/Umbraco.Web.UI.Client/src/packages/core/{ => extension-registry}/components/extension-with-api-slot/extension-with-api-slot.test.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{ => extension-registry}/components/extension-with-api-slot/index.ts (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/index.ts index 789608dba4..7d6646a4f4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/index.ts @@ -6,8 +6,6 @@ export * from './body-layout/body-layout.element.js'; export * from './code-block/index.js'; export * from './dropdown/index.js'; export * from './entity-actions-bundle/index.js'; -export * from './extension-slot/index.js'; -export * from './extension-with-api-slot/index.js'; export * from './footer-layout/index.js'; export * from './header-app/index.js'; export * from './history/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entry-point.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entry-point.ts index 1f88e46d6a..912cee601d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entry-point.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entry-point.ts @@ -8,6 +8,7 @@ import { UmbExtensionsApiInitializer, type UmbEntryPointOnInit } from '@umbraco- // TODO temp relative import until modules ship a component sub module import './menu/components/index.js'; +import './extension-registry/components/index.js'; export const onInit: UmbEntryPointOnInit = (host, extensionRegistry) => { new UmbExtensionsApiInitializer(host, extensionRegistry, 'globalContext', [host]); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts similarity index 98% rename from src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts index a09e8f9bf0..303a5d397a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts @@ -1,4 +1,4 @@ -import { umbExtensionsRegistry } from '../../extension-registry/index.js'; +import { umbExtensionsRegistry } from '../../registry.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { TemplateResult } from '@umbraco-cms/backoffice/external/lit'; import { css, repeat, customElement, property, state, html } from '@umbraco-cms/backoffice/external/lit'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.test.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.test.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.test.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts similarity index 98% rename from src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts index e056b60241..45199b6099 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts @@ -1,4 +1,4 @@ -import { umbExtensionsRegistry } from '../../extension-registry/index.js'; +import { umbExtensionsRegistry } from '../../registry.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { TemplateResult } from '@umbraco-cms/backoffice/external/lit'; import { css, repeat, customElement, property, state, html } from '@umbraco-cms/backoffice/external/lit'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.test.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.test.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.test.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/index.ts new file mode 100644 index 0000000000..4f454594ee --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/index.ts @@ -0,0 +1,2 @@ +export * from './extension-slot/index.js'; +export * from './extension-with-api-slot/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts index e6397911a7..3c780449af 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts @@ -1,5 +1,5 @@ -import { umbExtensionsRegistry, type ManifestPropertyEditorUi } from '../../extension-registry/index.js'; import { UmbPropertyContext } from './property.context.js'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, property, state, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit'; import { createExtensionElement } from '@umbraco-cms/backoffice/extension-api'; From f8fab3a3a75d8d3b92a97a839226f002fa7992ad Mon Sep 17 00:00:00 2001 From: JesmoDev <26099018+JesmoDev@users.noreply.github.com> Date: Tue, 14 May 2024 17:14:45 +0200 Subject: [PATCH 03/13] language back button and cleanup --- .../language/language-workspace-editor.element.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace-editor.element.ts index fa5bc5f053..4d2c558e03 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace-editor.element.ts @@ -45,11 +45,10 @@ export class UmbLanguageWorkspaceEditorElement extends UmbLitElement { } render() { - return html` + return html`