Filter out disallowed content types from the delivery API content index (#14156)
* Filter out disallowed content types from the delivery api content index * Added . * Allow children of disallowed content types in the index --------- Co-authored-by: Elitsa <elm@umbraco.dk>
This commit is contained in:
@@ -70,5 +70,5 @@ public class ApiPublishedContentCache : IApiPublishedContentCache
|
||||
: null;
|
||||
|
||||
private bool IsAllowedContentType(IPublishedContent content)
|
||||
=> _deliveryApiSettings.DisallowedContentTypeAliases.InvariantContains(content.ContentType.Alias) is false;
|
||||
=> _deliveryApiSettings.IsAllowedContentType(content);
|
||||
}
|
||||
|
||||
19
src/Umbraco.Core/Extensions/DeliveryApiSettingsExtensions.cs
Normal file
19
src/Umbraco.Core/Extensions/DeliveryApiSettingsExtensions.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Extensions;
|
||||
|
||||
public static class DeliveryApiSettingsExtensions
|
||||
{
|
||||
public static bool IsAllowedContentType(this DeliveryApiSettings settings, IPublishedContent content)
|
||||
=> settings.IsAllowedContentType(content.ContentType.Alias);
|
||||
|
||||
public static bool IsDisallowedContentType(this DeliveryApiSettings settings, IPublishedContent content)
|
||||
=> settings.IsDisallowedContentType(content.ContentType.Alias);
|
||||
|
||||
public static bool IsAllowedContentType(this DeliveryApiSettings settings, string contentTypeAlias)
|
||||
=> settings.IsDisallowedContentType(contentTypeAlias) is false;
|
||||
|
||||
public static bool IsDisallowedContentType(this DeliveryApiSettings settings, string contentTypeAlias)
|
||||
=> settings.DisallowedContentTypeAliases.InvariantContains(contentTypeAlias);
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
using Examine;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Persistence.Querying;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Examine;
|
||||
|
||||
@@ -12,12 +15,19 @@ public class DeliveryApiContentIndexPopulator : IndexPopulator
|
||||
private readonly IContentService _contentService;
|
||||
private readonly IUmbracoDatabaseFactory _umbracoDatabaseFactory;
|
||||
private readonly IDeliveryApiContentIndexValueSetBuilder _deliveryContentIndexValueSetBuilder;
|
||||
private DeliveryApiSettings _deliveryApiSettings;
|
||||
|
||||
public DeliveryApiContentIndexPopulator(IContentService contentService, IDeliveryApiContentIndexValueSetBuilder deliveryContentIndexValueSetBuilder, IUmbracoDatabaseFactory umbracoDatabaseFactory)
|
||||
public DeliveryApiContentIndexPopulator(
|
||||
IContentService contentService,
|
||||
IDeliveryApiContentIndexValueSetBuilder deliveryContentIndexValueSetBuilder,
|
||||
IUmbracoDatabaseFactory umbracoDatabaseFactory,
|
||||
IOptionsMonitor<DeliveryApiSettings> deliveryApiSettings)
|
||||
{
|
||||
_contentService = contentService;
|
||||
_deliveryContentIndexValueSetBuilder = deliveryContentIndexValueSetBuilder;
|
||||
_umbracoDatabaseFactory = umbracoDatabaseFactory;
|
||||
_deliveryApiSettings = deliveryApiSettings.CurrentValue;
|
||||
deliveryApiSettings.OnChange(settings => _deliveryApiSettings = settings);
|
||||
RegisterIndex(Constants.UmbracoIndexes.DeliveryApiContentIndexName);
|
||||
}
|
||||
|
||||
@@ -38,19 +48,31 @@ public class DeliveryApiContentIndexPopulator : IndexPopulator
|
||||
{
|
||||
descendants = _contentService.GetPagedDescendants(Constants.System.Root, pageIndex, pageSize, out _, publishedQuery, Ordering.By("Path")).ToArray();
|
||||
|
||||
// children of unpublished content can still be published; we need to filter them out, as they're not supposed to go into the index.
|
||||
// there are a few rules we need to abide to when populating the index:
|
||||
// - children of unpublished content can still be published; we need to filter them out, as they're not supposed to go into the index.
|
||||
// - content of disallowed content types are not allowed in the index, but their children are
|
||||
// as we're querying published content and ordering by path, we can construct a list of "allowed" published content IDs like this.
|
||||
var allowedDescendants = new List<IContent>();
|
||||
foreach (IContent content in descendants)
|
||||
{
|
||||
if (_deliveryApiSettings.IsDisallowedContentType(content.ContentType.Alias))
|
||||
{
|
||||
// the content type is disallowed; make sure we consider all its children as candidates for the index anyway
|
||||
publishedContentIds.Add(content.Id);
|
||||
continue;
|
||||
}
|
||||
|
||||
// content at root level is by definition published, because we only fetch published content in the query above.
|
||||
// content not at root level should be included only if their parents are included (unbroken chain of published content)
|
||||
if (content.Level == 1 || publishedContentIds.Contains(content.ParentId))
|
||||
{
|
||||
publishedContentIds.Add(content.Id);
|
||||
allowedDescendants.Add(content);
|
||||
}
|
||||
}
|
||||
|
||||
// now we can utilize the list of "allowed" published content to filter out the ones we don't want in the index.
|
||||
IContent[] allowedDescendants = descendants.Where(content => publishedContentIds.Contains(content.Id)).ToArray();
|
||||
ValueSet[] valueSets = _deliveryContentIndexValueSetBuilder.GetValueSets(allowedDescendants).ToArray();
|
||||
// now build the value sets based on the "allowed" published content only
|
||||
ValueSet[] valueSets = _deliveryContentIndexValueSetBuilder.GetValueSets(allowedDescendants.ToArray()).ToArray();
|
||||
|
||||
foreach (IIndex index in indexes)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Examine;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.DeliveryApi;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
@@ -12,12 +14,19 @@ public class DeliveryApiContentIndexValueSetBuilder : IDeliveryApiContentIndexVa
|
||||
private readonly ContentIndexHandlerCollection _contentIndexHandlerCollection;
|
||||
private readonly IScopeProvider _scopeProvider;
|
||||
private readonly IPublicAccessService _publicAccessService;
|
||||
private DeliveryApiSettings _deliveryApiSettings;
|
||||
|
||||
public DeliveryApiContentIndexValueSetBuilder(ContentIndexHandlerCollection contentIndexHandlerCollection, IScopeProvider scopeProvider, IPublicAccessService publicAccessService)
|
||||
public DeliveryApiContentIndexValueSetBuilder(
|
||||
ContentIndexHandlerCollection contentIndexHandlerCollection,
|
||||
IScopeProvider scopeProvider,
|
||||
IPublicAccessService publicAccessService,
|
||||
IOptionsMonitor<DeliveryApiSettings> deliveryApiSettings)
|
||||
{
|
||||
_contentIndexHandlerCollection = contentIndexHandlerCollection;
|
||||
_scopeProvider = scopeProvider;
|
||||
_publicAccessService = publicAccessService;
|
||||
_deliveryApiSettings = deliveryApiSettings.CurrentValue;
|
||||
deliveryApiSettings.OnChange(settings => _deliveryApiSettings = settings);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -49,11 +58,19 @@ public class DeliveryApiContentIndexValueSetBuilder : IDeliveryApiContentIndexVa
|
||||
|
||||
private bool CanIndex(IContent content)
|
||||
{
|
||||
// is the content in a state that is allowed in the index?
|
||||
if (content.Published is false || content.Trashed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// is the content type allowed in the index?
|
||||
if (_deliveryApiSettings.IsDisallowedContentType(content.ContentType.Alias))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// is the content protected?
|
||||
using (_scopeProvider.CreateScope(autoComplete: true))
|
||||
{
|
||||
if (_publicAccessService.IsProtected(content.Path).Success)
|
||||
|
||||
Reference in New Issue
Block a user