Пример #1
0
        public Field GetField(string identifier, ClaimsIdentity claims = null)
        {
            if (_fieldsByName.ContainsKey(identifier))
            {
                var field = _fieldsByName[identifier];
                if (!AuthUtil.IsAuthorized(claims, field.AuthorizeClaims))
                {
                    throw new EntityGraphQLAccessException($"You do not have access to field '{identifier}' on type '{Name}'. You require any of the following security claims [{string.Join(", ", field.AuthorizeClaims.Claims.SelectMany(r => r))}]");
                }
                return(_fieldsByName[identifier]);
            }

            throw new EntityGraphQLCompilerException($"Field {identifier} not found");
        }
Пример #2
0
 public IMethodType GetFieldOnContext(Expression context, string fieldName, ClaimsIdentity claims)
 {
     if (context.Type == ContextType && mutations.ContainsKey(fieldName))
     {
         var mutation = mutations[fieldName];
         if (!AuthUtil.IsAuthorized(claims, mutation.AuthorizeClaims))
         {
             throw new EntityGraphQLAccessException($"You do not have access to mutation '{fieldName}'. You require any of the following security claims [{string.Join(", ", mutation.AuthorizeClaims.Claims.SelectMany(r => r))}]");
         }
         return(mutation);
     }
     if (types.ContainsKey(GetSchemaTypeNameForClrType(context.Type)))
     {
         var field = types[GetSchemaTypeNameForClrType(context.Type)].GetField(fieldName, claims);
         return(field);
     }
     throw new EntityGraphQLCompilerException($"No field or mutation '{fieldName}' found in schema.");
 }
Пример #3
0
        public ExpressionResult GetExpressionForField(Expression context, string typeName, string fieldName, Dictionary <string, ExpressionResult> args, ClaimsIdentity claims)
        {
            if (!types.ContainsKey(typeName))
            {
                throw new EntityQuerySchemaException($"{typeName} not found in schema.");
            }

            ISchemaType schemaType = types[typeName];

            if (!AuthUtil.IsAuthorized(claims, schemaType.AuthorizeClaims))
            {
                throw new EntityGraphQLAccessException($"You do not have access to the '{typeName}' type. You require any of the following security claims [{string.Join(", ", schemaType.AuthorizeClaims.Claims.SelectMany(r => r))}]");
            }

            var field = schemaType.GetField(fieldName, claims);

            if (!AuthUtil.IsAuthorized(claims, field.ReturnType.SchemaType.AuthorizeClaims))
            {
                throw new EntityGraphQLAccessException($"You do not have access to the '{field.ReturnType.SchemaType.Name}' type. You require any of the following security claims [{string.Join(", ", field.ReturnType.SchemaType.AuthorizeClaims.Claims.SelectMany(r => r))}]");
            }

            var result = new ExpressionResult(field.Resolve ?? Expression.Property(context, fieldName), field.Services);

            if (field.ArgumentTypesObject != null)
            {
                var argType = field.ArgumentTypesObject.GetType();
                // get the values for the argument anonymous type object constructor
                var propVals  = new Dictionary <PropertyInfo, object>();
                var fieldVals = new Dictionary <FieldInfo, object>();
                // if they used AddField("field", new { id = Required<int>() }) the compiler makes properties and a constructor with the values passed in
                foreach (var argField in argType.GetProperties())
                {
                    var val = BuildArgumentFromMember(args, field, argField.Name, argField.PropertyType, argField.GetValue(field.ArgumentTypesObject));
                    // if this was a EntityQueryType we actually get a Func from BuildArgumentFromMember but the anonymous type requires EntityQueryType<>. We marry them here, this allows users to EntityQueryType<> as a Func in LINQ methods while not having it defined until runtime
                    if (argField.PropertyType.IsConstructedGenericType && argField.PropertyType.GetGenericTypeDefinition() == typeof(EntityQueryType <>))
                    {
                        // make sure we create a new instance and not update the schema
                        var entityQuery = Activator.CreateInstance(argField.PropertyType);

                        // set Query
                        var hasValue = val != null;
                        if (hasValue)
                        {
                            var genericProp = entityQuery.GetType().GetProperty("Query");
                            genericProp.SetValue(entityQuery, ((ExpressionResult)val).Expression);
                        }

                        propVals.Add(argField, entityQuery);
                    }
                    else
                    {
                        if (val != null && val.GetType() != argField.PropertyType)
                        {
                            val = ExpressionUtil.ChangeType(val, argField.PropertyType);
                        }
                        propVals.Add(argField, val);
                    }
                }
                // The auto argument is built at runtime from LinqRuntimeTypeBuilder which just makes public fields
                // they could also use a custom class, so we need to look for both fields and properties
                foreach (var argField in argType.GetFields())
                {
                    var val = BuildArgumentFromMember(args, field, argField.Name, argField.FieldType, argField.GetValue(field.ArgumentTypesObject));
                    fieldVals.Add(argField, val);
                }

                // create a copy of the anonymous object. It will have the default values set
                // there is only 1 constructor for the anonymous type that takes all the property values
                var    con = argType.GetConstructor(propVals.Keys.Select(v => v.PropertyType).ToArray());
                object parameters;
                if (con != null)
                {
                    parameters = con.Invoke(propVals.Values.ToArray());
                    foreach (var item in fieldVals)
                    {
                        item.Key.SetValue(parameters, item.Value);
                    }
                }
                else
                {
                    // expect an empty constructor
                    con        = argType.GetConstructor(new Type[0]);
                    parameters = con.Invoke(new object[0]);
                    foreach (var item in fieldVals)
                    {
                        item.Key.SetValue(parameters, item.Value);
                    }
                    foreach (var item in propVals)
                    {
                        item.Key.SetValue(parameters, item.Value);
                    }
                }
                // tell them this expression has another parameter
                var argParam = Expression.Parameter(argType, $"arg_{argType.Name}");
                result.Expression = new ParameterReplacer().ReplaceByType(result.Expression, argType, argParam);
                result.AddConstantParameter(argParam, parameters);
            }

            // the expressions we collect have a different starting parameter. We need to change that
            var paramExp = field.FieldParam;

            result.Expression = new ParameterReplacer().Replace(result.Expression, paramExp, context);

            return(result);
        }