Пример #1
0
    /// <inheritdoc/>
    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        if (Source == null)
        {
            WhenNull?.Invoke(builder);
            return;
        }

        var componentType = MatchingTypeFinder.TryFind(Source.GetType(), Scope);

        if (componentType == null)
        {
            if (WhenNoMatchFound == null)
            {
                throw Errors.NoMatchingComponentFound(Source.GetType(), Scope);
            }
            WhenNoMatchFound(Source)(builder);
            return;
        }

        var i = 0;

        builder.OpenComponent(i++, componentType);
        if (!string.IsNullOrEmpty(SourceParameterName))
        {
            builder.AddAttribute(i++, SourceParameterName, Source);
        }
        if (Attributes != null)
        {
            foreach (var(key, value) in Attributes)
            {
                builder.AddAttribute(i++, key, value);
            }
        }
        builder.CloseComponent();
    }
Пример #2
0
        /// <summary>
        /// Secures an entity by an enumerable property.
        /// </summary>
        /// <typeparam name="TK">The type to secure by.</typeparam>
        /// <typeparam name="TId">The type of the IDs to secure by.</typeparam>
        /// <param name="pathToCollection">An expression representing the path from an instance of T to the property of Type TK that T should be  by.</param>
        /// <param name="whenNull">The behaviour to use when entitlements are null.</param>
        /// <returns>A  Relationship representing how T should be  by TK.</returns>
        public SecuredRelationship ByCollection <TK, TId>(Expression <Func <T, IEnumerable <TK> > > pathToCollection, WhenNull whenNull)
            where TK : IIdentifiable <TId>
            where TId : IEquatable <TId>
        {
            var closuredLambdaBuilder = PredicateBuilder.BuildPredicateFactoryForCollectionProperty <T, TK, TId>(pathToCollection, whenNull);

            return(new SecuredRelationship(typeof(T), typeof(IEnumerable <TK>), closuredLambdaBuilder.Compile()));
        }
Пример #3
0
        public static LambdaExpression BuildPredicateFactoryForCollectionProperty(Type rootType, Type typeInCollection, Type keyType, LambdaExpression pathToRelationship, WhenNull whenNull)
        {
            // We are building one of the below expression factories
            // ids => return x => !x.CollectionProperty.Any() || x.CollectionProperty.Any(c => ids.Contains(c.Id))
            // ids => return x => x.CollectionProperty.Any() && x.CollectionProperty.Any(c => ids.Contains(c.Id))
            // Create the constructed generic type of Func<T, bool> without having access to a generic parameter of T ( the parameter rootType is the result of typeof(T) )
            var typeForRootPredicate = MakeFuncOfTBool(rootType);

            // Create a parameter that represents the object from the collection, this will later become the {parameter of typeInCollection} => part of a lambda
            var parameterForSingleId = Expression.Parameter(typeInCollection);

            // Create an Expression to turn the parameter into an accessor like {parameter of typeInCollection}.Id, when combined in a lambda this will become {parameter of typeInCollection} => {parameter of typeInCollection}.Id
            var accessorForSingleId = Expression.PropertyOrField(parameterForSingleId, "Id");

            // Reflect the generic method information from the keyType for checking later. This will be IEnumberable<keyType>.Contains({parameter of keyType})
            var containsMethod = MakeContainsMethod(keyType, 2);

            // Create a parameter that represents the type of list of  Ids that your user is entitled to access, this is IEnumerable<keyType>
            var typeForEntitledIdsParameter = MakeEnumerableOfT(keyType);

            // Create a parameter that represents the list of  Ids that your user is entitled to access, created from the above type
            var parameterForEntitledIds = MakeIdsParameter(typeForEntitledIdsParameter);

            // Reflect LINQ methods to get the .Any() and .Any(x => [lambda predicate here]) methods
            var reflectedMethodInfoForLinqAnyThatDoesNotTakeParameters = MakeAnyMethod(typeInCollection, 1);
            var reflectedMethodInfoForLinqAnyThatTakesAPredicate       = MakeAnyMethod(typeInCollection, 2);

            // Create an expression that given a collection of Ids calls contains, and passes the Id accessor from above. Outputs - ids.Contains({parameter of typeInCollection}.Id)
            var containsMethodCall = Expression.Call(null, containsMethod, parameterForEntitledIds, accessorForSingleId);

            // Create a lambda from the above method call that closures in a reference to the type in collection. Outputs - {parameter of typeInCollection} => ids.Contains({parameter of typeInCollection}.Id)
            var containsPredicate = Expression.Lambda(containsMethodCall, parameterForSingleId);

            // Create a placeholder for variations of which where predicate we are going to need based on null behavior.
            Expression wherePredicate;

            switch (whenNull)
            {
            // When we find a null object, the security expression should treat this the same as finding an object the user has permissions to
            case WhenNull.Allow:
            {
                // Build the follow predicate x => !x.CollectionProperty.Any() || x.CollectionProperty.Any(c => ids.Contains(c.Id))
                wherePredicate = BuildAllowWhenNullWherePredicate(pathToRelationship, typeForRootPredicate, reflectedMethodInfoForLinqAnyThatTakesAPredicate, reflectedMethodInfoForLinqAnyThatDoesNotTakeParameters, containsPredicate);
            }
            break;

            // When we find a null object, the security expression should treat this the same as finding an object that the user doesn't have permission to
            case WhenNull.Deny:
            {
                // Build the following predicate x => x.CollectionProperty.Any() && x.CollectionProperty.Any(c => ids.Contains(c.Id))
                wherePredicate = BuildDenyWhenNullWherePredicate(pathToRelationship, typeForRootPredicate, reflectedMethodInfoForLinqAnyThatDoesNotTakeParameters, reflectedMethodInfoForLinqAnyThatTakesAPredicate, containsPredicate);
            }
            break;

            default:
            {
                throw new NotImplementedException("Allow and Deny are the only supported behaviors.  Stop modifying the enum without fixing the expression generator too!!");
            }
            }

            // Return a expression that when compiled will build a where predicate on execution. ids => { predicate that takes ids from above }
            return(Expression.Lambda(Expression.Quote(wherePredicate), parameterForEntitledIds));
        }
