Persistence Model: Replace some hard coded strings in DTOs#21327
Persistence Model: Replace some hard coded strings in DTOs#21327AndyButland merged 34 commits intoumbraco:mainfrom
Conversation
…v173/20453-fix-more-sql-syntax-issues-squash (copy of main)
|
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:
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 🤖 🙂 |
There was a problem hiding this comment.
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.DatabaseSchemafor 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 |
src/Umbraco.Infrastructure/Persistence/Dtos/PropertyTypeGroupDto.cs
Outdated
Show resolved
Hide resolved
src/Umbraco.Infrastructure/Persistence/Dtos/User2NodeNotifyDto.cs
Outdated
Show resolved
Hide resolved
src/Umbraco.Infrastructure/Persistence/Dtos/ContentTypeAllowedContentTypeDto.cs
Outdated
Show resolved
Hide resolved
AndyButland
left a comment
There was a problem hiding this comment.
Thanks for the contribution @idseefeld - I've given this a careful lookover and you can see my comments inline.
src/Umbraco.Infrastructure/Persistence/Dtos/ContentTypeAllowedContentTypeDto.cs
Outdated
Show resolved
Hide resolved
src/Umbraco.Infrastructure/Persistence/Dtos/ContentTypeAllowedContentTypeDto.cs
Outdated
Show resolved
Hide resolved
src/Umbraco.Infrastructure/Persistence/Dtos/Webhook2HeadersDto.cs
Outdated
Show resolved
Hide resolved
...ests.UnitTests/Umbraco.Infrastructure/Persistence/Mappers/DictionaryTranslationMapperTest.cs
Outdated
Show resolved
Hide resolved
...UnitTests/Umbraco.Infrastructure/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs
Outdated
Show resolved
Hide resolved
...UnitTests/Umbraco.Infrastructure/Persistence/Querying/ContentTypeRepositorySqlClausesTest.cs
Outdated
Show resolved
Hide resolved
|
@AndyButland I have reverted all database schema changes and replaced some more hard coded strings in DTOs. |
AndyButland
left a comment
There was a problem hiding this comment.
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.
src/Umbraco.Infrastructure/Persistence/Dtos/ContentTypeAllowedContentTypeDto.cs
Outdated
Show resolved
Hide resolved
src/Umbraco.Infrastructure/Persistence/Dtos/Webhook2HeadersDto.cs
Outdated
Show resolved
Hide resolved
src/Umbraco.Infrastructure/Persistence/Dtos/PropertyTypeGroupReadOnlyDto.cs
Outdated
Show resolved
Hide resolved
src/Umbraco.Infrastructure/Persistence/Dtos/PropertyTypeReadOnlyDto.cs
Outdated
Show resolved
Hide resolved
src/Umbraco.Infrastructure/Persistence/Dtos/ContentType2ContentTypeDto.cs
Outdated
Show resolved
Hide resolved
src/Umbraco.Infrastructure/Persistence/Dtos/MemberPropertyTypeDto.cs
Outdated
Show resolved
Hide resolved
…ContentTypeDto.cs Co-authored-by: Andy Butland <abutland73@gmail.com>
|
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. |
…utes again, because some integration tests for PostgreSQL provider fail without them. Again a case sensitivty issue.
There was a problem hiding this comment.
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.
src/Umbraco.Infrastructure/Persistence/Dtos/ContentVersionDto.cs
Outdated
Show resolved
Hide resolved
make all column name const consistent
|
umb-issue-20453.sql These are my generated sql scripts. Comments removed with Regex: |
AndyButland
left a comment
There was a problem hiding this comment.
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.
src/Umbraco.Infrastructure/Persistence/Dtos/PropertyTypeGroupReadOnlyDto.cs
Outdated
Show resolved
Hide resolved
src/Umbraco.Infrastructure/Persistence/Dtos/PropertyTypeReadOnlyDto.cs
Outdated
Show resolved
Hide resolved
* 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>
Prerequisites
This is a partial PR to split up complex PR #21326
All unit & integration test should succeed.