示例#1
0
        /// <summary>
        /// Returns a filter contexualised to the logged on user and entity.
        /// </summary>
        private static Expression <Func <TEntity, bool> > GetFilter <TEntity>(out GetActionTypes actionType) where TEntity : BaseModel
        {
            Logger.InstanceVerbose.LogFunctionEntry(typeof(RepositoryFactory).Name, String.Format("GetFilter<{0}>", typeof(TEntity).Name));

            Expression <Func <TEntity, bool> > filters;

            if (Thread.CurrentPrincipal.Identity as TEIdentityBase == null)
            {
                // Disallow access completely
                actionType = GetActionTypes.ThrowsUnauthorizedException;
                return(t => false);
                //throw new UnauthorizedException("A repository can not be created for an anon user");
            }

            // Based on the appliesWhen outcome, concat all applicable filters and return
            var applicableFilters =
                RepositoryFactory.filters[typeof(TEntity)].Where(t => t.AppliesWhen(Thread.CurrentPrincipal.Identity as TEIdentityBase)).ToList();

            actionType = GetActionTypes.ReturnsNull;

            if (applicableFilters.Any())
            {
                if (applicableFilters.Any(t => t.Action == GetActionTypes.ThrowsUnauthorizedException))
                {
                    actionType = GetActionTypes.ThrowsUnauthorizedException;
                }

                filters = applicableFilters.Select(t => t.FilterExpression as Expression <Func <TEntity, bool> >).Aggregate((a, b) => a.And(b));
            }
            else
            {
                filters = null;
            }

            // Log outcome
            var message = "Applicable Filters Found? = " + (filters != null);

            if (filters != null)
            {
                message += "(" + actionType + ")";
            }

            Logger.InstanceVerbose.Info(typeof(RepositoryFactory).Name, String.Format("GetFilter<{0}>", typeof(TEntity).Name), message);

            Logger.InstanceVerbose.LogFunctionExit(typeof(RepositoryFactory).Name, String.Format("GetFilter<{0}>", typeof(TEntity).Name));

            return(filters);
        }
示例#2
0
        /// <summary>
        /// This will register the given filter in the repository. Until Reset() is called, this filter will
        /// always be applied when "appliesWhen" is true.
        /// </summary>
        /// <typeparam name="TEntity">The entity to apply the filter too. Note that this does not affect navigation properties (at this time)</typeparam>
        /// <param name="filter">The filter expression. Will be used in the LINQ to SQL query</param>
        /// <param name="appliesWhen">The filter is applied when this is true. This need not be convertable to SQL.</param>
        /// <param name="action">Dictates the behaviour that any get by ID methods undertake</param>
        /// <remarks>For both functions above, you should not save state between threads and users.
        /// Additionaly, the appliesWhen should be consistent  per authenticated user(TEIdentityBase) and will be called at least once, but maybe only once (with outcome cached).
        /// </remarks>
        public static void RegisterFilter <TEntity, TIdentity>(Expression <Func <TEntity, bool> > filter, Func <TIdentity, bool> appliesWhen = null, GetActionTypes action = GetActionTypes.ThrowsUnauthorizedException)
            where TEntity : BaseModel
            where TIdentity : TEIdentityBase
        {
            Logger.InstanceVerbose.LogFunctionEntry(typeof(RepositoryFactory).Name, String.Format("RegisterFilter<{0}>", typeof(TEntity).Name));

            Logger.InstanceVerbose.Debug(typeof(RepositoryFactory).Name, String.Format("RegisterFilter<{0}>", typeof(TEntity).Name),
                                         "Registering a filter for type " + typeof(TEntity) + " with action " + action);
            lock (syncRoot)
            {
                var appliesWhenToUse = appliesWhen ?? AppliesToAllFunc;

                if (!filters.ContainsKey(typeof(TEntity)))
                {
                    var list = new List <Filter>
                    {
                        new Filter {
                            FilterExpression = filter, AppliesWhen = t => t is TIdentity && appliesWhenToUse(t as TIdentity), Action = action
                        }
                    };

                    filters.Add(typeof(TEntity), list);
                }
                else
                {
                    var list = filters[typeof(TEntity)];

                    // Yes - this is a reference check on the delegate so we can concat the filters properly
                    var match = list.SingleOrDefault(d => d.AppliesWhen == appliesWhenToUse && d.Action == action);

                    // We need to add it to the list as there is a different appliesWhen property
                    if (match == null)
                    {
                        list.Add(new Filter {
                            FilterExpression = filter, AppliesWhen = t => t is TIdentity && appliesWhenToUse(t as TIdentity), Action = action
                        });
                    }
                    else
                    {
                        // Concat it to the previous expression
                        var expression = (Expression <Func <TEntity, bool> >)match.FilterExpression;
                        match.FilterExpression = expression.And(filter);
                    }
                }
            }

            Logger.InstanceVerbose.LogFunctionExit(typeof(RepositoryFactory).Name, String.Format("RegisterFilter<{0}>", typeof(TEntity).Name));
        }