Move document related operations to DocumentControllerBase (#15661)

* Clean up ContentControllerBase and move document related operations to DocumentControllerBase

* Rename content to document

---------

Co-authored-by: Elitsa <elm@umbraco.dk>
This commit is contained in:
Kenn Jacobsen
2024-02-01 11:29:52 +01:00
committed by GitHub
parent 296b7e061a
commit d29e05efb7
6 changed files with 118 additions and 135 deletions

View File

@@ -1,10 +1,8 @@
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.ViewModels.Content; using Umbraco.Cms.Api.Management.ViewModels.Content;
using Umbraco.Cms.Api.Management.ViewModels.Document;
using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Models.ContentEditing.Validation; using Umbraco.Cms.Core.Models.ContentEditing.Validation;
using Umbraco.Cms.Core.Models.ContentPublishing;
using Umbraco.Cms.Core.Services.OperationStatus; using Umbraco.Cms.Core.Services.OperationStatus;
using Umbraco.Extensions; using Umbraco.Extensions;
@@ -63,7 +61,8 @@ public class ContentControllerBase : ManagementApiControllerBase
.WithTitle("Invalid sorting options") .WithTitle("Invalid sorting options")
.WithDetail("The supplied sorting operations were invalid. Additional details can be found in the log.") .WithDetail("The supplied sorting operations were invalid. Additional details can be found in the log.")
.Build()), .Build()),
ContentEditingOperationStatus.Unknown => StatusCode(StatusCodes.Status500InternalServerError, ContentEditingOperationStatus.Unknown => StatusCode(
StatusCodes.Status500InternalServerError,
problemDetailsBuilder problemDetailsBuilder
.WithTitle("Unknown error. Please see the log for more details.") .WithTitle("Unknown error. Please see the log for more details.")
.Build()), .Build()),
@@ -112,125 +111,4 @@ public class ContentControllerBase : ManagementApiControllerBase
.WithExtension("missingProperties", missingPropertyAliases.ToArray()) .WithExtension("missingProperties", missingPropertyAliases.ToArray())
.Build())); .Build()));
} }
protected IActionResult ContentPublishingOperationStatusResult(
ContentPublishingOperationStatus status,
IEnumerable<string>? invalidPropertyAliases = null,
IEnumerable<ContentPublishingBranchItemResult>? failedBranchItems = null)
=> OperationStatusResult(status, problemDetailsBuilder => status switch
{
ContentPublishingOperationStatus.ContentNotFound => NotFound(problemDetailsBuilder
.WithTitle("The requested content could not be found")
.Build()),
ContentPublishingOperationStatus.CancelledByEvent => BadRequest(problemDetailsBuilder
.WithTitle("Publish cancelled by event")
.WithDetail("The publish operation was cancelled by an event.")
.Build()),
ContentPublishingOperationStatus.ContentInvalid => BadRequest(problemDetailsBuilder
.WithTitle("Invalid content")
.WithDetail("The specified content had an invalid configuration.")
.WithExtension("invalidProperties", invalidPropertyAliases ?? Enumerable.Empty<string>())
.Build()),
ContentPublishingOperationStatus.NothingToPublish => BadRequest(problemDetailsBuilder
.WithTitle("Nothing to publish")
.WithDetail("None of the specified cultures needed publishing.")
.Build()),
ContentPublishingOperationStatus.MandatoryCultureMissing => BadRequest(problemDetailsBuilder
.WithTitle("Mandatory culture missing")
.WithDetail("Must include all mandatory cultures when publishing.")
.Build()),
ContentPublishingOperationStatus.HasExpired => BadRequest(problemDetailsBuilder
.WithTitle("Content expired")
.WithDetail("Could not publish the content because it was expired.")
.Build()),
ContentPublishingOperationStatus.CultureHasExpired => BadRequest(problemDetailsBuilder
.WithTitle("Content culture expired")
.WithDetail("Could not publish the content because some of the specified cultures were expired.")
.Build()),
ContentPublishingOperationStatus.AwaitingRelease => BadRequest(problemDetailsBuilder
.WithTitle("Content awaiting release")
.WithDetail("Could not publish the content because it was awaiting release.")
.Build()),
ContentPublishingOperationStatus.CultureAwaitingRelease => BadRequest(problemDetailsBuilder
.WithTitle("Content culture awaiting release")
.WithDetail(
"Could not publish the content because some of the specified cultures were awaiting release.")
.Build()),
ContentPublishingOperationStatus.InTrash => BadRequest(problemDetailsBuilder
.WithTitle("Content in the recycle bin")
.WithDetail("Could not publish the content because it was in the recycle bin.")
.Build()),
ContentPublishingOperationStatus.PathNotPublished => BadRequest(problemDetailsBuilder
.WithTitle("Parent not published")
.WithDetail("Could not publish the content because its parent was not published.")
.Build()),
ContentPublishingOperationStatus.ConcurrencyViolation => BadRequest(problemDetailsBuilder
.WithTitle("Concurrency violation detected")
.WithDetail("An attempt was made to publish a version older than the latest version.")
.Build()),
ContentPublishingOperationStatus.UnsavedChanges => BadRequest(problemDetailsBuilder
.WithTitle("Unsaved changes")
.WithDetail(
"Could not publish the content because it had unsaved changes. Make sure to save all changes before attempting a publish.")
.Build()),
ContentPublishingOperationStatus.FailedBranch => BadRequest(problemDetailsBuilder
.WithTitle("Failed branch operation")
.WithDetail("One or more items in the branch could not complete the operation.")
.WithExtension("failedBranchItems", failedBranchItems?.Select(item => new DocumentPublishBranchItemResult
{
Id = item.Key,
OperationStatus = item.OperationStatus
}) ?? Enumerable.Empty<DocumentPublishBranchItemResult>())
.Build()),
ContentPublishingOperationStatus.Failed => BadRequest(problemDetailsBuilder
.WithTitle("Publish or unpublish failed")
.WithDetail(
"An unspecified error occurred while (un)publishing. Please check the logs for additional information.")
.Build()),
_ => StatusCode(StatusCodes.Status500InternalServerError, "Unknown content operation status."),
});
protected IActionResult ContentCreatingOperationStatusResult(ContentCreatingOperationStatus status)
=> OperationStatusResult(status, problemDetailsBuilder => status switch
{
ContentCreatingOperationStatus.NotFound => NotFound(problemDetailsBuilder
.WithTitle("The content type could not be found")
.Build()),
_ => StatusCode(StatusCodes.Status500InternalServerError, problemDetailsBuilder
.WithTitle("Unknown content operation status.")
.Build()),
});
protected IActionResult PublicAccessOperationStatusResult(PublicAccessOperationStatus status)
=> OperationStatusResult(status, problemDetailsBuilder => status switch
{
PublicAccessOperationStatus.ContentNotFound => NotFound(problemDetailsBuilder
.WithTitle("The content could not be found")
.Build()),
PublicAccessOperationStatus.ErrorNodeNotFound => NotFound(problemDetailsBuilder
.WithTitle("The error page could not be found")
.Build()),
PublicAccessOperationStatus.LoginNodeNotFound => NotFound(problemDetailsBuilder
.WithTitle("The login page could not be found")
.Build()),
PublicAccessOperationStatus.NoAllowedEntities => BadRequest(problemDetailsBuilder
.WithTitle("No allowed entities given")
.WithDetail("Both MemberGroups and Members were empty, thus no entities can be allowed.")
.Build()),
PublicAccessOperationStatus.CancelledByNotification => BadRequest(problemDetailsBuilder
.WithTitle("Request cancelled by notification")
.WithDetail("The request to save a public access entry was cancelled by a notification handler.")
.Build()),
PublicAccessOperationStatus.AmbiguousRule => BadRequest(problemDetailsBuilder
.WithTitle("Ambiguous Rule")
.WithDetail("The specified rule is ambiguous, because both member groups and member names were given.")
.Build()),
PublicAccessOperationStatus.EntryNotFound => BadRequest(problemDetailsBuilder
.WithTitle("Entry not found")
.WithDetail("The specified entry was not found.")
.Build()),
_ => StatusCode(StatusCodes.Status500InternalServerError, problemDetailsBuilder
.WithTitle("Unknown content operation status.")
.Build()),
});
} }

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Controllers.Content; using Umbraco.Cms.Api.Management.Controllers.Content;
using Umbraco.Cms.Api.Management.Routing; using Umbraco.Cms.Api.Management.Routing;
@@ -6,6 +7,7 @@ using Umbraco.Cms.Api.Management.ViewModels.Content;
using Umbraco.Cms.Api.Management.ViewModels.Document; using Umbraco.Cms.Api.Management.ViewModels.Document;
using Umbraco.Cms.Core; using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Models.ContentPublishing;
using Umbraco.Cms.Core.Services.OperationStatus; using Umbraco.Cms.Core.Services.OperationStatus;
using Umbraco.Cms.Web.Common.Authorization; using Umbraco.Cms.Web.Common.Authorization;
@@ -20,7 +22,7 @@ public abstract class DocumentControllerBase : ContentControllerBase
protected IActionResult DocumentNotFound() protected IActionResult DocumentNotFound()
=> OperationStatusResult(ContentEditingOperationStatus.NotFound, problemDetailsBuilder => OperationStatusResult(ContentEditingOperationStatus.NotFound, problemDetailsBuilder
=> NotFound(problemDetailsBuilder => NotFound(problemDetailsBuilder
.WithTitle("The requested Document could not be found") .WithTitle("The document could not be found")
.Build())); .Build()));
protected IActionResult DocumentEditingOperationStatusResult<TContentModelBase>( protected IActionResult DocumentEditingOperationStatusResult<TContentModelBase>(
@@ -29,4 +31,114 @@ public abstract class DocumentControllerBase : ContentControllerBase
ContentValidationResult validationResult) ContentValidationResult validationResult)
where TContentModelBase : ContentModelBase<DocumentValueModel, DocumentVariantRequestModel> where TContentModelBase : ContentModelBase<DocumentValueModel, DocumentVariantRequestModel>
=> ContentEditingOperationStatusResult<TContentModelBase, DocumentValueModel, DocumentVariantRequestModel>(status, requestModel, validationResult); => ContentEditingOperationStatusResult<TContentModelBase, DocumentValueModel, DocumentVariantRequestModel>(status, requestModel, validationResult);
protected IActionResult DocumentPublishingOperationStatusResult(
ContentPublishingOperationStatus status,
IEnumerable<string>? invalidPropertyAliases = null,
IEnumerable<ContentPublishingBranchItemResult>? failedBranchItems = null)
=> OperationStatusResult(status, problemDetailsBuilder => status switch
{
ContentPublishingOperationStatus.ContentNotFound => NotFound(problemDetailsBuilder
.WithTitle("The requested document could not be found")
.Build()),
ContentPublishingOperationStatus.CancelledByEvent => BadRequest(problemDetailsBuilder
.WithTitle("Publish cancelled by event")
.WithDetail("The publish operation was cancelled by an event.")
.Build()),
ContentPublishingOperationStatus.ContentInvalid => BadRequest(problemDetailsBuilder
.WithTitle("Invalid document")
.WithDetail("The specified document had an invalid configuration.")
.WithExtension("invalidProperties", invalidPropertyAliases ?? Enumerable.Empty<string>())
.Build()),
ContentPublishingOperationStatus.NothingToPublish => BadRequest(problemDetailsBuilder
.WithTitle("Nothing to publish")
.WithDetail("None of the specified cultures needed publishing.")
.Build()),
ContentPublishingOperationStatus.MandatoryCultureMissing => BadRequest(problemDetailsBuilder
.WithTitle("Mandatory culture missing")
.WithDetail("Must include all mandatory cultures when publishing.")
.Build()),
ContentPublishingOperationStatus.HasExpired => BadRequest(problemDetailsBuilder
.WithTitle("Document expired")
.WithDetail("Could not publish the document because it was expired.")
.Build()),
ContentPublishingOperationStatus.CultureHasExpired => BadRequest(problemDetailsBuilder
.WithTitle("Document culture expired")
.WithDetail("Could not publish the document because some of the specified cultures were expired.")
.Build()),
ContentPublishingOperationStatus.AwaitingRelease => BadRequest(problemDetailsBuilder
.WithTitle("Document awaiting release")
.WithDetail("Could not publish the document because it was awaiting release.")
.Build()),
ContentPublishingOperationStatus.CultureAwaitingRelease => BadRequest(problemDetailsBuilder
.WithTitle("Document culture awaiting release")
.WithDetail(
"Could not publish the document because some of the specified cultures were awaiting release.")
.Build()),
ContentPublishingOperationStatus.InTrash => BadRequest(problemDetailsBuilder
.WithTitle("Document in the recycle bin")
.WithDetail("Could not publish the document because it was in the recycle bin.")
.Build()),
ContentPublishingOperationStatus.PathNotPublished => BadRequest(problemDetailsBuilder
.WithTitle("Parent not published")
.WithDetail("Could not publish the document because its parent was not published.")
.Build()),
ContentPublishingOperationStatus.ConcurrencyViolation => BadRequest(problemDetailsBuilder
.WithTitle("Concurrency violation detected")
.WithDetail("An attempt was made to publish a version older than the latest version.")
.Build()),
ContentPublishingOperationStatus.UnsavedChanges => BadRequest(problemDetailsBuilder
.WithTitle("Unsaved changes")
.WithDetail(
"Could not publish the document because it had unsaved changes. Make sure to save all changes before attempting a publish.")
.Build()),
ContentPublishingOperationStatus.FailedBranch => BadRequest(problemDetailsBuilder
.WithTitle("Failed branch operation")
.WithDetail("One or more items in the branch could not complete the operation.")
.WithExtension("failedBranchItems", failedBranchItems?.Select(item => new DocumentPublishBranchItemResult
{
Id = item.Key,
OperationStatus = item.OperationStatus
}) ?? Enumerable.Empty<DocumentPublishBranchItemResult>())
.Build()),
ContentPublishingOperationStatus.Failed => BadRequest(problemDetailsBuilder
.WithTitle("Publish or unpublish failed")
.WithDetail(
"An unspecified error occurred while (un)publishing. Please check the logs for additional information.")
.Build()),
_ => StatusCode(StatusCodes.Status500InternalServerError, "Unknown content operation status."),
});
protected IActionResult PublicAccessOperationStatusResult(PublicAccessOperationStatus status)
=> OperationStatusResult(status, problemDetailsBuilder => status switch
{
PublicAccessOperationStatus.ContentNotFound => NotFound(problemDetailsBuilder
.WithTitle("The document could not be found")
.Build()),
PublicAccessOperationStatus.ErrorNodeNotFound => NotFound(problemDetailsBuilder
.WithTitle("The error page could not be found")
.Build()),
PublicAccessOperationStatus.LoginNodeNotFound => NotFound(problemDetailsBuilder
.WithTitle("The login page could not be found")
.Build()),
PublicAccessOperationStatus.NoAllowedEntities => BadRequest(problemDetailsBuilder
.WithTitle("No allowed entities given")
.WithDetail("Both MemberGroups and Members were empty, thus no entities can be allowed.")
.Build()),
PublicAccessOperationStatus.CancelledByNotification => BadRequest(problemDetailsBuilder
.WithTitle("Request cancelled by notification")
.WithDetail("The request to save a public access entry was cancelled by a notification handler.")
.Build()),
PublicAccessOperationStatus.AmbiguousRule => BadRequest(problemDetailsBuilder
.WithTitle("Ambiguous Rule")
.WithDetail("The specified rule is ambiguous, because both member groups and member names were given.")
.Build()),
PublicAccessOperationStatus.EntryNotFound => BadRequest(problemDetailsBuilder
.WithTitle("Entry not found")
.WithDetail("The specified entry was not found.")
.Build()),
_ => StatusCode(StatusCodes.Status500InternalServerError, problemDetailsBuilder
.WithTitle("Unknown content operation status.")
.Build()),
});
} }

