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);
                    }
                });
            });
        }
Ejemplo n.º 2
0
        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));
            }
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
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();

                    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."));
        }
Ejemplo n.º 6
0
        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());
        }
Ejemplo n.º 7
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 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);
            }
        }
Ejemplo n.º 11
0
        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);
                    });
                }
            }
        }