private void HandleRelativeChangesOfCollection(ModelAttributesInfo modelAttributesInfo, KeyValuePair <Type, string> property, IGrouping <string, ChangeResponse> collectionChanges, List <IPrefilterBase> prefilters, List <Subscription> equalCollectionSubscriptions) { List <ChangeResponse> completeChanges = CollectionChangeHelper.CalculateRelativeChanges(prefilters, collectionChanges.ToList(), property); Parallel.ForEach(equalCollectionSubscriptions, subscription => { Task.Run(() => { List <ChangeResponse> connectionChanges = CollectionChangeHelper.CalculateRelativeAuthenticatedChanges(modelAttributesInfo, completeChanges, property, subscription.Connection.Information, serviceProvider); ChangesResponse changesResponse = new ChangesResponse() { ReferenceId = subscription.ReferenceId, Changes = connectionChanges.Select(change => { object value = change.Value.GetAuthenticatedQueryModel(subscription.Connection.Information, serviceProvider); return(change.CreateResponse(subscription.ReferenceId, value)); }).ToList() }; if (changesResponse.Changes.Any()) { _ = subscription.Connection.Send(changesResponse); } }); }); }
private static bool CallHandleAuthAttribute(this Type t, SapphireAuthResource.OperationTypeEnum operationTypeEnum, HttpInformation httpInformation, object entityObject, IServiceProvider serviceProvider) { ModelAttributesInfo modelAttributesInfo = t.GetModelAttributesInfo(); switch (operationTypeEnum) { case SapphireAuthResource.OperationTypeEnum.Create: return(HandleAuthAttributes(modelAttributesInfo.CreateAuthAttributes, httpInformation, operationTypeEnum, entityObject, serviceProvider)); case SapphireAuthResource.OperationTypeEnum.Remove: return(HandleAuthAttributes(modelAttributesInfo.RemoveAuthAttributes, httpInformation, operationTypeEnum, entityObject, serviceProvider)); case SapphireAuthResource.OperationTypeEnum.Update: return(HandleAuthAttributes(modelAttributesInfo.UpdateAuthAttributes, httpInformation, operationTypeEnum, entityObject, serviceProvider)); default: return(HandleAuthAttributes(modelAttributesInfo.QueryAuthAttributes, httpInformation, operationTypeEnum, entityObject, serviceProvider)); } }
public static ResponseBase GetCollection(SapphireDbContext db, QueryCommand command, HttpInformation information, IServiceProvider serviceProvider) { SapphireDatabaseOptions sapphireDatabaseOptions = serviceProvider.GetService <SapphireDatabaseOptions>(); if (sapphireDatabaseOptions.DisableIncludePrefilter && command.Prefilters.Any(p => p is IncludePrefilter)) { throw new IncludeNotAllowedException(command.CollectionName); } Type dbContextType = db.GetType(); KeyValuePair <Type, string> property = dbContextType.GetDbSetType(command.CollectionName); if (property.Key == null) { throw new CollectionNotFoundException(command.CollectionName); } if (!property.Key.CanQuery(information, serviceProvider)) { throw new UnauthorizedException("Not allowed to query values from collection"); } IQueryable <object> collectionValues = db.GetCollectionValues(property, command.Prefilters); QueryResponse queryResponse = new QueryResponse() { ReferenceId = command.ReferenceId, }; IAfterQueryPrefilter afterQueryPrefilter = command.Prefilters.OfType <IAfterQueryPrefilter>().FirstOrDefault(); if (afterQueryPrefilter != null) { afterQueryPrefilter.Initialize(property.Key); queryResponse.Result = afterQueryPrefilter.Execute(collectionValues); } else { IEnumerable <object> values = collectionValues.AsEnumerable(); ModelAttributesInfo modelAttributesInfo = property.Key.GetModelAttributesInfo(); if (modelAttributesInfo.QueryEntryAuthAttributes.Any()) { values = values.Where(value => property.Key.CanQueryEntry(information, serviceProvider, value)); } values = values.Select(v => v.GetAuthenticatedQueryModel(information, serviceProvider)); queryResponse.Result = values.ToList(); } return(queryResponse); }
public static List <IPrefilterBase> GetQueryPrefilters(KeyValuePair <Type, string> property, QueryQueryCommand queryCommand, HttpInformation information, IServiceProvider serviceProvider) { ModelAttributesInfo modelAttributesInfo = property.Key.GetModelAttributesInfo(); QueryAttribute query = modelAttributesInfo.QueryAttributes .FirstOrDefault(q => q.QueryName.Equals(queryCommand.QueryName, StringComparison.InvariantCultureIgnoreCase)); DefaultQueryAttribute defaultQuery = modelAttributesInfo.DefaultQueryAttributes.SingleOrDefault(); if (query == null) { throw new QueryNotFoundException(queryCommand.ContextName, queryCommand.CollectionName, queryCommand.QueryName); } dynamic queryBuilder = Activator.CreateInstance(typeof(SapphireQueryBuilder <>).MakeGenericType(property.Key)); if (defaultQuery != null) { if (defaultQuery.FunctionLambda != null) { queryBuilder = defaultQuery.FunctionLambda(queryBuilder, information, queryCommand.Parameters); } else if (defaultQuery.FunctionInfo != null) { queryBuilder = defaultQuery.FunctionInfo.Invoke(null, defaultQuery.FunctionInfo.CreateParameters(information, serviceProvider, queryCommand.Parameters, (object)queryBuilder)); } } if (query.FunctionLambda != null) { queryBuilder = query.FunctionLambda(queryBuilder, information, queryCommand.Parameters); } else if (query.FunctionInfo != null) { queryBuilder = query.FunctionInfo.Invoke(null, query.FunctionInfo.CreateParameters(information, serviceProvider, queryCommand.Parameters, (object)queryBuilder)); } List <IPrefilterBase> prefilters = typeof(SapphireQueryBuilderBase <>) .MakeGenericType(property.Key) .GetField("prefilters")? .GetValue(queryBuilder); prefilters.ForEach(prefilter => prefilter.Initialize(property.Key)); return(prefilters); }
public static ResponseBase GetCollection(SapphireDbContext db, QueryCommand command, HttpInformation information, IServiceProvider serviceProvider) { Type dbContextType = db.GetType(); KeyValuePair <Type, string> property = dbContextType.GetDbSetType(command.CollectionName); if (property.Key != null) { if (!property.Key.CanQuery(information, serviceProvider)) { return(command.CreateExceptionResponse <QueryResponse>( "Not allowed to query values from collection")); } IQueryable <object> collectionValues = db.GetCollectionValues(serviceProvider, information, property, command.Prefilters); QueryResponse queryResponse = new QueryResponse() { ReferenceId = command.ReferenceId, }; IAfterQueryPrefilter afterQueryPrefilter = command.Prefilters.OfType <IAfterQueryPrefilter>().FirstOrDefault(); if (afterQueryPrefilter != null) { afterQueryPrefilter.Initialize(property.Key); queryResponse.Result = afterQueryPrefilter.Execute(collectionValues); } else { IEnumerable <object> values = collectionValues.AsEnumerable(); ModelAttributesInfo modelAttributesInfo = property.Key.GetModelAttributesInfo(); if (modelAttributesInfo.QueryEntryAuthAttributes.Any()) { values = values.Where(value => property.Key.CanQueryEntry(information, serviceProvider, value)); } values = values.Select(v => v.GetAuthenticatedQueryModel(information, serviceProvider)); queryResponse.Result = values.ToList(); } return(queryResponse); } return(command.CreateExceptionResponse <QueryResponse>("No set for collection was found.")); }
public static List <ChangeResponse> CalculateRelativeAuthenticatedChanges( ModelAttributesInfo modelAttributesInfo, List <ChangeResponse> allChanges, KeyValuePair <Type, string> property, HttpInformation connectionInformation, IServiceProvider requestServiceProvider) { if (!modelAttributesInfo.QueryEntryAuthAttributes.Any()) { return(allChanges); } IEnumerable <ChangeResponse> authenticatedChanges = allChanges .Where(change => property.Key.CanQueryEntry(connectionInformation, requestServiceProvider, change.Value) && (change.State != ChangeResponse.ChangeState.Modified || property.Key.CanQueryEntry( connectionInformation, requestServiceProvider, change.OriginalValue))); IEnumerable <ChangeResponse> oldLoadedNotAllowed = allChanges .Where(change => change.State == ChangeResponse.ChangeState.Modified && !property.Key.CanQueryEntry(connectionInformation, requestServiceProvider, change.Value) && property.Key.CanQueryEntry(connectionInformation, requestServiceProvider, change.OriginalValue)) .Select(change => { ChangeResponse newChangeResponse = change.CreateResponse(null, change.Value); newChangeResponse.State = ChangeResponse.ChangeState.Deleted; return(newChangeResponse); }); IEnumerable <ChangeResponse> notLoadedNewAllowed = allChanges .Where(change => change.State == ChangeResponse.ChangeState.Modified && property.Key.CanQueryEntry(connectionInformation, requestServiceProvider, change.Value) && !property.Key.CanQueryEntry(connectionInformation, requestServiceProvider, change.OriginalValue)) .Select(change => { ChangeResponse newChangeResponse = change.CreateResponse(null, change.Value); newChangeResponse.State = ChangeResponse.ChangeState.Added; return(newChangeResponse); }); return(authenticatedChanges.Concat(oldLoadedNotAllowed).Concat(notLoadedNewAllowed).ToList()); }
public static ResponseBase GetCollection(SapphireDbContext db, IQueryCommand command, KeyValuePair <Type, string> property, List <IPrefilterBase> prefilters, HttpInformation information, IServiceProvider serviceProvider) { if (!property.Key.CanQuery(information, serviceProvider)) { throw new UnauthorizedException("Not allowed to query values from collection"); } IQueryable <object> collectionValues = db.GetCollectionValues(property, prefilters); QueryResponse queryResponse = new QueryResponse() { ReferenceId = command.ReferenceId, }; IAfterQueryPrefilter afterQueryPrefilter = prefilters.OfType <IAfterQueryPrefilter>().FirstOrDefault(); if (afterQueryPrefilter != null) { queryResponse.Result = afterQueryPrefilter.Execute(collectionValues); } else { IEnumerable <object> values = collectionValues.AsEnumerable(); ModelAttributesInfo modelAttributesInfo = property.Key.GetModelAttributesInfo(); if (modelAttributesInfo.QueryEntryAuthAttributes.Any()) { values = values.Where(value => property.Key.CanQueryEntry(information, serviceProvider, value)); } values = values.Select(v => v.GetAuthenticatedQueryModel(information, serviceProvider)); queryResponse.Result = values.ToList(); } return(queryResponse); }
private void HandleChangesOfCollection(Type dbContextType, IGrouping <string, ChangeResponse> collectionChanges, string contextName, List <ChangeResponse> changes, Guid handlingId) { KeyValuePair <Type, string> property = dbContextType.GetDbSetType(collectionChanges.Key); ModelAttributesInfo modelAttributesInfo = property.Key.GetModelAttributesInfo(); Dictionary <PrefilterContainer, List <Subscription> > equalCollectionSubscriptionsGrouping = subscriptionManager.GetSubscriptions(contextName, collectionChanges.Key); if (equalCollectionSubscriptionsGrouping == null) { return; } Parallel.ForEach(equalCollectionSubscriptionsGrouping, equalCollectionSubscriptions => { Task.Run(() => { HandleEqualCollectionSubscriptions(equalCollectionSubscriptions.Key, equalCollectionSubscriptions.Value, collectionChanges, dbContextType, changes, property, modelAttributesInfo, handlingId); }); }); }
public SapphireModelBuilder() { attributesInfo = typeof(T).GetModelAttributesInfo(); }
private void HandleEqualCollectionSubscriptions(PrefilterContainer prefilterContainer, List <Subscription> equalCollectionSubscriptions, IGrouping <string, ChangeResponse> collectionChanges, Type dbContextType, List <ChangeResponse> changes, KeyValuePair <Type, string> property, ModelAttributesInfo modelAttributesInfo, Guid handlingId) { List <IPrefilterBase> prefilters = prefilterContainer.Prefilters; if (prefilters.Any(prefilter => prefilter is IAfterQueryPrefilter || prefilter is TakePrefilter || prefilter is SkipPrefilter || prefilter is IncludePrefilter)) { HandleReloadOfCollectionData(dbContextType, property, prefilterContainer, equalCollectionSubscriptions, handlingId); } else { HandleRelativeChangesOfCollection(modelAttributesInfo, property, collectionChanges, prefilters, equalCollectionSubscriptions); } }
public void HandleCollections(ConnectionBase connection, string contextName, Type dbContextType, List <ChangeResponse> changes, IServiceProvider requestServiceProvider) { IEnumerable <IGrouping <string, CollectionSubscription> > subscriptionGroupings = connection.Subscriptions .Where(s => s.ContextName == contextName) .GroupBy(s => s.CollectionName); foreach (IGrouping <string, CollectionSubscription> subscriptionGrouping in subscriptionGroupings) { KeyValuePair <Type, string> property = dbContextType.GetDbSetType(subscriptionGrouping.Key); List <ChangeResponse> changesForCollection = changes .Where(c => c.CollectionName == subscriptionGrouping.Key) .ToList(); ModelAttributesInfo modelAttributesInfo = property.Key.GetModelAttributesInfo(); IEnumerable <ChangeResponse> authenticatedChanges = changesForCollection; if (modelAttributesInfo.QueryEntryAuthAttributes.Any()) { authenticatedChanges = changesForCollection .Where(change => change.State == ChangeResponse.ChangeState.Deleted || property.Key.CanQueryEntry(connection.Information, requestServiceProvider, change.Value)); IEnumerable <ChangeResponse> oldLoadedNotAllowed = changesForCollection .Where(change => change.State == ChangeResponse.ChangeState.Modified && !property.Key.CanQueryEntry(connection.Information, requestServiceProvider, change.Value)) .Select(change => { ChangeResponse newChangeResponse = change.CreateResponse(null, change.Value); newChangeResponse.State = ChangeResponse.ChangeState.Deleted; return(newChangeResponse); }); authenticatedChanges = authenticatedChanges.Concat(oldLoadedNotAllowed); } List <ChangeResponse> collectionChanges = authenticatedChanges.ToList(); if (collectionChanges.Any()) { if (modelAttributesInfo.QueryFunctionAttribute != null) { if (modelAttributesInfo.QueryFunctionAttribute.FunctionBuilder != null) { Func <object, bool> expression = modelAttributesInfo.QueryFunctionAttribute.GetLambda(connection.Information, property.Key).Compile(); collectionChanges = collectionChanges.Where(change => expression(change.Value)).ToList(); } else if (modelAttributesInfo.QueryFunctionAttribute.FunctionInfo != null) { object[] methodParameters = modelAttributesInfo.QueryFunctionAttribute.FunctionInfo.CreateParameters(connection.Information, serviceProvider); dynamic queryFunctionExpression = ((dynamic)modelAttributesInfo.QueryFunctionAttribute.FunctionInfo.Invoke(null, methodParameters)).Compile(); collectionChanges = collectionChanges.Where(change => queryFunctionExpression(change.Value)) .ToList(); } } } foreach (CollectionSubscription subscription in subscriptionGrouping) { Task.Run(() => { HandleSubscription(subscription, dbContextType, requestServiceProvider, connection, property, collectionChanges, changes); }); } } }