Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
203 commits
Select commit Hold shift + click to select a range
97e0c79
Caching: Fixes regression of the caching of null representations for …
AndyButland Oct 2, 2025
d9592aa
Bumped version to 16.3.0-rc2.
AndyButland Oct 2, 2025
bfd2594
Hybrid cache: Check for `ContentCacheNode` instead of object on exist…
AndyButland Oct 6, 2025
629e905
Bump version
Zeegaan Oct 6, 2025
b036eb3
Performance: Added request cache to media type retrieval in media pic…
AndyButland Oct 8, 2025
dab9df3
Bumped version to 16.3.0-rc4.
AndyButland Oct 8, 2025
d6ce8d9
PropertyType workspace: layout & labeling adjustments (#20131)
engijlr Oct 8, 2025
16132b0
Update Umbraco version for LTS release in template
AndyButland Oct 9, 2025
64836e0
Update version from 17.0.0-rc to 17.1.0-rc
AndyButland Oct 9, 2025
1fe7931
Migrations: Adjust the `JsonBlockValueConverter` to handle conflicts …
lauraneto Oct 9, 2025
296858c
Merge branch 'main' into v17/dev
lauraneto Oct 9, 2025
767894b
Color Picker: Validate uniqueness of selected colors (#20431)
Programeerik Oct 9, 2025
bcedc8d
Emails: Add `Expires` header (#20285)
rickbutterfield Oct 9, 2025
5f14365
Merge branch 'main' into v17/dev
AndyButland Oct 9, 2025
a4c373d
Entity Actions: Create button discernible text (fixes #20205) (#20434)
OskarKruger Oct 9, 2025
10bcf5b
Merge branch 'main' into v17/dev
leekelleher Oct 10, 2025
de44907
Fixed build error
leekelleher Oct 10, 2025
99c2aaf
Members: Forward port of fix for member lockout issue #16988 from PR …
AndyButland Oct 10, 2025
7a48c11
Merge branch 'main' into v17/dev
AndyButland Oct 10, 2025
fd34ce5
Icon Picker: Fit icons scroll container to modal height (#20438)
bjarnef Oct 10, 2025
0996891
Merge branch 'main' into v17/dev
AndyButland Oct 10, 2025
3df8b9e
Refactoring: Fixed spelling mistake in method name (#20460)
AndyButland Oct 10, 2025
2c284a7
Merge branch 'main' into v17/dev
AndyButland Oct 10, 2025
7b4684c
UX: Center align log type in media history view (#20469)
bjarnef Oct 13, 2025
e28153f
Merge branch 'main' into v17/dev
AndyButland Oct 13, 2025
0a027dd
Dependencies: Fixed dependency conflicts when installing Microsoft.En…
lauraneto Oct 13, 2025
3ac37f3
Recycle Bin: Trigger cache invalidation for trashed document/media it…
leekelleher Oct 13, 2025
28e4caa
fix merge gone wrong
nielslyngsoe Oct 13, 2025
3393feb
News dashboard: API and rendering of news stories on dashboard (#20416)
NillasKA Oct 13, 2025
e336f9d
Merge branch 'release/16.3'
AndyButland Oct 14, 2025
4ba1866
UFM: Adds `$index` support to Block editors (fixes #20470) (#20488)
leekelleher Oct 14, 2025
4c42175
Merge branch 'release/17.0' into v17/dev
nielslyngsoe Oct 14, 2025
494674d
Entity Actions: More create button discernible text, extension of #20…
OskarKruger Oct 14, 2025
b5662d9
Dependencies: Remove `Microsoft.CodeAnalysis.CSharp` dependency from …
lauraneto Oct 14, 2025
4dbb4eb
Merge branch 'main' into v17/dev
lauraneto Oct 14, 2025
12adfd5
Performance: Reduce number of database calls in save and publish oper…
AndyButland Oct 14, 2025
e53220c
Delivery API: Fix not reindexing branch descendants when branch root …
Migaroez Oct 14, 2025
068183a
Merge branch 'main' into v17/dev
Migaroez Oct 14, 2025
ac56bff
fix import in storybook of moved file
madsrasmussen Oct 14, 2025
cdf9ee4
Added culture to the ApiContentRouteBuilder to include variant langua…
andersreus Oct 14, 2025
07d0d7d
Merge branch 'main' into v17/dev
AndyButland Oct 14, 2025
a19b9fb
UFM: Add camelCase aliases for UFM filters to support UFMJS expressio…
Copilot Oct 14, 2025
e22b459
WorkspaceView: Add tests for create and using custom workspace view (…
NguyenThuyLan Oct 15, 2025
1ab13a9
Dashboard: Add tests for create and using custom dashboard (#20253)
NguyenThuyLan Oct 15, 2025
fdf759d
Content Types: Prevent creation of document type with an alias that c…
AndyButland Oct 15, 2025
a95fd9f
Merge branch 'main' into v17/dev
AndyButland Oct 15, 2025
e71f36d
Back Office: Fixes link to workspace root from breadcrumb trail (clos…
AndyButland Oct 15, 2025
b25feac
Merge branch 'main' into v17/dev
AndyButland Oct 15, 2025
2412c66
Merge branch 'release/17.0' into v17/dev
nielslyngsoe Oct 15, 2025
4c05a11
Fixes 20476 - Changes icon to be no entry sign (#20496)
warrenbuckley Oct 15, 2025
cee163a
Merge branch 'release/17.0' into v17/dev
nielslyngsoe Oct 15, 2025
c5c417d
Merge branch 'release/17.0' into v17/dev
AndyButland Oct 15, 2025
a504fd1
Bump version to 16.3.0
lauraneto Oct 16, 2025
ec354ce
Merge branch 'release/16.3'
lauraneto Oct 16, 2025
ae73fb3
E2E: Updated acceptance tests to match changes (#20493)
andr317c Oct 16, 2025
369b020
Explicitly flush isolated caches by key for content updates (#20519)
kjac Oct 16, 2025
271edb5
News Dashboard: split into card + container, parent handles the data …
engijlr Oct 16, 2025
4a504e8
Extensions: Adds `@provideContext` and `@consumeContext` decorators f…
iOvergaard Oct 16, 2025
62edad1
Bumped version to 16.3.1.
AndyButland Oct 16, 2025
31bcbc1
Don't use non-generic ILogger as a fallback in BlockEditorPropertyVal…
BenWhite27 Oct 16, 2025
6458bb4
Don't use non-generic ILogger as a fallback in BlockEditorPropertyVal…
BenWhite27 Oct 16, 2025
de0503d
Merge branch 'main' into v17/dev
AndyButland Oct 16, 2025
96f597e
Merge branch 'release/16.3.1'
AndyButland Oct 17, 2025
d17ba80
build(deps): bumps @umbraco-ui/uui from 1.16.0-rc.0 to 1.16.0
iOvergaard Oct 17, 2025
a3a8be4
Templates: Retain layout from file when loading template (closes #205…
AndyButland Oct 17, 2025
105cb9d
Added trashed state so when requesting content from the recycle bin v…
andersreus Oct 17, 2025
5278b67
Merge branch 'main' into v17/dev
AndyButland Oct 17, 2025
5a65eb1
Update OpenApi.json and client-side models.
AndyButland Oct 17, 2025
8b1f186
Update OpenApi.json and client-side models.
AndyButland Oct 17, 2025
b142dcc
Merge branch 'main' into v17/dev
AndyButland Oct 17, 2025
ae2c59b
Make the indexing batch size configurable (#20543)
kjac Oct 17, 2025
d5a2f05
Preview: Redirect to published URL on exit (#20556)
leekelleher Oct 20, 2025
7751e40
E2E: QA Fixed the flaky tests related to publishing content with imag…
nhudinh0309 Oct 21, 2025
5337c38
Bump vite from 7.1.9 to 7.1.11 in /src/Umbraco.Web.UI.Client
dependabot[bot] Oct 20, 2025
ae41438
Tiptap RTE: Allow removal of unregistered extensions (#20571)
leekelleher Oct 21, 2025
81a8a0c
Hybrid Cache: Resolve start-up errors with mis-matched types (#20554)
AndyButland Oct 21, 2025
1ceec18
Media: Fixes SQL error to ensure database relation between user group…
AndyButland Oct 21, 2025
daace4b
Publishing: Resolve exceptions on publish branch (#20464)
AndyButland Oct 21, 2025
5488c77
Bumped version to 16.3.2.
AndyButland Oct 21, 2025
8aa9dc8
Hybrid Cache: Resolve start-up errors with mis-matched types (#20554)
AndyButland Oct 21, 2025
942ccc8
docs: Add 'Running Umbraco in Different Modes' section to copilot-ins…
iOvergaard Oct 21, 2025
caeb345
build(dev): adds umbracoapplicationurl to vscode launch params
iOvergaard Oct 21, 2025
4717264
Merge branch 'release/17.0' into v17/dev
leekelleher Oct 21, 2025
0792e43
Merge branch 'release/16.3.2'
AndyButland Oct 22, 2025
44d5239
Merge branch 'release/17.0' into v17/dev
iOvergaard Oct 22, 2025
79639c0
Item Repository: Sort statuses by order of unique (#20603)
nielslyngsoe Oct 22, 2025
298db76
Merge branch 'release/17.0' into v17/dev
nielslyngsoe Oct 22, 2025
48759b9
Migrations: Use reliable GUID to check for existence of data type whe…
AndyButland Oct 22, 2025
21bf23b
Dictionary: Fix shortcut Ctrl + S not saving dictionary items (#20605)
nielslyngsoe Oct 22, 2025
c2eea5d
Populate IncludeDescendants on ContentPublishedNotification when publ…
AndyButland Oct 22, 2025
62c1d44
Webhooks: Register OutputExpansionStrategy for webhooks if Delivery A…
Migaroez Oct 22, 2025
4a65f56
Hotfix: Implement a specific sorting method for statuses as the exist…
nielslyngsoe Oct 22, 2025
194fee7
Use tryExecute for delete API call
madsrasmussen Oct 22, 2025
924af4b
Merge branch 'main' into v17/dev
leekelleher Oct 22, 2025
f88e28d
Filesystem: Prevent tree showing other filetypes than the supported o…
NillasKA Oct 22, 2025
c422a9e
Merge branch 'main' into v17/dev
AndyButland Oct 22, 2025
6bc498a
Trees: Restore backward compatibility for file system based tree cont…
AndyButland Oct 22, 2025
7dcf329
Merge branch 'main' into v17/dev
AndyButland Oct 22, 2025
9cb59fe
Bumped version to 16.3.3.
AndyButland Oct 22, 2025
a09e177
Migrations: Use reliable GUID to check for existence of data type whe…
AndyButland Oct 22, 2025
644334c
Trees: Restore backward compatibility for file system based tree cont…
AndyButland Oct 22, 2025
b762135
Exclude 'release/no-notes' from release labels
nul800sebastiaan Oct 23, 2025
9cc2df7
Preview: Removes sessions (#20561)
leekelleher Oct 23, 2025
08d2173
Bump vite from 7.1.9 to 7.1.11 in /src/Umbraco.Web.UI.Login
dependabot[bot] Oct 23, 2025
602ad42
Merge branch 'release/17.0' into v17/dev
nielslyngsoe Oct 23, 2025
1d8cadb
Merge branch 'main' into v17/dev
nielslyngsoe Oct 23, 2025
3854b2b
Block List: Remove bold label from inline editing (#20437)
bjarnef Oct 23, 2025
e482976
User And User Group Workspace: Make views extendable (#20548) (#20617)
madsrasmussen Oct 23, 2025
67d1ac3
Merge branch 'main' into v17/dev
nielslyngsoe Oct 23, 2025
8434c7d
Icon Picker: Fix empty selection allowed on mandatory fields and add …
engijlr Oct 23, 2025
6ba03a4
Merge branch 'release/16.3.3'
AndyButland Oct 24, 2025
a5fcfc2
Merge branch 'main' of https://github.com/umbraco/Umbraco-CMS
AndyButland Oct 24, 2025
d9c201e
docs: Add backoffice preview URL to README files (#20623)
iOvergaard Oct 24, 2025
d9cdf03
Preview: Allows changing the preview environment inside the preview a…
leekelleher Oct 24, 2025
e893682
Don't call generateAlias on #onAliasChange()
BatJan Oct 23, 2025
f33eb3f
Media types: Handle null configured file extensions when populating a…
AndyButland Oct 27, 2025
13c164d
Bump version to 16.3.4.
AndyButland Oct 28, 2025
fd91f88
Item Repository: Sort statuses by order of unique (#20603)
nielslyngsoe Oct 22, 2025
18ab333
Hotfix: Implement a specific sorting method for statuses as the exist…
nielslyngsoe Oct 22, 2025
3dc65c4
Bump package-lock.json to 16.3.4.
AndyButland Oct 28, 2025
cee7305
Merge branch 'main' into v17/dev
nielslyngsoe Oct 28, 2025
bea21d7
Caching: Resolves publish and install issues related to stale cached …
AndyButland Oct 28, 2025
0d2393d
Caching: Resolves publish and install issues related to stale cached …
AndyButland Oct 28, 2025
498bb5e
Merge branch 'main' into v17/dev
AndyButland Oct 28, 2025
8733230
Property Editors: Added form control and mandatory support to editors…
engijlr Oct 28, 2025
1f82bdd
Merge branch 'release/16.3.4'
AndyButland Oct 29, 2025
e7ccfaa
Routing: Added method to `IDocumentUrlService` for retrieving documen…
AndyButland Oct 29, 2025
f87e15b
build: adds back the ^ missing from openapi-ts to allow newer version…
iOvergaard Oct 29, 2025
ce59537
build: updates lockfile
iOvergaard Oct 29, 2025
7af67d2
Have to control of the state store navigation for custom sections or …
rammi987 Oct 29, 2025
837a566
Merge branch 'release/17.0' into v17/dev
nielslyngsoe Oct 29, 2025
cdf0e5b
Merge remote-tracking branch 'origin/v17/dev'
iOvergaard Oct 30, 2025
1c6d4f3
bumps package.json version to 17.1.0-rc
iOvergaard Oct 30, 2025
3d24f0a
Implementing an inline toggle button to show/hide password. (#20611)
MrHutmat Oct 30, 2025
5032b25
Icon picker: Better title for icon colors (#20649)
bjarnef Oct 30, 2025
b8cb198
Document Recycle Bin: Remove non-relevant entity bulk actions (closes…
madsrasmussen Oct 30, 2025
f27fb58
box-sizing to ensure height is correct (#20694)
nathanwoulfe Oct 31, 2025
66409b9
Performance: Request cache referenced entities when saving documents …
AndyButland Oct 31, 2025
973a957
Task: Dependency track (#20670)
lauraneto Oct 31, 2025
b4220a4
Collection children: A slim navigation of collection children + highe…
nielslyngsoe Oct 31, 2025
5e87dea
Task: Dependency track (#20670)
lauraneto Oct 31, 2025
96ecef0
Performance: Request cache referenced entities when saving documents …
AndyButland Oct 31, 2025
4fc79ad
Preview: Add `allow-forms` to iframe sandbox attributes (#20701)
rickbutterfield Oct 31, 2025
43ac322
Preview: Add `allow-forms` to iframe sandbox attributes (#20701)
rickbutterfield Oct 31, 2025
cfa5304
Property Editors: Add mandatory support to Number Range (Refactor). (…
engijlr Nov 3, 2025
c1a8500
Tiptap RTE: Localizes property editor UI label (removes "[Tiptap]" fr…
leekelleher Nov 3, 2025
76fed82
E2E: QA cherry picked acceptance tests updates from 17 (#20714)
andr317c Nov 4, 2025
b502e29
Merge remote-tracking branch 'origin/release/17.0'
iOvergaard Nov 4, 2025
2b8146f
Media: Add protection to restrict access to media in recycle bin (clo…
AndyButland Nov 4, 2025
fa5c53b
Auth: Cleans up stale or completed auth details from storage (#20725)
iOvergaard Nov 4, 2025
4e74dbf
Merge branch 'release/16.4' into v16/dev
iOvergaard Nov 4, 2025
5739049
Merge remote-tracking branch 'origin/v16/dev'
iOvergaard Nov 4, 2025
e8f2bb3
E2E: QA Fixed the failing tests due to the recent UI changes (#20576)
nhudinh0309 Nov 5, 2025
297c5d3
Header: Adjusted button focus border color contrast (#20562)
MrHutmat Nov 5, 2025
72d7ed4
Property Editors: Hide "add button" when maximum configuration is 1 (…
NguyenThuyLan Nov 5, 2025
594c3f4
Rich Text Editor: The media picker skips the "edit media" dialog when…
iOvergaard Nov 5, 2025
7502a38
Dependencies: Update dotnet sdk and node development dependency to la…
AndyButland Nov 5, 2025
e155fdf
Block Custom View: Add tests for create and using block custom view (…
NguyenThuyLan Nov 6, 2025
f11b8ff
User Workspace: localize password mismatch feedback (#20747)
nielslyngsoe Nov 6, 2025
3ab12e9
Migrations: Fixes migrations from 13 to 17. Media Folder without Coll…
NillasKA Nov 6, 2025
f4a7a2d
Reset password localization + format (#20750)
nielslyngsoe Nov 6, 2025
7162c45
Fix memory leak with `IOptionsMonitor.OnChange` and non-singleton reg…
AndyButland Nov 6, 2025
b866c31
Property action: Add tests for create and using Property Action UI Ex…
NguyenThuyLan Nov 7, 2025
ca08652
Installer: Fix issues with newsletter signup (#20705)
AndyButland Nov 7, 2025
aae316e
Localization: Supply the display name to the localization key for the…
warrenbuckley Nov 9, 2025
04918ec
Slider property editor: Fix for preset value handling of `enableRange…
Luuk1983 Nov 9, 2025
fcfaff9
Querying: Restore ability to retrieve all children published in any c…
AndyButland Nov 10, 2025
bce85e1
Package section: use command icon for migrations, remove prop (#20775)
nielslyngsoe Nov 10, 2025
73fd52a
Login: Added custom validation for missing password and user/email on…
MrHutmat Nov 10, 2025
89989d6
Templates: Fix "Discard changes?" dialog after creating template with…
iOvergaard Nov 10, 2025
afec900
Merge branch 'release/17.0'
nielslyngsoe Nov 10, 2025
ab51aac
Backoffice Item Pickers: Show error for missing items in 10 picker ty…
iOvergaard Nov 10, 2025
9fa382e
Fix block list inline mode (#20745)
andrejd22 Nov 10, 2025
12b483f
Fix block list inline mode (#20745)
nielslyngsoe Nov 10, 2025
d8198d2
Accessibility: Adding a label attribute for `<uui-button>` in news da…
MrHutmat Nov 11, 2025
cfa32b2
Integration Tests: Avoid asserting on errors for permission tests (#2…
AndyButland Nov 11, 2025
41582de
Collection view: add tests for create and using collection view (#20667)
NguyenThuyLan Nov 11, 2025
0797a3f
Merge remote-tracking branch 'origin/release/16.4'
iOvergaard Nov 11, 2025
55769b1
Merge remote-tracking branch 'origin/release/17.0'
iOvergaard Nov 11, 2025
524912a
Fix accidental update to global.json.
AndyButland Nov 11, 2025
0858d02
Single block migration (#20663)
Migaroez Nov 11, 2025
9ad4a7e
Adds Clear Clipboard button & logic (#20757)
warrenbuckley Nov 11, 2025
c9fc2f2
Bump playwright and @playwright/test in /tests/Umbraco.Tests.Acceptan…
dependabot[bot] Nov 12, 2025
c60cf90
E2E: QA added entity picker acceptance tests (#20776)
andr317c Nov 12, 2025
ca15aad
Fix for partial view caches not being cleared when content is publish…
justin-nevitech Nov 13, 2025
139b528
Database migrations: Support `DateOnly` and `TimeOnly` in syntax prov…
NguyenThuyLan Nov 13, 2025
c295271
Bumped version to 16.4.0-rc2.
AndyButland Nov 13, 2025
49ba89c
Move access/refresh tokens to secure cookies (#20779)
kjac Nov 13, 2025
d4d4b8a
Content Type Designer: Always register root route to support drag-and…
engijlr Nov 13, 2025
f075223
Relations: Exclude the relate parent on delete relation type from che…
AndyButland Nov 13, 2025
b65d2b0
Collection view test: update changes for v17 (#20812)
NguyenThuyLan Nov 13, 2025
597eb58
Merge branch 'release/17.0'
AndyButland Nov 13, 2025
eeda55c
Preview: Add validation support to Save and Preview button (closes #2…
iOvergaard Nov 13, 2025
714fbf3
Keyboard navigation: Return to opening element after modal close (#20…
MrHutmat Nov 13, 2025
15c6ca7
Merge remote-tracking branch 'origin/release/16.4' into v16/dev
iOvergaard Nov 13, 2025
931041c
Merge remote-tracking branch 'origin/v16/dev'
iOvergaard Nov 13, 2025
617d301
Hides the content files that come from the Microsoft.CodeAnalysis.Wor…
andr317c Nov 13, 2025
bbd3036
Media Picker: Remove duplicate loaders in media cards. (#20793)
engijlr Nov 13, 2025
8b07659
Entity Sign: Improve Firefox visibility and add focus support. (#20733)
engijlr Nov 13, 2025
e549217
Content Type Designer: Use input-with-alias and implement regex valid…
engijlr Nov 13, 2025
73847d1
Property Editors: Added form control and mandatory support to editors…
engijlr Nov 13, 2025
a4438e5
Decimal property editor: Flexibly parse decimal value with different …
AndyButland Nov 14, 2025
33ba522
Remove Client build and restore targets from CSPROJ in template
warrenbuckley Nov 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
13 changes: 10 additions & 3 deletions .github/BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ In order to work with the Umbraco source code locally, first make sure you have

### Familiarizing yourself with the code

Umbraco is a .NET application using C#. The solution is broken down into multiple projects. There are several class libraries. The `Umbraco.Web.UI` project is the main project that hosts the back office and login screen. This is the project you will want to run to see your changes.
Umbraco is a .NET application using C#. The solution is broken down into multiple projects. There are several class libraries. The `Umbraco.Web.UI` project is the main project that hosts the back office and login screen. This is the project you will want to run to see your changes.

There are two web projects in the solution with client-side assets based on TypeScript, `Umbraco.Web.UI.Client` and `Umbraco.Web.UI.Login`.

Expand Down Expand Up @@ -73,13 +73,20 @@ Just be careful not to include this change in your PR.

Conversely, if you are working on front-end only, you want to build the back-end once and then run it. Before you do so, update the configuration in `appSettings.json` to add the following under `Umbraco:Cms:Security`:

```
```json
"BackOfficeHost": "http://localhost:5173",
"AuthorizeCallbackPathName": "/oauth_complete",
"AuthorizeCallbackLogoutPathName": "/logout",
"AuthorizeCallbackErrorPathName": "/error"
"AuthorizeCallbackErrorPathName": "/error",
"BackOfficeTokenCookie": {
"Enabled": true,
"SameSite": "None"
}
```

> [!NOTE]
> If you get stuck in a login loop, try clearing your browser cookies for localhost, and make sure that the `BackOfficeTokenCookie` settings are correct. Namely, that `SameSite` should be set to `None` when running the front-end server separately.

Then run Umbraco from the command line.

```
Expand Down
8 changes: 8 additions & 0 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ Some important documentation links to get you started:
- [Getting to know Umbraco](https://docs.umbraco.com/umbraco-cms/fundamentals/get-to-know-umbraco)
- [Tutorials for creating a basic website and customizing the editing experience](https://docs.umbraco.com/umbraco-cms/tutorials/overview)

## Backoffice Preview

Want to see the latest backoffice UI in action? Check out our live preview:

**[backofficepreview.umbraco.com](https://backofficepreview.umbraco.com/)**

This preview is automatically deployed from the main branch and showcases the latest backoffice features and improvements. It runs from mock data and persistent edits are not supported.

## Get help

If you need a bit of feedback while building your Umbraco projects, we are [chatty on Discord](https://discord.umbraco.com). Our Discord server serves as a social space for all Umbracians. If you have any questions or need some help with a problem, head over to our [dedicated forum](https://forum.umbraco.com/) where the Umbraco Community will be happy to help.
Expand Down
27 changes: 21 additions & 6 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,19 +94,34 @@ The solution contains 30 C# projects organized as follows:

## Common Tasks

### Frontend Development
For frontend-only changes:
1. Configure backend for frontend development:
```json
<!-- Add to src/Umbraco.Web.UI/appsettings.json under Umbraco:Cms:Security: -->
### Running Umbraco in Different Modes

**Production Mode (Standard Development)**
Use this for backend development, testing full builds, or when you don't need hot reloading:
1. Build frontend assets: `cd src/Umbraco.Web.UI.Client && npm run build:for:cms`
2. Run backend: `cd src/Umbraco.Web.UI && dotnet run --no-build`
3. Access backoffice: `https://localhost:44339/umbraco`
4. Application uses compiled frontend from `wwwroot/umbraco/backoffice/`

**Vite Dev Server Mode (Frontend Development with Hot Reload)**
Use this for frontend-only development with hot module reloading:
1. Configure backend for frontend development - Add to `src/Umbraco.Web.UI/appsettings.json` under `Umbraco:CMS:Security`:
```json
"BackOfficeHost": "http://localhost:5173",
"AuthorizeCallbackPathName": "/oauth_complete",
"AuthorizeCallbackLogoutPathName": "/logout",
"AuthorizeCallbackErrorPathName": "/error"
"AuthorizeCallbackErrorPathName": "/error",
"BackOfficeTokenCookie": {
"Enabled": true,
"SameSite": "None"
}
```
2. Run backend: `cd src/Umbraco.Web.UI && dotnet run --no-build`
3. Run frontend dev server: `cd src/Umbraco.Web.UI.Client && npm run dev:server`
4. Access backoffice: `http://localhost:5173/` (no `/umbraco` prefix)
5. Changes to TypeScript/Lit files hot reload automatically

**Important:** Remove the `BackOfficeHost` configuration before committing or switching back to production mode.

### Backend-Only Development
For backend-only changes, disable frontend builds:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/label-to-release-announcement.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
for (const item of items) {
const releaseLabels = (item.labels || [])
.map(l => (typeof l === "string" ? l : l.name)) // always get the name
.filter(n => typeof n === "string" && n.startsWith("release/"));
.filter(n => typeof n === "string" && n.startsWith("release/") && n !== "release/no-notes");
if (releaseLabels.length === 0) continue;

core.info(`#${item.number}: ${releaseLabels.join(", ")}`);
Expand Down
6 changes: 5 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,14 @@
"env": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "https://localhost:44339",
"UMBRACO__CMS__WEBROUTING__UMBRACOAPPLICATIONURL": "https://localhost:44339",
"UMBRACO__CMS__SECURITY__BACKOFFICEHOST": "http://localhost:5173",
"UMBRACO__CMS__SECURITY__AUTHORIZECALLBACKPATHNAME": "/oauth_complete",
"UMBRACO__CMS__SECURITY__AUTHORIZECALLBACKLOGOUTPATHNAME": "/logout",
"UMBRACO__CMS__SECURITY__AUTHORIZECALLBACKERRORPATHNAME": "/error"
"UMBRACO__CMS__SECURITY__AUTHORIZECALLBACKERRORPATHNAME": "/error",
"UMBRACO__CMS__SECURITY__KEEPUSERLOGGEDIN": "true",
"UMBRACO__CMS__SECURITY__BACKOFFICETOKENCOOKIE__ENABLED": "true",
"UMBRACO__CMS__SECURITY__BACKOFFICETOKENCOOKIE__SAMESITE": "None"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Umbraco.Web.UI/Views"
Expand Down
35 changes: 26 additions & 9 deletions build/nightly-E2E-test-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ schedules:
branches:
include:
- v15/dev
- v16/dev
- main
- v17/dev

parameters:
- name: skipIntegrationTests
displayName: Skip integration tests
type: boolean
default: false

- name: differentAppSettingsAcceptanceTests
displayName: Run acceptance tests with different app settings
- name: skipDifferentAppSettingsAcceptanceTests
displayName: Skip acceptance tests with different app settings
type: boolean
default: true
default: false

- name: skipDefaultConfigAcceptanceTests
displayName: Skip tests with DefaultConfig
Expand Down Expand Up @@ -443,15 +443,15 @@ stages:
vmImage: "ubuntu-latest"
CONNECTIONSTRINGS__UMBRACODBDSN: "Server=(local);Database=Umbraco;User Id=sa;Password=$(SA_PASSWORD);Encrypt=True;TrustServerCertificate=True"
WindowsPart1Of3:
testCommand: "npm run test -- --shard=1/3"
testCommand: "npm run testWindows -- --shard=1/3"
testFolder: "DefaultConfig"
vmImage: "windows-latest"
WindowsPart2Of3:
testCommand: "npm run test -- --shard=2/3"
testCommand: "npm run testWindows -- --shard=2/3"
testFolder: "DefaultConfig"
vmImage: "windows-latest"
WindowsPart3Of3:
testCommand: "npm run test -- --shard=3/3"
testCommand: "npm run testWindows -- --shard=3/3"
testFolder: "DefaultConfig"
vmImage: "windows-latest"
pool:
Expand Down Expand Up @@ -505,7 +505,7 @@ stages:
jobs:
- job:
displayName: E2E Tests with Different App settings (SQL Server)
condition: ${{ eq(parameters.differentAppSettingsAcceptanceTests, true) }}
condition: ${{ eq(parameters.skipDifferentAppSettingsAcceptanceTests, false) }}
timeoutInMinutes: 180
variables:
SA_PASSWORD: UmbracoAcceptance123!
Expand Down Expand Up @@ -564,6 +564,23 @@ stages:
CONNECTIONSTRINGS__UMBRACODBDSN: Server=(local);Database=Umbraco;User Id=sa;Password=$(SA_PASSWORD);Encrypt=True;TrustServerCertificate=True
CONNECTIONSTRINGS__UMBRACODBDSN_PROVIDERNAME: Microsoft.Data.SqlClient
additionalEnvironmentVariables: false
# EntityDataPicker
WindowsEntityDataPicker:
vmImage: "windows-latest"
testFolder: "EntityDataPicker"
port: ''
testCommand: "npx playwright test --project=entityDataPicker"
CONNECTIONSTRINGS__UMBRACODBDSN: Data Source=(localdb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Umbraco.mdf;Integrated Security=True
CONNECTIONSTRINGS__UMBRACODBDSN_PROVIDERNAME: Microsoft.Data.SqlClient
additionalEnvironmentVariables: false
LinuxEntityDataPicker:
vmImage: "ubuntu-latest"
testFolder: "EntityDataPicker"
port: ''
testCommand: "npx playwright test --project=entityDataPicker"
CONNECTIONSTRINGS__UMBRACODBDSN: Server=(local);Database=Umbraco;User Id=sa;Password=$(SA_PASSWORD);Encrypt=True;TrustServerCertificate=True
CONNECTIONSTRINGS__UMBRACODBDSN_PROVIDERNAME: Microsoft.Data.SqlClient
additionalEnvironmentVariables: false
pool:
vmImage: $(vmImage)
steps:
Expand Down Expand Up @@ -695,4 +712,4 @@ stages:
--data "$PAYLOAD" \
"$SLACK_WEBHOOK_URL"
env:
SLACK_WEBHOOK_URL: $(E2ESLACKWEBHOOKURL)
SLACK_WEBHOOK_URL: $(E2ESLACKWEBHOOKURL)
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using OpenIddict.Server;
using OpenIddict.Validation;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Web.Common.Security;
using Umbraco.Extensions;

namespace Umbraco.Cms.Api.Common.DependencyInjection;

internal sealed class HideBackOfficeTokensHandler
: IOpenIddictServerHandler<OpenIddictServerEvents.ApplyTokenResponseContext>,
IOpenIddictServerHandler<OpenIddictServerEvents.ExtractTokenRequestContext>,
IOpenIddictValidationHandler<OpenIddictValidationEvents.ProcessAuthenticationContext>,
INotificationHandler<UserLogoutSuccessNotification>
{
private const string RedactedTokenValue = "[redacted]";
private const string AccessTokenCookieKey = "__Host-umbAccessToken";
private const string RefreshTokenCookieKey = "__Host-umbRefreshToken";

private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IDataProtectionProvider _dataProtectionProvider;
private readonly BackOfficeTokenCookieSettings _backOfficeTokenCookieSettings;
private readonly GlobalSettings _globalSettings;

public HideBackOfficeTokensHandler(
IHttpContextAccessor httpContextAccessor,
IDataProtectionProvider dataProtectionProvider,
IOptions<BackOfficeTokenCookieSettings> backOfficeTokenCookieSettings,
IOptions<GlobalSettings> globalSettings)
{
_httpContextAccessor = httpContextAccessor;
_dataProtectionProvider = dataProtectionProvider;
_backOfficeTokenCookieSettings = backOfficeTokenCookieSettings.Value;
_globalSettings = globalSettings.Value;
}

/// <summary>
/// This is invoked when tokens (access and refresh tokens) are issued to a client. For the back-office client,
/// we will intercept the response, write the tokens from the response into HTTP-only cookies, and redact the
/// tokens from the response, so they are not exposed to the client.
/// </summary>
public ValueTask HandleAsync(OpenIddictServerEvents.ApplyTokenResponseContext context)
{
if (context.Request?.ClientId is not Constants.OAuthClientIds.BackOffice)
{
// Only ever handle the back-office client.
return ValueTask.CompletedTask;
}

HttpContext httpContext = GetHttpContext();

if (context.Response.AccessToken is not null)
{
SetCookie(httpContext, AccessTokenCookieKey, context.Response.AccessToken);
context.Response.AccessToken = RedactedTokenValue;
}

if (context.Response.RefreshToken is not null)
{
SetCookie(httpContext, RefreshTokenCookieKey, context.Response.RefreshToken);
context.Response.RefreshToken = RedactedTokenValue;
}

return ValueTask.CompletedTask;
}

/// <summary>
/// This is invoked when requesting new tokens.
/// </summary>
public ValueTask HandleAsync(OpenIddictServerEvents.ExtractTokenRequestContext context)
{
if (context.Request?.ClientId != Constants.OAuthClientIds.BackOffice)
{
// Only ever handle the back-office client.
return ValueTask.CompletedTask;
}

// For the back-office client, this only happens when a refresh token is being exchanged for a new access token.
if (context.Request.RefreshToken == RedactedTokenValue
&& TryGetCookie(RefreshTokenCookieKey, out var refreshToken))
{
context.Request.RefreshToken = refreshToken;
}
else
{
// If we got here, either the refresh token was not redacted, or nothing was found in the refresh token cookie.
// If OpenIddict found a refresh token, it could be an old token that is potentially still valid. For security
// reasons, we cannot accept that; at this point, we expect the refresh tokens to be explicitly redacted.
context.Request.RefreshToken = null;
}


return ValueTask.CompletedTask;
}

/// <summary>
/// This is invoked when extracting the auth context for a client request.
/// </summary>
public ValueTask HandleAsync(OpenIddictValidationEvents.ProcessAuthenticationContext context)
{
// For the back-office client, this only happens when an access token is sent to the API.
if (context.AccessToken != RedactedTokenValue)
{
return ValueTask.CompletedTask;
}

if (TryGetCookie(AccessTokenCookieKey, out var accessToken))
{
context.AccessToken = accessToken;
}

return ValueTask.CompletedTask;
}

public void Handle(UserLogoutSuccessNotification notification)
{
HttpContext? context = _httpContextAccessor.HttpContext;
if (context is null)
{
// For some reason there is no ambient HTTP context, so we can't clean up the cookies.
// This is OK, because the tokens in the cookies have already been revoked at user sign-out,
// so the cookie clean-up is mostly cosmetic.
return;
}

context.Response.Cookies.Delete(AccessTokenCookieKey);
context.Response.Cookies.Delete(RefreshTokenCookieKey);
}

private HttpContext GetHttpContext()
=> _httpContextAccessor.GetRequiredHttpContext();

private void SetCookie(HttpContext httpContext, string key, string value)
{
var cookieValue = EncryptionHelper.Encrypt(value, _dataProtectionProvider);

var cookieOptions = new CookieOptions
{
// Prevent the client-side scripts from accessing the cookie.
HttpOnly = true,

// Mark the cookie as essential to the application, to enforce it despite any
// data collection consent options. This aligns with how ASP.NET Core Identity
// does when writing cookies for cookie authentication.
IsEssential = true,

// Cookie path must be root for optimal security.
Path = "/",

// For optimal security, the cooke must be secure. However, Umbraco allows for running development
// environments over HTTP, so we need to take that into account here.
// Thus, we will make the cookie secure if:
// - HTTPS is explicitly enabled by config (default for production environments), or
// - The current request is over HTTPS (meaning the environment supports it regardless of config).
Secure = _globalSettings.UseHttps || httpContext.Request.IsHttps,

// SameSite is configurable (see BackOfficeTokenCookieSettings for defaults):
SameSite = ParseSameSiteMode(_backOfficeTokenCookieSettings.SameSite),
};

httpContext.Response.Cookies.Delete(key, cookieOptions);
httpContext.Response.Cookies.Append(key, cookieValue, cookieOptions);
}

private bool TryGetCookie(string key, [NotNullWhen(true)] out string? value)
{
if (GetHttpContext().Request.Cookies.TryGetValue(key, out var cookieValue))
{
value = EncryptionHelper.Decrypt(cookieValue, _dataProtectionProvider);
return true;
}

value = null;
return false;
}

private static SameSiteMode ParseSameSiteMode(string sameSiteMode) =>
Enum.TryParse(sameSiteMode, ignoreCase: true, out SameSiteMode result)
? result
: throw new ArgumentException($"The provided {nameof(sameSiteMode)} value could not be parsed into as SameSiteMode value.", nameof(sameSiteMode));
}
Loading
Loading