Skip to content

Commit b61b9db

Browse files
Merge branch 'v15/dev' into contrib
2 parents d9a31d3 + f926316 commit b61b9db

File tree

112 files changed

+3939
-1628
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+3939
-1628
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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.TrackedReferences;
7+
using Umbraco.Cms.Core.Models;
8+
using Umbraco.Cms.Core.Services;
9+
10+
namespace Umbraco.Cms.Api.Management.Controllers.DataType.References;
11+
12+
[ApiVersion("1.0")]
13+
public class ReferencedByDataTypeController : DataTypeControllerBase
14+
{
15+
private readonly IDataTypeService _dataTypeService;
16+
private readonly IRelationTypePresentationFactory _relationTypePresentationFactory;
17+
18+
public ReferencedByDataTypeController(IDataTypeService dataTypeService, IRelationTypePresentationFactory relationTypePresentationFactory)
19+
{
20+
_dataTypeService = dataTypeService;
21+
_relationTypePresentationFactory = relationTypePresentationFactory;
22+
}
23+
24+
/// <summary>
25+
/// Gets a paged list of references for the current data type, so you can see where it is being used.
26+
/// </summary>
27+
[HttpGet("{id:guid}/referenced-by")]
28+
[MapToApiVersion("1.0")]
29+
[ProducesResponseType(typeof(PagedViewModel<IReferenceResponseModel>), StatusCodes.Status200OK)]
30+
public async Task<ActionResult<PagedViewModel<IReferenceResponseModel>>> ReferencedBy(
31+
CancellationToken cancellationToken,
32+
Guid id,
33+
int skip = 0,
34+
int take = 20)
35+
{
36+
PagedModel<RelationItemModel> relationItems = await _dataTypeService.GetPagedRelationsAsync(id, skip, take);
37+
38+
var pagedViewModel = new PagedViewModel<IReferenceResponseModel>
39+
{
40+
Total = relationItems.Total,
41+
Items = await _relationTypePresentationFactory.CreateReferenceResponseModelsAsync(relationItems.Items),
42+
};
43+
44+
return pagedViewModel;
45+
}
46+
}

src/Umbraco.Cms.Api.Management/Controllers/DataType/ReferencesDataTypeController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Asp.Versioning;
1+
using Asp.Versioning;
22
using Microsoft.AspNetCore.Http;
33
using Microsoft.AspNetCore.Mvc;
44
using Umbraco.Cms.Api.Management.Factories;
@@ -10,6 +10,7 @@
1010
namespace Umbraco.Cms.Api.Management.Controllers.DataType;
1111

1212
[ApiVersion("1.0")]
13+
[Obsolete("Please use ReferencedByDataTypeController and the referenced-by endpoint. Scheduled for removal in Umbraco 17.")]
1314
public class ReferencesDataTypeController : DataTypeControllerBase
1415
{
1516
private readonly IDataTypeService _dataTypeService;

src/Umbraco.Cms.Api.Management/Controllers/Document/DocumentControllerBase.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Microsoft.AspNetCore.Authorization;
1+
using Microsoft.AspNetCore.Authorization;
22
using Microsoft.AspNetCore.Http;
33
using Microsoft.AspNetCore.Mvc;
44
using Umbraco.Cms.Api.Management.Controllers.Content;
@@ -140,6 +140,10 @@ protected IActionResult DocumentPublishingOperationStatusResult(
140140
.WithDetail(
141141
"An unspecified error occurred while (un)publishing. Please check the logs for additional information.")
142142
.Build()),
143+
ContentPublishingOperationStatus.TaskResultNotFound => NotFound(problemDetailsBuilder
144+
.WithTitle("The result of the submitted task could not be found")
145+
.Build()),
146+
143147
_ => StatusCode(StatusCodes.Status500InternalServerError, "Unknown content operation status."),
144148
});
145149

src/Umbraco.Cms.Api.Management/Controllers/Document/PublishDocumentWithDescendantsController.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public PublishDocumentWithDescendantsController(
3535

3636
[HttpPut("{id:guid}/publish-with-descendants")]
3737
[MapToApiVersion("1.0")]
38-
[ProducesResponseType(StatusCodes.Status200OK)]
38+
[ProducesResponseType(typeof(PublishWithDescendantsResultModel), StatusCodes.Status200OK)]
3939
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
4040
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
4141
public async Task<IActionResult> PublishWithDescendants(CancellationToken cancellationToken, Guid id, PublishDocumentWithDescendantsRequestModel requestModel)
@@ -54,10 +54,15 @@ public async Task<IActionResult> PublishWithDescendants(CancellationToken cancel
5454
id,
5555
requestModel.Cultures,
5656
BuildPublishBranchFilter(requestModel),
57-
CurrentUserKey(_backOfficeSecurityAccessor));
57+
CurrentUserKey(_backOfficeSecurityAccessor),
58+
true);
5859

