Skip to content

Commit ddf663d

Browse files
kjacelit0451
andauthored
Support containers for blueprints (#15983)
* Support containers for blueprints * Update OpenApi.json * Fix tree ordering * Add CancellationToken to new endpoints * Change to doc blueprint specific things * Fix policies * Cleanup * Use ContentBlueprintEditingService methods instead of underlying ContentService * Review comments --------- Co-authored-by: Elitsa <[email protected]>
1 parent e326370 commit ddf663d

39 files changed

Lines changed: 1602 additions & 63 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Asp.Versioning;
2+
using Microsoft.AspNetCore.Http;
3+
using Microsoft.AspNetCore.Mvc;
4+
using Umbraco.Cms.Api.Management.ViewModels.Folder;
5+
using Umbraco.Cms.Core.Security;
6+
using Umbraco.Cms.Core.Services;
7+
8+
namespace Umbraco.Cms.Api.Management.Controllers.DocumentBlueprint.Folder;
9+
10+
[ApiVersion("1.0")]
11+
public class ByKeyDocumentBlueprintFolderController : DocumentBlueprintFolderControllerBase
12+
{
13+
public ByKeyDocumentBlueprintFolderController(
14+
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
15+
IContentBlueprintContainerService contentBlueprintContainerService)
16+
: base(backOfficeSecurityAccessor, contentBlueprintContainerService)
17+
{
18+
}
19+
20+
[HttpGet("{id:guid}")]
21+
[MapToApiVersion("1.0")]
22+
[ProducesResponseType(typeof(FolderResponseModel), StatusCodes.Status200OK)]
23+
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
24+
public async Task<IActionResult> ByKey(CancellationToken cancellationToken, Guid id) => await GetFolderAsync(id);
25+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Asp.Versioning;
2+
using Microsoft.AspNetCore.Http;
3+
using Microsoft.AspNetCore.Mvc;
4+
using Umbraco.Cms.Api.Management.ViewModels.Folder;
5+
using Umbraco.Cms.Core.Security;
6+
using Umbraco.Cms.Core.Services;
7+
8+
namespace Umbraco.Cms.Api.Management.Controllers.DocumentBlueprint.Folder;
9+
10+
[ApiVersion("1.0")]
11+
public class CreateDocumentBlueprintFolderController : DocumentBlueprintFolderControllerBase
12+
{
13+
public CreateDocumentBlueprintFolderController(
14+
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
15+
IContentBlueprintContainerService contentBlueprintContainerService)
16+
: base(backOfficeSecurityAccessor, contentBlueprintContainerService)
17+
{
18+
}
19+
20+
[HttpPost]
21+
[MapToApiVersion("1.0")]
22+
[ProducesResponseType(StatusCodes.Status201Created)]
23+
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
24+
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
25+
public async Task<IActionResult> Create(CancellationToken cancellationToken, CreateFolderRequestModel createFolderRequestModel)
26+
=> await CreateFolderAsync<ByKeyDocumentBlueprintFolderController>(
27+
createFolderRequestModel,
28+
controller => nameof(controller.ByKey));
29+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Asp.Versioning;
2+
using Microsoft.AspNetCore.Http;
3+
using Microsoft.AspNetCore.Mvc;
4+
using Umbraco.Cms.Core.Security;
5+
using Umbraco.Cms.Core.Services;
6+
7+
namespace Umbraco.Cms.Api.Management.Controllers.DocumentBlueprint.Folder;
8+
9+
[ApiVersion("1.0")]
10+
public class DeleteDocumentBlueprintFolderController : DocumentBlueprintFolderControllerBase
11+
{
12+
public DeleteDocumentBlueprintFolderController(
13+
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
14+
IContentBlueprintContainerService contentBlueprintContainerService)
15+
: base(backOfficeSecurityAccessor, contentBlueprintContainerService)
16+
{
17+
}
18+
19+
[HttpDelete("{id:guid}")]
20+
[MapToApiVersion("1.0")]
21+
[ProducesResponseType(StatusCodes.Status200OK)]
22+
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
23+
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
24+
public async Task<IActionResult> Delete(CancellationToken cancellationToken, Guid id) => await DeleteFolderAsync(id);
25+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using Microsoft.AspNetCore.Authorization;
2+
using Microsoft.AspNetCore.Mvc;
3+
using Umbraco.Cms.Api.Management.Routing;
4+
using Umbraco.Cms.Core;
5+
using Umbraco.Cms.Core.Models;
6+
using Umbraco.Cms.Core.Security;
7+
using Umbraco.Cms.Core.Services;
8+
using Umbraco.Cms.Web.Common.Authorization;
9+
10+
namespace Umbraco.Cms.Api.Management.Controllers.DocumentBlueprint.Folder;
11+
12+
[VersionedApiBackOfficeRoute($"{Constants.UdiEntityType.DocumentBlueprint}/folder")]
13+
[ApiExplorerSettings(GroupName = "Document Blueprint")]
14+
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
15+
public abstract class DocumentBlueprintFolderControllerBase : FolderManagementControllerBase<IContent>
16+
{
17+
protected DocumentBlueprintFolderControllerBase(
18+
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
19+
IContentBlueprintContainerService contentBlueprintContainerService)
20+
: base(backOfficeSecurityAccessor, contentBlueprintContainerService)
21+
{
22+
}
23+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Asp.Versioning;
2+
using Microsoft.AspNetCore.Http;
3+
using Microsoft.AspNetCore.Mvc;
4+
using Umbraco.Cms.Api.Management.ViewModels.Folder;
5+
using Umbraco.Cms.Core.Security;
6+
using Umbraco.Cms.Core.Services;
7+
8+
namespace Umbraco.Cms.Api.Management.Controllers.DocumentBlueprint.Folder;
9+
10+
[ApiVersion("1.0")]
11+
public class UpdateDocumentBlueprintFolderController : DocumentBlueprintFolderControllerBase
12+
{
13+
public UpdateDocumentBlueprintFolderController(
14+
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
15+
IContentBlueprintContainerService contentBlueprintContainerService)
16+
: base(backOfficeSecurityAccessor, contentBlueprintContainerService)
17+
{
18+
}
19+
20+
[HttpPut("{id:guid}")]
21+
[MapToApiVersion("1.0")]
22+
[ProducesResponseType(StatusCodes.Status200OK)]
23+
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
24+
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
25+
public async Task<IActionResult> Update(CancellationToken cancellationToken, Guid id, UpdateFolderResponseModel updateFolderResponseModel)
26+
=> await UpdateFolderAsync(id, updateFolderResponseModel);
27+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Asp.Versioning;
2+
using Microsoft.AspNetCore.Authorization;
3+
using Microsoft.AspNetCore.Http;
4+
using Microsoft.AspNetCore.Mvc;
5+
using Umbraco.Cms.Api.Management.ViewModels.DocumentBlueprint;
6+
using Umbraco.Cms.Core;
7+
using Umbraco.Cms.Core.Security;
8+
using Umbraco.Cms.Core.Services;
9+
using Umbraco.Cms.Core.Services.OperationStatus;
10+
using Umbraco.Cms.Web.Common.Authorization;
11+
12+
namespace Umbraco.Cms.Api.Management.Controllers.DocumentBlueprint;
13+
14+
[ApiVersion("1.0")]
15+
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
16+
public class MoveDocumentBlueprintController : DocumentBlueprintControllerBase
17+
{
18+
private readonly IContentBlueprintEditingService _contentBlueprintEditingService;
19+
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
20+
21+
public MoveDocumentBlueprintController(IContentBlueprintEditingService contentBlueprintEditingService, IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
22+
{
23+
_contentBlueprintEditingService = contentBlueprintEditingService;
24+
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
25+
}
26+
27+
[HttpPut("{id:guid}/move")]
28+
[MapToApiVersion("1.0")]
29+
[ProducesResponseType(StatusCodes.Status200OK)]
30+
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
31+
public async Task<IActionResult> Move(CancellationToken cancellationToken, Guid id, MoveDocumentBlueprintRequestModel requestModel)
32+
{
33+
Attempt<ContentEditingOperationStatus> result = await _contentBlueprintEditingService.MoveAsync(id, requestModel.Target?.Id, CurrentUserKey(_backOfficeSecurityAccessor));
34+
return result.Success
35+
? Ok()
36+
: ContentEditingOperationStatusResult(result.Result);
37+
}
38+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Asp.Versioning;
2+
using Microsoft.AspNetCore.Http;
3+
using Microsoft.AspNetCore.Mvc;
4+
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
5+
using Umbraco.Cms.Api.Management.Factories;
6+
using Umbraco.Cms.Api.Management.ViewModels.Tree;
7+
using Umbraco.Cms.Core.Services;
8+
9+
namespace Umbraco.Cms.Api.Management.Controllers.DocumentBlueprint.Tree;
10+
11+
[ApiVersion("1.0")]
12+
public class ChildrenDocumentBlueprintTreeController : DocumentBlueprintTreeControllerBase
13+
{
14+
public ChildrenDocumentBlueprintTreeController(IEntityService entityService, IDocumentPresentationFactory documentPresentationFactory)
15+
: base(entityService, documentPresentationFactory)
16+
{
17+
}
18+
19+
[HttpGet("children")]
20+
[MapToApiVersion("1.0")]
21+
[ProducesResponseType(typeof(PagedViewModel<DocumentBlueprintTreeItemResponseModel>), StatusCodes.Status200OK)]
22+
public async Task<ActionResult<PagedViewModel<DocumentBlueprintTreeItemResponseModel>>> Children(CancellationToken cancellationToken, Guid parentId, int skip = 0, int take = 100, bool foldersOnly = false)
23+
{
24+
RenderFoldersOnly(foldersOnly);
25+
return await GetChildren(parentId, skip, take);
26+
}
27+
}

src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/DocumentBlueprintTreeControllerBase.cs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ namespace Umbraco.Cms.Api.Management.Controllers.DocumentBlueprint.Tree;
1414

1515
[VersionedApiBackOfficeRoute($"{Constants.Web.RoutePath.Tree}/{Constants.UdiEntityType.DocumentBlueprint}")]
1616
[ApiExplorerSettings(GroupName = "Document Blueprint")]
17-
[Authorize(Policy = AuthorizationPolicies.SectionAccessContent)]
18-
public class DocumentBlueprintTreeControllerBase : NamedEntityTreeControllerBase<DocumentBlueprintTreeItemResponseModel>
17+
[Authorize(Policy = AuthorizationPolicies.TreeAccessDocumentTypes)]
18+
public class DocumentBlueprintTreeControllerBase : FolderTreeControllerBase<DocumentBlueprintTreeItemResponseModel>
1919
{
2020
private readonly IDocumentPresentationFactory _documentPresentationFactory;
2121

@@ -25,18 +25,28 @@ public DocumentBlueprintTreeControllerBase(IEntityService entityService, IDocume
2525

2626
protected override UmbracoObjectTypes ItemObjectType => UmbracoObjectTypes.DocumentBlueprint;
2727

28-
protected override DocumentBlueprintTreeItemResponseModel[] MapTreeItemViewModels(Guid? parentId, IEntitySlim[] entities)
28+
protected override UmbracoObjectTypes FolderObjectType => UmbracoObjectTypes.DocumentBlueprintContainer;
29+
30+
protected override Ordering ItemOrdering
2931
{
30-
IDocumentEntitySlim[] documentEntities = entities
31-
.OfType<IDocumentEntitySlim>()
32-
.ToArray();
32+
get
33+
{
34+
var ordering = Ordering.By(nameof(Infrastructure.Persistence.Dtos.NodeDto.NodeObjectType), Direction.Descending); // We need to override to change direction
35+
ordering.Next = Ordering.By(nameof(Infrastructure.Persistence.Dtos.NodeDto.Text));
3336

34-
return documentEntities.Select(entity =>
37+
return ordering;
38+
}
39+
}
40+
41+
protected override DocumentBlueprintTreeItemResponseModel[] MapTreeItemViewModels(Guid? parentId, IEntitySlim[] entities)
42+
=> entities.Select(entity =>
3543
{
36-
DocumentBlueprintTreeItemResponseModel responseModel = base.MapTreeItemViewModel(parentId, entity);
37-
responseModel.HasChildren = false;
38-
responseModel.DocumentType = _documentPresentationFactory.CreateDocumentTypeReferenceResponseModel(entity);
44+
DocumentBlueprintTreeItemResponseModel responseModel = MapTreeItemViewModel(parentId, entity);
45+
if (entity is IDocumentEntitySlim documentEntitySlim)
46+
{
47+
responseModel.HasChildren = false;
48+
responseModel.DocumentType = _documentPresentationFactory.CreateDocumentTypeReferenceResponseModel(documentEntitySlim);
49+
}
3950
return responseModel;
4051
}).ToArray();
41-
}
4252
}

src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/Tree/RootDocumentBlueprintTreeController.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ public RootDocumentBlueprintTreeController(IEntityService entityService, IDocume
1919
[HttpGet("root")]
2020
[MapToApiVersion("1.0")]
2121
[ProducesResponseType(typeof(PagedViewModel<DocumentBlueprintTreeItemResponseModel>), StatusCodes.Status200OK)]
22-
public async Task<ActionResult<PagedViewModel<DocumentBlueprintTreeItemResponseModel>>> Root(int skip = 0, int take = 100)
23-
=> await GetRoot(skip, take);
22+
public async Task<ActionResult<PagedViewModel<DocumentBlueprintTreeItemResponseModel>>> Root(CancellationToken cancellationToken, int skip = 0, int take = 100, bool foldersOnly = false)
23+
{
24+
RenderFoldersOnly(foldersOnly);
25+
return await GetRoot(skip, take);
26+
}
2427
}

0 commit comments

Comments
 (0)