Skip to content

Persistence Model: Replace some hard coded strings in DTOs#21327

Merged
AndyButland merged 34 commits intoumbraco:mainfrom
idseefeld:v173/20453-dto-constants
Jan 16, 2026
Merged

Persistence Model: Replace some hard coded strings in DTOs#21327
AndyButland merged 34 commits intoumbraco:mainfrom
idseefeld:v173/20453-dto-constants

Conversation

@idseefeld
Copy link
Contributor

Prerequisites

This is a partial PR to split up complex PR #21326

All unit & integration test should succeed.

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Hi there @idseefeld, thank you for this contribution! 👍

While we wait for one of the Core Collaborators team to have a look at your work, we wanted to let you know about that we have a checklist for some of the things we will consider during review:

  • It's clear what problem this is solving, there's a connected issue or a description of what the changes do and how to test them
  • The automated tests all pass (see "Checks" tab on this PR)
  • The level of security for this contribution is the same or improved
  • The level of performance for this contribution is the same or improved
  • Avoids creating breaking changes; note that behavioral changes might also be perceived as breaking
  • If this is a new feature, Umbraco HQ provided guidance on the implementation beforehand
  • 💡 The contribution looks original and the contributor is presumably allowed to share it

Don't worry if you got something wrong. We like to think of a pull request as the start of a conversation, we're happy to provide guidance on improving your contribution.

If you realize that you might want to make some changes then you can do that by adding new commits to the branch you created for this work and pushing new commits. They should then automatically show up as updates to this pull request.

Thanks, from your friendly Umbraco GitHub bot 🤖 🙂

