Пример #1
0
        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);
        }
Пример #2
0
        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();

                    AuthModelInfo authModelInfo = property.Key.GetAuthModelInfos();

                    if (authModelInfo.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."));
        }
Пример #3
0
        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 HandleReloadOfCollectionData(Type dbContextType, KeyValuePair <Type, string> property,
                                                  PrefilterContainer prefilterContainer,
                                                  List <Subscription> equalCollectionSubscriptions, Guid handlingId)
        {
            try
            {
                if (!prefilterContainer.StartHandling(handlingId))
                {
                    return;
                }

                SapphireDbContext db = dbContextAccessor.GetContext(dbContextType, serviceProvider);

                IQueryable <object> collectionValues =
                    db.GetCollectionValues(property, prefilterContainer.Prefilters);

                IAfterQueryPrefilter afterQueryPrefilter =
                    prefilterContainer.Prefilters.OfType <IAfterQueryPrefilter>().FirstOrDefault();

                if (afterQueryPrefilter != null)
                {
                    afterQueryPrefilter.Initialize(property.Key);
                    object result = afterQueryPrefilter.Execute(collectionValues);

                    Parallel.ForEach(equalCollectionSubscriptions, subscription =>
                    {
                        Task.Run(() =>
                        {
                            _ = subscription.Connection.Send(new QueryResponse()
                            {
                                ReferenceId = subscription.ReferenceId,
                                Result      = result
                            });
                        });
                    });
                }
                else
                {
                    List <object> values = collectionValues.ToList();

                    Parallel.ForEach(equalCollectionSubscriptions, subscription =>
                    {
                        Task.Run(() =>
                        {
                            _ = subscription.Connection.Send(new QueryResponse()
                            {
                                ReferenceId = subscription.ReferenceId,
                                Result      = values
                                              .Where(v => property.Key.CanQueryEntry(subscription.Connection.Information,
                                                                                     serviceProvider, v))
                                              .Select(v =>
                                                      v.GetAuthenticatedQueryModel(subscription.Connection.Information,
                                                                                   serviceProvider))
                                              .ToList()
                            });
                        });
                    });
                }
            }
            finally
            {
                prefilterContainer.FinishHandling();
            }
        }
        public void HandleSubscription(CollectionSubscription subscription, Type dbContextType,
                                       IServiceProvider requestServiceProvider, ConnectionBase connection, KeyValuePair <Type, string> property,
                                       List <ChangeResponse> collectionChanges, List <ChangeResponse> allChanges)
        {
            try
            {
                bool anyCollectionChanges = collectionChanges.Any();

                if ((anyCollectionChanges && subscription.Prefilters.Any(prefilter =>
                                                                         prefilter is IAfterQueryPrefilter || prefilter is TakePrefilter || prefilter is SkipPrefilter)) ||
                    HasIncludePrefilterWithChange(subscription, allChanges))
                {
                    SapphireDbContext db = dbContextAccessor.GetContext(dbContextType, requestServiceProvider);

                    IQueryable <object> collectionValues = db.GetCollectionValues(requestServiceProvider,
                                                                                  connection.Information, property, subscription.Prefilters);

                    IAfterQueryPrefilter afterQueryPrefilter =
                        subscription.Prefilters.OfType <IAfterQueryPrefilter>().FirstOrDefault();

                    if (afterQueryPrefilter != null)
                    {
                        afterQueryPrefilter.Initialize(property.Key);

                        _ = connection.Send(new QueryResponse()
                        {
                            ReferenceId = subscription.ReferenceId,
                            Result      = afterQueryPrefilter.Execute(collectionValues)
                        });
                    }
                    else
                    {
                        _ = connection.Send(new QueryResponse()
                        {
                            ReferenceId = subscription.ReferenceId,
                            Result      = collectionValues
                                          .AsEnumerable()
                                          .Select(v => v.GetAuthenticatedQueryModel(connection.Information, serviceProvider))
                                          .ToList()
                        });
                    }
                }
                else if (anyCollectionChanges)
                {
                    IEnumerable <WherePrefilter> wherePrefilters = subscription.Prefilters.OfType <WherePrefilter>();

                    foreach (WherePrefilter wherePrefilter in wherePrefilters)
                    {
                        wherePrefilter.Initialize(property.Key);
                        Func <object, bool> whereFunction = wherePrefilter.WhereExpression.Compile();
                        collectionChanges = collectionChanges.Where((change) => whereFunction(change.Value)).ToList();
                    }

                    collectionChanges.ForEach(change =>
                    {
                        object value =
                            change.Value.GetAuthenticatedQueryModel(connection.Information, requestServiceProvider);
                        _ = connection.Send(change.CreateResponse(subscription.ReferenceId, value));
                    });
                }
            }
            catch (Exception ex)
            {
                SubscribeCommand tempErrorCommand = new SubscribeCommand()
                {
                    CollectionName = subscription.CollectionName,
                    ReferenceId    = subscription.ReferenceId,
                    Prefilters     = subscription.Prefilters
                };

                _ = connection.Send(tempErrorCommand.CreateExceptionResponse <ResponseBase>(ex));
                logger.LogError(
                    $"Error handling subscription '{subscription.ReferenceId}' of {subscription.CollectionName}");
                logger.LogError(ex.Message);
            }
        }
        public void HandleSubscription(CollectionSubscription subscription, Type dbContextType,
                                       IServiceProvider requestServiceProvider, ConnectionBase connection, KeyValuePair <Type, string> property,
                                       List <ChangeResponse> collectionChanges, List <ChangeResponse> allChanges)
        {
            try
            {
                bool anyCollectionChanges = collectionChanges.Any();

                if ((anyCollectionChanges && subscription.Prefilters.Any(prefilter =>
                                                                         prefilter is IAfterQueryPrefilter || prefilter is TakePrefilter || prefilter is SkipPrefilter)) ||
                    HasIncludePrefilterWithChange(subscription, allChanges))
                {
                    SapphireDbContext db = dbContextAccessor.GetContext(dbContextType, requestServiceProvider);

                    IQueryable <object> collectionValues = db.GetCollectionValues(requestServiceProvider,
                                                                                  connection.Information, property, subscription.Prefilters);

                    IAfterQueryPrefilter afterQueryPrefilter =
                        subscription.Prefilters.OfType <IAfterQueryPrefilter>().FirstOrDefault();

                    if (afterQueryPrefilter != null)
                    {
                        afterQueryPrefilter.Initialize(property.Key);

                        _ = connection.Send(new QueryResponse()
                        {
                            ReferenceId = subscription.ReferenceId,
                            Result      = afterQueryPrefilter.Execute(collectionValues)
                        });
                    }
                    else
                    {
                        _ = connection.Send(new QueryResponse()
                        {
                            ReferenceId = subscription.ReferenceId,
                            Result      = collectionValues
                                          .AsEnumerable()
                                          .Select(v => v.GetAuthenticatedQueryModel(connection.Information, serviceProvider))
                                          .ToList()
                        });
                    }
                }
                else if (anyCollectionChanges)
                {
                    IEnumerable <WherePrefilter> wherePrefilters = subscription.Prefilters.OfType <WherePrefilter>();

                    List <ChangeResponse> oldValuesUnloadResponses = new List <ChangeResponse>();
                    List <ChangeResponse> newValuesLoadResponses   = new List <ChangeResponse>();

                    foreach (WherePrefilter wherePrefilter in wherePrefilters)
                    {
                        wherePrefilter.Initialize(property.Key);

                        // Values that did change know do match the
                        oldValuesUnloadResponses.AddRange(
                            collectionChanges
                            .Where(change => change.State == ChangeResponse.ChangeState.Modified &&
                                   !wherePrefilter.WhereExpressionCompiled(change.Value) &&
                                   wherePrefilter.WhereExpressionCompiled(change.OriginalValue))
                            .Select(change =>
                        {
                            ChangeResponse newChangeResponse = change.CreateResponse(null, change.Value);
                            newChangeResponse.State          = ChangeResponse.ChangeState.Deleted;
                            return(newChangeResponse);
                        })
                            );

                        newValuesLoadResponses.AddRange(
                            collectionChanges
                            .Where(change => change.State == ChangeResponse.ChangeState.Modified &&
                                   wherePrefilter.WhereExpressionCompiled(change.Value) &&
                                   !wherePrefilter.WhereExpressionCompiled(change.OriginalValue))
                            .Select(change =>
                        {
                            ChangeResponse newChangeResponse = change.CreateResponse(null, change.Value);
                            newChangeResponse.State          = ChangeResponse.ChangeState.Added;
                            return(newChangeResponse);
                        })
                            );

                        collectionChanges = collectionChanges
                                            .Where((change) => wherePrefilter.WhereExpressionCompiled(change.Value)).ToList();
                    }

                    IEnumerable <ChangeResponse> changesForWherePrefilter = oldValuesUnloadResponses
                                                                            .Concat(newValuesLoadResponses)
                                                                            .GroupBy(v => v.Value)
                                                                            .Select(g => g.LastOrDefault());

                    collectionChanges = collectionChanges.Concat(changesForWherePrefilter).ToList();

                    ChangesResponse changesResponse = new ChangesResponse()
                    {
                        ReferenceId = subscription.ReferenceId,
                        Changes     = collectionChanges.Select(change =>
                        {
                            object value =
                                change.Value.GetAuthenticatedQueryModel(connection.Information, requestServiceProvider);
                            return(change.CreateResponse(subscription.ReferenceId, value));
                        }).ToList()
                    };

                    if (changesResponse.Changes.Any())
                    {
                        _ = connection.Send(changesResponse);
                    }
                }
            }
            catch (Exception ex)
            {
                SubscribeCommand tempErrorCommand = new SubscribeCommand()
                {
                    CollectionName = subscription.CollectionName,
                    ReferenceId    = subscription.ReferenceId,
                    Prefilters     = subscription.Prefilters
                };

                _ = connection.Send(tempErrorCommand.CreateExceptionResponse <ResponseBase>(ex));
                logger.LogError(
                    $"Error handling subscription '{subscription.ReferenceId}' of {subscription.CollectionName}");
                logger.LogError(ex.Message);
            }
        }