Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
8e0912c
Only prevent the unpublish or delete of a related item when configure…
AndyButland Apr 1, 2025
11c1984
Feature: highlight invariant doc with variant blocks is unsupported (…
nielslyngsoe Apr 2, 2025
9d30d5b
Fix pagination for users restricted by start nodes (#18907)
kjac Apr 2, 2025
bbfe40d
Fix issue preventing blueprint derived values from being scaffolded (…
AndyButland Apr 3, 2025
3b736d8
ci: add Azure Static Web Apps workflow file
iOvergaard Apr 3, 2025
3cd6fcf
ci: add Azure Static Web Apps workflow file
iOvergaard Apr 3, 2025
9db62a2
ci: add Azure Static Web Apps workflow file
iOvergaard Apr 3, 2025
e4b3104
Remove admin permission on user configuration, allowing users with us…
AndyButland Apr 3, 2025
f3658bf
Tiptap RTE: Style Menu extension kind (#18918)
leekelleher Apr 3, 2025
157b7d1
Merge branch 'v15/dev' into contrib
nielslyngsoe Apr 3, 2025
7d41791
Ensure has children reflects only items with folder children when fol…
AndyButland Apr 3, 2025
3e6b931
Only apply validation on content update to variant cultures where the…
AndyButland Apr 3, 2025
6247f54
Adds ancestor ID details on document tree and collection responses (#…
AndyButland Apr 4, 2025
ad7053a
Move publish with descendants to a background task with polling (#18497)
AndyButland Apr 4, 2025
5f3ce28
Clear roots before rebuilding navigation dictionary (#18766)
AndyButland Apr 4, 2025
ebd5fb4
Fixes save of empty, invariant block list on variant content. (#18932)
AndyButland Apr 4, 2025
788e5cd
remove unnecessary code (#18927)
nielslyngsoe Apr 4, 2025
806f10e
V15/bugfix/fix route issue from 18859 (#18931)
nielslyngsoe Apr 4, 2025
90a34e1
Bump vite from 6.2.3 to 6.2.4 in /src/Umbraco.Web.UI.Client
dependabot[bot] Apr 3, 2025
c139015
removes autogenerated workflows
iOvergaard Apr 4, 2025
1aff4c6
Merge remote-tracking branch 'origin/contrib' into v15/dev
iOvergaard Apr 4, 2025
bf74636
make getHasUnpersistedChanges public (#18929)
nielslyngsoe Apr 4, 2025
fd77074
Added management API endpoint, service and repository for retrieval o…
AndyButland Apr 4, 2025
1f4c19d
Updated management API endpoint and model for data type references to…
AndyButland Apr 4, 2025
4b01631
Skip lock tests
Zeegaan Apr 4, 2025
4078e83
Look-up redirect in content finder for multi-lingual sites using path…
AndyButland Apr 7, 2025
1d9a031
Bump vite from 6.2.4 to 6.2.5 in /src/Umbraco.Web.UI.Client
dependabot[bot] Apr 4, 2025
ae423de
Add raw value validation to multiple text strings property editor (#1…
kjac Apr 7, 2025
3d1e17b
Integration tests for content publishing with ancestor unpublished (#…
AndyButland Apr 7, 2025
f6d93ef
fix circular icon import (#18952)
madsrasmussen Apr 7, 2025
c0f820a
remove segment toggle for elements (#18949)
madsrasmussen Apr 7, 2025
b991976
Fix modal route registration circular import (#18953)
madsrasmussen Apr 7, 2025
f926316
V15/fix/18595 (#18925)
Welander1994 Apr 7, 2025
2723e4f
Avoid unneeded Dictionary operations (#18890)
Henr1k80 Apr 7, 2025
db43799
Avoid some heap allocations
Henr1k80 Mar 31, 2025
4239f0f
Remove unneeded double seek
Henr1k80 Apr 1, 2025
822c837
Avoid allocating new empty arrays, reuse existing empty array
Henr1k80 Mar 31, 2025
d9a31d3
Avoid allocating strings for parsing comma separated int values (#18199)
Henr1k80 Apr 7, 2025
b61b9db
Merge branch 'v15/dev' into contrib
nul800sebastiaan Apr 7, 2025
9c03422
Data type References UI: Workspace + Delete (#18914)
madsrasmussen Apr 7, 2025
4c90842
Feature: discard changes for block workspace (#18930)
nielslyngsoe Apr 7, 2025
17a5218
fix 18367 (#18956)
nielslyngsoe Apr 7, 2025
06a2a50
Merge commit from fork
AndyButland Apr 8, 2025
aa76f78
Merge branch 'release/15.3.1' into v15/dev
AndyButland Apr 8, 2025
84d0ae3
V15 QA Fixing the failing media acceptance tests (#18881)
nhudinh0309 Apr 8, 2025
86e7343
V15 QA added clipboard test for not being able to copy to root when b…
andr317c Apr 8, 2025
4024de0
Merge branch 'v15/dev' into v16/dev
kjac Apr 8, 2025
e1712ea
build: adjusts circular ref number to 4
iOvergaard Apr 8, 2025
c09a370
Merge remote-tracking branch 'origin/v16/dev' into v16/temp/merge-v15…
iOvergaard Apr 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public void Apply(OpenApiOperation operation, OperationFilterContext context)
Id = AuthSchemeName,
}
},
new string[] { }
[]
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ private IPublishedMediaCache GetRequiredPublishedMediaCache()
}


private Attempt<PagedModel<Guid>, ApiMediaQueryOperationStatus> PagedResult(IEnumerable<IPublishedContent> children, int skip, int take)
private static Attempt<PagedModel<Guid>, ApiMediaQueryOperationStatus> PagedResult(IEnumerable<IPublishedContent> children, int skip, int take)
{
IPublishedContent[] childrenAsArray = children as IPublishedContent[] ?? children.ToArray();
var result = new PagedModel<Guid>
Expand Down
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.Common.ViewModels.Pagination;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;

namespace Umbraco.Cms.Api.Management.Controllers.DataType.References;

[ApiVersion("1.0")]
public class ReferencedByDataTypeController : DataTypeControllerBase
{
private readonly IDataTypeService _dataTypeService;
private readonly IRelationTypePresentationFactory _relationTypePresentationFactory;

public ReferencedByDataTypeController(IDataTypeService dataTypeService, IRelationTypePresentationFactory relationTypePresentationFactory)
{
_dataTypeService = dataTypeService;
_relationTypePresentationFactory = relationTypePresentationFactory;
}

/// <summary>
/// Gets a paged list of references for the current data type, so you can see where it is being used.
/// </summary>
[HttpGet("{id:guid}/referenced-by")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(PagedViewModel<IReferenceResponseModel>), StatusCodes.Status200OK)]
public async Task<ActionResult<PagedViewModel<IReferenceResponseModel>>> ReferencedBy(
CancellationToken cancellationToken,
Guid id,
int skip = 0,
int take = 20)
{
PagedModel<RelationItemModel> relationItems = await _dataTypeService.GetPagedRelationsAsync(id, skip, take);

var pagedViewModel = new PagedViewModel<IReferenceResponseModel>
{
Total = relationItems.Total,
Items = await _relationTypePresentationFactory.CreateReferenceResponseModelsAsync(relationItems.Items),
};

return pagedViewModel;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Asp.Versioning;
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Factories;
Expand All @@ -10,6 +10,7 @@
namespace Umbraco.Cms.Api.Management.Controllers.DataType;

[ApiVersion("1.0")]
[Obsolete("Please use ReferencedByDataTypeController and the referenced-by endpoint. Scheduled for removal in Umbraco 17.")]
public class ReferencesDataTypeController : DataTypeControllerBase
{
private readonly IDataTypeService _dataTypeService;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Controllers.Content;
Expand Down Expand Up @@ -140,6 +140,10 @@
.WithDetail(
"An unspecified error occurred while (un)publishing. Please check the logs for additional information.")
.Build()),
ContentPublishingOperationStatus.TaskResultNotFound => NotFound(problemDetailsBuilder
.WithTitle("The result of the submitted task could not be found")
.Build()),

Check warning on line 146 in src/Umbraco.Cms.Api.Management/Controllers/Document/DocumentControllerBase.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (v16/dev)

❌ Getting worse: Large Method

DocumentPublishingOperationStatusResult increases from 112 to 115 lines of code, threshold = 70. Large functions with many lines of code are generally harder to understand and lower the code health. Avoid adding more lines to this function.
_ => StatusCode(StatusCodes.Status500InternalServerError, "Unknown content operation status."),
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public PublishDocumentWithDescendantsController(

[HttpPut("{id:guid}/publish-with-descendants")]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(PublishWithDescendantsResultModel), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public async Task<IActionResult> PublishWithDescendants(CancellationToken cancellationToken, Guid id, PublishDocumentWithDescendantsRequestModel requestModel)
Expand All @@ -54,10 +54,15 @@ public async Task<IActionResult> PublishWithDescendants(CancellationToken cancel
id,
requestModel.Cultures,
BuildPublishBranchFilter(requestModel),
CurrentUserKey(_backOfficeSecurityAccessor));
CurrentUserKey(_backOfficeSecurityAccessor),
true);

return attempt.Success
? Ok()
return attempt.Success && attempt.Result.AcceptedTaskId.HasValue
? Ok(new PublishWithDescendantsResultModel
{
TaskId = attempt.Result.AcceptedTaskId.Value,
IsComplete = false
})
: DocumentPublishingOperationStatusResult(attempt.Status, failedBranchItems: attempt.Result.FailedItems);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.ViewModels.Document;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Actions;
using Umbraco.Cms.Core.Models.ContentPublishing;
using Umbraco.Cms.Core.Security.Authorization;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;
using Umbraco.Cms.Web.Common.Authorization;
using Umbraco.Extensions;

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

[ApiVersion("1.0")]
public class PublishDocumentWithDescendantsResultController : DocumentControllerBase
{
private readonly IAuthorizationService _authorizationService;
private readonly IContentPublishingService _contentPublishingService;

public PublishDocumentWithDescendantsResultController(
IAuthorizationService authorizationService,
IContentPublishingService contentPublishingService)
{
_authorizationService = authorizationService;
_contentPublishingService = contentPublishingService;
}

[HttpGet("{id:guid}/publish-with-descendants/result/{taskId:guid}")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(PublishWithDescendantsResultModel), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
public async Task<IActionResult> PublishWithDescendantsResult(CancellationToken cancellationToken, Guid id, Guid taskId)
{
AuthorizationResult authorizationResult = await _authorizationService.AuthorizeResourceAsync(
User,
ContentPermissionResource.Branch(ActionPublish.ActionLetter, id),
AuthorizationPolicies.ContentPermissionByResource);

if (!authorizationResult.Succeeded)
{
return Forbidden();
}

// Check if the publishing task has completed, if not, return the status.
var isPublishing = await _contentPublishingService.IsPublishingBranchAsync(taskId);
if (isPublishing)
{
return Ok(new PublishWithDescendantsResultModel
{
TaskId = taskId,
IsComplete = false
});
};

// If completed, get the result and return the status.
Attempt<ContentPublishingBranchResult, ContentPublishingOperationStatus> attempt = await _contentPublishingService.GetPublishBranchResultAsync(taskId);
return attempt.Success
? Ok(new PublishWithDescendantsResultModel
{
TaskId = taskId,
IsComplete = true
})
: DocumentPublishingOperationStatusResult(attempt.Status, failedBranchItems: attempt.Result.FailedItems);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.ViewModels.TrackedReferences;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;

namespace Umbraco.Cms.Api.Management.Controllers.Document.RecycleBin;

[ApiVersion("1.0")]
public class ReferencedByDocumentRecycleBinController : DocumentRecycleBinControllerBase
{
private readonly ITrackedReferencesService _trackedReferencesService;
private readonly IRelationTypePresentationFactory _relationTypePresentationFactory;

public ReferencedByDocumentRecycleBinController(
IEntityService entityService,
IDocumentPresentationFactory documentPresentationFactory,
ITrackedReferencesService trackedReferencesService,
IRelationTypePresentationFactory relationTypePresentationFactory)
: base(entityService, documentPresentationFactory)
{
_trackedReferencesService = trackedReferencesService;
_relationTypePresentationFactory = relationTypePresentationFactory;
}

/// <summary>
/// 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.
/// </summary>
[HttpGet("referenced-by")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(PagedViewModel<IReferenceResponseModel>), StatusCodes.Status200OK)]
public async Task<ActionResult<PagedViewModel<IReferenceResponseModel>>> ReferencedBy(
CancellationToken cancellationToken,
int skip = 0,
int take = 20)
{
PagedModel<RelationItemModel> relationItems = await _trackedReferencesService.GetPagedRelationsForRecycleBinAsync(UmbracoObjectTypes.Document, skip, take, true);

var pagedViewModel = new PagedViewModel<IReferenceResponseModel>
{
Total = relationItems.Total,
Items = await _relationTypePresentationFactory.CreateReferenceResponseModelsAsync(relationItems.Items),
};

return pagedViewModel;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Api.Management.Services.Entities;
using Umbraco.Cms.Api.Management.ViewModels;
using Umbraco.Cms.Api.Management.ViewModels.Tree;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
Expand Down Expand Up @@ -33,7 +34,7 @@ protected DocumentTreeControllerBase(
AppCaches appCaches,
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
IDocumentPresentationFactory documentPresentationFactory)
: base(entityService, userStartNodeEntitiesService, dataTypeService)
: base(entityService, userStartNodeEntitiesService, dataTypeService)
{
_publicAccessService = publicAccessService;
_appCaches = appCaches;
Expand All @@ -52,6 +53,8 @@ protected override DocumentTreeItemResponseModel MapTreeItemViewModel(Guid? pare
if (entity is IDocumentEntitySlim documentEntitySlim)
{
responseModel.IsProtected = _publicAccessService.IsProtected(entity.Path);
responseModel.Ancestors = EntityService.GetPathKeys(entity, omitSelf: true)
.Select(x => new ReferenceByIdModel(x));
responseModel.IsTrashed = entity.Trashed;
responseModel.Id = entity.Key;
responseModel.CreateDate = entity.CreateDate;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using Asp.Versioning;
using Asp.Versioning;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.ViewModels.Document;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;

Expand All @@ -16,15 +19,32 @@ public class ValidateCreateDocumentController : CreateDocumentControllerBase
{
private readonly IDocumentEditingPresentationFactory _documentEditingPresentationFactory;
private readonly IContentEditingService _contentEditingService;
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;

[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 17.")]
public ValidateCreateDocumentController(
IAuthorizationService authorizationService,
IDocumentEditingPresentationFactory documentEditingPresentationFactory,
IContentEditingService contentEditingService)
: this(
authorizationService,
documentEditingPresentationFactory,
contentEditingService,
StaticServiceProvider.Instance.GetRequiredService<IBackOfficeSecurityAccessor>())
{
}

[ActivatorUtilitiesConstructor]
public ValidateCreateDocumentController(
IAuthorizationService authorizationService,
IDocumentEditingPresentationFactory documentEditingPresentationFactory,
IContentEditingService contentEditingService,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
: base(authorizationService)
{
_documentEditingPresentationFactory = documentEditingPresentationFactory;
_contentEditingService = contentEditingService;
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
}

[HttpPost("validate")]
Expand All @@ -36,7 +56,10 @@ public async Task<IActionResult> Validate(CancellationToken cancellationToken, C
=> await HandleRequest(requestModel, async () =>
{
ContentCreateModel model = _documentEditingPresentationFactory.MapCreateModel(requestModel);
Attempt<ContentValidationResult, ContentEditingOperationStatus> result = await _contentEditingService.ValidateCreateAsync(model);
Attempt<ContentValidationResult, ContentEditingOperationStatus> result =
await _contentEditingService.ValidateCreateAsync(
model,
CurrentUserKey(_backOfficeSecurityAccessor));

return result.Success
? Ok()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.ViewModels.Document;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.OperationStatus;

Expand All @@ -16,15 +19,32 @@ public class ValidateUpdateDocumentController : UpdateDocumentControllerBase
{
private readonly IContentEditingService _contentEditingService;
private readonly IDocumentEditingPresentationFactory _documentEditingPresentationFactory;
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;

[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 17.")]
public ValidateUpdateDocumentController(
IAuthorizationService authorizationService,
IContentEditingService contentEditingService,
IDocumentEditingPresentationFactory documentEditingPresentationFactory)
: this(
authorizationService,
contentEditingService,
documentEditingPresentationFactory,
StaticServiceProvider.Instance.GetRequiredService<IBackOfficeSecurityAccessor>())
{
}

[ActivatorUtilitiesConstructor]
public ValidateUpdateDocumentController(
IAuthorizationService authorizationService,
IContentEditingService contentEditingService,
IDocumentEditingPresentationFactory documentEditingPresentationFactory,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
: base(authorizationService)
{
_contentEditingService = contentEditingService;
_documentEditingPresentationFactory = documentEditingPresentationFactory;
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
}

[HttpPut("{id:guid}/validate")]
Expand All @@ -36,7 +56,11 @@ public async Task<IActionResult> ValidateV1_1(CancellationToken cancellationToke
=> await HandleRequest(id, requestModel, async () =>
{
ValidateContentUpdateModel model = _documentEditingPresentationFactory.MapValidateUpdateModel(requestModel);
Attempt<ContentValidationResult, ContentEditingOperationStatus> result = await _contentEditingService.ValidateUpdateAsync(id, model);
Attempt<ContentValidationResult, ContentEditingOperationStatus> result =
await _contentEditingService.ValidateUpdateAsync(
id,
model,
CurrentUserKey(_backOfficeSecurityAccessor));

return result.Success
? Ok()
Expand Down
Loading
Loading