Only prevent the unpublish or delete of a related item when configured to do so if it is related as a child, not as a parent (#18886)
* Only prevent the unpubkish or delete of a related item when configured to do so if it is related as a child, not as a parent. * Fixed incorect parameter names. * Fixed failing integration tests. * Use using variable instead to reduce nesting * Applied suggestions from code review. * Used simple using statement throughout RelationService for consistency. * Applied XML header comments consistently. --------- Co-authored-by: mole <nikolajlauridsen@protonmail.ch>
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
using Umbraco.Cms.Tests.Integration.Attributes;
|
||||
@@ -12,29 +11,20 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services;
|
||||
public partial class ContentEditingServiceTests
|
||||
{
|
||||
protected IRelationService RelationService => GetRequiredService<IRelationService>();
|
||||
|
||||
public static void ConfigureDisableDeleteWhenReferenced(IUmbracoBuilder builder)
|
||||
{
|
||||
builder.Services.Configure<ContentSettings>(config =>
|
||||
=> builder.Services.Configure<ContentSettings>(config =>
|
||||
config.DisableDeleteWhenReferenced = true);
|
||||
}
|
||||
|
||||
public void Relate(IContent child, IContent parent)
|
||||
{
|
||||
var relatedContentRelType = RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedDocumentAlias);
|
||||
|
||||
var relation = RelationService.Relate(child.Id, parent.Id, relatedContentRelType);
|
||||
RelationService.Save(relation);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
[ConfigureBuilder(ActionName = nameof(ConfigureDisableDeleteWhenReferenced))]
|
||||
public async Task Cannot_Delete_Referenced_Content()
|
||||
public async Task Cannot_Delete_When_Content_Is_Related_As_A_Child_And_Configured_To_Disable_When_Related()
|
||||
{
|
||||
var moveAttempt = await ContentEditingService.MoveToRecycleBinAsync(Subpage.Key, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(moveAttempt.Success);
|
||||
|
||||
Relate(Subpage, Subpage2);
|
||||
// Setup a relation where the page being deleted is related to another page as a child (e.g. the other page has a picker and has selected this page).
|
||||
Relate(Subpage2, Subpage);
|
||||
var result = await ContentEditingService.DeleteFromRecycleBinAsync(Subpage.Key, Constants.Security.SuperUserKey);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.CannotDeleteWhenReferenced, result.Status);
|
||||
@@ -44,6 +34,24 @@ public partial class ContentEditingServiceTests
|
||||
Assert.IsNotNull(subpage);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ConfigureBuilder(ActionName = nameof(ConfigureDisableDeleteWhenReferenced))]
|
||||
public async Task Can_Delete_When_Content_Is_Related_As_A_Parent_And_Configured_To_Disable_When_Related()
|
||||
{
|
||||
var moveAttempt = await ContentEditingService.MoveToRecycleBinAsync(Subpage.Key, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(moveAttempt.Success);
|
||||
|
||||
// Setup a relation where the page being deleted is related to another page as a child (e.g. the other page has a picker and has selected this page).
|
||||
Relate(Subpage, Subpage2);
|
||||
var result = await ContentEditingService.DeleteFromRecycleBinAsync(Subpage.Key, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status);
|
||||
|
||||
// re-get and verify deleted
|
||||
var subpage = await ContentEditingService.GetAsync(Subpage.Key);
|
||||
Assert.IsNull(subpage);
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public async Task Can_Delete_FromRecycleBin(bool variant)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
@@ -9,12 +9,9 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services;
|
||||
|
||||
public partial class ContentEditingServiceTests
|
||||
{
|
||||
|
||||
public static void ConfigureDisableDelete(IUmbracoBuilder builder)
|
||||
{
|
||||
builder.Services.Configure<ContentSettings>(config =>
|
||||
public static new void ConfigureDisableUnpublishWhenReferencedTrue(IUmbracoBuilder builder)
|
||||
=> builder.Services.Configure<ContentSettings>(config =>
|
||||
config.DisableUnpublishWhenReferenced = true);
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
@@ -33,10 +30,11 @@ public partial class ContentEditingServiceTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ConfigureBuilder(ActionName = nameof(ConfigureDisableDelete))]
|
||||
public async Task Cannot_Move_To_Recycle_Bin_If_Referenced()
|
||||
[ConfigureBuilder(ActionName = nameof(ConfigureDisableUnpublishWhenReferencedTrue))]
|
||||
public async Task Cannot_Move_To_Recycle_Bin_When_Content_Is_Related_As_A_Child_And_Configured_To_Disable_When_Related()
|
||||
{
|
||||
Relate(Subpage, Subpage2);
|
||||
// Setup a relation where the page being deleted is related to another page as a child (e.g. the other page has a picker and has selected this page).
|
||||
Relate(Subpage2, Subpage);
|
||||
var moveAttempt = await ContentEditingService.MoveToRecycleBinAsync(Subpage.Key, Constants.Security.SuperUserKey);
|
||||
Assert.IsFalse(moveAttempt.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.CannotMoveToRecycleBinWhenReferenced, moveAttempt.Status);
|
||||
@@ -47,6 +45,22 @@ public partial class ContentEditingServiceTests
|
||||
Assert.IsFalse(content.Trashed);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ConfigureBuilder(ActionName = nameof(ConfigureDisableUnpublishWhenReferencedTrue))]
|
||||
public async Task Can_Move_To_Recycle_Bin_When_Content_Is_Related_As_A_Parent_And_Configured_To_Disable_When_Related()
|
||||
{
|
||||
// Setup a relation where the page being deleted is related to another page as a child (e.g. the other page has a picker and has selected this page).
|
||||
Relate(Subpage, Subpage2);
|
||||
var moveAttempt = await ContentEditingService.MoveToRecycleBinAsync(Subpage.Key, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(moveAttempt.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.Success, moveAttempt.Status);
|
||||
|
||||
// re-get and verify moved
|
||||
var content = await ContentEditingService.GetAsync(Subpage.Key);
|
||||
Assert.IsNotNull(content);
|
||||
Assert.IsTrue(content.Trashed);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Move_Non_Existing_To_Recycle_Bin()
|
||||
{
|
||||
|
||||
@@ -16,6 +16,14 @@ public partial class ContentEditingServiceTests : ContentEditingServiceTestsBase
|
||||
[SetUp]
|
||||
public void Setup() => ContentRepositoryBase.ThrowOnWarning = true;
|
||||
|
||||
public void Relate(IContent parent, IContent child)
|
||||
{
|
||||
var relatedContentRelType = RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedDocumentAlias);
|
||||
|
||||
var relation = RelationService.Relate(parent.Id, child.Id, relatedContentRelType);
|
||||
RelationService.Save(relation);
|
||||
}
|
||||
|
||||
protected override void CustomTestSetup(IUmbracoBuilder builder)
|
||||
=> builder.AddNotificationHandler<ContentCopiedNotification, RelateOnCopyNotificationHandler>();
|
||||
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
using Umbraco.Cms.Tests.Common.Builders;
|
||||
using Umbraco.Cms.Tests.Common.Builders.Extensions;
|
||||
using Umbraco.Cms.Tests.Integration.Attributes;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services;
|
||||
|
||||
public partial class ContentPublishingServiceTests
|
||||
{
|
||||
public static new void ConfigureDisableUnpublishWhenReferencedTrue(IUmbracoBuilder builder)
|
||||
=> builder.Services.Configure<ContentSettings>(config =>
|
||||
config.DisableUnpublishWhenReferenced = true);
|
||||
|
||||
[Test]
|
||||
public async Task Can_Unpublish_Root()
|
||||
{
|
||||
@@ -92,6 +100,40 @@ public partial class ContentPublishingServiceTests
|
||||
VerifyIsPublished(Textpage.Key);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ConfigureBuilder(ActionName = nameof(ConfigureDisableUnpublishWhenReferencedTrue))]
|
||||
public async Task Cannot_Unpublish_When_Content_Is_Related_As_A_Child_And_Configured_To_Disable_When_Related()
|
||||
{
|
||||
await ContentPublishingService.PublishAsync(Textpage.Key, MakeModel(_allCultures), Constants.Security.SuperUserKey);
|
||||
VerifyIsPublished(Textpage.Key);
|
||||
|
||||
// Setup a relation where the page being unpublished is related to another page as a child (e.g. the other page has a picker and has selected this page).
|
||||
RelationService.Relate(Subpage, Textpage, Constants.Conventions.RelationTypes.RelatedDocumentAlias);
|
||||
|
||||
var result = await ContentPublishingService.UnpublishAsync(Textpage.Key, null, Constants.Security.SuperUserKey);
|
||||
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentPublishingOperationStatus.CannotUnpublishWhenReferenced, result.Result);
|
||||
VerifyIsPublished(Textpage.Key);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ConfigureBuilder(ActionName = nameof(ConfigureDisableUnpublishWhenReferencedTrue))]
|
||||
public async Task Can_Unpublish_When_Content_Is_Related_As_A_Parent_And_Configured_To_Disable_When_Related()
|
||||
{
|
||||
await ContentPublishingService.PublishAsync(Textpage.Key, MakeModel(_allCultures), Constants.Security.SuperUserKey);
|
||||
VerifyIsPublished(Textpage.Key);
|
||||
|
||||
// Setup a relation where the page being unpublished is related to another page as a parent (e.g. this page has a picker and has selected the other page).
|
||||
RelationService.Relate(Textpage, Subpage, Constants.Conventions.RelationTypes.RelatedDocumentAlias);
|
||||
|
||||
var result = await ContentPublishingService.UnpublishAsync(Textpage.Key, null, Constants.Security.SuperUserKey);
|
||||
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentPublishingOperationStatus.Success, result.Result);
|
||||
VerifyIsNotPublished(Textpage.Key);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Unpublish_Single_Culture()
|
||||
{
|
||||
@@ -229,8 +271,6 @@ public partial class ContentPublishingServiceTests
|
||||
Assert.AreEqual(0, content.PublishedCultures.Count());
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task Can_Unpublish_Non_Mandatory_Cultures()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
@@ -20,6 +20,8 @@ public partial class ContentPublishingServiceTests : UmbracoIntegrationTestWithC
|
||||
{
|
||||
private IContentPublishingService ContentPublishingService => GetRequiredService<IContentPublishingService>();
|
||||
|
||||
private IRelationService RelationService => GetRequiredService<IRelationService>();
|
||||
|
||||
private static readonly ISet<string> _allCultures = new HashSet<string>(){ "*" };
|
||||
|
||||
private static CultureAndScheduleModel MakeModel(ISet<string> cultures) => new CultureAndScheduleModel()
|
||||
|
||||
Reference in New Issue
Block a user