* Persist and expose Umbraco system dates as UTC (#19705) * Updated persistence DTOs defining default dates to use UTC. * Remove ForceToUtc = false from all persistence DTO attributes (default when not specified is true). * Removed use of SpecifyKind setting dates to local. * Removed unnecessary Utc suffixes on properties. * Persist current date time with UtcNow. * Removed further necessary Utc suffixes and fixed failing unit tests. * Added migration for SQL server to update database date default constraints. * Added comment justifying not providing a migration for SQLite default date constraints. * Ensure UTC for datetimes created from persistence DTOs. * Ensure UTC when creating dates for published content rendering in Razor and outputting in delivery API. * Fixed migration SQL syntax. * Introduced AuditItemFactory for creating entries for the backoffice document history, so we can control the UTC setting on the retrieved persisted dates. * Ensured UTC dates are retrieved for document versions. * Ensured UTC is returned for backoffice display of last edited and published for variant content. * Fixed SQLite syntax for default current datetime. * Apply suggestions from code review Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com> * Further updates from code review. --------- Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com> * Migrate system dates from local server time to UTC (#19798) * Add settings for the migration. * Add migration and implement for SQL server. * Implement for SQLite. * Fixes from testing with SQL Server. * Fixes from testing with SQLite. * Code tidy. * Cleaned up usings. * Removed audit log date from conversion. * Removed webhook log date from conversion. * Updated update date initialization on saving dictionary items. * Updated filter on log queries. * Use timezone ID instead of system name to work cross-culture. --------- Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
123 lines
4.4 KiB
C#
123 lines
4.4 KiB
C#
using System.Diagnostics;
|
|
using NUnit.Framework;
|
|
using Umbraco.Cms.Core.Models;
|
|
using Umbraco.Cms.Core.Services;
|
|
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
|
using Umbraco.Cms.Tests.Common.Builders;
|
|
using Umbraco.Cms.Tests.Common.Testing;
|
|
using Umbraco.Cms.Tests.Integration.Testing;
|
|
|
|
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services;
|
|
|
|
[TestFixture]
|
|
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
|
|
internal class ContentVersionCleanupServiceTest : UmbracoIntegrationTest
|
|
{
|
|
public IFileService FileService => GetRequiredService<IFileService>();
|
|
|
|
public IContentTypeService ContentTypeService => GetRequiredService<IContentTypeService>();
|
|
|
|
public IContentService ContentService => GetRequiredService<IContentService>();
|
|
|
|
public IContentVersionService ContentVersionService => GetRequiredService<IContentVersionService>();
|
|
|
|
/// <remarks>
|
|
/// This is covered by the unit tests, but nice to know it deletes on infra.
|
|
/// And proves implementation is compatible with SQL CE.
|
|
/// </remarks>
|
|
[Test]
|
|
public void PerformContentVersionCleanup_WithNoKeepPeriods_DeletesEverythingExceptActive()
|
|
{
|
|
// For reference, Our currently has
|
|
// 5000 Documents
|
|
// With 200K Versions
|
|
// With 11M Property data
|
|
|
|
var template = TemplateBuilder.CreateTextPageTemplate();
|
|
FileService.SaveTemplate(template);
|
|
|
|
var contentTypeA =
|
|
ContentTypeBuilder.CreateSimpleContentType("contentTypeA", "contentTypeA", defaultTemplateId: template.Id);
|
|
|
|
// Kill all historic
|
|
contentTypeA.HistoryCleanup.PreventCleanup = false;
|
|
contentTypeA.HistoryCleanup.KeepAllVersionsNewerThanDays = 0;
|
|
contentTypeA.HistoryCleanup.KeepLatestVersionPerDayForDays = 0;
|
|
|
|
ContentTypeService.Save(contentTypeA);
|
|
|
|
var content = ContentBuilder.CreateSimpleContent(contentTypeA);
|
|
ContentService.Save(content);
|
|
ContentService.Publish(content, Array.Empty<string>());
|
|
|
|
for (var i = 0; i < 10; i++)
|
|
{
|
|
ContentService.Publish(content, Array.Empty<string>());
|
|
}
|
|
|
|
var before = GetReport();
|
|
|
|
Debug.Assert(before.ContentVersions == 12); // 10 historic + current draft + current published
|
|
Debug.Assert(before.PropertyData == 12 * 3); // CreateSimpleContentType = 3 props
|
|
|
|
ContentVersionService.PerformContentVersionCleanup(DateTime.UtcNow.AddHours(1));
|
|
|
|
var after = GetReport();
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.AreEqual(2, after.ContentVersions); // current draft, current published
|
|
Assert.AreEqual(2, after.DocumentVersions);
|
|
Assert.AreEqual(6, after.PropertyData); // CreateSimpleContentType = 3 props
|
|
});
|
|
}
|
|
|
|
private Report GetReport()
|
|
{
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
{
|
|
// SQL CE is fun!
|
|
var contentVersions =
|
|
ScopeAccessor.AmbientScope.Database.Single<int>(@"select count(1) from umbracoContentVersion");
|
|
var documentVersions =
|
|
ScopeAccessor.AmbientScope.Database.Single<int>(@"select count(1) from umbracoDocumentVersion");
|
|
var propertyData =
|
|
ScopeAccessor.AmbientScope.Database.Single<int>(@"select count(1) from umbracoPropertyData");
|
|
|
|
return new Report
|
|
{
|
|
ContentVersions = contentVersions,
|
|
DocumentVersions = documentVersions,
|
|
PropertyData = propertyData
|
|
};
|
|
}
|
|
}
|
|
|
|
private void InsertCleanupPolicy(IContentType contentType, int daysToKeepAll, int daysToRollupAll,
|
|
bool preventCleanup = false)
|
|
{
|
|
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
|
{
|
|
var entity = new ContentVersionCleanupPolicyDto
|
|
{
|
|
ContentTypeId = contentType.Id,
|
|
KeepAllVersionsNewerThanDays = daysToKeepAll,
|
|
KeepLatestVersionPerDayForDays = daysToRollupAll,
|
|
PreventCleanup = preventCleanup,
|
|
Updated = DateTime.Today
|
|
};
|
|
|
|
ScopeAccessor.AmbientScope.Database.Insert(entity);
|
|
}
|
|
}
|
|
|
|
private class Report
|
|
{
|
|
public int ContentVersions { get; set; }
|
|
|
|
public int DocumentVersions { get; set; }
|
|
|
|
public int PropertyData { get; set; }
|
|
}
|
|
}
|