Posted on 31/10/2025 13:15:43
Here is a sample from our docs:
using System;
using System.Collections.Generic;
using System.Linq;
using Dynamicweb.Ecommerce.Shops;
using Dynamicweb.Environment;
using Dynamicweb.Extensibility;
using Dynamicweb.Extensibility.Notifications;
using Dynamicweb.Indexing;
using Dynamicweb.Indexing.Querying;
using Dynamicweb.Indexing.Querying.Expressions;
using Dynamicweb.Security.Permissions;
namespace Dynamicweb.Ecommerce.Indexing
{
[Subscribe(Dynamicweb.Indexing.Notifications.Query.BeforeQuery)]
public class BeforeQueryObserver : NotificationSubscriber
{
public override void OnNotify(string notification, NotificationArgs args)
{
if (ExecutingContext.IsBackEnd())
{
Dynamicweb.Indexing.Notifications.Query.BeforeQueryArgs beforeQueryArgs = args as Dynamicweb.Indexing.Notifications.Query.BeforeQueryArgs;
var query = beforeQueryArgs?.Query;
if (query is object)
{
var indexService = ServiceLocator.Current.GetInstance<IIndexService>();
var index = indexService.LoadIndex(query.Source.Repository, query.Source.Item);
if (index.Builds.Any(build => build.Value is ProductIndexBuilder))
{
var expressions = new List<Expression>(new[] { query.Expression });
var permissionService = new UnifiedPermissionService();
var disallowedProductGroupIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var disallowedShopIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var allowedGroupIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var allowedShopIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
using (var backendPermission = PermissionContext.Backend())
{
foreach (List<IdWithDefaultPermissionLevel<string>> permissionQueue in backendPermission.PermissionPriority)
{
foreach (var userPermission in permissionQueue)
{
foreach (string allowedProductGroupId in permissionService.GetAllMatchingKeys<Products.Group>(userPermission.Id.ToString()))
allowedGroupIds.Add(allowedProductGroupId);
foreach (string allowedShopId in permissionService.GetAllMatchingKeys<Shop>(userPermission.Id.ToString()))
allowedShopIds.Add(allowedShopId);
foreach (string disallowedGroupId in permissionService.GetAllMatchingKeys<Products.Group>(userPermission.Id.ToString(), PermissionLevel.None))
{
if (!allowedGroupIds.Contains(disallowedGroupId))
{
disallowedProductGroupIds.Add(disallowedGroupId);
}
}
foreach (string disallowedShopId in permissionService.GetAllMatchingKeys<Shop>(userPermission.Id.ToString(), PermissionLevel.None))
{
if (!allowedShopIds.Contains(disallowedShopId))
{
disallowedShopIds.Add(disallowedShopId);
}
}
}
}
}
UpdateExpressions(query, expressions, disallowedShopIds, "ShopIDs");
UpdateExpressions(query, expressions, disallowedProductGroupIds, "GroupIDs");
UpdateExpressions(query, expressions, disallowedProductGroupIds, "ParentGroupIDs");
query.Expression = Expression.Group(false, OperatorType.And, expressions);
}
}
}
}
private void UpdateExpressions(IQuery query, List<Expression> expressions, HashSet<string> disalowedValues, string fieldName)
{
var existingExpression = FindPermissionExpression(fieldName, query.Expression);
if (disalowedValues.Any() && existingExpression is null)
{
var g = Expression.Group(true, OperatorType.And, new List<Expression>(new[] { Expression.In(Expression.Field(fieldName, fieldName), Expression.Term(disalowedValues.ToArray())) }));
expressions.Add(g);
}
}
private BinaryExpression FindPermissionExpression(string fieldName, Expression topLevelExpression)
{
var groupExpression = topLevelExpression as GroupExpression;
if (groupExpression is object)
{
foreach (var item in groupExpression.Expressions)
{
var childExpression = item as GroupExpression;
if (childExpression is object && childExpression.Negate && childExpression.Expressions?.Count() == 1 && childExpression.Operator == OperatorType.And)
{
var binaryExpression = childExpression.Expressions?.First() as BinaryExpression;
if (binaryExpression is object && binaryExpression.Operator == OperatorType.In)
{
if (binaryExpression.Left is FieldExpression)
{
var fieldExpression = binaryExpression.Left as FieldExpression;
if (fieldName.Equals(fieldExpression?.FieldName, StringComparison.OrdinalIgnoreCase))
{
return binaryExpression;
}
}
}
}
}
}
return null;
}
}
}