示例#1
0
        public override (Expression Expression, ExpressionConversionResult ExpressionConversionResult) Convert(Esprima.Ast.CallExpression methodCallExpression, ExpressionConverterContext context, ExpressionConverterScope scope, bool allowTerminal, params Type[] genericArguments)
        {
            var memberExpression = methodCallExpression.Callee as Esprima.Ast.MemberExpression;

            Esprima.Ast.Identifier methodIdentifier = null;
            if (memberExpression != null)
            {
                methodIdentifier = (Esprima.Ast.Identifier)memberExpression.Property;
            }
            else
            {
                methodIdentifier = (Esprima.Ast.Identifier)methodCallExpression.Callee;
            }
            var        arguments              = methodCallExpression.Arguments.Cast <Esprima.Ast.INode>().ToArray();
            MethodInfo methodInfo             = null;
            Expression instanceExpression     = null;
            Expression instanceExpressionDump = null;

            Expression[] argumentsExpressions = null;
            ExpressionConversionResult expressionConversionResult = null;

            if (memberExpression == null)
            {
                //method is static
                (methodInfo, argumentsExpressions, expressionConversionResult) = FindMethodInfo(context.StaticMethods.FindMethodInfos(methodIdentifier.Name, arguments.Count()).ToArray(), arguments, context, scope);
            }
            else
            {
                //method is not static
                instanceExpression = instanceExpressionDump = context.ExpressionConverterResolver.Convert(memberExpression.Object, context, scope, true);
                var instanceType          = instanceExpression.Type;
                var methodInfosCandidates = instanceType.GetMethods().FindMethodInfos(methodIdentifier.Name, arguments.Length);
                (methodInfo, argumentsExpressions, expressionConversionResult) = FindMethodInfo(methodInfosCandidates, arguments, context, scope, instanceExpression);

                if (methodInfo == null)
                {
                    //try extension methods
                    methodInfosCandidates = context.ExtensionMethods.FindMethodInfos(methodIdentifier.Name, arguments.Length + 1);
                    (methodInfo, argumentsExpressions, expressionConversionResult) = FindMethodInfo(methodInfosCandidates, arguments, context, scope, instanceExpression, true);
                    if (methodInfo != null)
                    {
                        argumentsExpressions = new Expression[] { instanceExpression }.Concat(argumentsExpressions).ToArray();
                        instanceExpression   = null;
                    }
                }
            }
            if (methodInfo == null)
            {
                //Fallback on custom converters
                var customConverter = context.CustomMethodCallExpressionConverters.FirstOrDefault(converter => converter.CanHandle(methodCallExpression, context, scope, allowTerminal, genericArguments));
                if (customConverter != null)
                {
                    return(customConverter.Convert(methodCallExpression, context, scope, allowTerminal, genericArguments));
                }
                throw new NotImplementedException($"Method {methodIdentifier.Name} on type {instanceExpressionDump.Type} not found.");
            }
            var callExpressiom = Expression.Call(instanceExpression, methodInfo, argumentsExpressions);

            return(callExpressiom, expressionConversionResult);
        }
示例#2
0
        public override (System.Linq.Expressions.Expression, ExpressionConversionResult) Convert(Esprima.Ast.MemberExpression memberExpression, ExpressionConverterContext context, ExpressionConverterScope scope, bool allowTerminal, params Type[] genericArguments)
        {
            var objectExpression   = context.ExpressionConverterResolver.Convert(memberExpression.Object, context, scope, true);
            var propertyIdentifier = memberExpression.Property.As <Identifier>();
            var propertyInfo       = objectExpression.Type.GetProperty(propertyIdentifier.Name) ?? objectExpression.Type.GetProperty(propertyIdentifier.Name.ToPascalCase());

            if (propertyInfo == null)
            {
                throw new Exception($"Unable to find property ${propertyIdentifier.Name} on type ${objectExpression.Type.Name}");
            }
            if (!context.IsAdmin)
            {
                var ruleMap = context.RuleMapRegistry.GetRuleMap(objectExpression.Type, context.securityContext);
                if (ruleMap == null)
                {
                    throw new UnauthorizedAccessException($"You do not have access to type { objectExpression.Type }.");
                }
                var typePermission = (bool?)ruleMap.ResolveTypeCustom(Permission.Read, context.securityContext);
                var hasInstancePermissionResolverExpression = ruleMap.HasAnyInstancePermissionResolverExpression;
                var propertyPermission = (bool?)ruleMap.ResolvePropertyCustom(Permission.Read, propertyInfo, context.securityContext);
                var shouldFilter       = ruleMap.ShouldFilterForProperty(propertyInfo, context.securityContext);
                var hasInstancePropertyPermissionResolverExpression = ruleMap.HasAnyInstancePropertyPermissionResolverExpression(propertyInfo, Permission.Read);

                var result = new ExpressionConversionResult()
                {
                    ShouldApplyFilter     = shouldFilter,
                    ShouldApplyProjection = true
                };

                //var hasAccess = typePermission == null && (hasInstancePermissionResolverExpression || (propertyPermission.HasValue && propertyPermission.Value) || hasInstancePropertyPermissionResolverExpression);
                //hasAccess = hasAccess || (typePermission.Value && !(propertyPermission.HasValue && !propertyPermission.Value));
                //hasAccess = hasAccess || (!typePermission.Value && (hasInstancePermissionResolverExpression || (propertyPermission.HasValue && propertyPermission.Value) || hasInstancePropertyPermissionResolverExpression));
                //hasAccess = hasAccess || (!hasInstancePermissionResolverExpression && ((propertyPermission.HasValue && propertyPermission.Value) || hasInstancePropertyPermissionResolverExpression));
                //hasAccess = hasAccess || (hasInstancePermissionResolverExpression && !(propertyPermission.HasValue && !propertyPermission.Value));
                //hasAccess = hasAccess || (!propertyPermission.HasValue && hasInstancePropertyPermissionResolverExpression);

                var hasAccess = ruleMap.PropertiesDefaultPermission == Permission.Read;


                var propertyAccessExpression = (System.Linq.Expressions.Expression)System.Linq.Expressions.Expression.MakeMemberAccess(objectExpression, propertyInfo);
                if (hasInstancePropertyPermissionResolverExpression)
                {
                    var instancePropertyPermissionExpression = ruleMap.ResolveInstancePropertyCustomResolverExpression(propertyInfo, Permission.Read, context.securityContext, objectExpression);
                    var predicateExpression = instancePropertyPermissionExpression;
                    if (predicateExpression != null && predicateExpression.Type != typeof(bool))
                    {
                        predicateExpression = System.Linq.Expressions.Expression.Convert(predicateExpression, typeof(bool));
                    }
                    propertyAccessExpression = System.Linq.Expressions.Expression.Condition(predicateExpression, propertyAccessExpression, System.Linq.Expressions.Expression.Default(propertyInfo.PropertyType));
                }

                if (!context.IsAdmin && !hasAccess)
                {
                    throw new UnauthorizedAccessException($"You do not have access to property {propertyInfo.Name} on type { objectExpression.Type }.");
                }
                return(propertyAccessExpression, result);
            }
            return((System.Linq.Expressions.Expression)System.Linq.Expressions.Expression.MakeMemberAccess(objectExpression, propertyInfo), DefaultResult);
        }
