Skip to content

Commit a29f510

Browse files
Link to content type and/or template from content/media/member info workspace view only if current user has access to settings (#17965)
* Link to content type and/or template from content/media/member info workspace view only if current user has access to sections. * Fixed HTML * add const for condition alias * export const * return permitted value in onChange callback * use condition to check for access * implement across content * replace strings with consts * replace strings with const * remove attr with the ifDefined directive * allow to pass in callback type * Pass callback type * Update index.ts * add tests for UmbSectionUserPermissionCondition --------- Co-authored-by: Mads Rasmussen <[email protected]>
1 parent b8ee161 commit a29f510

File tree

27 files changed

+211
-29
lines changed

27 files changed

+211
-29
lines changed

src/Umbraco.Web.UI.Client/src/libs/extension-api/condition/condition-controller-arguments.type.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,9 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
33

44
export type UmbConditionControllerArguments<
55
ConditionConfigType extends UmbConditionConfigBase = UmbConditionConfigBase,
6-
> = { host: UmbControllerHost; config: ConditionConfigType; onChange: () => void };
6+
ConditionOnChangeCallbackType = () => void,
7+
> = {
8+
host: UmbControllerHost;
9+
config: ConditionConfigType;
10+
onChange: ConditionOnChangeCallbackType;
11+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS = 'Umb.Condition.SectionUserPermission';

src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/manifests.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
import { UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS } from './constants.js';
12
import { UmbSectionAliasCondition } from './section-alias.condition.js';
23
import { UmbSectionUserPermissionCondition } from './section-user-permission.condition.js';
34

45
export const manifests: Array<UmbExtensionManifest> = [
56
{
67
type: 'condition',
78
name: 'Section User Permission Condition',
8-
alias: 'Umb.Condition.SectionUserPermission',
9+
alias: UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS,
910
api: UmbSectionUserPermissionCondition,
1011
},
1112
{
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { expect } from '@open-wc/testing';
2+
import { UmbNotificationContext } from '@umbraco-cms/backoffice/notification';
3+
import { UmbControllerHostElementMixin } from '@umbraco-cms/backoffice/controller-api';
4+
import { customElement } from '@umbraco-cms/backoffice/external/lit';
5+
import { UmbCurrentUserContext, UmbCurrentUserStore } from '@umbraco-cms/backoffice/current-user';
6+
import { UmbSectionUserPermissionCondition } from './section-user-permission.condition';
7+
import { UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS } from './constants.js';
8+
9+
@customElement('test-controller-host')
10+
class UmbTestControllerHostElement extends UmbControllerHostElementMixin(HTMLElement) {
11+
currentUserContext = new UmbCurrentUserContext(this);
12+
13+
constructor() {
14+
super();
15+
new UmbCurrentUserStore(this);
16+
new UmbNotificationContext(this);
17+
}
18+
19+
async init() {
20+
await this.currentUserContext.load();
21+
}
22+
}
23+
24+
describe('UmbSectionUserPermissionCondition', () => {
25+
let hostElement: UmbTestControllerHostElement;
26+
let condition: UmbSectionUserPermissionCondition;
27+
28+
beforeEach(async () => {
29+
hostElement = new UmbTestControllerHostElement();
30+
document.body.appendChild(hostElement);
31+
await hostElement.init();
32+
});
33+
34+
afterEach(() => {
35+
document.body.innerHTML = '';
36+
});
37+
38+
it('should return true if the user have access to the section', (done) => {
39+
condition = new UmbSectionUserPermissionCondition(hostElement, {
40+
host: hostElement,
41+
config: {
42+
alias: UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS,
43+
match: 'Umb.Section.Content',
44+
},
45+
onChange: (permitted) => {
46+
expect(permitted).to.be.true;
47+
done();
48+
},
49+
});
50+
});
51+
52+
it('should return false if the user does not have access to the section', (done) => {
53+
condition = new UmbSectionUserPermissionCondition(hostElement, {
54+
host: hostElement,
55+
config: {
56+
alias: UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS,
57+
match: 'DOES_NOT_EXIST',
58+
},
59+
onChange: (permitted) => {
60+
expect(permitted).to.be.false;
61+
done();
62+
},
63+
});
64+
});
65+
});

src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-user-permission.condition.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@ import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
44
import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api';
55
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
66

7+
// Do not export - for internal use only
8+
type UmbOnChangeCallbackType = (permitted: boolean) => void;
9+
710
export class UmbSectionUserPermissionCondition extends UmbControllerBase implements UmbExtensionCondition {
811
config: UmbSectionUserPermissionConditionConfig;
912
permitted = false;
10-
#onChange: () => void;
13+
#onChange: UmbOnChangeCallbackType;
1114

12-
constructor(host: UmbControllerHost, args: UmbConditionControllerArguments<UmbSectionUserPermissionConditionConfig>) {
15+
constructor(
16+
host: UmbControllerHost,
17+
args: UmbConditionControllerArguments<UmbSectionUserPermissionConditionConfig, UmbOnChangeCallbackType>,
18+
) {
1319
super(host);
1420
this.config = args.config;
1521
this.#onChange = args.onChange;
@@ -20,7 +26,7 @@ export class UmbSectionUserPermissionCondition extends UmbControllerBase impleme
2026
(currentUser) => {
2127
const allowedSections = currentUser?.allowedSections || [];
2228
this.permitted = allowedSections.includes(this.config.match);
23-
this.#onChange();
29+
this.#onChange(this.permitted);
2430
},
2531
'umbSectionUserPermissionConditionObserver',
2632
);

src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import type { UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS } from './constants.js';
12
import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api';
23

3-
export type UmbSectionUserPermissionConditionConfig = UmbConditionConfigBase<'Umb.Condition.SectionUserPermission'> & {
4+
export type UmbSectionUserPermissionConditionConfig = UmbConditionConfigBase<
5+
typeof UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS
6+
> & {
47
/**
58
*
69
*
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export * from './conditions/constants.js';
12
export * from './paths.js';
23
export * from './repository/constants.js';

src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/manifests.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
22
import { UMB_USER_PERMISSION_DOCUMENT_PUBLIC_ACCESS } from '../../user-permissions/index.js';
3+
import { UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS } from '@umbraco-cms/backoffice/section';
34
import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin';
45

56
export const manifests: Array<UmbExtensionManifest> = [
@@ -25,7 +26,7 @@ export const manifests: Array<UmbExtensionManifest> = [
2526
alias: UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS,
2627
},
2728
{
28-
alias: 'Umb.Condition.SectionUserPermission',
29+
alias: UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS,
2930
match: 'Umb.Section.Members',
3031
},
3132
],

src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace';
1111
import { UMB_TEMPLATE_PICKER_MODAL, UmbTemplateItemRepository } from '@umbraco-cms/backoffice/template';
1212
import type { UmbDocumentTypeDetailModel } from '@umbraco-cms/backoffice/document-type';
1313
import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router';
14+
import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry';
15+
import { UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS } from '@umbraco-cms/backoffice/section';
16+
import { UMB_SETTINGS_SECTION_ALIAS } from '@umbraco-cms/backoffice/settings';
1417

1518
// import of local components
1619
import './document-workspace-view-info-links.element.js';
@@ -48,6 +51,9 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement {
4851
@state()
4952
private _variantsWithPendingChanges: Array<any> = [];
5053

54+
@state()
55+
private _hasSettingsAccess: boolean = false;
56+
5157
#workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE;
5258
#templateRepository = new UmbTemplateItemRepository(this);
5359
#documentPublishingWorkspaceContext?: typeof UMB_DOCUMENT_PUBLISHING_WORKSPACE_CONTEXT.TYPE;
@@ -83,6 +89,17 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement {
8389
this.#documentPublishingWorkspaceContext = instance;
8490
this.#observePendingChanges();
8591
});
92+
93+
createExtensionApiByAlias(this, UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS, [
94+
{
95+
config: {
96+
match: UMB_SETTINGS_SECTION_ALIAS,
97+
},
98+
onChange: (permitted: boolean) => {
99+
this._hasSettingsAccess = permitted;
100+
},
101+
},
102+
]);
86103
}
87104

88105
#observeContent() {
@@ -189,7 +206,10 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement {
189206
<strong><umb-localize key="content_documentType">Document Type</umb-localize></strong>
190207
<uui-ref-node-document-type
191208
standalone
192-
href=${editDocumentTypePath + 'edit/' + this._documentTypeUnique}
209+
href=${ifDefined(
210+
this._hasSettingsAccess ? editDocumentTypePath + 'edit/' + this._documentTypeUnique : undefined,
211+
)}
212+
?readonly=${!this._hasSettingsAccess}
193213
name=${ifDefined(this.localize.string(this._documentTypeName ?? ''))}>
194214
<umb-icon slot="icon" name=${ifDefined(this._documentTypeIcon)}></umb-icon>
195215
</uui-ref-node-document-type>
@@ -215,7 +235,10 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement {
215235
<uui-ref-node
216236
standalone
217237
name=${ifDefined(this._templateName)}
218-
href=${editTemplatePath + 'edit/' + this._templateUnique}>
238+
href=${ifDefined(
239+
this._hasSettingsAccess ? editTemplatePath + 'edit/' + this._templateUnique : undefined,
240+
)}
241+
?readonly=${!this._hasSettingsAccess}>
219242
<uui-icon slot="icon" name="icon-document-html"></uui-icon>
220243
<uui-action-bar slot="actions">
221244
<uui-button
@@ -311,6 +334,11 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement {
311334
.variant-state > span {
312335
color: var(--uui-color-divider-emphasis);
313336
}
337+
338+
uui-ref-node-document-type[readonly] {
339+
padding-top: 7px;
340+
padding-bottom: 7px;
341+
}
314342
`,
315343
];
316344
}

src/Umbraco.Web.UI.Client/src/packages/documents/section/manifests.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { UMB_CONTENT_SECTION_ALIAS } from '@umbraco-cms/backoffice/content';
22
import { UMB_DOCUMENT_ROOT_ENTITY_TYPE, UMB_CONTENT_MENU_ALIAS } from '@umbraco-cms/backoffice/document';
3+
import { UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS } from '@umbraco-cms/backoffice/section';
34

45
export const manifests: Array<UmbExtensionManifest> = [
56
{
@@ -13,7 +14,7 @@ export const manifests: Array<UmbExtensionManifest> = [
1314
},
1415
conditions: [
1516
{
16-
alias: 'Umb.Condition.SectionUserPermission',
17+
alias: UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS,
1718
match: UMB_CONTENT_SECTION_ALIAS,
1819
},
1920
],

0 commit comments

Comments
 (0)