From 537a657de364f75293a1967bbe586a5bd40ce105 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 3 Oct 2024 15:35:17 +0200 Subject: [PATCH] V15: Fix previews (#17181) * default to preview value from cookie instead of draft. * Fix tests --------- Co-authored-by: Zeegaan --- .../PublishedCache/IPublishedContentCache.cs | 4 +-- src/Umbraco.Core/Services/IPreviewService.cs | 2 ++ src/Umbraco.Core/Services/PreviewService.cs | 11 ++++++- .../DocumentCache.cs | 8 ++--- .../Services/DocumentCacheService.cs | 30 +++++++++++++------ .../Services/IDocumentCacheService.cs | 4 +-- .../DocumentHybridCacheMockTests.cs | 3 +- 7 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Core/PublishedCache/IPublishedContentCache.cs b/src/Umbraco.Core/PublishedCache/IPublishedContentCache.cs index 8353225f1057..8230b0f306d8 100644 --- a/src/Umbraco.Core/PublishedCache/IPublishedContentCache.cs +++ b/src/Umbraco.Core/PublishedCache/IPublishedContentCache.cs @@ -11,7 +11,7 @@ public interface IPublishedContentCache : IPublishedCache /// A value indicating whether to consider unpublished content. /// The content, or null. /// Considers published or unpublished content depending on defaults. - Task GetByIdAsync(int id, bool preview = false); + Task GetByIdAsync(int id, bool? preview = null); /// /// Gets a content identified by its unique identifier. @@ -20,7 +20,7 @@ public interface IPublishedContentCache : IPublishedCache /// A value indicating whether to consider unpublished content. /// The content, or null. /// Considers published or unpublished content depending on defaults. - Task GetByIdAsync(Guid key, bool preview = false); + Task GetByIdAsync(Guid key, bool? preview = null); // FIXME: All these routing methods needs to be removed, as they are no longer part of the content cache /// diff --git a/src/Umbraco.Core/Services/IPreviewService.cs b/src/Umbraco.Core/Services/IPreviewService.cs index c9e276d83eab..c65dbe16bbd3 100644 --- a/src/Umbraco.Core/Services/IPreviewService.cs +++ b/src/Umbraco.Core/Services/IPreviewService.cs @@ -15,5 +15,7 @@ public interface IPreviewService /// Task EndPreviewAsync(); + bool IsInPreview(); + Task> TryGetPreviewClaimsIdentityAsync(); } diff --git a/src/Umbraco.Core/Services/PreviewService.cs b/src/Umbraco.Core/Services/PreviewService.cs index bc11ab53bfaa..c487d4d407e4 100644 --- a/src/Umbraco.Core/Services/PreviewService.cs +++ b/src/Umbraco.Core/Services/PreviewService.cs @@ -1,5 +1,6 @@ using System.Security.Claims; using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Preview; using Umbraco.Cms.Core.Security; @@ -13,15 +14,18 @@ public class PreviewService : IPreviewService private readonly ICookieManager _cookieManager; private readonly IPreviewTokenGenerator _previewTokenGenerator; private readonly IServiceScopeFactory _serviceScopeFactory; + private readonly IRequestCache _requestCache; public PreviewService( ICookieManager cookieManager, IPreviewTokenGenerator previewTokenGenerator, - IServiceScopeFactory serviceScopeFactory) + IServiceScopeFactory serviceScopeFactory, + IRequestCache requestCache) { _cookieManager = cookieManager; _previewTokenGenerator = previewTokenGenerator; _serviceScopeFactory = serviceScopeFactory; + _requestCache = requestCache; } public async Task TryEnterPreviewAsync(IUser user) @@ -42,6 +46,11 @@ public Task EndPreviewAsync() return Task.CompletedTask; } + public bool IsInPreview() => + _requestCache.Get( + "IsInPreview", + () => TryGetPreviewClaimsIdentityAsync().GetAwaiter().GetResult().Success) as bool? ?? false; + public async Task> TryGetPreviewClaimsIdentityAsync() { var cookieValue = _cookieManager.GetCookieValue(Constants.Web.PreviewCookieName); diff --git a/src/Umbraco.PublishedCache.HybridCache/DocumentCache.cs b/src/Umbraco.PublishedCache.HybridCache/DocumentCache.cs index d978919a65c2..9be78a9ea235 100644 --- a/src/Umbraco.PublishedCache.HybridCache/DocumentCache.cs +++ b/src/Umbraco.PublishedCache.HybridCache/DocumentCache.cs @@ -21,19 +21,19 @@ public DocumentCache(IDocumentCacheService documentCacheService, IPublishedConte _publishedContentTypeCache = publishedContentTypeCache; } - public async Task GetByIdAsync(int id, bool preview = false) => await _documentCacheService.GetByIdAsync(id, preview); + public async Task GetByIdAsync(int id, bool? preview = null) => await _documentCacheService.GetByIdAsync(id, preview); - public async Task GetByIdAsync(Guid key, bool preview = false) => await _documentCacheService.GetByKeyAsync(key, preview); + public async Task GetByIdAsync(Guid key, bool? preview = null) => await _documentCacheService.GetByKeyAsync(key, preview); public IPublishedContent? GetById(bool preview, int contentId) => GetByIdAsync(contentId, preview).GetAwaiter().GetResult(); public IPublishedContent? GetById(bool preview, Guid contentId) => GetByIdAsync(contentId, preview).GetAwaiter().GetResult(); - public IPublishedContent? GetById(int contentId) => GetByIdAsync(contentId, false).GetAwaiter().GetResult(); + public IPublishedContent? GetById(int contentId) => GetByIdAsync(contentId).GetAwaiter().GetResult(); - public IPublishedContent? GetById(Guid contentId) => GetByIdAsync(contentId, false).GetAwaiter().GetResult(); + public IPublishedContent? GetById(Guid contentId) => GetByIdAsync(contentId).GetAwaiter().GetResult(); public IPublishedContentType? GetContentType(int id) => _publishedContentTypeCache.Get(PublishedItemType.Content, id); diff --git a/src/Umbraco.PublishedCache.HybridCache/Services/DocumentCacheService.cs b/src/Umbraco.PublishedCache.HybridCache/Services/DocumentCacheService.cs index 4b8628574f07..b73f48dcd7ad 100644 --- a/src/Umbraco.PublishedCache.HybridCache/Services/DocumentCacheService.cs +++ b/src/Umbraco.PublishedCache.HybridCache/Services/DocumentCacheService.cs @@ -22,6 +22,7 @@ internal sealed class DocumentCacheService : IDocumentCacheService private readonly ICacheNodeFactory _cacheNodeFactory; private readonly IEnumerable _seedKeyProviders; private readonly IPublishedModelFactory _publishedModelFactory; + private readonly IPreviewService _previewService; private readonly CacheSettings _cacheSettings; private HashSet? _seedKeys; @@ -54,7 +55,8 @@ public DocumentCacheService( ICacheNodeFactory cacheNodeFactory, IEnumerable seedKeyProviders, IOptions cacheSettings, - IPublishedModelFactory publishedModelFactory) + IPublishedModelFactory publishedModelFactory, + IPreviewService previewService) { _databaseCacheRepository = databaseCacheRepository; _idKeyMap = idKeyMap; @@ -64,22 +66,30 @@ public DocumentCacheService( _cacheNodeFactory = cacheNodeFactory; _seedKeyProviders = seedKeyProviders; _publishedModelFactory = publishedModelFactory; + _previewService = previewService; _cacheSettings = cacheSettings.Value; } - public async Task GetByKeyAsync(Guid key, bool preview = false) + public async Task GetByKeyAsync(Guid key, bool? preview = null) { using ICoreScope scope = _scopeProvider.CreateCoreScope(); + bool calculatedPreview = preview ?? GetPreview(); + ContentCacheNode? contentCacheNode = await _hybridCache.GetOrCreateAsync( - GetCacheKey(key, preview), // Unique key to the cache entry - async cancel => await _databaseCacheRepository.GetContentSourceAsync(key, preview)); + GetCacheKey(key, calculatedPreview), // Unique key to the cache entry + async cancel => await _databaseCacheRepository.GetContentSourceAsync(key, calculatedPreview)); scope.Complete(); - return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedContent(contentCacheNode, preview).CreateModel(_publishedModelFactory); + return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedContent(contentCacheNode, calculatedPreview).CreateModel(_publishedModelFactory); + } + + private bool GetPreview() + { + return _previewService.IsInPreview(); } - public async Task GetByIdAsync(int id, bool preview = false) + public async Task GetByIdAsync(int id, bool? preview = null) { Attempt keyAttempt = _idKeyMap.GetKeyForId(id, UmbracoObjectTypes.Document); if (keyAttempt.Success is false) @@ -87,12 +97,14 @@ public DocumentCacheService( return null; } + bool calculatedPreview = preview ?? GetPreview(); + using ICoreScope scope = _scopeProvider.CreateCoreScope(); ContentCacheNode? contentCacheNode = await _hybridCache.GetOrCreateAsync( - GetCacheKey(keyAttempt.Result, preview), // Unique key to the cache entry - async cancel => await _databaseCacheRepository.GetContentSourceAsync(id, preview)); + GetCacheKey(keyAttempt.Result, calculatedPreview), // Unique key to the cache entry + async cancel => await _databaseCacheRepository.GetContentSourceAsync(id, calculatedPreview)); scope.Complete(); - return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedContent(contentCacheNode, preview).CreateModel(_publishedModelFactory);; + return contentCacheNode is null ? null : _publishedContentFactory.ToIPublishedContent(contentCacheNode, calculatedPreview).CreateModel(_publishedModelFactory);; } public IEnumerable GetByContentType(IPublishedContentType contentType) diff --git a/src/Umbraco.PublishedCache.HybridCache/Services/IDocumentCacheService.cs b/src/Umbraco.PublishedCache.HybridCache/Services/IDocumentCacheService.cs index 873551c06b86..18a25496e234 100644 --- a/src/Umbraco.PublishedCache.HybridCache/Services/IDocumentCacheService.cs +++ b/src/Umbraco.PublishedCache.HybridCache/Services/IDocumentCacheService.cs @@ -5,9 +5,9 @@ namespace Umbraco.Cms.Infrastructure.HybridCache.Services; public interface IDocumentCacheService { - Task GetByKeyAsync(Guid key, bool preview = false); + Task GetByKeyAsync(Guid key, bool? preview = null); - Task GetByIdAsync(int id, bool preview = false); + Task GetByIdAsync(int id, bool? preview = null); Task SeedAsync(CancellationToken cancellationToken); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheMockTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheMockTests.cs index b0e3bc6ec7e2..2e810114d0d0 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheMockTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheMockTests.cs @@ -104,7 +104,8 @@ public void SetUp() GetRequiredService(), GetSeedProviders(), Options.Create(new CacheSettings()), - GetRequiredService()); + GetRequiredService(), + GetRequiredService()); _mockedCache = new DocumentCache(_mockDocumentCacheService, GetRequiredService()); }