2023-01-06 08:45:06 +01:00
|
|
|
|
using System.Linq.Expressions;
|
2023-08-24 09:32:36 +02:00
|
|
|
|
using Microsoft.AspNetCore.Http;
|
2023-01-06 08:45:06 +01:00
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
2024-02-06 13:19:30 +01:00
|
|
|
|
using Umbraco.Cms.Api.Management.ViewModels;
|
2023-01-06 08:45:06 +01:00
|
|
|
|
using Umbraco.Cms.Api.Management.ViewModels.Folder;
|
|
|
|
|
|
using Umbraco.Cms.Core;
|
|
|
|
|
|
using Umbraco.Cms.Core.Models;
|
2023-08-24 09:32:36 +02:00
|
|
|
|
using Umbraco.Cms.Core.Models.Entities;
|
2023-01-06 08:45:06 +01:00
|
|
|
|
using Umbraco.Cms.Core.Security;
|
2023-08-24 09:32:36 +02:00
|
|
|
|
using Umbraco.Cms.Core.Services;
|
|
|
|
|
|
using Umbraco.Cms.Core.Services.OperationStatus;
|
2023-01-06 08:45:06 +01:00
|
|
|
|
|
|
|
|
|
|
namespace Umbraco.Cms.Api.Management.Controllers;
|
|
|
|
|
|
|
2023-08-24 09:32:36 +02:00
|
|
|
|
public abstract class FolderManagementControllerBase<TTreeEntity> : ManagementApiControllerBase
|
|
|
|
|
|
where TTreeEntity : ITreeEntity
|
2023-01-06 08:45:06 +01:00
|
|
|
|
{
|
|
|
|
|
|
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
|
2023-08-24 09:32:36 +02:00
|
|
|
|
private readonly IEntityTypeContainerService<TTreeEntity> _treeEntityTypeContainerService;
|
2023-01-06 08:45:06 +01:00
|
|
|
|
|
2023-08-24 09:32:36 +02:00
|
|
|
|
protected FolderManagementControllerBase(IBackOfficeSecurityAccessor backOfficeSecurityAccessor, IEntityTypeContainerService<TTreeEntity> treeEntityTypeContainerService)
|
|
|
|
|
|
{
|
|
|
|
|
|
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
|
|
|
|
|
|
_treeEntityTypeContainerService = treeEntityTypeContainerService;
|
|
|
|
|
|
}
|
2023-01-06 08:45:06 +01:00
|
|
|
|
|
2023-02-01 08:38:36 +01:00
|
|
|
|
protected async Task<IActionResult> GetFolderAsync(Guid key)
|
2023-01-06 08:45:06 +01:00
|
|
|
|
{
|
2023-08-24 09:32:36 +02:00
|
|
|
|
EntityContainer? container = await _treeEntityTypeContainerService.GetAsync(key);
|
2023-01-06 08:45:06 +01:00
|
|
|
|
if (container == null)
|
|
|
|
|
|
{
|
2024-02-22 15:17:06 +01:00
|
|
|
|
return OperationStatusResult(
|
|
|
|
|
|
EntityContainerOperationStatus.NotFound,
|
|
|
|
|
|
problemDetailsBuilder => NotFound(problemDetailsBuilder
|
|
|
|
|
|
.WithTitle($"Could not find the folder with id: {key}")
|
|
|
|
|
|
.Build()));
|
2023-01-06 08:45:06 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-24 09:32:36 +02:00
|
|
|
|
EntityContainer? parentContainer = await _treeEntityTypeContainerService.GetParentAsync(container);
|
2023-01-06 08:45:06 +01:00
|
|
|
|
|
|
|
|
|
|
// we could implement a mapper for this but it seems rather overkill at this point
|
2023-07-19 13:54:17 +02:00
|
|
|
|
return Ok(new FolderResponseModel
|
2023-01-06 08:45:06 +01:00
|
|
|
|
{
|
|
|
|
|
|
Name = container.Name!,
|
2023-03-31 13:59:44 +02:00
|
|
|
|
Id = container.Key,
|
2024-02-06 13:19:30 +01:00
|
|
|
|
Parent = ReferenceByIdModel.ReferenceOrNull(parentContainer?.Key)
|
2023-01-06 08:45:06 +01:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-01 08:38:36 +01:00
|
|
|
|
protected async Task<IActionResult> CreateFolderAsync<TCreatedActionController>(
|
2023-03-13 10:49:21 +01:00
|
|
|
|
CreateFolderRequestModel createFolderRequestModel,
|
2023-01-06 08:45:06 +01:00
|
|
|
|
Expression<Func<TCreatedActionController, string>> createdAction)
|
|
|
|
|
|
{
|
2023-08-24 09:32:36 +02:00
|
|
|
|
Attempt<EntityContainer?, EntityContainerOperationStatus> result = await _treeEntityTypeContainerService.CreateAsync(
|
|
|
|
|
|
createFolderRequestModel.Id,
|
|
|
|
|
|
createFolderRequestModel.Name,
|
2024-02-06 13:19:30 +01:00
|
|
|
|
createFolderRequestModel.Parent?.Id,
|
2023-03-21 12:41:20 +01:00
|
|
|
|
CurrentUserKey(_backOfficeSecurityAccessor));
|
2023-01-06 08:45:06 +01:00
|
|
|
|
|
2023-02-01 08:38:36 +01:00
|
|
|
|
return result.Success
|
2024-01-22 08:20:45 +01:00
|
|
|
|
? CreatedAtId(createdAction, result.Result!.Key)
|
2023-02-01 08:38:36 +01:00
|
|
|
|
: OperationStatusResult(result.Status);
|
2023-01-06 08:45:06 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-24 09:32:36 +02:00
|
|
|
|
protected async Task<IActionResult> UpdateFolderAsync(Guid key, UpdateFolderResponseModel updateFolderResponseModel)
|
2023-01-06 08:45:06 +01:00
|
|
|
|
{
|
2023-08-24 09:32:36 +02:00
|
|
|
|
Attempt<EntityContainer?, EntityContainerOperationStatus> result = await _treeEntityTypeContainerService.UpdateAsync(
|
|
|
|
|
|
key,
|
|
|
|
|
|
updateFolderResponseModel.Name,
|
|
|
|
|
|
CurrentUserKey(_backOfficeSecurityAccessor));
|
2023-01-06 08:45:06 +01:00
|
|
|
|
|
2023-02-01 08:38:36 +01:00
|
|
|
|
return result.Success
|
|
|
|
|
|
? Ok()
|
|
|
|
|
|
: OperationStatusResult(result.Status);
|
2023-01-06 08:45:06 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-01 08:38:36 +01:00
|
|
|
|
protected async Task<IActionResult> DeleteFolderAsync(Guid key)
|
2023-01-06 08:45:06 +01:00
|
|
|
|
{
|
2023-08-24 09:32:36 +02:00
|
|
|
|
Attempt<EntityContainer?, EntityContainerOperationStatus> result = await _treeEntityTypeContainerService.DeleteAsync(key, CurrentUserKey(_backOfficeSecurityAccessor));
|
2023-02-01 08:38:36 +01:00
|
|
|
|
return result.Success
|
|
|
|
|
|
? Ok()
|
|
|
|
|
|
: OperationStatusResult(result.Status);
|
2023-01-06 08:45:06 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-24 09:32:36 +02:00
|
|
|
|
protected IActionResult OperationStatusResult(EntityContainerOperationStatus status)
|
2024-02-22 15:17:06 +01:00
|
|
|
|
=> OperationStatusResult(status, problemDetailsBuilder => status switch
|
2023-08-24 09:32:36 +02:00
|
|
|
|
{
|
2024-02-22 15:17:06 +01:00
|
|
|
|
EntityContainerOperationStatus.NotFound => NotFound(problemDetailsBuilder
|
2023-08-24 09:32:36 +02:00
|
|
|
|
.WithTitle("The folder could not be found")
|
|
|
|
|
|
.Build()),
|
2024-02-22 15:17:06 +01:00
|
|
|
|
EntityContainerOperationStatus.ParentNotFound => NotFound(problemDetailsBuilder
|
2023-08-24 09:32:36 +02:00
|
|
|
|
.WithTitle("The parent folder could not be found")
|
|
|
|
|
|
.Build()),
|
2024-02-22 15:17:06 +01:00
|
|
|
|
EntityContainerOperationStatus.DuplicateName => BadRequest(problemDetailsBuilder
|
2023-08-24 09:32:36 +02:00
|
|
|
|
.WithTitle("The name is already used")
|
|
|
|
|
|
.WithDetail("The folder name must be unique on this parent.")
|
|
|
|
|
|
.Build()),
|
2024-02-22 15:17:06 +01:00
|
|
|
|
EntityContainerOperationStatus.DuplicateKey => BadRequest(problemDetailsBuilder
|
2023-08-24 09:32:36 +02:00
|
|
|
|
.WithTitle("The id is already used")
|
|
|
|
|
|
.WithDetail("The folder id must be unique.")
|
|
|
|
|
|
.Build()),
|
2024-02-22 15:17:06 +01:00
|
|
|
|
EntityContainerOperationStatus.NotEmpty => BadRequest(problemDetailsBuilder
|
2023-08-24 09:32:36 +02:00
|
|
|
|
.WithTitle("The folder is not empty")
|
|
|
|
|
|
.WithDetail("The folder must be empty to perform this action.")
|
|
|
|
|
|
.Build()),
|
2024-02-22 15:17:06 +01:00
|
|
|
|
EntityContainerOperationStatus.CancelledByNotification => BadRequest(problemDetailsBuilder
|
2023-08-24 09:32:36 +02:00
|
|
|
|
.WithTitle("Cancelled by notification")
|
|
|
|
|
|
.WithDetail("A notification handler prevented the folder operation.")
|
|
|
|
|
|
.Build()),
|
2024-02-22 15:17:06 +01:00
|
|
|
|
_ => StatusCode(StatusCodes.Status500InternalServerError, problemDetailsBuilder
|
2023-08-24 09:32:36 +02:00
|
|
|
|
.WithTitle("Unknown folder operation status.")
|
|
|
|
|
|
.Build()),
|
2024-02-22 15:17:06 +01:00
|
|
|
|
});
|
2023-01-06 08:45:06 +01:00
|
|
|
|
}
|