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); }
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); }
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]));