-
I have such a resolver:
with custom attribute UseDateTimeFilter
How to add mongoFilter in middleware? I want to take the arguments before and after and make date filters out of them.
|
Beta Was this translation helpful? Give feedback.
Answered by
Buk7op
Jul 21, 2023
Replies: 2 comments
-
I think I managed to add a filter inside middleware, but I'm not sure if this is correct. Anyway, it works. Please correct me if I'm wrong. [UseOffsetPaging(order: 1)]
[UseProjection(order: 3)]
[UseSorting(order: 4)]
[UseFiltering(order: 5)]
[UseDateTimeFilter(order: 2)]
[Authorize(Policy = Constants.ADMINS_ONLY_POLICY)]
public IExecutable<DalRequest> GetCalllog(DateTime before, DateTime after)
{
var filter = FilterDefinition<DalRequest>.Empty;
return _db.Requests.Find(filter).AsExecutable();
}
public sealed class UseDateTimeFilterAttribute : ObjectFieldDescriptorAttribute
{
public UseDateTimeFilterAttribute([CallerLineNumber] int order = 0)
{
Order = order;
}
protected override void OnConfigure(
IDescriptorContext context,
IObjectFieldDescriptor descriptor,
MemberInfo member)
{
descriptor.AddDateTimeFilter();
}
}
public static class DescriptorExtentions
{
private const string AFTER_ARGUMENT = "after";
private const string BEFORE_ARGUMENT = "before";
public static IObjectFieldDescriptor AddDateTimeFilter(this IObjectFieldDescriptor descriptor)
=> descriptor.Use(next => async context =>
{
var after = context.ArgumentValue<DateTime>(AFTER_ARGUMENT);
var before = context.ArgumentValue<DateTime>(BEFORE_ARGUMENT);
await next(context);
if (context.Result is MongoDbFindFluentExecutable<DalRequest> mongoContext)
{
var filter = Builders<DalRequest>.Filter.Empty;
filter = filter.AddDateFilter(before, after);
var hotChocolateFilter = filter.Wrap();
context.Result = mongoContext.WithFiltering(hotChocolateFilter);
}
});
}
|
Beta Was this translation helpful? Give feedback.
0 replies
-
And another modified implementation that allows you to add filters without using IFindFluent. public class CallLogQuery
{
private readonly IRequestsAccessor _db;
public CallLogQuery(IRequestsAccessor db)
{
_db = db;
}
// default
[Authorize(Policy = Constants.ADMINS_ONLY_POLICY)]
[UsePaging(order:Constants.GRAPHQL_ATTRIBUTES_ORDER_PAGING)]
[UseProjection(order: Constants.GRAPHQL_ATTRIBUTES_ORDER_PROJECTION)]
[UseSorting(order: Constants.GRAPHQL_ATTRIBUTES_ORDER_SORTING)]
[UseFiltering(order: Constants.GRAPHQL_ATTRIBUTES_ORDER_FILTERING)]
// our middlewares
[UseDateTimeFilter(order: 2)]
[UseTenantIdx(order:3)]
public IExecutable<DalRequest> GetCalllog()
{
return new MCMongoDbExecutable<DalRequest>(_db.Requests);
}
}
/// <summary>
/// Our implementation of IExecutable
/// </summary>
/// <typeparam name="T"></typeparam>
public class MCMongoDbExecutable<T> : MongoDbCollectionExecutable<T>
{
public MCMongoDbExecutable(IMongoCollection<T> collection)
: base(collection)
{
}
/// <summary>
/// Modify protected field Filters = '$and': [Filters, filter]
/// </summary>
/// <param name="filter"></param>
/// <returns></returns>
public IMongoDbExecutable AndWithFiltering(FilterDefinition<T> filter)
{
if (Filters is not null)
{
return WithFiltering(new AndFilterDefinition(Filters, filter.Wrap()));
}
return WithFiltering(filter.Wrap());
}
}
/// <summary>
/// Easy way to create a middleware.
/// </summary>
public abstract class FilteringAttribute : ObjectFieldDescriptorAttribute
{
public FilteringAttribute(int order)
{
Order = order;
}
protected override void OnConfigure(
IDescriptorContext context,
IObjectFieldDescriptor descriptor,
MemberInfo member)
{
Configure(descriptor);
descriptor.Use(next => async context =>
{
await next(context);
if (context.Result is MCMongoDbExecutable<DalRequest> mongoContext)
{
var filter = ProvideFilterDefinition(context);
if (filter is not null)
{
context.Result = mongoContext.AndWithFiltering(filter);
}
}
});
}
/// <summary>
/// Provide special filter that will be injected to the filtering flow
/// </summary>
/// <param name="serviceProvider"></param>
/// <returns></returns>
protected abstract FilterDefinition<DalRequest>? ProvideFilterDefinition(IMiddlewareContext middlewareContext);
/// <summary>
/// Can be used to configure schema
/// </summary>
/// <param name="descriptor"></param>
protected virtual void Configure(IObjectFieldDescriptor descriptor)
{
}
}
/// <summary>
/// Inject datetime before/after filter to the filtering flow
/// </summary>
public sealed class UseDateTimeFilterAttribute : FilteringAttribute
{
public UseDateTimeFilterAttribute(int order) : base(order)
{
}
/// <inheritdoc/>
protected override FilterDefinition<DalRequest>? ProvideFilterDefinition(IMiddlewareContext context)
{
var after = context.ArgumentValue<DateTime>(ArgumentNames.AFTER_ARGUMENT);
var before = context.ArgumentValue<DateTime>(ArgumentNames.BEFORE_ARGUMENT);
var filter = Builders<DalRequest>.Filter.Empty;
return filter.AddDateFilter(before, after);
}
/// <inheritdoc/>
protected override void Configure(IObjectFieldDescriptor descriptor)
{
descriptor.Argument(ArgumentNames.AFTER_ARGUMENT, a => a.Type<NonNullType<DateTimeType>>());
descriptor.Argument(ArgumentNames.BEFORE_ARGUMENT, a => a.Type<NonNullType<DateTimeType>>());
}
}
/// <summary>
/// Inject tidx filter to the filtering flow
/// </summary>
public class UseTenantIdx : FilteringAttribute
{
public UseTenantIdx(int order)
: base(order)
{
}
/// <inheritdoc/>
protected override FilterDefinition<DalRequest>? ProvideFilterDefinition(IMiddlewareContext context)
{
var claims = context.Services.GetRequiredService<IClaimsService>();
return Builders<DalRequest>.Filter.Eq(x => x.TenantIdx, claims.TenantIdx);
}
}
|
Beta Was this translation helpful? Give feedback.
0 replies
Answer selected by
Buk7op
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
And another modified implementation that allows you to add filters without using IFindFluent.