Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
acc6496
Add Element start node support for Users and UserGroups
lauraneto Jan 8, 2026
78e61f0
Add element root access for default user groups on fresh install
lauraneto Jan 8, 2026
d493b48
Add multi-type support to UserStartNodeEntitiesService
lauraneto Jan 9, 2026
11ef156
Add integration tests for Element start nodes with mixed hierarchy
lauraneto Jan 9, 2026
0424709
Merge branch 'v17/feature/global-elements' into v18/feature/element-s…
lauraneto Jan 12, 2026
1942750
Add Library section for Elements
lauraneto Jan 12, 2026
f7d0ed0
Add Element tree controller authorization tests
lauraneto Jan 12, 2026
fa42543
Fix ReadOnlyUserGroup not passing startElementId to constructor
lauraneto Jan 12, 2026
23f4ac4
Add Element controller authorization tests
lauraneto Jan 12, 2026
0b8400c
Re-generated OpenApi.json
lauraneto Jan 12, 2026
7233b93
Fix Element start node handling to use ElementContainer object type
lauraneto Jan 12, 2026
b3990d7
Revert ByKeyElementController to use synchronous Task.FromResult
lauraneto Jan 12, 2026
0c9fb86
Fix UserPresentationFactory to use ElementContainer for element start…
lauraneto Jan 12, 2026
edb0e31
Add recycle bin start node access test for Element controllers
lauraneto Jan 12, 2026
7120248
Fix UserGroupPresentationFactory and Element test section alias
lauraneto Jan 12, 2026
6cd9992
Add obsolete User constructor overload for backward compatibility
lauraneto Jan 13, 2026
de110bc
Merge branch 'v17/feature/global-elements' into v18/feature/element-s…
lauraneto Jan 13, 2026
9a65217
Merge branch 'v17/feature/global-elements' into v18/feature/element-s…
lauraneto Jan 14, 2026
b533601
Elements: Move NoAccess property to FolderTreeItemResponseModel base …
lauraneto Jan 14, 2026
146f71c
Elements: Add API versioning attributes to SiblingsElementTreeController
lauraneto Jan 14, 2026
897abee
Elements: Add integration tests for element tree start node permissions
lauraneto Jan 14, 2026
31944e7
Merge branch 'v17/feature/global-elements' into v18/feature/element-s…
lauraneto Jan 14, 2026
12acf9b
Merge branch 'v17/feature/global-elements' into v18/feature/element-s…
kjac Jan 15, 2026
0891b2a
Group test files
kjac Jan 15, 2026
59fb09c
Remove type check from GetAllPaths overload
kjac Jan 15, 2026
49eff4a
Merge branch 'v17/feature/global-elements' into v18/feature/element-s…
kjac Jan 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ namespace Umbraco.Cms.Api.Management.Controllers.Element;