@idseefeld idseefeld changed the title Replace some hard codes strings in DTOs Replace some hard coded strings in DTOs Jan 8, 2026
@idseefeld idseefeld marked this pull request as ready for review January 8, 2026 11:29
Copilot AI review requested due to automatic review settings January 8, 2026 11:29
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request replaces hard-coded column and primary key name strings in Data Transfer Objects (DTOs) with named constants, improving maintainability and consistency across the Umbraco Infrastructure persistence layer. This is part of a larger refactoring effort (split from PR #21326).

Key changes:

  • Introduces centralized constants in Constants.DatabaseSchema for commonly used column names (id, pk, key, nodeId, uniqueId)
  • Updates ~60 DTOs to use these constants instead of hard-coded strings in attributes
  • Updates test files to reflect the lowercase column name changes

Reviewed changes

Copilot reviewed 70 out of 70 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs Adds centralized constants for primary key and common column names
src/Umbraco.Infrastructure/Persistence/Dtos/WebhookRequestDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/WebhookLogDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/WebhookDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/Webhook2HeadersDto.cs Updates column attributes to use lowercase column names
src/Umbraco.Infrastructure/Persistence/Dtos/UserStartNodeDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/UserLoginDto.cs Replaces hardcoded "sessionId" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/UserGroupDto.cs Replaces hardcoded column names with constants for id and key
src/Umbraco.Infrastructure/Persistence/Dtos/UserGroup2PermissionDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/UserGroup2GranularPermissionDto.cs Replaces hardcoded strings with constants and updates foreign key references
src/Umbraco.Infrastructure/Persistence/Dtos/UserGroup2AppDto.cs Replaces hardcoded "userGroupId" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/UserDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/UserDataDto.cs Replaces hardcoded "key" with PrimaryKeyNameKey constant
src/Umbraco.Infrastructure/Persistence/Dtos/User2NodeNotifyDto.cs Replaces hardcoded column names with constants
src/Umbraco.Infrastructure/Persistence/Dtos/User2ClientIdDto.cs Replaces hardcoded "userId" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/TwoFactorLoginDto.cs Replaces hardcoded "Id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/TemplateDto.cs Replaces hardcoded "pk" with PrimaryKeyNamePK constant
src/Umbraco.Infrastructure/Persistence/Dtos/TagRelationshipDto.cs Replaces hardcoded "nodeId" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/TagDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/ServerRegistrationDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/RepositoryCacheVersionDto.cs Replaces hardcoded "identifier" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/RelationTypeDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/RelationDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/RedirectUrlDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/PropertyTypeReadOnlyDto.cs Updates column attributes to use lowercase uniqueId
src/Umbraco.Infrastructure/Persistence/Dtos/PropertyTypeGroupReadOnlyDto.cs Replaces hardcoded "PropertyTypeGroupId" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/PropertyTypeGroupDto.cs Replaces hardcoded strings with constants for column names and foreign key references
src/Umbraco.Infrastructure/Persistence/Dtos/PropertyTypeDto.cs Replaces hardcoded strings with constants for column names and foreign key references
src/Umbraco.Infrastructure/Persistence/Dtos/PropertyDataDto.cs Replaces hardcoded strings with constants for column names and index definitions
src/Umbraco.Infrastructure/Persistence/Dtos/NodeDto.cs Adds public constants for common column names and uses PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/MemberPropertyTypeDto.cs Replaces hardcoded strings with constants and updates foreign key references
src/Umbraco.Infrastructure/Persistence/Dtos/MemberDto.cs Replaces hardcoded "nodeId" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/Member2MemberGroupDto.cs Replaces hardcoded "Member" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/MediaVersionDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/LongRunningOperationDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/LogViewerQueryDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/LogDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/LockDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/LastSyncedDto.cs Replaces hardcoded "machineId" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/LanguageTextDto.cs Updates column attributes to use lowercase uniqueId
src/Umbraco.Infrastructure/Persistence/Dtos/LanguageDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/KeyValueDto.cs Replaces hardcoded "key" with PrimaryKeyNameKey constant
src/Umbraco.Infrastructure/Persistence/Dtos/ExternalLoginTokenDto.cs Replaces hardcoded "Id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/ExternalLoginDto.cs Replaces hardcoded "Id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/DomainDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/DocumentVersionDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/DocumentUrlDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/DocumentDto.cs Replaces hardcoded "nodeId" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/DocumentCultureVariationDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/DistributedJobDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/DictionaryDto.cs Updates column and reference attributes to use lowercase uniqueId
src/Umbraco.Infrastructure/Persistence/Dtos/DataTypeDto.cs Replaces hardcoded "nodeId" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/CreatedPackageSchemaDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/ContentVersionDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/ContentVersionCultureVariationDto.cs Replaces hardcoded "id" and adds explicit foreign key name
src/Umbraco.Infrastructure/Persistence/Dtos/ContentVersionCleanupPolicyDto.cs Replaces hardcoded "contentTypeId" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/ContentTypeTemplateDto.cs Replaces hardcoded "contentTypeNodeId" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/ContentTypeDto.cs Replaces hardcoded strings with constants for primary key and nodeId
src/Umbraco.Infrastructure/Persistence/Dtos/ContentTypeAllowedContentTypeDto.cs Replaces hardcoded strings with constants and uses string interpolation
src/Umbraco.Infrastructure/Persistence/Dtos/ContentType2ContentTypeDto.cs Replaces hardcoded strings with constants and uses string interpolation
src/Umbraco.Infrastructure/Persistence/Dtos/ContentScheduleDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/ContentNuDto.cs Replaces hardcoded "nodeId" with local PrimaryKeyName constant
src/Umbraco.Infrastructure/Persistence/Dtos/ContentDto.cs Replaces hardcoded strings with constants for primary key and references
src/Umbraco.Infrastructure/Persistence/Dtos/ConsentDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/CacheInstructionDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/AuditEntryDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/AccessRuleDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
src/Umbraco.Infrastructure/Persistence/Dtos/AccessDto.cs Replaces hardcoded "id" with PrimaryKeyNameId constant
tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs Updates test expectations to use lowercase column names
tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Persistence/Mappers/DictionaryTranslationMapperTest.cs Updates test expectations to use lowercase uniqueId

Copy link
Contributor

@AndyButland AndyButland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution @idseefeld - I've given this a careful lookover and you can see my comments inline.

@idseefeld idseefeld marked this pull request as draft January 9, 2026 11:46
@idseefeld
Copy link
Contributor Author

@AndyButland I have reverted all database schema changes and replaced some more hard coded strings in DTOs.

@idseefeld idseefeld marked this pull request as ready for review January 9, 2026 17:38
@idseefeld idseefeld requested a review from AndyButland January 9, 2026 20:10
Copy link
Contributor

@AndyButland AndyButland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking better @idseefeld - but I found a few more issues to look at.

Casing changes are a little tricky to spot, so as part of testing this, please could you create a new install on a SQL Server database both before and after the changes in your PR are applied? For each database you could generate a script to create the schema for both databases. Then you can do a comparison between them to see if there are any differences (Notepad++ has a good compare feature you could use here). We'd expect them to be exactly the same, and if so, then we can be confident that this update hasn't made any actual changes to the database schema generated for new installs. And if not, it'll identify the areas still to look at.

@idseefeld idseefeld marked this pull request as draft January 10, 2026 12:56
@idseefeld
Copy link
Contributor Author

idseefeld commented Jan 13, 2026

Initially I have used Visual Studio's Database Schema Compare to check the database. But I did not realise, that this is also case insensitiv.
Now I have compared the two generate sql scripts. I used a handy little Regex to remove the comments with different create time: (\/\*).+?(\*+?\/)
Than you can simply use the file compare feature in VS and the only difference is the database name!

@idseefeld idseefeld marked this pull request as ready for review January 13, 2026 13:50
@idseefeld idseefeld marked this pull request as draft January 13, 2026 14:58
…utes again, because some integration tests for PostgreSQL provider fail without them. Again a case sensitivty issue.
@idseefeld idseefeld marked this pull request as ready for review January 13, 2026 15:06
Copy link
Contributor

@AndyButland AndyButland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found a few small issues to note around inconsistencies if you could have a look at those please @idseefeld.

Otherwise I also carried out the check I suggested in my last comment - generating the schema for both before and after these changes - and I see no differences (other than the dates in comments). So looks safe to proceed with.

@idseefeld
Copy link
Contributor Author

umb-issue-20453.sql
umb-main.sql

These are my generated sql scripts. Comments removed with Regex: (\/\*).+?(\*+?\/)

Copy link
Contributor

@AndyButland AndyButland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @idseefeld, this all looks good to me now. I'm just going to update the obsoletion messages with details of when we expect to remove the classes, but otherwise, this is ready to merge in in my view.

@AndyButland AndyButland changed the title Replace some hard coded strings in DTOs Persistence Model: Replace some hard coded strings in DTOs Jan 16, 2026
@AndyButland AndyButland enabled auto-merge (squash) January 16, 2026 05:45
@AndyButland AndyButland merged commit a2c743c into umbraco:main Jan 16, 2026
26 checks passed
@idseefeld idseefeld deleted the v173/20453-dto-constants branch January 16, 2026 10:28
kjac added a commit that referenced this pull request Jan 21, 2026
kjac added a commit that referenced this pull request Feb 3, 2026
* CRUD + folders + API

* Fix infinite recursion

* Distributed cache handling for Elements

* Publishing for Elements (incl. refactor)

* Fix bad file name

* Added "foldersOnly" option to the siblings endpoint

* Update src/Umbraco.Core/Models/UmbracoObjectTypes.cs

Co-authored-by: Andy Butland <abutland73@gmail.com>

* API for publishing elements

* Published element cache (WIP)

* Fix delete at repo level

* Fixing up a little tests

* Element picker property editor

* Added tests to prove published element status

* Move scheduled content keys to base abstraction

* Add request caching for published element creation (similar to published document creation)

* Apply conditional appcache access to elements as well

* Fix test build errors

* Fix merge from main

* Fix merge

* Add cache invalidation on update (like content and media)

* Move element (incl. tests)

* Element copying

* Add items endpoint incl. variation info at item level

* Make the Element tree items look like Document tree items (with variations)

* Rename all things ElementType to DocumentType

* Move ElementRepository to the right place

* Fix auditing after merge (changes from #19357)

* Fix dates after merge (changes from #19822)

* Fix NPoco querying after merge (changes from #20184)

* Fix various build errors after merge

* Move containers

* Add migration to create element tables

* Re-implement #21105 at base class level

* Fix merge

* Add element tree recycle bin + move element to/from recycle bin

* Controllers for move to recycle bin + recycle bin root

* Support element containers in recycle bin (no controllers)

* Handle error cases for element moves and add more tests

* Do not allow creation of IPublishedElement for trashed elements

* Amend recycle bin controller output and add children controller

* Regenerate OpenApi.json with Element APIs

* Housekeeping: Organize element container service tests

* Fix bad housekeeping

* Add missing siblings controller for recycle bin

* Add "delete from recycle bin" and "empty recycle bin" operations (including API)

* Updated OpenApi.json to reflect new endpoints

* Added `CreateDate` to `ElementTreeItemResponseModel`

Marked `ElementRecycleBinItemResponseModel.DocumentTypeReferenceResponseModel` as nullable.

* Re-generated OpenAPI.json

* Add configuration endpoint for Elements

* Explicitly unpublish published elements when restoring from recycle bin.

* Elements: Remove invalid templateId from ElementVersionDto index definitions (#21384)

* Persistence: Remove invalid templateId from ElementVersionDto index definitions

The ElementVersionDto had index definitions that referenced templateId in
their IncludeColumns, but the ElementVersion table only has id and published
columns. This caused SQL Server clean installs to fail with error 1911:
"Column name 'templateId' does not exist in the target table or view."

This was likely a copy-paste error from DocumentVersionDto which does have
a templateId column.

* Ignore Cannot_Create_Element_Based_On_NonElement_ContentType for the time being

---------

Co-authored-by: kjac <kja@umbraco.dk>

* Fix the ordering of items in the tree

* It's 2026 now...

* Fix missing project structure

* Amend empty recycle bin

* Elements: Fix element recycle bin node insertion on SQL Server (#21390)

Enable IDENTITY_INSERT before inserting the element recycle bin node with an explicit ID, then disable it afterward. This fixes the migration failing on SQL Server with "Cannot insert explicit value for identity column" error.

* Fix count trashed children

* Moved newly added entity service tests to an isolated, per-test DB class so they do not interfere with the existing per-fixture DB tests

* Elements: Element start node permissions (#21375)

* Add Element start node support for Users and UserGroups

- Add StartElementId to UserGroup and element start nodes to User
- Add UserStartNodeFolderTreeControllerBase for tree filtering with folder support
- Update ElementTreeControllerBase to use start node filtering
- Add ElementTreeItemResponseModel.NoAccess property for "no access" items
- Add UserExtensions methods for element start node calculation
- Update User/UserGroup API models and factories
- Add database migration for startElementId column
- Add SectionAccessForElementTree authorization policy

Note: Granular element permissions deferred for future implementation

* Add element root access for default user groups on fresh install

Set StartElementId = -1 for Administrators, Writers, Editors, and
Translators user groups in DatabaseDataCreator, giving them element
root access on fresh installations (matching their content/media access).

* Add multi-type support to UserStartNodeEntitiesService

Added overloads to RootUserAccessEntities, ChildUserAccessEntities, and
SiblingUserAccessEntities that accept multiple UmbracoObjectTypes. This
enables querying for Elements and ElementContainers in a single call
rather than requiring separate queries for each type.

Also added GetAll and GetPagedChildren overloads to IEntityService and
IEntityRepository to support querying multiple object types efficiently
with a single database query.

* Add integration tests for Element start nodes with mixed hierarchy

Added UserStartNodeEntitiesServiceElementTests with a mixed hierarchy
structure containing both containers and elements at each level:
- Level 1: Containers (C1-C5) and Elements (E1-E3)
- Level 2: Child containers (C1-C1 through C1-C10) and Elements (C1-E1, C1-E2)
- Level 3: Leaf elements (C1-C1-E1 through C1-C1-E5)

This tests scenarios where containers and elements are siblings, ensuring
the access filtering works correctly for mixed-type queries.

Also refactored Content and Media tests to use a shared base class
(UserStartNodeEntitiesServiceTestsBase) to reduce code duplication.

* Add Library section for Elements

- Rename Constants.Applications.Elements to Library
- Add SectionAccessLibrary authorization policy
- Add library mapping to SectionMapper
- Grant Library section access to Administrators, Writers, and Editors on fresh install
- Update TreeAccessElements to use Library section

* Add Element tree controller authorization tests

Add integration tests for RootElementTreeController and
ChildrenElementTreeController to verify section-based
authorization works correctly for the Element tree endpoints.

* Fix ReadOnlyUserGroup not passing startElementId to constructor

The obsolete 13-parameter constructor was passing `null` instead of
the actual `startElementId` value to the next constructor, causing
user groups to appear to have no element start node access.

Also update UserFactory.ToReadOnlyGroup to pass the Description
parameter to the ReadOnlyUserGroup constructor.

* Add Element controller authorization tests

Add authorization tests for Element CRUD, Folder, RecycleBin, and Item
controllers to verify user group access permissions.

Tests cover Admin, Editor, Writer, SensitiveData, Translator, and
Unauthorized user groups for each controller endpoint.

* Re-generated OpenApi.json

* Fix Element start node handling to use ElementContainer object type

- Update UserStartNodeFolderTreeControllerBase to query both folder and
  item object types when filtering by user start nodes
- Fix UserGroupPresentationFactory to use ElementContainer instead of
  Element when resolving element start node IDs/keys

* Revert ByKeyElementController to use synchronous Task.FromResult

The method doesn't have any async operations, so async/await adds
unnecessary overhead.

* Fix UserPresentationFactory to use ElementContainer for element start nodes

Element start nodes reference ElementContainer (folders), not Element items.

* Add recycle bin start node access test for Element controllers

- Add WithStartElementId to UserGroupBuilder
- Add ElementRecycleBinControllerTestBase with shared test verifying
  users with non-root element start nodes cannot access recycle bin
- Update all Element recycle bin tests to use the new base class

* Fix UserGroupPresentationFactory and Element test section alias

- Use ElementContainer instead of Element for start node lookups in
  IReadOnlyUserGroup overload
- Use Constants.Applications.Library for Element test section alias

* Add obsolete User constructor overload for backward compatibility

- Add obsolete constructor without startElementIds parameter that delegates
  to the new constructor with an empty array
- Improve XML documentation for all User constructors

* Elements: Move NoAccess property to FolderTreeItemResponseModel base class

This allows both elements and folders to indicate access status in the tree.

* Elements: Add API versioning attributes to SiblingsElementTreeController

* Elements: Add integration tests for element tree start node permissions

Add tests to verify that users with element start node restrictions can only see
and access elements within their permitted hierarchy.

* Group test files

* Remove type check from GetAllPaths overload

---------

Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>

* Elements: Add rollback (#21393)

* Services, repos and tests

* Endpoints for Elements versioning

* Add extra test to prove handling of pinned versions

* Renaming from PR review

* Update tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ElementVersionCleanupServiceTest.cs

Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>

* More code clean-up after review

* Use correct deleting/deleted versions notifications

---------

Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>

* Elements: Regenerate OpenApi.json

* Elements: Add default and granular permissions for Element controllers (#21385)

* Add Element start node support for Users and UserGroups

- Add StartElementId to UserGroup and element start nodes to User
- Add UserStartNodeFolderTreeControllerBase for tree filtering with folder support
- Update ElementTreeControllerBase to use start node filtering
- Add ElementTreeItemResponseModel.NoAccess property for "no access" items
- Add UserExtensions methods for element start node calculation
- Update User/UserGroup API models and factories
- Add database migration for startElementId column
- Add SectionAccessForElementTree authorization policy

Note: Granular element permissions deferred for future implementation

* Add element root access for default user groups on fresh install

Set StartElementId = -1 for Administrators, Writers, Editors, and
Translators user groups in DatabaseDataCreator, giving them element
root access on fresh installations (matching their content/media access).

* Add multi-type support to UserStartNodeEntitiesService

Added overloads to RootUserAccessEntities, ChildUserAccessEntities, and
SiblingUserAccessEntities that accept multiple UmbracoObjectTypes. This
enables querying for Elements and ElementContainers in a single call
rather than requiring separate queries for each type.

Also added GetAll and GetPagedChildren overloads to IEntityService and
IEntityRepository to support querying multiple object types efficiently
with a single database query.

* Add integration tests for Element start nodes with mixed hierarchy

Added UserStartNodeEntitiesServiceElementTests with a mixed hierarchy
structure containing both containers and elements at each level:
- Level 1: Containers (C1-C5) and Elements (E1-E3)
- Level 2: Child containers (C1-C1 through C1-C10) and Elements (C1-E1, C1-E2)
- Level 3: Leaf elements (C1-C1-E1 through C1-C1-E5)

This tests scenarios where containers and elements are siblings, ensuring
the access filtering works correctly for mixed-type queries.

Also refactored Content and Media tests to use a shared base class
(UserStartNodeEntitiesServiceTestsBase) to reduce code duplication.

* Add Library section for Elements

- Rename Constants.Applications.Elements to Library
- Add SectionAccessLibrary authorization policy
- Add library mapping to SectionMapper
- Grant Library section access to Administrators, Writers, and Editors on fresh install
- Update TreeAccessElements to use Library section

* Add Element tree controller authorization tests

Add integration tests for RootElementTreeController and
ChildrenElementTreeController to verify section-based
authorization works correctly for the Element tree endpoints.

* Fix ReadOnlyUserGroup not passing startElementId to constructor

The obsolete 13-parameter constructor was passing `null` instead of
the actual `startElementId` value to the next constructor, causing
user groups to appear to have no element start node access.

Also update UserFactory.ToReadOnlyGroup to pass the Description
parameter to the ReadOnlyUserGroup constructor.

* Add Element controller authorization tests

Add authorization tests for Element CRUD, Folder, RecycleBin, and Item
controllers to verify user group access permissions.

Tests cover Admin, Editor, Writer, SensitiveData, Translator, and
Unauthorized user groups for each controller endpoint.

* Re-generated OpenApi.json

* Fix Element start node handling to use ElementContainer object type

- Update UserStartNodeFolderTreeControllerBase to query both folder and
  item object types when filtering by user start nodes
- Fix UserGroupPresentationFactory to use ElementContainer instead of
  Element when resolving element start node IDs/keys

* Revert ByKeyElementController to use synchronous Task.FromResult

The method doesn't have any async operations, so async/await adds
unnecessary overhead.

* Fix UserPresentationFactory to use ElementContainer for element start nodes

Element start nodes reference ElementContainer (folders), not Element items.

* Add recycle bin start node access test for Element controllers

- Add WithStartElementId to UserGroupBuilder
- Add ElementRecycleBinControllerTestBase with shared test verifying
  users with non-root element start nodes cannot access recycle bin
- Update all Element recycle bin tests to use the new base class

* Fix UserGroupPresentationFactory and Element test section alias

- Use ElementContainer instead of Element for start node lookups in
  IReadOnlyUserGroup overload
- Use Constants.Applications.Library for Element test section alias

* Add obsolete User constructor overload for backward compatibility

- Add obsolete constructor without startElementIds parameter that delegates
  to the new constructor with an empty array
- Improve XML documentation for all User constructors

* Elements: Add granular permissions for Element controllers

Add Element-specific permission actions:
- ActionElementBrowse, ActionElementNew, ActionElementUpdate, ActionElementDelete
- ActionElementPublish, ActionElementUnpublish, ActionElementMove, ActionElementCopy

Add permission infrastructure:
- ElementPermissionResource for authorization checks
- ElementPermissionHandler and ElementPermissionRequirement
- ElementPermissionService and IElementPermissionService
- ElementPermissionAuthorizer and IElementPermissionAuthorizer
- ElementGranularPermission model
- ElementPermissionMapper for user group permissions

Update Element controllers with authorization:
- Add HandleRequest pattern via CreateElementControllerBase and UpdateElementControllerBase
- Pass cultures for Publish/Unpublish authorization
- Apply authorization checks to Element CRUD and publishing operations

* Elements: Add default element permissions to user groups

Add element action permissions for Admin, Editor, Writer, and Translator
user groups in DatabaseDataCreator, mirroring the document permission pattern.

* Elements: Add current user element permissions endpoint and fix folder authorization

- Add GetElementPermissionsCurrentUserController endpoint to get current user's element permissions
- Fix ElementPermissionService to authorize both Element and ElementContainer (folders)
- Add GetElementPermissionsAsync to IUserService/UserService
- Add ElementNodeNotFound to UserOperationStatus
- Add IEntityService.GetAll overloads for multiple object types

* Elements: Move NoAccess property to FolderTreeItemResponseModel base class

This allows both elements and folders to indicate access status in the tree.

* Elements: Add default implementation to IUserService.GetElementPermissionsAsync

Adds a default throwing implementation to avoid breaking existing IUserService implementations when this method is added.

* Elements: Add API versioning attributes to SiblingsElementTreeController

* Elements: Add integration tests for element tree start node permissions

Add tests to verify that users with element start node restrictions can only see
and access elements within their permitted hierarchy.

* Add granular permissions to element rollback

* Update src/Umbraco.Core/Actions/ActionElementCopy.cs

Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>

* Elements: Use lowercase action aliases for consistency

Update all Element action aliases to lowercase to comply with the
IAction.Alias requirement for case-sensitive filesystems. Also rename
ActionElementNew alias from "elementNew" to "elementcreate" to match
the document action's "create" alias pattern.

* Elements: Refactor UserService permission methods to reduce duplication

Consolidate GetMediaPermissionsAsync, GetDocumentPermissionsAsync, and
GetElementPermissionsAsync into a single shared implementation via
a new private GetContentPermissionsAsync helper method.

---------

Co-authored-by: kjac <kja@umbraco.dk>

* Add element folder "item" endpoint

* Include "isTrashed" in folder response models

* Update TODOs

* Rollback a few unnecessarily breaking signature changes

* Use schema constants from #21327

* Elements: Add admin group element permissions during upgrade (#21452)

Grant the admin user group access to the element root node and all
element permissions when upgrading from a previous version. This
ensures parity with fresh installations where the admin group receives
these permissions by default.

* Elements: Fix Writer expected status codes in Element controller permission tests

Update WriterUserGroupAssertionModel to expect Forbidden for operations
that Writers don't have permission for, matching Document controller
behavior and the actual permissions assigned to the Writer group.

Changed from OK/Created to Forbidden:
- CopyElementControllerTests
- DeleteElementControllerTests
- MoveElementControllerTests
- MoveToRecycleBinElementControllerTests
- PublishElementControllerTests
- UnpublishElementControllerTests
- Folder/DeleteElementFolderControllerTests
- Folder/MoveElementFolderControllerTests
- Folder/MoveToRecycleBinElementFolderControllerTests
- RecycleBin/DeleteElementRecycleBinControllerTests
- RecycleBin/DeleteElementFolderRecycleBinControllerTests
- RecycleBin/EmptyElementRecycleBinControllerTests

* Elements: Fix duplicate column name in DocumentVersionDto index definition

The ForColumns parameter incorrectly specified PublishedColumnName twice
instead of IdColumnName and PublishedColumnName, causing SQL Server to
reject index creation with "duplicate column names" error on new installs.

* Add missing element mapper and allow deleting element types with active elements (#21483)

* Add missing element mapper and allow deleting element types with active elements

* Update src/Umbraco.Core/Services/ContentTypeService.cs

Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>

* Update src/Umbraco.Core/Services/ContentTypeService.cs

Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>

---------

Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>

* Update src/Umbraco.Core/Cache/Refreshers/Implement/ElementCacheRefresher.cs

Co-authored-by: Andy Butland <abutland73@gmail.com>

* Review comment: ReadOnlyUserGroup constructor

* Update comments in ElementEditingService

* Add Library section access to content, media, and member tree policies

* Elements: Add Elements access to data type, document type, and relation authorization policies (#21501)

Add Elements access to data type, document type, and relation authorization policies

* Amend merge from v18/dev

* Global Elements: Backoffice UI implementation (#21410)

* chore: generate new openapi types

* Added package/module for "Library"

* Added default dashboard for Library section

* [WIP] Adds "Elements" package module

Basics of the tree/menu.

* Adds entity-actions for Create and Reload

* Adds entity-action for Move To

* Adds collection workspace view

for root and folders

* Adds entity-action for Duplicate To

* "Reload Children" should only be for root & folders

* Reworked Library sidebar app

Replaced with Elements sidebar app
Removed the Library menu

* chore: generate new openapi types

* Added Item repository

* Added Reference repository

* Added Element Recycle Bin

Tree, menu, entity-actions, workspace (collection view)

* Adds "umb-element-tree-item" to identify the `isTrashed` state

* Re-added Library sidebar app

Removed Library dashboard (we'll figure it out later)

* Recycle Bin type tweaks

* [WIP] Element "Create" modal

* Reverted Element "Create" modal, to use create-options + picker

* chore: generate new openapi types

* Added Element Detail Repository

* [WIP] Element Workspace + Context

* Elements: Add workspace views for edit and info

Add edit and info workspace views to the Element workspace:
- Edit view using shared 'contentEditor' kind pattern
- Info view displaying state tag, dates, element type, and ID
- Menu structure context for tree navigation
- Split-view component for variant editing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Elements: Add save action and trash state handling

- Add Save workspace action using UmbSubmitWorkspaceAction
- Add isTrashed property to UmbElementDetailModel
- Implement trash state change handling with read-only guard
- Add recycle bin event listeners for trash/restore actions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Adds Workspace actions for Save, Publish, Scheduled Publish

* Adds Element Configuration repository

* Adds mock handle + data for Elements

* Adds Publish and Unpublish entity actions for Elements

Implements context menu actions for publishing and unpublishing elements
directly from the tree. Uses existing modals and publishing repository.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* package-lock.json update

* Adds bulk entity actions for Publish, Unpublish, Move and Trash

* Localization keys + code tweaks

* Adds reusable `emptyRecycleBin` `collectionAction` kind

* Adds `emptyRecycleBin` for Element Recycle Bin collection

* Element Recycle Bin refactoring

Working towards folder support

* Relations: exported entity-action types

* Restructured "Element Folder" code

* Restructured "Trash" entity-bulk-action code

* Adds `trashFolder` `entityAction` kind

* Adds "Trash" entity-action for Element Folders

* Tidy-up / restructuring

* [WIP] Element Picker property-editor UI

making use of an Elements property-data-source,
with Entity Picker.

* Renamed `UmbElementPropertyDatasetContext` to `UmbElementWorkspacePropertyDatasetContext`

to de-duplicate a class name clash with the underlying base class.

* Added "entity-data-picker" importmap

Exposing the "umb-input-entity-data" component

* Reworking the "Element Picker" property-editor UI

to reuse the Entity Picker internal input component

* Implemented "Element Item Data Resolver" helper

* chore: generate new openapi types

* Fixed up the mocks and types

with new Element start nodes and `noAccess` fields.

* Added UI for "Elements Start Nodes"

* Added "entity-data-picker" export to the Vite config

* Fixed Element Folder picker for "start nodes"

* Adds UI for Element's User Permissions

* Adds Element User Permission condition

Implemented the user permissions for entity actions, etc.

* Adds UI for Element's Granular Permissions

* Adds element-folder item repository

* Element Recycle Bin: implemented `isTrashed`

* Fixed mock folder data manager

* Adds move entity-action for element-folder

Implements the Move action for element folders using the
ElementService.putElementFolderByIdMove API endpoint.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix typos and element tag name mismatches in elements package

- Fix typo 'now' -> 'no' in user-permissions/types.ts
- Fix HTMLElementTagNameMap tag name to match @CustomElement decorator
- Fix typo 'TDOD' -> 'TODO' in element-detail.server.data-source.ts
- Fix missing 'u' prefix in element-picker tag name declaration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Ignore local Claude settings in UI Client

* Updated workspace assign access,

to disable root access when start nodes are selected.

* Elements: Display trashed state in Element workspace info panel (#21542)

The state tag in the Element workspace info view was missing a case
for the TRASHED state, causing trashed Elements to incorrectly display
"Not created" instead of "Trashed".

* Elements: Fix folder link in recycle bin list view (#21543)

The trashed element name column always used the element workspace path
pattern, causing folders clicked in the recycle bin list view to show
"Not found". Now checks isFolder and uses the correct workspace path
pattern for folders vs elements.

* Elements: Add missing delete permission conditions to recycle bin actions (#21547)

The Empty Recycle Bin collection action and the folder delete entity
action were missing user permission conditions, making them visible
to users without delete permission.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>

---------

Co-authored-by: Andy Butland <abutland73@gmail.com>
Co-authored-by: leekelleher <leekelleher@gmail.com>
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
Co-authored-by: Lee Kelleher <leekelleher@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants