Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[V14] import/export media/document type endpoints #16100

Merged
merged 13 commits into from
May 17, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Api.Management.ViewModels.DocumentType;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Services.OperationStatus;
using Umbraco.Cms.Web.Common.Authorization;
Expand Down Expand Up @@ -108,6 +109,31 @@ status is ContentTypeStructureOperationStatus.Success
_ => new ObjectResult("Unknown content type structure operation status") { StatusCode = StatusCodes.Status500InternalServerError }
});

protected IActionResult ContentTypeImportOperationStatusResult(ContentTypeImportOperationStatus operationStatus) =>
OperationStatusResult(operationStatus, problemDetailsBuilder => operationStatus switch
{
ContentTypeImportOperationStatus.TemporaryFileNotFound => NotFound(problemDetailsBuilder
.WithTitle("Temporary file not found")
.Build()),
ContentTypeImportOperationStatus.TemporaryFileConversionFailure => BadRequest(problemDetailsBuilder
.WithTitle("Failed to convert the specified file")
.WithDetail("The import failed due to not being able to convert the file into proper xml")
.Build()),
ContentTypeImportOperationStatus.DocumentTypeExists => BadRequest(problemDetailsBuilder
.WithTitle("Failed to import because document type exits")
.WithDetail("The import failed because the document type that was being imported already exits")
.Build()),
ContentTypeImportOperationStatus.TypeMismatch => BadRequest(problemDetailsBuilder
.WithTitle("Type Mismatch")
.WithDetail("The import failed because the file contained an entity that is not a content type.")
.Build()),
ContentTypeImportOperationStatus.IdMismatch => BadRequest(problemDetailsBuilder
.WithTitle("Invalid Id")
.WithDetail("The import failed because the id of the document type you are trying to update did not match the id in the file.")
.Build()),
_ => StatusCode(StatusCodes.Status500InternalServerError, "Unknown document type import operation status.")
});