示例#3
0
        protected (MethodInfo MethodInfo, Expression[] Arguments, ExpressionConversionResult ExpressionConversionResult) FindMethodInfo(MethodInfo[] methodInfosCandidates, Esprima.Ast.INode[] arguments, ExpressionConverterContext context, ExpressionConverterScope scope, Expression instanceExpression = null, bool isExtension = false)
        {
            MethodInfo methodInfo = null;

            Expression[] argumentsExpressions = null;
            ExpressionConversionResult expressionConversionResult = new ExpressionConversionResult();
            Permission?permission = Permission.None;
            var        methodInfoCandidateIndex = 0;

            while (methodInfo == null && methodInfoCandidateIndex < methodInfosCandidates.Length)
            {
                var methodInfoCandidate         = methodInfosCandidates[methodInfoCandidateIndex];
                var methodParameters            = methodInfoCandidate.GetParameters();
                var argumentParameterMap        = methodParameters.Skip(isExtension ? 1 : 0).Zip(arguments, (parameterInfo, argument) => (parameterInfo, argument: (Esprima.Ast.INode)argument)).ToArray();
                var parameterArgumentTupleIndex = 0;
                var isValid = true;
                var methodInfoCandidateArgumentsExpressions = new List <Expression>();
                if (isExtension)
                {
                    var instanceParameter = methodParameters.First();
                    isValid = instanceParameter.ParameterType.IsGenericType ? instanceParameter.ParameterType.GenericAssignableFrom(instanceExpression.Type, scope.GenericTypeResolutionMap) : instanceParameter.ParameterType.IsAssignableFrom(instanceExpression.Type);
                }
                while (isValid && parameterArgumentTupleIndex < argumentParameterMap.Length)
                {
                    var tuple     = argumentParameterMap[parameterArgumentTupleIndex];
                    var converter = context.ExpressionConverterResolver.FindExpressionConverter(tuple.argument);
                    if (converter.IsGenericType)
                    {
                        var argumentGenericType = converter.GetGenericType(tuple.argument, tuple.parameterInfo.ParameterType);
                        if ((isValid = AreGenericDefinitionEqual(tuple.parameterInfo.ParameterType, argumentGenericType)))
                        {
                            var nodes                  = converter.GetRequiredGenericArgumentIndices(tuple.argument, tuple.parameterInfo.ParameterType);
                            var parameterType          = tuple.parameterInfo.ParameterType;
                            var inputGenericArguments  = new List <(IEnumerable <int> path, Type Type)>();
                            var outputGenericArguments = new List <(IEnumerable <int> path, Type Type)>();
                            foreach (var node in nodes)
                            {
                                var stack = new Stack <(TypeNode, Type)>();
                                stack.Push((node, parameterType));
                                while (stack.Any())
                                {
                                    var currentNode          = stack.Pop();
                                    var nodeGenericArguments = currentNode.Item2.GetGenericArguments();
                                    if (currentNode.Item1.Children.Any())
                                    {
                                        foreach (var child in currentNode.Item1.Children)
                                        {
                                            stack.Push((child, nodeGenericArguments[currentNode.Item1.Index]));