[VersionedApiBackOfficeRoute(Constants.UdiEntityType.Element)]
[ApiExplorerSettings(GroupName = nameof(Constants.UdiEntityType.Element))]
// TODO ELEMENTS: backoffice authorization policies
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocuments)]
[Authorize(Policy = AuthorizationPolicies.TreeAccessElements)]
public class ElementControllerBase : ContentControllerBase
{
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.Common.Authorization;

namespace Umbraco.Cms.Api.Management.Controllers.Element.Folder;

[VersionedApiBackOfficeRoute($"{Constants.UdiEntityType.Element}/folder")]
[ApiExplorerSettings(GroupName = nameof(Constants.UdiEntityType.Element))]
// TODO ELEMENTS: backoffice authorization policies
[Authorize(Policy = AuthorizationPolicies.TreeAccessElements)]
public abstract class ElementFolderControllerBase : FolderManagementControllerBase<IElement>
{
protected ElementFolderControllerBase(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using Asp.Versioning;
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.ViewModels.Element;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Asp.Versioning;
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Factories;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@
namespace Umbraco.Cms.Api.Management.Controllers.Element.RecycleBin;

[VersionedApiBackOfficeRoute($"{Constants.Web.RoutePath.RecycleBin}/{Constants.UdiEntityType.Element}")]
// TODO ELEMENTS: backoffice authorization policies
[RequireDocumentTreeRootAccess]
[RequireElementTreeRootAccess]
[ApiExplorerSettings(GroupName = nameof(Constants.UdiEntityType.Element))]
// TODO ELEMENTS: backoffice authorization policies
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocuments)]
[Authorize(Policy = AuthorizationPolicies.TreeAccessElements)]
public class ElementRecycleBinControllerBase : RecycleBinControllerBase<ElementRecycleBinItemResponseModel>
{
private readonly IEntityService _entityService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,27 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.Services.Entities;
using Umbraco.Cms.Api.Management.Services.Flags;
using Umbraco.Cms.Api.Management.ViewModels.Tree;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;

namespace Umbraco.Cms.Api.Management.Controllers.Element.Tree;

[ApiVersion("1.0")]
public class AncestorsElementTreeController : ElementTreeControllerBase
{
public AncestorsElementTreeController(IEntityService entityService, IUmbracoMapper umbracoMapper, IElementPresentationFactory elementPresentationFactory)
: base(entityService, umbracoMapper, elementPresentationFactory)
public AncestorsElementTreeController(
IEntityService entityService,
FlagProviderCollection flagProviders,
IUserStartNodeEntitiesService userStartNodeEntitiesService,
IDataTypeService dataTypeService,
AppCaches appCaches,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
IElementPresentationFactory elementPresentationFactory)
: base(entityService, flagProviders, userStartNodeEntitiesService, dataTypeService, appCaches, backOfficeSecurityAccessor, elementPresentationFactory)

Check warning on line 25 in src/Umbraco.Cms.Api.Management/Controllers/Element/Tree/AncestorsElementTreeController.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (v17/feature/global-elements)

❌ New issue: Constructor Over-Injection

AncestorsElementTreeController has 7 arguments, max arguments = 5. This constructor has too many arguments, indicating an object with low cohesion or missing function argument abstraction. Avoid adding more arguments.
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,27 @@
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.Services.Entities;
using Umbraco.Cms.Api.Management.Services.Flags;
using Umbraco.Cms.Api.Management.ViewModels.Tree;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;

namespace Umbraco.Cms.Api.Management.Controllers.Element.Tree;

[ApiVersion("1.0")]
public class ChildrenElementTreeController : ElementTreeControllerBase
{
public ChildrenElementTreeController(IEntityService entityService, IUmbracoMapper umbracoMapper, IElementPresentationFactory elementPresentationFactory)
: base(entityService, umbracoMapper, elementPresentationFactory)
public ChildrenElementTreeController(
IEntityService entityService,
FlagProviderCollection flagProviders,
IUserStartNodeEntitiesService userStartNodeEntitiesService,
IDataTypeService dataTypeService,
AppCaches appCaches,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
IElementPresentationFactory elementPresentationFactory)
: base(entityService, flagProviders, userStartNodeEntitiesService, dataTypeService, appCaches, backOfficeSecurityAccessor, elementPresentationFactory)

Check warning on line 26 in src/Umbraco.Cms.Api.Management/Controllers/Element/Tree/ChildrenElementTreeController.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (v17/feature/global-elements)

❌ New issue: Constructor Over-Injection

ChildrenElementTreeController has 7 arguments, max arguments = 5. This constructor has too many arguments, indicating an object with low cohesion or missing function argument abstraction. Avoid adding more arguments.
{
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,82 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Controllers.Tree;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Api.Management.ViewModels.DocumentType;
using Umbraco.Cms.Api.Management.Services.Entities;
using Umbraco.Cms.Api.Management.Services.Flags;
using Umbraco.Cms.Api.Management.ViewModels.Tree;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Entities;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.Common.Authorization;

namespace Umbraco.Cms.Api.Management.Controllers.Element.Tree;

[VersionedApiBackOfficeRoute($"{Constants.Web.RoutePath.Tree}/{Constants.UdiEntityType.Element}")]
[ApiExplorerSettings(GroupName = nameof(Constants.UdiEntityType.Element))]
// TODO ELEMENTS: backoffice authorization policies
public class ElementTreeControllerBase : FolderTreeControllerBase<ElementTreeItemResponseModel>
[Authorize(Policy = AuthorizationPolicies.SectionAccessForElementTree)]
public class ElementTreeControllerBase : UserStartNodeFolderTreeControllerBase<ElementTreeItemResponseModel>
{
private readonly IUmbracoMapper _umbracoMapper;
private readonly AppCaches _appCaches;
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
private readonly IElementPresentationFactory _elementPresentationFactory;

public ElementTreeControllerBase(IEntityService entityService, IUmbracoMapper umbracoMapper, IElementPresentationFactory elementPresentationFactory)
: base(entityService)
public ElementTreeControllerBase(
IEntityService entityService,
FlagProviderCollection flagProviders,
IUserStartNodeEntitiesService userStartNodeEntitiesService,
IDataTypeService dataTypeService,
AppCaches appCaches,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
IElementPresentationFactory elementPresentationFactory)
: base(entityService, flagProviders, userStartNodeEntitiesService, dataTypeService)
{
_umbracoMapper = umbracoMapper;
_appCaches = appCaches;
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;

Check warning on line 39 in src/Umbraco.Cms.Api.Management/Controllers/Element/Tree/ElementTreeControllerBase.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (v17/feature/global-elements)

❌ New issue: Constructor Over-Injection

ElementTreeControllerBase has 7 arguments, max arguments = 5. This constructor has too many arguments, indicating an object with low cohesion or missing function argument abstraction. Avoid adding more arguments.
_elementPresentationFactory = elementPresentationFactory;
}

protected override UmbracoObjectTypes ItemObjectType => UmbracoObjectTypes.Element;

protected override UmbracoObjectTypes FolderObjectType => UmbracoObjectTypes.ElementContainer;

protected override ElementTreeItemResponseModel[] MapTreeItemViewModels(Guid? parentKey, IEntitySlim[] entities)
=> entities.Select(entity =>
protected override int[] GetUserStartNodeIds()
=> _backOfficeSecurityAccessor
.BackOfficeSecurity?
.CurrentUser?
.CalculateElementStartNodeIds(EntityService, _appCaches)
?? [];

protected override string[] GetUserStartNodePaths()
=> _backOfficeSecurityAccessor
.BackOfficeSecurity?
.CurrentUser?
.GetElementStartNodePaths(EntityService, _appCaches)
?? [];

protected override ElementTreeItemResponseModel MapTreeItemViewModel(Guid? parentKey, IEntitySlim entity)
{
ElementTreeItemResponseModel responseModel = base.MapTreeItemViewModel(parentKey, entity);

if (entity is IElementEntitySlim elementEntitySlim)
{
ElementTreeItemResponseModel responseModel = MapTreeItemViewModel(parentKey, entity);
if (entity is IElementEntitySlim elementEntitySlim)
{
responseModel.HasChildren = false;
responseModel.CreateDate = elementEntitySlim.CreateDate;
responseModel.DocumentType = _elementPresentationFactory.CreateDocumentTypeReferenceResponseModel(elementEntitySlim);
responseModel.Variants = _elementPresentationFactory.CreateVariantsItemResponseModels(elementEntitySlim);
}

return responseModel;
}).ToArray();
responseModel.HasChildren = false;
responseModel.CreateDate = elementEntitySlim.CreateDate;
responseModel.DocumentType = _elementPresentationFactory.CreateDocumentTypeReferenceResponseModel(elementEntitySlim);
responseModel.Variants = _elementPresentationFactory.CreateVariantsItemResponseModels(elementEntitySlim);
}

return responseModel;
}

protected override ElementTreeItemResponseModel MapTreeItemViewModelAsNoAccess(Guid? parentKey, IEntitySlim entity)
{
ElementTreeItemResponseModel viewModel = MapTreeItemViewModel(parentKey, entity);
viewModel.NoAccess = true;
return viewModel;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,27 @@
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.Services.Entities;
using Umbraco.Cms.Api.Management.Services.Flags;
using Umbraco.Cms.Api.Management.ViewModels.Tree;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;

namespace Umbraco.Cms.Api.Management.Controllers.Element.Tree;

[ApiVersion("1.0")]
public class RootElementTreeController : ElementTreeControllerBase
{
public RootElementTreeController(IEntityService entityService, IUmbracoMapper umbracoMapper, IElementPresentationFactory elementPresentationFactory)
: base(entityService, umbracoMapper, elementPresentationFactory)
public RootElementTreeController(
IEntityService entityService,
FlagProviderCollection flagProviders,
IUserStartNodeEntitiesService userStartNodeEntitiesService,
IDataTypeService dataTypeService,
AppCaches appCaches,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
IElementPresentationFactory elementPresentationFactory)
: base(entityService, flagProviders, userStartNodeEntitiesService, dataTypeService, appCaches, backOfficeSecurityAccessor, elementPresentationFactory)

Check warning on line 26 in src/Umbraco.Cms.Api.Management/Controllers/Element/Tree/RootElementTreeController.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (v17/feature/global-elements)

❌ New issue: Constructor Over-Injection

RootElementTreeController has 7 arguments, max arguments = 5. This constructor has too many arguments, indicating an object with low cohesion or missing function argument abstraction. Avoid adding more arguments.
{
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.Services.Entities;
using Umbraco.Cms.Api.Management.Services.Flags;
using Umbraco.Cms.Api.Management.ViewModels.Tree;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;

namespace Umbraco.Cms.Api.Management.Controllers.Element.Tree;

[ApiVersion("1.0")]
public class SiblingsElementTreeController : ElementTreeControllerBase
{
public SiblingsElementTreeController(IEntityService entityService, IUmbracoMapper umbracoMapper, IElementPresentationFactory elementPresentationFactory)
: base(entityService, umbracoMapper, elementPresentationFactory)
public SiblingsElementTreeController(
IEntityService entityService,
FlagProviderCollection flagProviders,
IUserStartNodeEntitiesService userStartNodeEntitiesService,
IDataTypeService dataTypeService,
AppCaches appCaches,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
IElementPresentationFactory elementPresentationFactory)
: base(entityService, flagProviders, userStartNodeEntitiesService, dataTypeService, appCaches, backOfficeSecurityAccessor, elementPresentationFactory)

Check warning on line 26 in src/Umbraco.Cms.Api.Management/Controllers/Element/Tree/SiblingsElementTreeController.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (v17/feature/global-elements)

❌ New issue: Constructor Over-Injection

SiblingsElementTreeController has 7 arguments, max arguments = 5. This constructor has too many arguments, indicating an object with low cohesion or missing function argument abstraction. Avoid adding more arguments.
{
}

[HttpGet("siblings")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(SubsetViewModel<ElementTreeItemResponseModel>), StatusCodes.Status200OK)]
public async Task<ActionResult<SubsetViewModel<ElementTreeItemResponseModel>>> Siblings(
CancellationToken cancellationToken,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Asp.Versioning;
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.ViewModels.Element;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Security;
Expand All @@ -15,16 +14,13 @@ public class UnpublishElementController : ElementControllerBase
{
private readonly IElementPublishingService _elementPublishingService;
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
private readonly IDocumentPresentationFactory _documentPresentationFactory;

public UnpublishElementController(
IElementPublishingService elementPublishingService,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
IDocumentPresentationFactory documentPresentationFactory)
IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
{
_elementPublishingService = elementPublishingService;
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
_documentPresentationFactory = documentPresentationFactory;
}

[HttpPut("{id:guid}/unpublish")]
Expand Down
Loading