59-
return attempt.Success
60-
? Ok()
60+
return attempt.Success && attempt.Result.AcceptedTaskId.HasValue
61+
? Ok(new PublishWithDescendantsResultModel
62+
{
63+
TaskId = attempt.Result.AcceptedTaskId.Value,
64+
IsComplete = false
65+
})
6166
: DocumentPublishingOperationStatusResult(attempt.Status, failedBranchItems: attempt.Result.FailedItems);
6267
}
6368

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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.Document;
6+
using Umbraco.Cms.Core;
7+
using Umbraco.Cms.Core.Actions;
8+
using Umbraco.Cms.Core.Models.ContentPublishing;
9+
using Umbraco.Cms.Core.Security.Authorization;
10+
using Umbraco.Cms.Core.Services;
11+
using Umbraco.Cms.Core.Services.OperationStatus;
12+
using Umbraco.Cms.Web.Common.Authorization;
13+
using Umbraco.Extensions;
14+
15+
namespace Umbraco.Cms.Api.Management.Controllers.Document;
16+
17+
[ApiVersion("1.0")]
18+
public class PublishDocumentWithDescendantsResultController : DocumentControllerBase
19+
{
20+
private readonly IAuthorizationService _authorizationService;
21+
private readonly IContentPublishingService _contentPublishingService;
22+
23+
public PublishDocumentWithDescendantsResultController(
24+
IAuthorizationService authorizationService,
25+
IContentPublishingService contentPublishingService)
26+
{
27+
_authorizationService = authorizationService;
28+
_contentPublishingService = contentPublishingService;
29+
}
30+
31+
[HttpGet("{id:guid}/publish-with-descendants/result/{taskId:guid}")]
32+
[MapToApiVersion("1.0")]
33+
[ProducesResponseType(typeof(PublishWithDescendantsResultModel), StatusCodes.Status200OK)]
34+
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
35+
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
36+
public async Task<IActionResult> PublishWithDescendantsResult(CancellationToken cancellationToken, Guid id, Guid taskId)
37+
{
38+
AuthorizationResult authorizationResult = await _authorizationService.AuthorizeResourceAsync(
39+
User,
40+
ContentPermissionResource.Branch(ActionPublish.ActionLetter, id),
41+
AuthorizationPolicies.ContentPermissionByResource);
42+
43+
if (!authorizationResult.Succeeded)
44+
{
45+
return Forbidden();
46+
}
47+
48+
// Check if the publishing task has completed, if not, return the status.
49+
var isPublishing = await _contentPublishingService.IsPublishingBranchAsync(taskId);
50+
if (isPublishing)
51+
{
52+
return Ok(new PublishWithDescendantsResultModel
53+
{
54+
TaskId = taskId,
55+
IsComplete = false
56+
});
57+
};
58+
59+
// If completed, get the result and return the status.
60+
Attempt<ContentPublishingBranchResult, ContentPublishingOperationStatus> attempt = await _contentPublishingService.GetPublishBranchResultAsync(taskId);
61+
return attempt.Success
62+
? Ok(new PublishWithDescendantsResultModel
63+
{
64+
TaskId = taskId,
65+
IsComplete = true
66+
})
67+
: DocumentPublishingOperationStatusResult(attempt.Status, failedBranchItems: attempt.Result.FailedItems);
68+
}
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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.TrackedReferences;
7+
using Umbraco.Cms.Core.Models;
8+
using Umbraco.Cms.Core.Services;
9+
10+
namespace Umbraco.Cms.Api.Management.Controllers.Document.RecycleBin;
11+
12+
[ApiVersion("1.0")]
13+
public class ReferencedByDocumentRecycleBinController : DocumentRecycleBinControllerBase
14+
{
15+
private readonly ITrackedReferencesService _trackedReferencesService;
16+
private readonly IRelationTypePresentationFactory _relationTypePresentationFactory;
17+
18+
public ReferencedByDocumentRecycleBinController(
19+
IEntityService entityService,
20+
IDocumentPresentationFactory documentPresentationFactory,
21+
ITrackedReferencesService trackedReferencesService,
22+
IRelationTypePresentationFactory relationTypePresentationFactory)
23+
: base(entityService, documentPresentationFactory)
24+
{
25+
_trackedReferencesService = trackedReferencesService;
26+
_relationTypePresentationFactory = relationTypePresentationFactory;
27+
}
28+
29+
/// <summary>
30+
/// Gets a paged list of tracked references for all items in the document recycle bin, so you can see where an item is being used.
31+
/// </summary>
32+
[HttpGet("referenced-by")]
33+
[MapToApiVersion("1.0")]
34+
[ProducesResponseType(typeof(PagedViewModel<IReferenceResponseModel>), StatusCodes.Status200OK)]
35+
public async Task<ActionResult<PagedViewModel<IReferenceResponseModel>>> ReferencedBy(
36+
CancellationToken cancellationToken,
37+
int skip = 0,
38+
int take = 20)
39+
{
40+
PagedModel<RelationItemModel> relationItems = await _trackedReferencesService.GetPagedRelationsForRecycleBinAsync(UmbracoObjectTypes.Document, skip, take, true);
41+
42+
var pagedViewModel = new PagedViewModel<IReferenceResponseModel>
43+
{
44+
Total = relationItems.Total,
45+
Items = await _relationTypePresentationFactory.CreateReferenceResponseModelsAsync(relationItems.Items),
46+
};
47+
48+
return pagedViewModel;
49+
}
50+
}

src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/DocumentTreeControllerBase.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Umbraco.Cms.Api.Management.Factories;
55
using Umbraco.Cms.Api.Management.Routing;
66
using Umbraco.Cms.Api.Management.Services.Entities;
7+
using Umbraco.Cms.Api.Management.ViewModels;
78
using Umbraco.Cms.Api.Management.ViewModels.Tree;
89
using Umbraco.Cms.Core;
910
using Umbraco.Cms.Core.Cache;
@@ -33,7 +34,7 @@ protected DocumentTreeControllerBase(
3334
AppCaches appCaches,
3435
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
3536
IDocumentPresentationFactory documentPresentationFactory)
36-
: base(entityService, userStartNodeEntitiesService, dataTypeService)
37+
: base(entityService, userStartNodeEntitiesService, dataTypeService)
3738
{
3839
_publicAccessService = publicAccessService;
3940
_appCaches = appCaches;
@@ -52,6 +53,8 @@ protected override DocumentTreeItemResponseModel MapTreeItemViewModel(Guid? pare
5253
if (entity is IDocumentEntitySlim documentEntitySlim)
5354
{
5455
responseModel.IsProtected = _publicAccessService.IsProtected(entity.Path);
56+
responseModel.Ancestors = EntityService.GetPathKeys(entity, omitSelf: true)
57+
.Select(x => new ReferenceByIdModel(x));
5558
responseModel.IsTrashed = entity.Trashed;
5659
responseModel.Id = entity.Key;
5760
responseModel.CreateDate = entity.CreateDate;

src/Umbraco.Cms.Api.Management/Controllers/Document/ValidateCreateDocumentController.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
using Asp.Versioning;
1+
using Asp.Versioning;
22
using Microsoft.AspNetCore.Authorization;
33
using Microsoft.AspNetCore.Http;
44
using Microsoft.AspNetCore.Mvc;
5+
using Microsoft.Extensions.DependencyInjection;
56
using Umbraco.Cms.Api.Management.Factories;
67
using Umbraco.Cms.Api.Management.ViewModels.Document;
78
using Umbraco.Cms.Core;
9+
using Umbraco.Cms.Core.DependencyInjection;
810
using Umbraco.Cms.Core.Models.ContentEditing;
11+
using Umbraco.Cms.Core.Security;
912
using Umbraco.Cms.Core.Services;
1013
using Umbraco.Cms.Core.Services.OperationStatus;
1114

@@ -16,15 +19,32 @@ public class ValidateCreateDocumentController : CreateDocumentControllerBase
1619
{
1720
private readonly IDocumentEditingPresentationFactory _documentEditingPresentationFactory;
1821
private readonly IContentEditingService _contentEditingService;
22+
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
1923

24+
[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 17.")]
2025
public ValidateCreateDocumentController(
2126
IAuthorizationService authorizationService,
2227
IDocumentEditingPresentationFactory documentEditingPresentationFactory,
2328
IContentEditingService contentEditingService)
29+
: this(
30+
authorizationService,
31+
documentEditingPresentationFactory,
32+
contentEditingService,
33+
StaticServiceProvider.Instance.GetRequiredService<IBackOfficeSecurityAccessor>())
34+
{
35+
}
36+
37+
[ActivatorUtilitiesConstructor]
38+
public ValidateCreateDocumentController(
39+
IAuthorizationService authorizationService,
40+
IDocumentEditingPresentationFactory documentEditingPresentationFactory,
41+
IContentEditingService contentEditingService,
42+
IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
2443
: base(authorizationService)
2544
{
2645
_documentEditingPresentationFactory = documentEditingPresentationFactory;
2746
_contentEditingService = contentEditingService;
47+
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
2848
}
2949

3050
[HttpPost("validate")]
@@ -36,7 +56,10 @@ public async Task<IActionResult> Validate(CancellationToken cancellationToken, C
3656
=> await HandleRequest(requestModel, async () =>
3757
{
3858
ContentCreateModel model = _documentEditingPresentationFactory.MapCreateModel(requestModel);
39-
Attempt<ContentValidationResult, ContentEditingOperationStatus> result = await _contentEditingService.ValidateCreateAsync(model);
59+
Attempt<ContentValidationResult, ContentEditingOperationStatus> result =
60+
await _contentEditingService.ValidateCreateAsync(
61+
model,
62+
CurrentUserKey(_backOfficeSecurityAccessor));
4063

4164
return result.Success
4265
? Ok()

src/Umbraco.Cms.Api.Management/Controllers/Document/ValidateUpdateDocumentController.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
using Asp.Versioning;
1+
using Asp.Versioning;
22
using Microsoft.AspNetCore.Authorization;
33
using Microsoft.AspNetCore.Http;
44
using Microsoft.AspNetCore.Mvc;
5+
using Microsoft.Extensions.DependencyInjection;
56
using Umbraco.Cms.Api.Management.Factories;
67
using Umbraco.Cms.Api.Management.ViewModels.Document;
78
using Umbraco.Cms.Core;
9+
using Umbraco.Cms.Core.DependencyInjection;
810
using Umbraco.Cms.Core.Models.ContentEditing;
11+
using Umbraco.Cms.Core.Security;
912
using Umbraco.Cms.Core.Services;
1013
using Umbraco.Cms.Core.Services.OperationStatus;
1114

@@ -17,15 +20,32 @@ public class ValidateUpdateDocumentController : UpdateDocumentControllerBase
1720
{
1821
private readonly IContentEditingService _contentEditingService;
1922
private readonly IDocumentEditingPresentationFactory _documentEditingPresentationFactory;
23+
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
2024

25+
[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 17.")]
2126
public ValidateUpdateDocumentController(
2227
IAuthorizationService authorizationService,
2328
IContentEditingService contentEditingService,
2429
IDocumentEditingPresentationFactory documentEditingPresentationFactory)
30+
: this(
31+
authorizationService,
32+
contentEditingService,
33+
documentEditingPresentationFactory,
34+
StaticServiceProvider.Instance.GetRequiredService<IBackOfficeSecurityAccessor>())
35+
{
36+
}
37+
38+
[ActivatorUtilitiesConstructor]
39+
public ValidateUpdateDocumentController(
40+
IAuthorizationService authorizationService,
41+
IContentEditingService contentEditingService,
42+
IDocumentEditingPresentationFactory documentEditingPresentationFactory,
43+
IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
2544
: base(authorizationService)
2645
{
2746
_contentEditingService = contentEditingService;
2847
_documentEditingPresentationFactory = documentEditingPresentationFactory;
48+
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
2949
}
3050

3151
[HttpPut("{id:guid}/validate")]
@@ -62,7 +82,11 @@ public async Task<IActionResult> ValidateV1_1(CancellationToken cancellationToke
6282
=> await HandleRequest(id, requestModel, async () =>
6383
{
6484
ValidateContentUpdateModel model = _documentEditingPresentationFactory.MapValidateUpdateModel(requestModel);
65-
Attempt<ContentValidationResult, ContentEditingOperationStatus> result = await _contentEditingService.ValidateUpdateAsync(id, model);
85+
Attempt<ContentValidationResult, ContentEditingOperationStatus> result =
86+
await _contentEditingService.ValidateUpdateAsync(
87+
id,
88+
model,
89+
CurrentUserKey(_backOfficeSecurityAccessor));
6690

6791
return result.Success
6892
? Ok()

0 commit comments

Comments
 (0)