protected IActionResult ContentEditingOperationStatusResult(ContentEditingOperationStatus status) =>
OperationStatusResult(status, problemDetailsBuilder => status switch
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;

namespace Umbraco.Cms.Api.Management.Controllers.DocumentType;

[ApiVersion("1.0")]
public class ExportDocumentTypeController : DocumentTypeControllerBase
{
private readonly IContentTypeService _contentTypeService;
private readonly IUdtFileContentFactory _fileContentFactory;

public ExportDocumentTypeController(
IContentTypeService contentTypeService,
IUdtFileContentFactory fileContentFactory)
{
_contentTypeService = contentTypeService;
_fileContentFactory = fileContentFactory;
}

[HttpGet("{id:guid}/export")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public IActionResult Export(
CancellationToken cancellationToken,
Guid id)
{
IContentType? contentType = _contentTypeService.Get(id);
if (contentType is null)
{
return OperationStatusResult(ContentTypeOperationStatus.NotFound);
}

return _fileContentFactory.Create(contentType);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.ViewModels.DocumentType;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services.ImportExport;
using Umbraco.Cms.Core.Services.OperationStatus;

namespace Umbraco.Cms.Api.Management.Controllers.DocumentType;

[ApiVersion("1.0")]
public class ImportExistingDocumentTypeController : DocumentTypeControllerBase
{
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
private readonly IContentTypeImportService _contentTypeImportService;

public ImportExistingDocumentTypeController(
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
IContentTypeImportService contentTypeImportService)
{
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
_contentTypeImportService = contentTypeImportService;
}

[HttpPut("{id:guid}/import")]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Import(
CancellationToken cancellationToken,
Guid id,
ImportDocumentTypeRequestModel model)
{
Attempt<IContentType?, ContentTypeImportOperationStatus> importAttempt = await _contentTypeImportService.Import(model.File.Id, CurrentUserKey(_backOfficeSecurityAccessor), id);

return importAttempt.Success is false
? ContentTypeImportOperationStatusResult(importAttempt.Status)
: Ok();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.ViewModels.DocumentType;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services.ImportExport;
using Umbraco.Cms.Core.Services.OperationStatus;

namespace Umbraco.Cms.Api.Management.Controllers.DocumentType;

[ApiVersion("1.0")]
public class ImportNewDocumentTypeController : DocumentTypeControllerBase
{
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
private readonly IContentTypeImportService _contentTypeImportService;

public ImportNewDocumentTypeController(
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
IContentTypeImportService contentTypeImportService)
{
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
_contentTypeImportService = contentTypeImportService;
}

[HttpPost("import")]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Import(
CancellationToken cancellationToken,
ImportDocumentTypeRequestModel model)
{

Attempt<IContentType?, ContentTypeImportOperationStatus> importAttempt = await _contentTypeImportService.Import(model.File.Id, CurrentUserKey(_backOfficeSecurityAccessor));

return importAttempt.Success is false
? ContentTypeImportOperationStatusResult(importAttempt.Status)
: CreatedAtId<ByKeyDocumentTypeController>(
controller => nameof(controller.ByKey),
importAttempt.Result!.Key);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.ViewModels.Import;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Models.ImportExport;
using Umbraco.Cms.Core.Services.ImportExport;
using Umbraco.Cms.Core.Services.OperationStatus;

namespace Umbraco.Cms.Api.Management.Controllers.Import;

[ApiVersion("1.0")]
public class AnalyzeImportController : ImportControllerBase
{
private readonly ITemporaryFileToXmlImportService _temporaryFileToXmlImportService;
private readonly IUmbracoMapper _mapper;

public AnalyzeImportController(
ITemporaryFileToXmlImportService temporaryFileToXmlImportService,
IUmbracoMapper mapper)
{
_temporaryFileToXmlImportService = temporaryFileToXmlImportService;
_mapper = mapper;
}

[HttpGet("analyze")]
[ProducesResponseType(typeof(EntityImportAnalysisResponseModel), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Analyze(CancellationToken cancellationToken, Guid temporaryFileId)
{
Attempt<EntityXmlAnalysis?, TemporaryFileXmlImportOperationStatus> analyzeResult = await _temporaryFileToXmlImportService.AnalyzeAsync(temporaryFileId);

return analyzeResult.Success is false
? TemporaryFileXmlImportOperationStatusResult(analyzeResult.Status)
: Ok(_mapper.Map<EntityImportAnalysisResponseModel>(analyzeResult.Result));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Core.Services.OperationStatus;

namespace Umbraco.Cms.Api.Management.Controllers.Import;

[VersionedApiBackOfficeRoute("import")]
[ApiExplorerSettings(GroupName = "Import")]
public abstract class ImportControllerBase : ManagementApiControllerBase
{
protected static IActionResult TemporaryFileXmlImportOperationStatusResult(TemporaryFileXmlImportOperationStatus operationStatus) =>
OperationStatusResult(operationStatus, problemDetailsBuilder => operationStatus switch
{
TemporaryFileXmlImportOperationStatus.TemporaryFileNotFound => new NotFoundObjectResult(problemDetailsBuilder
.WithTitle("Temporary file not found")
.Build()),
TemporaryFileXmlImportOperationStatus.UndeterminedEntityType => new BadRequestObjectResult(problemDetailsBuilder
.WithTitle("Unable to determine entity type")
.Build()),
_ => new ObjectResult("Unknown temporary file import operation status") { StatusCode = StatusCodes.Status500InternalServerError },
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;

namespace Umbraco.Cms.Api.Management.Controllers.MediaType;

[ApiVersion("1.0")]
public class ExportMediaTypeController : MediaTypeControllerBase
{
private readonly IMediaTypeService _mediaTypeService;
private readonly IUdtFileContentFactory _fileContentFactory;

public ExportMediaTypeController(
IMediaTypeService mediaTypeService,
IUdtFileContentFactory fileContentFactory)
{
_mediaTypeService = mediaTypeService;
_fileContentFactory = fileContentFactory;
}

[HttpGet("{id:guid}/export")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public IActionResult Export(
CancellationToken cancellationToken,
Guid id)
{
IMediaType? mediaType = _mediaTypeService.Get(id);
if (mediaType is null)
{
return OperationStatusResult(ContentTypeOperationStatus.NotFound);
}

return _fileContentFactory.Create(mediaType);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.ViewModels.MediaType;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services.ImportExport;
using Umbraco.Cms.Core.Services.OperationStatus;

namespace Umbraco.Cms.Api.Management.Controllers.MediaType;

[ApiVersion("1.0")]
public class ImportExistingMediaTypeController : MediaTypeControllerBase
{
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
private readonly IMediaTypeImportService _mediaTypeImportService;

public ImportExistingMediaTypeController(
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
IMediaTypeImportService mediaTypeImportService)
{
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
_mediaTypeImportService = mediaTypeImportService;
}

[HttpPut("{id:guid}/import")]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Import(
CancellationToken cancellationToken,
Guid id,
ImportMediaTypeRequestModel model)
{
Attempt<IMediaType?, MediaTypeImportOperationStatus> importAttempt = await _mediaTypeImportService.Import(model.File.Id, CurrentUserKey(_backOfficeSecurityAccessor));

return importAttempt.Success is false
? MediaTypeImportOperationStatusResult(importAttempt.Status)
: Ok();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Controllers.DocumentType;
using Umbraco.Cms.Api.Management.ViewModels.MediaType;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services.ImportExport;
using Umbraco.Cms.Core.Services.OperationStatus;

namespace Umbraco.Cms.Api.Management.Controllers.MediaType;

[ApiVersion("1.0")]
public class ImportNewMediaTypeController : MediaTypeControllerBase
{
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
private readonly IMediaTypeImportService _mediaTypeImportService;

public ImportNewMediaTypeController(
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
IMediaTypeImportService mediaTypeImportService)
{
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
_mediaTypeImportService = mediaTypeImportService;
}

[HttpPost("import")]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Import(
CancellationToken cancellationToken,
ImportMediaTypeRequestModel model)
{
Attempt<IMediaType?, MediaTypeImportOperationStatus> importAttempt = await _mediaTypeImportService.Import(model.File.Id, CurrentUserKey(_backOfficeSecurityAccessor));

return importAttempt.Success is false
? MediaTypeImportOperationStatusResult(importAttempt.Status)
: CreatedAtId<ByKeyMediaTypeController>(controller => nameof(controller.ByKey), importAttempt.Result!.Key);
}
}
Loading
Loading