diff --git a/16/umbraco-cms/.gitbook/assets/granular-user-permissions-ui-custom.png b/16/umbraco-cms/.gitbook/assets/granular-user-permissions-ui-custom.png
new file mode 100644
index 00000000000..cbf863e98a0
Binary files /dev/null and b/16/umbraco-cms/.gitbook/assets/granular-user-permissions-ui-custom.png differ
diff --git a/16/umbraco-cms/customizing/extending-overview/extension-types/entity-actions.md b/16/umbraco-cms/customizing/extending-overview/extension-types/entity-actions.md
index 9408aaad8c4..0e0502ca346 100644
--- a/16/umbraco-cms/customizing/extending-overview/extension-types/entity-actions.md
+++ b/16/umbraco-cms/customizing/extending-overview/extension-types/entity-actions.md
@@ -1,170 +1,174 @@
---
-description: Entity Actions perform an action on a specific item
+description: Entity Actions give developers the ability to add custom actions to a fly-out menu.
---
# Entity Actions
-{% hint style="warning" %}
-This page is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
-{% endhint %}
-
{% hint style="info" %}
-Entity Actions was previously called Tree Actions.
+**Entity Actions** was previously known as **Tree Actions.**
{% endhint %}
-Entity Actions is a feature that provides a generic place for secondary or additional functionality for an entity type. An entity type can be a media, document and so on.
+Entity Actions is an extension type that provides a fly-out context menu for secondary or additional functionality to an entity (document, media, etc...).
-Items in an Umbraco Tree can have associated Actions. The actions visible to the currently logged in user can be controlled via User Permissions.
+Developers can define and associate custom actions for entities in a [tree extension](tree.md), workspace, or collection view. Access to these actions can be controlled via user permissions. The Users section of the backoffice allows Administrators to control which actions a user has permissions to access.
-You can set a User's permissions for each item in the Umbraco Content tree from the User Section of the Umbraco Backoffice.
+## Display Modes
-If you are developing a custom section or a custom Dashboard, you might want to display some different options. This depends on a User's permission set on a particular item.
+Entity Actions extensions can be displayed in a variety of formats.
-## Entity Actions in the UI
+### Sidebar Context Menu
-
+The sidebar context mode provides a second-level context menu that flies out from the content tree. Backoffice users will typically find default items such as sorting, moving, deleting, and publishing workflow actions here.
-
Sidebar Context Menu
+
-
+### Workspace Entity Menu
-
Workspace Entity Action Menu
+The workspace entity mode provides a drop-down menu that flies out from the upper decking of a workspace.
-
+
-
+### Collection Menu
-
Collection
+The collection mode provides a drop-down menu that appears above a collection view.
-
+
-
Pickers
+### Picker Menu
-
+The picker mode provides a menu in a sidebar modal.
-### Sidebar Context Menu
+
-Sidebar Context Menu is an entity action that can be performed on a menu item. For example in the content section you can perform some extra actions on the content such as sorting, moving, etc.
+## Registering an Entity Action
-
Default Entity Action in the Content Section
+To register an entity action, developers declare the entity action in the manifest file, and then extend the `UmbEntityActionBase` class to program the action's behavior.
-## Registering an Entity Action
+### Declare the Entity Action
+{% code title="entity-action/manifest.ts" %}
```typescript
import { extensionRegistry } from '@umbraco-cms/extension-registry';
import { MyEntityAction } from './entity-action';
const manifest = {
- type: 'entityAction',
- alias: 'My.EntityAction',
- name: 'My Entity Action',
- weight: 10,
- api: MyEntityAction,
- forEntityTypes: ['my-entity'],
- meta: {
- icon: 'icon-add',
- label: 'My Entity Action',
- repositoryAlias: 'My.Repository',
- },
+ type: 'entityAction',
+ alias: 'My.EntityAction',
+ name: 'My Entity Action',
+ weight: 10,
+ api: MyEntityAction,
+ forEntityTypes: ['my-entity'],
+ meta: {
+ icon: 'icon-add',
+ label: 'My Entity Action',
+ },
};
extensionRegistry.register(manifest);
```
+{% endcode %}
-**Default Element**
+## The Entity Action Class
-```typescript
-interface UmbEntityActionElement {}
-```
+Umbraco provides a few generic actions that can be used across silos, such as copy, move, trash, etc. Umbraco may include additional generic actions in the future.
-### The Entity Action Class
+Entity Action extensions will need to supply a class to the extension definition using the `api` property in the manifest file. This class will be instantiated as part of the action and will be passed a reference to the entity that invoked it.
-As part of the Extension Manifest you can attach a class that will be instantiated as part of the action. It will have access to the host element, a repository with the given alias and the unique (key etc) of the entity.
+The entity action class will provide one of the following methods:
+* `getHref` - returns a url that will be used for navigation
+* `execute` - programs custom imperative behaviors that can work with contexts and service apis
-The class either provides a getHref method, or an execute method. If the getHref method is provided, the action will use the link. Otherwise the `execute` method will be used. When the action is clicked the `execute` method on the api class will be run. When the action is completed, an event on the host element will be dispatched to notify any surrounding elements.
+If both methods are provided in the entity action class, the `getHref` method will be preferred.
-Example of providing a `getHref` method:
+When the action is completed, an event on the host element will be dispatched to notify any surrounding elements.
-```typescript
-import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
-import type { MyRepository } from './my-repository';
-
-export class MyEntityAction extends UmbEntityActionBase {
- constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) {
- super(host, repositoryAlias, unique);
- }
-
- async getHref() {
- return 'my-link/path-to-something';
- }
-}
-```
+### The `getHref()` Method
-Example of providing a `execute` method:
+Entity action extensions are provided `this.args` by the `UmbEntityActionBase` superclass. The `this.args` contains a property, `unique` that allows developers to identity which element the user selected.
+The `getHref()` method must return a string value, and the result will be rendered into the DOM as an anchor/link.
+
+{% code title="entity-action/my-entity-action.ts" %}
```typescript
-import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
-import type { MyRepository } from './my-repository';
-
-export class MyEntityAction extends UmbEntityActionBase {
- constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) {
- super(host, repositoryAlias, unique);
- }
-
- async execute() {
- await this.repository.myAction(this.unique);
- }
+import {UmbEntityActionBase} from '@umbraco-cms/backoffice/entity-action';
+
+export class MyEntityAction extends UmbEntityActionBase {
+ async getHref() {
+ return `my-link/path-to-something/${this.args.unique}`;
+ }
}
```
+{% endcode %}
-If any additional contexts are needed, these can be consumed from the host element:
+### The `execute()` Method
+
+The `execute()` method is flexible and allows developers to perform nearly any task on an entity. Developers can perform network requests using `fetch()`, or access a repository.
+
+{% hint style="info" %}
+The [Executing Requests](../../foundation/fetching-data) article provides an overview of the methods for fetching data from Umbraco, including `tryExecute()` requests.
+{% endhint %}
+{% code title="entity-action/enable-xgrid-action.ts" %}
```typescript
-import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
-import { UmbContextConsumerController } from '@umbraco-cms/controller';
-import { UMB_MODAL_SERVICE_CONTEXT } from '@umbraco-cms/modal';
-import { MyRepository } from './my-repository';
+import {
+ UmbEntityActionBase,
+} from "@umbraco-cms/backoffice/entity-action";
+
+export class EnableXgridAction extends UmbEntityActionBase {
+ async execute() {
+ // perform a network request
+ // fetch(`/server-resource/${this.args.unique}`)
-export class MyEntityAction extends UmbEntityActionBase {
- constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) {
- super(host, repositoryAlias, unique);
+ // or fetch repository
+ //const repository = ...
- new UmbContextConsumerController(this.host, UMB_MODAL_SERVICE_CONTEXT, (instance) => {
- this.#modalService = instance;
- });
- }
- ...
+ console.log(this.args.unique);
+ }
}
```
+{% endcode %}
-We currently have a couple of generic actions that can be used across silos, so we don't have to write the same logic again. These actions include copy, move, trash, delete, etc. We can add more as we discover the needs.
+### Overriding the UmbEntityActionBase Constructor
-## User Permission Codes
-
-Here is a list of the entity actions and associated user permission codes shipped by Umbraco CMS and add-on projects, such as Umbraco Deploy. This list also includes codes used by some community packages.
+If additional contexts are needed, they can be consumed from the host element via the `constructor` method.
-If you are building a package or adding custom entity actions to your solution, it's important to pick a permission letter. Ensure that it doesn't clash with one of these.
-
-If you have created a package using a custom entity action, consider providing an update to this documentation page. You can do this via a PR to the [documentation repository](https://github.com/umbraco/UmbracoDocs). This will allow other developers to discover and avoid using the same permission letter.
+{% code title="entity-action/link-to-server-services-action.ts" %}
+```typescript
+import {
+ UmbEntityActionBase,
+ UmbEntityActionArgs,
+} from "@umbraco-cms/backoffice/entity-action";
+import { UmbControllerHostElement } from "@umbraco-cms/backoffice/controller-api";
+import { UmbContextConsumerController } from '@umbraco-cms/controller';
+import { UMB_MODAL_SERVICE_CONTEXT } from '@umbraco-cms/modal';
-Currently, we allow two extension points on the client for user permissions:
+export class LinkToServerServicesAction extends UmbEntityActionBase {
+ constructor(
+ host: UmbControllerHostElement,
+ args: UmbEntityActionArgs,
+ ) {
+ super(host, args);
-* **Entity User Permissions** - Relates to an entity (example document).
+ new UmbContextConsumerController(this.host, UMB_MODAL_SERVICE_CONTEXT, (instance) => {
+ this.#modalService = instance;
+ });
+ }
-
Entity User Permissions UI
+ // ...
+}
+```
+{% endcode %}
-* **Granular User Permission** - Relates to a $type server schemaType.
+## User Permission Codes
-
Granular User Permission UI
+Developers can define custom user permission codes to control access to their actions, in addition to the standard Umbraco user permission codes. Custom permission codes need to be unique and should not clash with existing permission codes.
-Each permission comes with a set of verbs, that will be checked against client and server-side.
+Each permission has a set of verbs that will be checked against on both the client and server.
-The Core currently ships with entity user permission for documents. The permissions are as follows:
+### Standard Umbraco Permission Letters
-| Current Backoffice Letter | Verb |
-| ------------------------- | -------------------------------- |
+| Current Backoffice letter | Verb |
+|---------------------------|----------------------------------|
| C | Umb.Document.Create |
| F | Umb.Document.Read |
| A | Umb.Document.Update |
@@ -182,35 +186,127 @@ The Core currently ships with entity user permission for documents. The permissi
| K | Umb.Document.Rollback |
| V | Umb.DocumentRecycleBin.Restore |
-**Entity User Permissions** will be registered in the extension registry with a manifest with the following type. Example:
+### Custom Permission Letters
-```typescript
+Developers who create packages with custom entity actions are encouraged to update this document by submitting pull requests to the [documentation repository](https://github.com/umbraco/UmbracoDocs). This will inform other developers which permission letters they should avoid defining.
+
+| Custom Backoffice letter | Verb |
+|--------------------------|--------------------------------|
+| ⌘ | *Placeholder* |
+
+## Entity Action Permissions
+
+Umbraco provides two extension types for user permissions: **entity user permissions** and **granular user permissions.**
+
+These two extension types are used in tandem with each other.
+
+* `entityUserPermission`: Defines _what_ can be done and allows assigning them globally to a User Group.
+* `userGranularPermission`: Defines _how_ those same verbs can be assigned to specific nodes in the User Management UI. These extension types provide an interactive interface in the backoffice to control permission assignment.
+
+### Entity User Permissions
+
+Entity user permissions are assigned to a document, media, member, etc., and are registered using the `entityUserPermission` type in the extension's manifest.
+
+{% code title="entity-action/manifests.json" %}
+```json
{
- "type": "entityUserPermission",
- "alias": "Umb.UserPermission.Document.Rollback",
- "name": "Document Rollback User Permission",
- "meta": {
- "entityType": "document",
- "verbs": ["Umb.Document.Rollback"],
- "labelKey": "actions_rollback",
- "descriptionKey": "actionDescriptions_rollback",
- "group": "administration",
- },
- },
+ "$schema": "../../umbraco-package-schema.json",
+ "name": "My Package",
+ "version": "0.1.0",
+ "extensions": [
+ {
+ "type": "entityUserPermission",
+ "alias": "My.UserPermission.Document.Archive",
+ "name": "Document Archive User Permission",
+ "forEntityTypes": ["document"],
+ "meta": {
+ "verbs": ["My.Document.Archive"],
+ "label": "Archive Document",
+ "description": "Allow user to archive documents",
+ "group": "administration"
+ }
+ }
+ ]
+}
```
+{% endcode %}
-**Granular permissions** will also be registered. It is possible to provide a custom element to build the needed UX for that type of permission:
+#### Management Interface
-```typescript
+The `entityUserPermission` extension type will render a toggle control in the **Default permissions** pane in the Users > User Groups editor.
+
+
Entity User Permissions UI
+
+### Granular User Permission
+
+Extension developers can customize the selection and interaction style of a granular permission using the `element` property. The `element` property accepts the file location of a custom web component, and will render that component in the management interface.
+
+{% code title="entity-action/manifests.json" %}
+```json
{
- "type": "userGranularPermission",
- "alias": "Umb.UserGranularPermission.Document",
- "name": "Document Granular User Permission",
- "element": "element.js",
- "meta": {
- "schemaType": "DocumentPermissionPresentationModel",
- "label": "Documents",
- "description": "Assign permissions to specific documents",
- },
- },
+ "$schema": "../../umbraco-package-schema.json",
+ "name": "My Package",
+ "version": "0.1.0",
+ "extensions": [
+ {
+ "type": "userGranularPermission",
+ "alias": "Umb.UserGranularPermission.Document",
+ "name": "Document Granular User Permission",
+ "element": "element.js",
+ "meta": {
+ "schemaType": "DocumentPermissionPresentationModel",
+ "label": "Documents",
+ "description": "Assign permissions to specific documents"
+ }
+ }
+ ]
+}
+```
+{% endcode %}
+
+#### Management Interface
+
+The `userGranularPermission` extension type will render a document selection control in the **Granular permissions** pane in the Users > User Groups editor by default. The default selector can be replaced with a custom web component.
+
+
Default Granular User Permission UI
+
+
Custom Granular User Permission UI
+
+### Enforcing Permissions
+
+Developers can enforce permission controls on **Entity Action** extensions by defining conditions in the `conditions` array.
+
+In the following example, the `conditions:alias` property of an `entityAction` extension matches the `alias` property of the `entityUserPermission` extension definition.
+
+Similarly, the `conditions:config:allOf` array must contain the one of the values from the `meta:verbs` array of the `entityUserPermission` extension definition.
+
+{% code title="entity-action/manifests.json" %}
+```json
+{
+ "$schema": "../../umbraco-package-schema.json",
+ "name": "My Package",
+ "version": "0.1.0",
+ "extensions": [
+ {
+ "type": "entityAction",
+ "alias": "My.EntityAction.Archive",
+ "name": "Archive Document Action",
+ "forEntityTypes": ["document"],
+ "api": "...",
+ "meta": {
+ "icon": "icon-box",
+ "label": "Archive"
+ },
+ "conditions": [
+ {
+ "alias": "Umb.Condition.UserPermission.Document",
+ "config": {
+ "allOf": ["My.Document.Archive"]
+ }
+ }
+ ]
+ }
+ ]
+}
```
+{% endcode %}
diff --git a/17/umbraco-cms/.gitbook/assets/granular-user-permissions-ui-custom.png b/17/umbraco-cms/.gitbook/assets/granular-user-permissions-ui-custom.png
new file mode 100644
index 00000000000..cbf863e98a0
Binary files /dev/null and b/17/umbraco-cms/.gitbook/assets/granular-user-permissions-ui-custom.png differ
diff --git a/17/umbraco-cms/customizing/extending-overview/extension-types/entity-actions.md b/17/umbraco-cms/customizing/extending-overview/extension-types/entity-actions.md
index 9408aaad8c4..0e0502ca346 100644
--- a/17/umbraco-cms/customizing/extending-overview/extension-types/entity-actions.md
+++ b/17/umbraco-cms/customizing/extending-overview/extension-types/entity-actions.md
@@ -1,170 +1,174 @@
---
-description: Entity Actions perform an action on a specific item
+description: Entity Actions give developers the ability to add custom actions to a fly-out menu.
---
# Entity Actions
-{% hint style="warning" %}
-This page is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
-{% endhint %}
-
{% hint style="info" %}
-Entity Actions was previously called Tree Actions.
+**Entity Actions** was previously known as **Tree Actions.**
{% endhint %}
-Entity Actions is a feature that provides a generic place for secondary or additional functionality for an entity type. An entity type can be a media, document and so on.
+Entity Actions is an extension type that provides a fly-out context menu for secondary or additional functionality to an entity (document, media, etc...).
-Items in an Umbraco Tree can have associated Actions. The actions visible to the currently logged in user can be controlled via User Permissions.
+Developers can define and associate custom actions for entities in a [tree extension](tree.md), workspace, or collection view. Access to these actions can be controlled via user permissions. The Users section of the backoffice allows Administrators to control which actions a user has permissions to access.
-You can set a User's permissions for each item in the Umbraco Content tree from the User Section of the Umbraco Backoffice.
+## Display Modes
-If you are developing a custom section or a custom Dashboard, you might want to display some different options. This depends on a User's permission set on a particular item.
+Entity Actions extensions can be displayed in a variety of formats.
-## Entity Actions in the UI
+### Sidebar Context Menu
-
+The sidebar context mode provides a second-level context menu that flies out from the content tree. Backoffice users will typically find default items such as sorting, moving, deleting, and publishing workflow actions here.
-
Sidebar Context Menu
+
-
+### Workspace Entity Menu
-
Workspace Entity Action Menu
+The workspace entity mode provides a drop-down menu that flies out from the upper decking of a workspace.
-
+
-
+### Collection Menu
-
Collection
+The collection mode provides a drop-down menu that appears above a collection view.
-
+
-
Pickers
+### Picker Menu
-
+The picker mode provides a menu in a sidebar modal.
-### Sidebar Context Menu
+
-Sidebar Context Menu is an entity action that can be performed on a menu item. For example in the content section you can perform some extra actions on the content such as sorting, moving, etc.
+## Registering an Entity Action
-
Default Entity Action in the Content Section
+To register an entity action, developers declare the entity action in the manifest file, and then extend the `UmbEntityActionBase` class to program the action's behavior.
-## Registering an Entity Action
+### Declare the Entity Action
+{% code title="entity-action/manifest.ts" %}
```typescript
import { extensionRegistry } from '@umbraco-cms/extension-registry';
import { MyEntityAction } from './entity-action';
const manifest = {
- type: 'entityAction',
- alias: 'My.EntityAction',
- name: 'My Entity Action',
- weight: 10,
- api: MyEntityAction,
- forEntityTypes: ['my-entity'],
- meta: {
- icon: 'icon-add',
- label: 'My Entity Action',
- repositoryAlias: 'My.Repository',
- },
+ type: 'entityAction',
+ alias: 'My.EntityAction',
+ name: 'My Entity Action',
+ weight: 10,
+ api: MyEntityAction,
+ forEntityTypes: ['my-entity'],
+ meta: {
+ icon: 'icon-add',
+ label: 'My Entity Action',
+ },
};
extensionRegistry.register(manifest);
```
+{% endcode %}
-**Default Element**
+## The Entity Action Class
-```typescript
-interface UmbEntityActionElement {}
-```
+Umbraco provides a few generic actions that can be used across silos, such as copy, move, trash, etc. Umbraco may include additional generic actions in the future.
-### The Entity Action Class
+Entity Action extensions will need to supply a class to the extension definition using the `api` property in the manifest file. This class will be instantiated as part of the action and will be passed a reference to the entity that invoked it.
-As part of the Extension Manifest you can attach a class that will be instantiated as part of the action. It will have access to the host element, a repository with the given alias and the unique (key etc) of the entity.
+The entity action class will provide one of the following methods:
+* `getHref` - returns a url that will be used for navigation
+* `execute` - programs custom imperative behaviors that can work with contexts and service apis
-The class either provides a getHref method, or an execute method. If the getHref method is provided, the action will use the link. Otherwise the `execute` method will be used. When the action is clicked the `execute` method on the api class will be run. When the action is completed, an event on the host element will be dispatched to notify any surrounding elements.
+If both methods are provided in the entity action class, the `getHref` method will be preferred.
-Example of providing a `getHref` method:
+When the action is completed, an event on the host element will be dispatched to notify any surrounding elements.
-```typescript
-import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
-import type { MyRepository } from './my-repository';
-
-export class MyEntityAction extends UmbEntityActionBase {
- constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) {
- super(host, repositoryAlias, unique);
- }
-
- async getHref() {
- return 'my-link/path-to-something';
- }
-}
-```
+### The `getHref()` Method
-Example of providing a `execute` method:
+Entity action extensions are provided `this.args` by the `UmbEntityActionBase` superclass. The `this.args` contains a property, `unique` that allows developers to identity which element the user selected.
+The `getHref()` method must return a string value, and the result will be rendered into the DOM as an anchor/link.
+
+{% code title="entity-action/my-entity-action.ts" %}
```typescript
-import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
-import type { MyRepository } from './my-repository';
-
-export class MyEntityAction extends UmbEntityActionBase {
- constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) {
- super(host, repositoryAlias, unique);
- }
-
- async execute() {
- await this.repository.myAction(this.unique);
- }
+import {UmbEntityActionBase} from '@umbraco-cms/backoffice/entity-action';
+
+export class MyEntityAction extends UmbEntityActionBase {
+ async getHref() {
+ return `my-link/path-to-something/${this.args.unique}`;
+ }
}
```
+{% endcode %}
-If any additional contexts are needed, these can be consumed from the host element:
+### The `execute()` Method
+
+The `execute()` method is flexible and allows developers to perform nearly any task on an entity. Developers can perform network requests using `fetch()`, or access a repository.
+
+{% hint style="info" %}
+The [Executing Requests](../../foundation/fetching-data) article provides an overview of the methods for fetching data from Umbraco, including `tryExecute()` requests.
+{% endhint %}
+{% code title="entity-action/enable-xgrid-action.ts" %}
```typescript
-import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
-import { UmbContextConsumerController } from '@umbraco-cms/controller';
-import { UMB_MODAL_SERVICE_CONTEXT } from '@umbraco-cms/modal';
-import { MyRepository } from './my-repository';
+import {
+ UmbEntityActionBase,
+} from "@umbraco-cms/backoffice/entity-action";
+
+export class EnableXgridAction extends UmbEntityActionBase {
+ async execute() {
+ // perform a network request
+ // fetch(`/server-resource/${this.args.unique}`)
-export class MyEntityAction extends UmbEntityActionBase {
- constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) {
- super(host, repositoryAlias, unique);
+ // or fetch repository
+ //const repository = ...
- new UmbContextConsumerController(this.host, UMB_MODAL_SERVICE_CONTEXT, (instance) => {
- this.#modalService = instance;
- });
- }
- ...
+ console.log(this.args.unique);
+ }
}
```
+{% endcode %}
-We currently have a couple of generic actions that can be used across silos, so we don't have to write the same logic again. These actions include copy, move, trash, delete, etc. We can add more as we discover the needs.
+### Overriding the UmbEntityActionBase Constructor
-## User Permission Codes
-
-Here is a list of the entity actions and associated user permission codes shipped by Umbraco CMS and add-on projects, such as Umbraco Deploy. This list also includes codes used by some community packages.
+If additional contexts are needed, they can be consumed from the host element via the `constructor` method.
-If you are building a package or adding custom entity actions to your solution, it's important to pick a permission letter. Ensure that it doesn't clash with one of these.
-
-If you have created a package using a custom entity action, consider providing an update to this documentation page. You can do this via a PR to the [documentation repository](https://github.com/umbraco/UmbracoDocs). This will allow other developers to discover and avoid using the same permission letter.
+{% code title="entity-action/link-to-server-services-action.ts" %}
+```typescript
+import {
+ UmbEntityActionBase,
+ UmbEntityActionArgs,
+} from "@umbraco-cms/backoffice/entity-action";
+import { UmbControllerHostElement } from "@umbraco-cms/backoffice/controller-api";
+import { UmbContextConsumerController } from '@umbraco-cms/controller';
+import { UMB_MODAL_SERVICE_CONTEXT } from '@umbraco-cms/modal';
-Currently, we allow two extension points on the client for user permissions:
+export class LinkToServerServicesAction extends UmbEntityActionBase {
+ constructor(
+ host: UmbControllerHostElement,
+ args: UmbEntityActionArgs,
+ ) {
+ super(host, args);
-* **Entity User Permissions** - Relates to an entity (example document).
+ new UmbContextConsumerController(this.host, UMB_MODAL_SERVICE_CONTEXT, (instance) => {
+ this.#modalService = instance;
+ });
+ }
-
Entity User Permissions UI
+ // ...
+}
+```
+{% endcode %}
-* **Granular User Permission** - Relates to a $type server schemaType.
+## User Permission Codes
-
Granular User Permission UI
+Developers can define custom user permission codes to control access to their actions, in addition to the standard Umbraco user permission codes. Custom permission codes need to be unique and should not clash with existing permission codes.
-Each permission comes with a set of verbs, that will be checked against client and server-side.
+Each permission has a set of verbs that will be checked against on both the client and server.
-The Core currently ships with entity user permission for documents. The permissions are as follows:
+### Standard Umbraco Permission Letters
-| Current Backoffice Letter | Verb |
-| ------------------------- | -------------------------------- |
+| Current Backoffice letter | Verb |
+|---------------------------|----------------------------------|
| C | Umb.Document.Create |
| F | Umb.Document.Read |
| A | Umb.Document.Update |
@@ -182,35 +186,127 @@ The Core currently ships with entity user permission for documents. The permissi
| K | Umb.Document.Rollback |
| V | Umb.DocumentRecycleBin.Restore |
-**Entity User Permissions** will be registered in the extension registry with a manifest with the following type. Example:
+### Custom Permission Letters
-```typescript
+Developers who create packages with custom entity actions are encouraged to update this document by submitting pull requests to the [documentation repository](https://github.com/umbraco/UmbracoDocs). This will inform other developers which permission letters they should avoid defining.
+
+| Custom Backoffice letter | Verb |
+|--------------------------|--------------------------------|
+| ⌘ | *Placeholder* |
+
+## Entity Action Permissions
+
+Umbraco provides two extension types for user permissions: **entity user permissions** and **granular user permissions.**
+
+These two extension types are used in tandem with each other.
+
+* `entityUserPermission`: Defines _what_ can be done and allows assigning them globally to a User Group.
+* `userGranularPermission`: Defines _how_ those same verbs can be assigned to specific nodes in the User Management UI. These extension types provide an interactive interface in the backoffice to control permission assignment.
+
+### Entity User Permissions
+
+Entity user permissions are assigned to a document, media, member, etc., and are registered using the `entityUserPermission` type in the extension's manifest.
+
+{% code title="entity-action/manifests.json" %}
+```json
{
- "type": "entityUserPermission",
- "alias": "Umb.UserPermission.Document.Rollback",
- "name": "Document Rollback User Permission",
- "meta": {
- "entityType": "document",
- "verbs": ["Umb.Document.Rollback"],
- "labelKey": "actions_rollback",
- "descriptionKey": "actionDescriptions_rollback",
- "group": "administration",
- },
- },
+ "$schema": "../../umbraco-package-schema.json",
+ "name": "My Package",
+ "version": "0.1.0",
+ "extensions": [
+ {
+ "type": "entityUserPermission",
+ "alias": "My.UserPermission.Document.Archive",
+ "name": "Document Archive User Permission",
+ "forEntityTypes": ["document"],
+ "meta": {
+ "verbs": ["My.Document.Archive"],
+ "label": "Archive Document",
+ "description": "Allow user to archive documents",
+ "group": "administration"
+ }
+ }
+ ]
+}
```
+{% endcode %}
-**Granular permissions** will also be registered. It is possible to provide a custom element to build the needed UX for that type of permission:
+#### Management Interface
-```typescript
+The `entityUserPermission` extension type will render a toggle control in the **Default permissions** pane in the Users > User Groups editor.
+
+
Entity User Permissions UI
+
+### Granular User Permission
+
+Extension developers can customize the selection and interaction style of a granular permission using the `element` property. The `element` property accepts the file location of a custom web component, and will render that component in the management interface.
+
+{% code title="entity-action/manifests.json" %}
+```json
{
- "type": "userGranularPermission",
- "alias": "Umb.UserGranularPermission.Document",
- "name": "Document Granular User Permission",
- "element": "element.js",
- "meta": {
- "schemaType": "DocumentPermissionPresentationModel",
- "label": "Documents",
- "description": "Assign permissions to specific documents",
- },
- },
+ "$schema": "../../umbraco-package-schema.json",
+ "name": "My Package",
+ "version": "0.1.0",
+ "extensions": [
+ {
+ "type": "userGranularPermission",
+ "alias": "Umb.UserGranularPermission.Document",
+ "name": "Document Granular User Permission",
+ "element": "element.js",
+ "meta": {
+ "schemaType": "DocumentPermissionPresentationModel",
+ "label": "Documents",
+ "description": "Assign permissions to specific documents"
+ }
+ }
+ ]
+}
+```
+{% endcode %}
+
+#### Management Interface
+
+The `userGranularPermission` extension type will render a document selection control in the **Granular permissions** pane in the Users > User Groups editor by default. The default selector can be replaced with a custom web component.
+
+
Default Granular User Permission UI
+
+
Custom Granular User Permission UI
+
+### Enforcing Permissions
+
+Developers can enforce permission controls on **Entity Action** extensions by defining conditions in the `conditions` array.
+
+In the following example, the `conditions:alias` property of an `entityAction` extension matches the `alias` property of the `entityUserPermission` extension definition.
+
+Similarly, the `conditions:config:allOf` array must contain the one of the values from the `meta:verbs` array of the `entityUserPermission` extension definition.
+
+{% code title="entity-action/manifests.json" %}
+```json
+{
+ "$schema": "../../umbraco-package-schema.json",
+ "name": "My Package",
+ "version": "0.1.0",
+ "extensions": [
+ {
+ "type": "entityAction",
+ "alias": "My.EntityAction.Archive",
+ "name": "Archive Document Action",
+ "forEntityTypes": ["document"],
+ "api": "...",
+ "meta": {
+ "icon": "icon-box",
+ "label": "Archive"
+ },
+ "conditions": [
+ {
+ "alias": "Umb.Condition.UserPermission.Document",
+ "config": {
+ "allOf": ["My.Document.Archive"]
+ }
+ }
+ ]
+ }
+ ]
+}
```
+{% endcode %}