Skip to content

V16: Adds a state for "forbidden" for entities that return 403 (Access denied) #19557

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7bbe302
feat: adds new localization keys for forbidden routes
iOvergaard Jun 13, 2025
8507f8d
feat: ignore all 400, 401, 403, and 404 errors as they are handled by…
iOvergaard Jun 13, 2025
489920c
feat: adds new elements to show forbidden routes and entities
iOvergaard Jun 13, 2025
7498fb6
feat: adds generic forbidden state to base entities
iOvergaard Jun 13, 2025
7bd8d51
feat: injects a forbidden route component to documents
iOvergaard Jun 13, 2025
9aeb95d
feat: adds 'forbidden' state to media workspace
iOvergaard Jun 13, 2025
1d5ad22
chore: aligns document and media workspaces
iOvergaard Jun 13, 2025
9e5a8bd
test(mock): adds user configuration endpoint
iOvergaard Jun 13, 2025
cc33714
test(mock): adds calculate-start-nodes endpoint to users
iOvergaard Jun 13, 2025
a8da6f2
test(mock): adds missing endpoint for 'client-credentials'
iOvergaard Jun 13, 2025
b5fe441
feat: clean up old observers on entity errors
iOvergaard Jun 13, 2025
6ed28be
feat: aligns UI for better DX if there is no user
iOvergaard Jun 13, 2025
24680ca
fix: returns early if there is no user, instead of trying to append p…
iOvergaard Jun 13, 2025
e7209eb
feat: adds 'forbidden' state to members
iOvergaard Jun 13, 2025
babb81a
Merge branch 'main' into v16/feature/forbidden-route
iOvergaard Jun 25, 2025
1d0ee75
feat: adds support for forbidden document blueprints
iOvergaard Jun 25, 2025
de49026
feat: allows parent to be undefined as well as null
iOvergaard Jun 26, 2025
edadbd1
feat: forbidden route for members as a state
iOvergaard Jun 26, 2025
5669092
chore: simplify language workspace
iOvergaard Jun 26, 2025
354c4fe
test: adds forbidden mock data
iOvergaard Jun 26, 2025
b4b012c
test: adds missing endpoints and a check for forbidden ids
iOvergaard Jun 26, 2025
a90a7f3
Merge branch 'main' into v16/feature/forbidden-route
iOvergaard Jun 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/Umbraco.Web.UI.Client/src/assets/lang/da.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,24 @@ export default {
blueprintDescription:
'En indholdskabelon er foruddefineret indhold, som en redaktør kan vælge at bruge\n som grundlag for at oprette nyt indhold\n ',
},
entityDetail: {
notFoundTitle: (entityType: string) => {
const entityName = entityType ?? 'Elementet';
return `${entityName} blev ikke fundet`;
},
notFoundDescription: (entityType: string) => {
const entityName = entityType ?? 'element';
return `Den/det ønskede ${entityName} kunne ikke findes. Dette kan skyldes, at den/det er blevet slettet, eller at du ikke har adgang. Kontakt din administrator for hjælp.`;
},
forbiddenTitle: (entityType: string) => {
const entityName = entityType ?? 'Elementet';
return `${entityName} er ikke tilgængelig`;
},
forbiddenDescription: (entityType: string) => {
const entityName = entityType ?? 'element';
return `Du har ikke adgang til den/det ønskede ${entityName}. Kontakt din administrator for hjælp.`;
},
},
media: {
clickToUpload: 'Klik for at uploade',
orClickHereToUpload: 'eller klik her for at vælge filer',
Expand Down Expand Up @@ -2605,6 +2623,9 @@ export default {
routing: {
routeNotFoundTitle: 'Ikke fundet',
routeNotFoundDescription: 'Den side du leder efter kunne ikke findes. Kontroller adressen og prøv igen.',
routeForbiddenTitle: 'Adgang nægtet',
routeForbiddenDescription:
'Du har ikke tilladelse til at få adgang til denne ressource. Kontakt venligst din administrator for hjælp.',
},
codeEditor: {
label: 'Code editor',
Expand Down
26 changes: 26 additions & 0 deletions src/Umbraco.Web.UI.Client/src/assets/lang/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,24 @@ export default {
blueprintDescription:
'Eine Inhaltsvorlage ist vordefinierter Inhalt,\n den ein Redakteur als Basis für neuen Inhalt verwenden kann\n ',
},
entityDetail: {
notFoundTitle: (entityType: string) => {
const entityName = entityType ?? 'Element';
return `${entityName} nicht gefunden`;
},
notFoundDescription: (entityType: string) => {
const entityName = entityType ?? 'element';
return `Der angeforderte ${entityName} konnte nicht gefunden werden. Bitte überprüfen Sie die URL und versuchen Sie es erneut.`;
},
forbiddenTitle: (entityType: string) => {
const entityName = entityType ?? 'Element';
return `${entityName} nicht verfügbar`;
},
forbiddenDescription: (entityType: string) => {
const entityName = entityType ?? 'dieses Element';
return `Sie haben keine Berechtigung, auf ${entityName} zuzugreifen. Bitte wenden Sie sich an Ihren Administrator, um Unterstützung zu erhalten.`;
},
},
media: {
clickToUpload: 'Für Upload klicken',
orClickHereToUpload: 'oder klicken Sie hier um eine Datei zu wählen',
Expand Down Expand Up @@ -2007,4 +2025,12 @@ export default {
searchResult: 'Element zurückgegeben',
searchResults: 'Elemente zurückgegeben',
},
routing: {
routeNotFoundTitle: 'Seite wurde nicht gefunden',
routeNotFoundDescription:
'Die angeforderte Seite konnte nicht gefunden werden. Bitte überprüfen Sie die URL und versuchen Sie es erneut.',
routeForbiddenTitle: 'Zugriff verweigert',
routeForbiddenDescription:
'Sie haben keine Berechtigung, auf diese Seite zuzugreifen. Bitte wenden Sie sich an Ihren Administrator, um Unterstützung zu erhalten.',
},
} as UmbLocalizationDictionary;
11 changes: 11 additions & 0 deletions src/Umbraco.Web.UI.Client/src/assets/lang/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,14 @@ export default {
const entityName = entityType ?? 'item';
return `The requested ${entityName} could not be found. Please check the URL and try again.`;
},
forbiddenTitle: (entityType: string) => {
const entityName = entityType ?? 'item';
return `Access denied to this ${entityName}`;
},
forbiddenDescription: (entityType: string) => {
const entityName = entityType ?? 'item';
return `You do not have permission to access this ${entityName}. Please contact your administrator for assistance.`;
},
},
media: {
clickToUpload: 'Click to upload',
Expand Down Expand Up @@ -2735,6 +2743,9 @@ export default {
routing: {
routeNotFoundTitle: 'Not found',
routeNotFoundDescription: 'The requested route could not be found. Please check the URL and try again.',
routeForbiddenTitle: 'Access denied',
routeForbiddenDescription:
'You do not have permission to access this resource. Please contact your administrator for assistance.',
},
codeEditor: {
label: 'Code editor',
Expand Down
2 changes: 2 additions & 0 deletions src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import * as manifestsHandlers from './handlers/manifests.handlers.js';
import * as serverHandlers from './handlers/server.handlers.js';
import { handlers as documentBlueprintHandlers } from './handlers/document-blueprint/index.js';
import { handlers as temporaryFileHandlers } from './handlers/temporary-file/index.js';
import { handlers as segmentHandlers } from './handlers/segment.handlers.js';

const handlers = [
...backofficeHandlers,
Expand Down Expand Up @@ -80,6 +81,7 @@ const handlers = [
...userHandlers,
...documentBlueprintHandlers,
...temporaryFileHandlers,
...segmentHandlers,
...serverHandlers.serverInformationHandlers,
serverHandlers.serverRunningHandler,
...manifestsHandlers.manifestEmptyHandlers,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ export const data: Array<UmbMockDataTypeModel> = [
isDeletable: true,
canIgnoreStartNodes: false,
},
{
id: 'forbidden',
parent: null,
name: 'Forbidden Data Type',
editorAlias: 'Umbraco.TextBox',
editorUiAlias: 'Umb.PropertyEditorUi.TextBox',
values: [],
hasChildren: false,
isFolder: false,
isDeletable: true,
canIgnoreStartNodes: false,
},
{
id: '0cc0eba1-9960-42c9-bf9b-60e150b429ae',
parent: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@ export type UmbMockDictionaryModel = DictionaryItemResponseModel &
DictionaryOverviewResponseModel;

export const data: Array<UmbMockDictionaryModel> = [
{
name: 'Forbidden',
id: 'forbidden',
parent: null,
hasChildren: false,
translatedIsoCodes: ['en-us'],
translations: [
{
isoCode: 'en-us',
translation: 'This is a forbidden dictionary item',
},
{
isoCode: 'da',
translation: 'Dette er et forbudt ordbogsobjekt',
},
],
},
{
name: 'Hello',
id: 'aae7d0ab-53ba-485d-b8bd-12537f9925cb',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const data: Array<UmbMockDocumentBlueprintModel> = [
},
hasChildren: false,
isFolder: false,
parent: null,
name: 'The Simplest Document Blueprint',
variants: [
{
Expand All @@ -40,4 +41,35 @@ export const data: Array<UmbMockDocumentBlueprintModel> = [
},
],
},
{
id: 'forbidden',
documentType: {
id: 'the-simplest-document-type-id',
icon: 'icon-document',
},
hasChildren: false,
isFolder: false,
parent: null,
name: 'A Forbidden Document Blueprint',
variants: [
{
state: DocumentVariantStateModel.DRAFT,
publishDate: '2023-02-06T15:32:24.957009',
culture: 'en-US',
segment: null,
name: 'A Forbidden Document Blueprint',
createDate: '2023-02-06T15:32:05.350038',
updateDate: '2023-02-06T15:32:24.957009',
},
],
values: [
{
editorAlias: 'Umbraco.TextBox',
alias: 'prop1',
culture: null,
segment: null,
value: 'my blueprint value',
},
],
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -1870,4 +1870,58 @@ export const data: Array<UmbMockDocumentTypeModel> = [
keepLatestVersionPerDayForDays: null,
},
},
{
allowedTemplates: [],
defaultTemplate: { id: 'the-simplest-document-type-id' },
id: 'forbidden',
alias: 'forbidden',
name: 'A forbidden document type',
description: null,
icon: 'icon-document',
allowedAsRoot: true,
variesByCulture: false,
variesBySegment: false,
isElement: false,
hasChildren: false,
parent: null,
isFolder: false,
properties: [
{
id: '1680d4d2-cda8-4ac2-affd-a69fc10382b1',
container: { id: 'the-simplest-document-type-id-container' },
alias: 'prop1',
name: 'Prop 1',
description: null,
dataType: { id: '0cc0eba1-9960-42c9-bf9b-60e150b429ae' },
variesByCulture: false,
variesBySegment: false,
sortOrder: 0,
validation: {
mandatory: false,
mandatoryMessage: null,
regEx: null,
regExMessage: null,
},
appearance: {
labelOnTop: false,
},
},
],
containers: [
{
id: 'the-simplest-document-type-id-container',
parent: null,
name: 'Content',
type: 'Group',
sortOrder: 0,
},
],
allowedDocumentTypes: [],
compositions: [],
cleanup: {
preventCleanup: false,
keepAllVersionsNewerThanDays: null,
keepLatestVersionPerDayForDays: null,
},
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const data: Array<UmbMockDocumentModel> = [
{
state: DocumentVariantStateModel.DRAFT,
publishDate: '2023-02-06T15:32:24.957009',
culture: 'en-us',
culture: 'en-US',
segment: null,
name: 'The Simplest Document',
createDate: '2023-02-06T15:32:05.350038',
Expand Down Expand Up @@ -1227,5 +1227,50 @@ export const data: Array<UmbMockDocumentModel> = [
},
],
},
{
ancestors: [],
urls: [],
template: null,
id: 'forbidden',
createDate: '2023-02-06T15:32:05.350038',
parent: null,
documentType: {
id: 'the-simplest-document-type-id',
icon: 'icon-document',
},
hasChildren: false,
noAccess: false,
isProtected: false,
isTrashed: false,
variants: [
{
state: DocumentVariantStateModel.PUBLISHED,
publishDate: '2023-02-06T15:32:24.957009',
culture: 'en-US',
segment: null,
name: 'A forbidden document',
createDate: '2023-02-06T15:32:05.350038',
updateDate: '2023-02-06T15:32:24.957009',
},
{
state: DocumentVariantStateModel.PUBLISHED,
publishDate: '2023-02-06T15:32:24.957009',
culture: 'da-dk',
segment: null,
name: 'Et utilgængeligt dokument',
createDate: '2023-02-06T15:32:05.350038',
updateDate: '2023-02-06T15:32:24.957009',
},
],
values: [
{
editorAlias: 'Umbraco.TextBox',
alias: 'prop1',
culture: null,
segment: null,
value: 'default value here',
},
],
},
...permissionsTestData,
];
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ export const data: Array<UmbMockLanguageModel> = [
isMandatory: false,
fallbackIsoCode: 'en-US',
},
{
name: 'Forbidden',
isoCode: 'forbidden',
isDefault: false,
isMandatory: false,
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -304,4 +304,54 @@ export const data: Array<UmbMockMediaTypeModel> = [
isDeletable: false,
aliasCanBeChanged: false,
},
{
name: 'A Forbidden Media Type',
id: 'forbidden',
parent: null,
description: 'Clicking on this results in a 403 Forbidden error',
alias: 'forbidden',
icon: 'icon-document',
properties: [
{
id: '19',
container: { id: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75' },
alias: 'umbracoFile',
name: 'File',
description: '',
dataType: { id: 'dt-uploadFieldFiles' },
variesByCulture: false,
variesBySegment: false,
sortOrder: 0,
validation: {
mandatory: true,
mandatoryMessage: null,
regEx: null,
regExMessage: null,
},
appearance: {
labelOnTop: false,
},
},
],
containers: [
{
id: 'c3cd2f12-b7c4-4206-8d8b-27c061589f75',
parent: null,
name: 'Content',
type: 'Group',
sortOrder: 0,
},
],
allowedAsRoot: true,
variesByCulture: false,
variesBySegment: false,
isElement: false,
allowedMediaTypes: [{ mediaType: { id: 'forbidden' }, sortOrder: 0 }],
compositions: [],
isFolder: false,
hasChildren: false,
collection: { id: 'dt-collectionView' },
isDeletable: true,
aliasCanBeChanged: false,
},
];
Loading
Loading