From d65fa04d284fe52194df86c21898dc69530943c7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 25 Mar 2025 14:43:53 +0100 Subject: [PATCH 1/4] Create ui-property-permissions.md --- .../customizing/ui-property-permissions.md | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 15/umbraco-cms/customizing/ui-property-permissions.md diff --git a/15/umbraco-cms/customizing/ui-property-permissions.md b/15/umbraco-cms/customizing/ui-property-permissions.md new file mode 100644 index 00000000000..0d77f2f74f3 --- /dev/null +++ b/15/umbraco-cms/customizing/ui-property-permissions.md @@ -0,0 +1,164 @@ +# UI Property Permissions + +The UI Property Permissions are used to restrict access to specific properties in the Backoffice UI. + +## Document Property Value User Permissions + +Out of the box, Umbraco provides a feature called Document Property Value User Permissions.This feature can restrict access to specific Document property values for certain user groups. By default, all the built-in User Groups have read and write permissions for all properties. However, you can limit a User Group's permissions specific properties through the UI. + +If a User Group does not have write access to a property, the property will be read-only for that User Group. If a User Group does not have read access to a property, the property will be hidden from that User Group. + +Be aware that the Document Property Value User Permissions are not enforced on the server-side. This means that a user can still access the property value through the API, even if the property is restricted in the UI. + +## Extending the Document Property Value User Permission with additional restrictions + +In addition to the User Permission logic, it is possible to add further restrictions to properties. This can be achieved through the `propertyReadOnlyState`-Manager available in property based Workspace Context. In the following example, we will make all invariant properties read-only. + +## Register a Workspace Context + +Register a [Workspace Context](./extending-overview/extension-types/workspaces/workspace-context.md) to append additional restrictions to properties. + +**Manifest** + +```ts +import { UMB_WORKSPACE_CONDITION_ALIAS } from "@umbraco-cms/backoffice/workspace"; +import { UMB_WORKSPACE_CONDITION_ALIAS } from "@umbraco-cms/backoffice/document"; + +const manifest: UmbExtensionManifest = { + type: "workspaceContext", + name: "My Document Property Permission Workspace Context", + alias: "My.WorkspaceContext.DocumentPropertyPermission", + api: () => import("./my-document-property-permission.workspace-context.js"), + conditions: [ + { + alias: UMB_WORKSPACE_CONDITION_ALIAS, + match: UMB_DOCUMENT_WORKSPACE_ALIAS, + }, + ], +}; +``` + +## Implement custom logic for Property Value Permissions + +Implement custom logic to identify all properties and add a read-only state for each one. To target a property, we use its unique identifier along with the variant ID that corresponds to that property. In the following example, we will focus specifically on the invariant properties. + +**Workspace Context** + +```ts +import { UmbControllerBase } from "@umbraco-cms/backoffice/class-api"; +import type { UmbControllerHost } from "@umbraco-cms/backoffice/controller-api"; +import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from "@umbraco-cms/backoffice/document"; +import { UmbVariantId } from "@umbraco-cms/backoffice/variant"; + +export class MyDocumentPropertyPermissionWorkspaceContext extends UmbControllerBase { + constructor(host: UmbControllerHost) { + super(host); + + // Consume the document workspace context + this.consumeContext( + UMB_DOCUMENT_WORKSPACE_CONTEXT, + this.#observeStructure + ); + } + + #observeStructure(context: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE) { + if (!context) return; + + // Observe all properties for the Content Type + this.observe(context.structure.contentTypeProperties, (properties) => { + if (properties.length === 0) return; + + // Create a new variant ID for the invariant properties + const invariantId = new UmbVariantId(); + + // Create a read-only state for each property + const states = properties.map((property) => { + return { + unique: + "MY_INVARIANT_PROPERTY_RESTRICTION_" + property.unique, + message: + "The property is read only because of my restriction", + propertyType: { + unique: property.unique, + variantId: invariantId, + }, + }; + }); + + // Add the read-only states to the property read-only state manager + context.structure.propertyReadOnlyState.addStates(states); + }); + } +} + +export { MyDocumentPropertyPermissionWorkspaceContext as api }; +``` + +## Custom logic For Property value permissions + +It is also possible to implement completely custom UI logic for managing property value permissions. To do this, you first need to remove the default read and write access to properties for the user group. As a result, all properties will be hidden from that user group. Afterward, you can create custom logic to determine whether a specific user group should have access to particular properties. + +We follow the same concept as the previous example, but instead of writing to the `propertyReadOnlyState`-Manager, we can use the `propertyViewState`-Manager and the `propertyWriteState`-Manager to control the view- and writability of properties. + +In the following example we will hide a specific property based on the propertyAlias. + +## Register a workspace context for the Document Workspace + +For the manifest we can use the same manifest as the previous example. + +## Implement custom logic for Property Value Permissions + +Implement custom logic to identify all properties and add a view and write state for each one. + +```ts +import { UmbControllerBase } from "@umbraco-cms/backoffice/class-api"; +import type { UmbControllerHost } from "@umbraco-cms/backoffice/controller-api"; +import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from "@umbraco-cms/backoffice/document"; +import { UmbVariantId } from "@umbraco-cms/backoffice/variant"; + +export class MyDocumentPropertyPermissionWorkspaceContext extends UmbControllerBase { + constructor(host: UmbControllerHost) { + super(host); + + // Consume the document workspace context + this.consumeContext( + UMB_DOCUMENT_WORKSPACE_CONTEXT, + this.#observeStructure + ); + } + + #observeStructure(context: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE) { + if (!context) return; + + // Observe all properties for the Content Type + this.observe(context.structure.contentTypeProperties, (properties) => { + if (properties.length === 0) return; + + // Filter out the property with the alias "myPropertyAlias" + const allowedProperties = properties.filter( + (property) => property.alias !== "myPropertyAlias" + ); + + // Create a new variant ID for the invariant properties + const invariantId = new UmbVariantId(); + + // Create a read-only state for each property + const states = allowedProperties.map((property) => { + return { + unique: + "MY_INVARIANT_PROPERTY_RESTRICTION_" + property.unique, + message: "", + propertyType: { + unique: property.unique, + variantId: invariantId, + }, + }; + }); + + // Add the read-only states to the property read-only state manager + context.structure.propertyViewState.addStates(states); + context.structure.propertyWriteState.addStates(states); + }); + } +} +``` From d1140f40dedf6f4723741a12e694d1ee32f86c99 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 25 Mar 2025 14:48:55 +0100 Subject: [PATCH 2/4] Update ui-property-permissions.md --- .../customizing/ui-property-permissions.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/15/umbraco-cms/customizing/ui-property-permissions.md b/15/umbraco-cms/customizing/ui-property-permissions.md index 0d77f2f74f3..ab4fc8e5b95 100644 --- a/15/umbraco-cms/customizing/ui-property-permissions.md +++ b/15/umbraco-cms/customizing/ui-property-permissions.md @@ -4,15 +4,15 @@ The UI Property Permissions are used to restrict access to specific properties i ## Document Property Value User Permissions -Out of the box, Umbraco provides a feature called Document Property Value User Permissions.This feature can restrict access to specific Document property values for certain user groups. By default, all the built-in User Groups have read and write permissions for all properties. However, you can limit a User Group's permissions specific properties through the UI. +Out of the box, Umbraco provides a feature called Document Property Value User Permissions. This feature can restrict access to specific Document property values for certain user groups. By default, all the built-in User Groups have read and write permissions for all properties. However, you can limit a User Group's permissions for specific properties through the UI. If a User Group does not have write access to a property, the property will be read-only for that User Group. If a User Group does not have read access to a property, the property will be hidden from that User Group. -Be aware that the Document Property Value User Permissions are not enforced on the server-side. This means that a user can still access the property value through the API, even if the property is restricted in the UI. +Be aware that the Document Property Value User Permissions are not enforced on the server side. This means that a user can still access the property value through the API, even if the property is restricted in the UI. ## Extending the Document Property Value User Permission with additional restrictions -In addition to the User Permission logic, it is possible to add further restrictions to properties. This can be achieved through the `propertyReadOnlyState`-Manager available in property based Workspace Context. In the following example, we will make all invariant properties read-only. +In addition to the User Permission logic, it is possible to add further restrictions to properties. This can be achieved through the `propertyReadOnlyState`-Manager available in property-based Workspace Contexts. In the following example, we will make all invariant properties read-only. ## Register a Workspace Context @@ -77,7 +77,7 @@ export class MyDocumentPropertyPermissionWorkspaceContext extends UmbControllerB unique: "MY_INVARIANT_PROPERTY_RESTRICTION_" + property.unique, message: - "The property is read only because of my restriction", + "The property is read-only because of my restriction.", propertyType: { unique: property.unique, variantId: invariantId, @@ -100,11 +100,11 @@ It is also possible to implement completely custom UI logic for managing propert We follow the same concept as the previous example, but instead of writing to the `propertyReadOnlyState`-Manager, we can use the `propertyViewState`-Manager and the `propertyWriteState`-Manager to control the view- and writability of properties. -In the following example we will hide a specific property based on the propertyAlias. +In the following example, we will hide a specific property based on the property alias. ## Register a workspace context for the Document Workspace -For the manifest we can use the same manifest as the previous example. +For the manifest, we can use the same manifest as the previous example. ## Implement custom logic for Property Value Permissions From f19965b9c57fd36eb7a071663cee2f194c403cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Apr 2025 13:39:12 +0200 Subject: [PATCH 3/4] Update ui-property-permissions.md --- .../customizing/ui-property-permissions.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/15/umbraco-cms/customizing/ui-property-permissions.md b/15/umbraco-cms/customizing/ui-property-permissions.md index ab4fc8e5b95..a4f9ceb27e2 100644 --- a/15/umbraco-cms/customizing/ui-property-permissions.md +++ b/15/umbraco-cms/customizing/ui-property-permissions.md @@ -72,21 +72,22 @@ export class MyDocumentPropertyPermissionWorkspaceContext extends UmbControllerB const invariantId = new UmbVariantId(); // Create a read-only state for each property - const states = properties.map((property) => { + const rules = properties.map((property) => { return { unique: "MY_INVARIANT_PROPERTY_RESTRICTION_" + property.unique, + permitted: false, message: - "The property is read-only because of my restriction.", + "The property is read-only because of my custom restriction.", + variantId: invariantId, propertyType: { - unique: property.unique, - variantId: invariantId, - }, + unique: property.unique + } }; }); // Add the read-only states to the property read-only state manager - context.structure.propertyReadOnlyState.addStates(states); + context.propertyWriteGuard.addRules(rules); }); } } From 180d6e9eb7ab722a24b7b209c71de03cbe811e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Apr 2025 13:40:32 +0200 Subject: [PATCH 4/4] Update ui-property-permissions.md --- .../customizing/ui-property-permissions.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/15/umbraco-cms/customizing/ui-property-permissions.md b/15/umbraco-cms/customizing/ui-property-permissions.md index a4f9ceb27e2..85e609ec599 100644 --- a/15/umbraco-cms/customizing/ui-property-permissions.md +++ b/15/umbraco-cms/customizing/ui-property-permissions.md @@ -71,7 +71,7 @@ export class MyDocumentPropertyPermissionWorkspaceContext extends UmbControllerB // Create a new variant ID for the invariant properties const invariantId = new UmbVariantId(); - // Create a read-only state for each property + // Create a read-only rule for each property const rules = properties.map((property) => { return { unique: @@ -143,22 +143,22 @@ export class MyDocumentPropertyPermissionWorkspaceContext extends UmbControllerB // Create a new variant ID for the invariant properties const invariantId = new UmbVariantId(); - // Create a read-only state for each property - const states = allowedProperties.map((property) => { + // Create a read-only rule for each property + const rules = allowedProperties.map((property) => { return { unique: "MY_INVARIANT_PROPERTY_RESTRICTION_" + property.unique, message: "", propertyType: { - unique: property.unique, - variantId: invariantId, + unique: property.unique }, + variantId: invariantId }; }); // Add the read-only states to the property read-only state manager - context.structure.propertyViewState.addStates(states); - context.structure.propertyWriteState.addStates(states); + context.structure.propertyViewGuard.addRules(rules); + context.structure.propertyWriteGuard.addRules(rules); }); } }