Make "create folder" return HTTP 201 Created for file system folders (#15459)

* Make "create folder" return 201 and add expected return types to "create" and "delete" for all file system folder endpoints

* Update OpenApi.json
This commit is contained in:
Kenn Jacobsen
2023-12-18 11:01:53 +01:00
committed by GitHub
parent 32cecbe14f
commit c2b970d0de
8 changed files with 329 additions and 29 deletions

View File

@@ -2,23 +2,32 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.ViewModels.Folder;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;
namespace Umbraco.Cms.Api.Management.Controllers.PartialView.Folder;
[ApiVersion("1.0")]
public class CreatePartialViewFolderController : PartialViewFolderControllerBase
{
public CreatePartialViewFolderController(
IUmbracoMapper mapper,
IPartialViewFolderService partialViewFolderService)
public CreatePartialViewFolderController(IUmbracoMapper mapper, IPartialViewFolderService partialViewFolderService)
: base(mapper, partialViewFolderService)
{
}
[HttpPost]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
public Task<IActionResult> Create(CreatePathFolderRequestModel model) => CreateAsync(model);
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Create(CreatePathFolderRequestModel model)
{
Attempt<PathContainer?, PartialViewFolderOperationStatus> result = await CreateAsync(model);
return result.Success
? CreatedAtAction<ByPathPartialViewFolderController>(controller => nameof(controller.ByPath), new { path = result.Result!.Path })
: OperationStatusResult(result.Status);
}
}

View File

@@ -19,5 +19,7 @@ public class DeletePartialViewFolderController : PartialViewFolderControllerBase
[HttpDelete]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public Task<IActionResult> Delete(string path) => DeleteAsync(path);
}

View File

@@ -30,18 +30,11 @@ public abstract class PathFolderManagementControllerBase<TStatus> : ManagementAp
return Ok(viewModel);
}
protected async Task<IActionResult> CreateAsync(CreatePathFolderRequestModel requestModel)
protected async Task<Attempt<PathContainer?, TStatus>> CreateAsync(CreatePathFolderRequestModel requestModel)
{
PathContainer folderModel = Mapper.Map<PathContainer>(requestModel)!;
Attempt<PathContainer?, TStatus> attempt = await CreateContainerAsync(folderModel);
if (attempt.Success is false)
{
return OperationStatusResult(attempt.Status);
}
PathFolderResponseModel? viewModel = Mapper.Map<PathFolderResponseModel>(attempt.Result);
return Ok(viewModel);
return await CreateContainerAsync(folderModel);
}
protected async Task<IActionResult> DeleteAsync(string path)

View File

@@ -2,23 +2,32 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.ViewModels.Folder;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;
namespace Umbraco.Cms.Api.Management.Controllers.Script.Folder;
[ApiVersion("1.0")]
public class CreateScriptFolderController : ScriptFolderControllerBase
{
public CreateScriptFolderController(
IUmbracoMapper mapper,
IScriptFolderService scriptFolderService)
public CreateScriptFolderController(IUmbracoMapper mapper, IScriptFolderService scriptFolderService)
: base(mapper, scriptFolderService)
{
}
[HttpPost]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
public Task<IActionResult> Create(CreatePathFolderRequestModel model) => CreateAsync(model);
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Create(CreatePathFolderRequestModel model)
{
Attempt<PathContainer?, ScriptFolderOperationStatus> result = await CreateAsync(model);
return result.Success
? CreatedAtAction<ByPathScriptFolderController>(controller => nameof(controller.ByPath), new { path = result.Result!.Path })
: OperationStatusResult(result.Status);
}
}

View File

@@ -17,5 +17,7 @@ public class DeleteScriptFolderController : ScriptFolderControllerBase
[HttpDelete]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public Task<IActionResult> Delete(string path) => DeleteAsync(path);
}

View File

@@ -2,21 +2,33 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.ViewModels.Folder;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;
namespace Umbraco.Cms.Api.Management.Controllers.Stylesheet.Folder;
[ApiVersion("1.0")]
public class CreateStylesheetFolderController : StylesheetFolderControllerBase
{
public CreateStylesheetFolderController(IUmbracoMapper mapper, IStylesheetFolderService stylesheetFolderService) : base(mapper, stylesheetFolderService)
public CreateStylesheetFolderController(IUmbracoMapper mapper, IStylesheetFolderService stylesheetFolderService)
: base(mapper, stylesheetFolderService)
{
}
[HttpPost]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
public Task<IActionResult> Create(CreatePathFolderRequestModel model) => CreateAsync(model);
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public async Task<IActionResult> Create(CreatePathFolderRequestModel model)
{
Attempt<PathContainer?, StylesheetFolderOperationStatus> result = await CreateAsync(model);
return result.Success
? CreatedAtAction<ByPathStylesheetFolderController>(controller => nameof(controller.ByPath), new { path = result.Result!.Path })
: OperationStatusResult(result.Status);
}
}

View File

@@ -9,12 +9,15 @@ namespace Umbraco.Cms.Api.Management.Controllers.Stylesheet.Folder;
[ApiVersion("1.0")]
public class DeleteStylesheetFolderController : StylesheetFolderControllerBase
{
public DeleteStylesheetFolderController(IUmbracoMapper mapper, IStylesheetFolderService stylesheetFolderService) : base(mapper, stylesheetFolderService)
public DeleteStylesheetFolderController(IUmbracoMapper mapper, IStylesheetFolderService stylesheetFolderService)
: base(mapper, stylesheetFolderService)
{
}
[HttpDelete]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public Task<IActionResult> Delete(string path) => DeleteAsync(path);
}

View File

@@ -10836,8 +10836,58 @@
}
},
"responses": {
"200": {
"description": "Success"
"201": {
"description": "Created",
"headers": {
"Location": {
"description": "Location of the newly created resource",
"schema": {
"type": "string",
"description": "Location of the newly created resource",
"format": "uri"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"401": {
"description": "The resource is protected and requires an authentication token"
@@ -10867,6 +10917,46 @@
"200": {
"description": "Success"
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"401": {
"description": "The resource is protected and requires an authentication token"
}
@@ -12646,8 +12736,58 @@
}
},
"responses": {
"200": {
"description": "Success"
"201": {
"description": "Created",
"headers": {
"Location": {
"description": "Location of the newly created resource",
"schema": {
"type": "string",
"description": "Location of the newly created resource",
"format": "uri"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"401": {
"description": "The resource is protected and requires an authentication token"
@@ -12677,6 +12817,46 @@
"200": {
"description": "Success"
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"401": {
"description": "The resource is protected and requires an authentication token"
}
@@ -14037,8 +14217,58 @@
}
},
"responses": {
"200": {
"description": "Success"
"201": {
"description": "Created",
"headers": {
"Location": {
"description": "Location of the newly created resource",
"schema": {
"type": "string",
"description": "Location of the newly created resource",
"format": "uri"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"401": {
"description": "The resource is protected and requires an authentication token"
@@ -14068,6 +14298,46 @@
"200": {
"description": "Success"
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
},
"text/plain": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"401": {
"description": "The resource is protected and requires an authentication token"
}