View File

@@ -56,6 +56,6 @@ public class PublishDocumentController : DocumentControllerBase
CurrentUserKey(_backOfficeSecurityAccessor)); CurrentUserKey(_backOfficeSecurityAccessor));
return attempt.Success return attempt.Success
? Ok() ? Ok()
: ContentPublishingOperationStatusResult(attempt.Status, invalidPropertyAliases: attempt.Result.InvalidPropertyAliases); : DocumentPublishingOperationStatusResult(attempt.Status, invalidPropertyAliases: attempt.Result.InvalidPropertyAliases);
} }
} }

View File

@@ -57,6 +57,6 @@ public class PublishDocumentWithDescendantsController : DocumentControllerBase
return attempt.Success return attempt.Success
? Ok() ? Ok()
: ContentPublishingOperationStatusResult(attempt.Status, failedBranchItems: attempt.Result.FailedItems); : DocumentPublishingOperationStatusResult(attempt.Status, failedBranchItems: attempt.Result.FailedItems);
} }
} }

View File

@@ -58,6 +58,6 @@ public class UnpublishDocumentController : DocumentControllerBase
CurrentUserKey(_backOfficeSecurityAccessor)); CurrentUserKey(_backOfficeSecurityAccessor));
return attempt.Success return attempt.Success
? Ok() ? Ok()
: ContentPublishingOperationStatusResult(attempt.Result); : DocumentPublishingOperationStatusResult(attempt.Result);
} }
} }

View File

@@ -1,7 +0,0 @@
namespace Umbraco.Cms.Core.Services.OperationStatus;
public enum ContentCreatingOperationStatus
{
Success,
NotFound
}