Пример #4
0
 public static LambdaExpression BuildPredicateFactoryForCollectionProperty <T, TK, TId>(Expression <Func <T, IEnumerable <TK> > > pathToRelationship, WhenNull whenNull)
     where TK : IIdentifiable <TId>
     where TId : IEquatable <TId>
 {
     return(BuildPredicateFactoryForCollectionProperty(typeof(T), typeof(TK), typeof(TId), pathToRelationship, whenNull));
 }
Пример #5
0
        public static LambdaExpression BuildPredicateFactoryForSingleProperty(Type rootType, Type typeInProperty, Type keyType, LambdaExpression pathToRelationship, WhenNull whenNull)
        {
            // We are building one of the below expression factories
            // ids => return x => x.SingleProperty == null || ids.Contains(x.SingleProperty.Id)
            // ids => return x => ids.Contains(x.SingleProperty.Id)

            // Create the constructed generic type of Func<T, bool> without having access to a generic parameter of T ( the parameter rootType is the result of typeof(T) )
            var typeForRootPredicate = MakeFuncOfTBool(rootType);

            // Create an Expression to turn the parameter into an accessor like {parameter of rootType}.SingleProperty.Id, when combined in a lambda this will become {parameter of rootType} => {parameter of rootType}.SingleProperty.Id
            var accessorForSingleId = Expression.PropertyOrField(pathToRelationship.Body, "Id");

            // Create a parameter that represents the type of list of  Ids that your user is entitled to access, this is IEnumerable<keyType>
            var typeForEntitledIdsParameter = MakeEnumerableOfT(keyType);

            // Create a parameter that represents the of list of  Ids that your user is entitled to access, created from the above type
            var parameterForEntitledIds = MakeIdsParameter(typeForEntitledIdsParameter);

            // Reflect the generic method infromation from the keyType for checking later. This will be IEnumberable<keyType>.Contains({parameter of keyType})
            var containsMethod = MakeContainsMethod(keyType, 2);

            // Create an expression that given a collection of Ids calls contains, and passes the Id accessor from above. Outputs - ids.Contains({parameter of rootType}.Id)
            var containsMethodCall = Expression.Call(null, containsMethod, parameterForEntitledIds, accessorForSingleId);

            // Create a placeholder for variations of which where predicate we are going to need based on null behavior.
            Expression wherePredicate;

            switch (whenNull)
            {
            // When we find a null object, the security expression should treat this the same as finding an object the user has permissions to
            case WhenNull.Allow:
            {
                // Create a check for property = null and add it in an or to the lambda
                var nullCheckOnProp = Expression.Equal(pathToRelationship.Body, Expression.Constant(null, typeInProperty));
                // Create the lambda ( x => x.SingleProperty == null || ids.Contains(x.SingleProperty.Id) )
                wherePredicate = Expression.Lambda(typeForRootPredicate, Expression.OrElse(nullCheckOnProp, containsMethodCall), pathToRelationship.Parameters);
            }
            break;

            // When we find a null object, the security expression should treat this the same as finding an object that the user doesn't have permission to
            case WhenNull.Deny:
            {
                // Create the lambda ( x => ids.Contains(x.SingleProperty.Id) )
                wherePredicate = Expression.Lambda(typeForRootPredicate, containsMethodCall, pathToRelationship.Parameters);
            }
            break;

            default:
            {
                throw new NotImplementedException("Allow and Deny are the only supported behaviors, stop modifying the enum without fixing the expression generator too!!");
            }
            }
            // Return a expression that when compiled will build a where predicate on execution. ids => { predicate that takes ids from above }
            return(Expression.Lambda(Expression.Quote(wherePredicate), parameterForEntitledIds));
        }