private static Field ProcessFieldOrProperty(MemberInfo prop, Type fieldOrPropType, ParameterExpression param, ISchemaProvider schema, bool createEnumTypes, bool createNewComplexTypes) { if (ignoreProps.Contains(prop.Name) || GraphQLIgnoreAttribute.ShouldIgnoreMemberFromQuery(prop)) { return(null); } // Get Description from ComponentModel.DescriptionAttribute string description = ""; var d = (DescriptionAttribute)prop.GetCustomAttribute(typeof(DescriptionAttribute), false); if (d != null) { description = d.Description; } LambdaExpression le = Expression.Lambda(prop.MemberType == MemberTypes.Property ? Expression.Property(param, prop.Name) : Expression.Field(param, prop.Name), param); var attributes = prop.GetCustomAttributes(typeof(GraphQLAuthorizeAttribute), true).Cast <GraphQLAuthorizeAttribute>(); var requiredClaims = new RequiredClaims(attributes); var returnType = le.ReturnType.IsEnumerableOrArray() ? le.ReturnType.GetEnumerableOrArrayType() : le.ReturnType; var t = CacheType(returnType, schema, createEnumTypes, createNewComplexTypes); var f = new Field(SchemaGenerator.ToCamelCaseStartsLower(prop.Name), le, description, null, null, requiredClaims); if (t != null && t.IsEnum && !f.ReturnTypeClr.IsNullableType()) { f.ReturnTypeNotNullable = true; } return(f); }
/// <summary> /// Add any methods marked with GraphQLMutationAttribute in the given type to the schema. Names are added as lowerCaseCamel` /// </summary> /// <param name="mutationClassInstance"></param> /// <typeparam name="TType"></typeparam> public void AddMutationFrom <TType>(TType mutationClassInstance) { foreach (var method in mutationClassInstance.GetType().GetMethods()) { if (method.GetCustomAttribute(typeof(GraphQLMutationAttribute)) is GraphQLMutationAttribute attribute) { var isAsync = method.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null; string name = SchemaGenerator.ToCamelCaseStartsLower(method.Name); //== JT: Allow user to customize the schema-first casing. var n = (System.ComponentModel.DisplayNameAttribute)method.GetCustomAttribute(typeof(System.ComponentModel.DisplayNameAttribute), false); if (n != null) { name = n.DisplayName; } //== var claims = method.GetCustomAttributes(typeof(GraphQLAuthorizeAttribute)).Cast <GraphQLAuthorizeAttribute>(); var requiredClaims = new RequiredClaims(claims); var actualReturnType = GetTypeFromMutationReturn(isAsync ? method.ReturnType.GetGenericArguments()[0] : method.ReturnType); var typeName = GetSchemaTypeNameForDotnetType(actualReturnType); var returnType = new GqlTypeInfo(() => GetReturnType(typeName), actualReturnType); var mutationType = new MutationType(this, name, returnType, mutationClassInstance, method, attribute.Description, requiredClaims, isAsync, SchemaFieldNamer); mutations[name] = mutationType; } } }
internal Field(string name, LambdaExpression resolve, string description, string returnSchemaType, Type returnClrType, RequiredClaims authorizeClaims) { Name = name; Description = description; returnTypeSingle = returnSchemaType; ReturnTypeClr = returnClrType; AuthorizeClaims = authorizeClaims; if (resolve != null) { if (resolve.Body.NodeType == ExpressionType.Call && ((MethodCallExpression)resolve.Body).Method.DeclaringType == typeof(ArgumentHelper) && ((MethodCallExpression)resolve.Body).Method.Name == "WithService") { // they are wanting services injected var call = (MethodCallExpression)resolve.Body; var lambdaExpression = (LambdaExpression)((UnaryExpression)call.Arguments.First()).Operand; Resolve = lambdaExpression.Body; Services = lambdaExpression.Parameters.Select(p => p.Type).ToList(); } else { Resolve = resolve.Body; } FieldParam = resolve.Parameters.First(); ReturnTypeClr = Resolve.Type; if (resolve.Body.NodeType == ExpressionType.MemberAccess) { ReturnTypeNotNullable = GraphQLNotNullAttribute.IsMemberMarkedNotNull(((MemberExpression)resolve.Body).Member); ReturnElementTypeNullable = GraphQLElementTypeNullable.IsMemberElementMarkedNullable(((MemberExpression)resolve.Body).Member); } } }
private static Field ProcessFieldOrProperty(MemberInfo prop, ParameterExpression param, ISchemaProvider schema, bool createEnumTypes, bool createNewComplexTypes, Func <MemberInfo, string> fieldNamer) { if (ignoreProps.Contains(prop.Name) || GraphQLIgnoreAttribute.ShouldIgnoreMemberFromQuery(prop)) { return(null); } // Get Description from ComponentModel.DescriptionAttribute string description = ""; var d = (DescriptionAttribute)prop.GetCustomAttribute(typeof(DescriptionAttribute), false); if (d != null) { description = d.Description; } LambdaExpression le = Expression.Lambda(prop.MemberType == MemberTypes.Property ? Expression.Property(param, prop.Name) : Expression.Field(param, prop.Name), param); var attributes = prop.GetCustomAttributes(typeof(GraphQLAuthorizeAttribute), true).Cast <GraphQLAuthorizeAttribute>(); var requiredClaims = new RequiredClaims(attributes); // get the object type returned (ignoring list etc) so we know the context to find fields etc var returnType = le.ReturnType.IsEnumerableOrArray() ? le.ReturnType.GetEnumerableOrArrayType() : le.ReturnType.GetNonNullableType(); var t = CacheType(returnType, schema, createEnumTypes, createNewComplexTypes, fieldNamer); // see if there is a direct type mapping from the expression return to to something. // otherwise build the type info var returnTypeInfo = schema.GetCustomTypeMapping(le.ReturnType) ?? new GqlTypeInfo(() => schema.Type(returnType), le.Body.Type); var f = new Field(fieldNamer(prop), le, description, returnTypeInfo, requiredClaims); return(f); }
public MutationType(ISchemaProvider schema, string methodName, GqlTypeInfo returnType, object mutationClassInstance, MethodInfo method, string description, RequiredClaims authorizeClaims, bool isAsync) { Description = description; ReturnType = returnType; this.mutationClassInstance = mutationClassInstance; this.method = method; Name = methodName; AuthorizeClaims = authorizeClaims; this.isAsync = isAsync; argInstanceType = method.GetParameters() .FirstOrDefault(p => p.GetCustomAttribute(typeof(MutationArgumentsAttribute)) != null || p.ParameterType.GetTypeInfo().GetCustomAttribute(typeof(MutationArgumentsAttribute)) != null)?.ParameterType; if (argInstanceType != null) { foreach (var item in argInstanceType.GetProperties()) { if (GraphQLIgnoreAttribute.ShouldIgnoreMemberFromInput(item)) { continue; } argumentTypes.Add(SchemaGenerator.ToCamelCaseStartsLower(item.Name), ArgType.FromProperty(schema, item)); } foreach (var item in argInstanceType.GetFields()) { if (GraphQLIgnoreAttribute.ShouldIgnoreMemberFromInput(item)) { continue; } argumentTypes.Add(SchemaGenerator.ToCamelCaseStartsLower(item.Name), ArgType.FromField(schema, item)); } } }
public MutationType(ISchemaProvider schema, string methodName, GqlTypeInfo returnType, object mutationClassInstance, MethodInfo method, string description, RequiredClaims authorizeClaims, bool isAsync, Func <MemberInfo, string> fieldNamer) { Description = description; ReturnType = returnType; this.mutationClassInstance = mutationClassInstance; this.method = method; Name = methodName; AuthorizeClaims = authorizeClaims; this.isAsync = isAsync; argInstanceType = method.GetParameters() .FirstOrDefault(p => p.GetCustomAttribute(typeof(MutationArgumentsAttribute)) != null || p.ParameterType.GetTypeInfo().GetCustomAttribute(typeof(MutationArgumentsAttribute)) != null)?.ParameterType; if (argInstanceType != null) { foreach (var item in argInstanceType.GetProperties()) { if (GraphQLIgnoreAttribute.ShouldIgnoreMemberFromInput(item)) { continue; } argumentTypes.Add(fieldNamer(item), ArgType.FromProperty(schema, item)); } foreach (var item in argInstanceType.GetFields()) { if (GraphQLIgnoreAttribute.ShouldIgnoreMemberFromInput(item)) { continue; } argumentTypes.Add(fieldNamer(item), ArgType.FromField(schema, item)); } } //== JT: Start Here else { /*== JT * When parameters are the standard System Types like; Int, String, etc or using the EntityGraphQL.Schema.RequiredField, * loop through the parameters and NOT the object's properties * NOTE: some parameters might be Services * EX: public ReturnModel RemoveById(DataContext context, RequiredField<int> id) */ // !! Forcing a single parameter ONLY. Anything more than that should require a POCO !! ParameterInfo item = method.GetParameters() .FirstOrDefault(p => p.ParameterType.Namespace.StartsWith("EntityGraphQL.Schema") || p.ParameterType.Namespace.StartsWith("System")); if (item.ParameterType.Name == "Nullable`1") { Type argType = item.ParameterType.GetGenericArguments()[0]; argInstanceType = argType; } else { argInstanceType = item.ParameterType; } //TODO: see if able to use the "fieldNamer()" function argumentTypes.Add(SchemaGenerator.ToCamelCaseStartsLower(item.Name), ArgType.FromParameter(schema, item)); } //== }
/// <summary> /// To access this type any of the claims listed is required /// </summary> /// <param name="claims"></param> /// <returns></returns> public SchemaType <TBaseType> RequiresAnyClaim(params string[] claims) { if (AuthorizeClaims == null) { AuthorizeClaims = new RequiredClaims(); } AuthorizeClaims.RequiresAnyClaim(claims); return(this); }
/// <summary> /// To access this field any claims listed is required /// </summary> /// <param name="claims"></param> /// <returns></returns> public Field RequiresAnyClaim(params string[] claims) { if (AuthorizeClaims == null) { AuthorizeClaims = new RequiredClaims(); } AuthorizeClaims.RequiresAnyClaim(claims); return(this); }
/// <summary> /// Check if this field required certain security claims and if so check against the ClaimsIdentity /// </summary> /// <param name="claims"></param> /// <returns></returns> public static bool IsAuthorized(ClaimsIdentity claims, RequiredClaims authorizeClaims) { // if the list is empty it means claims.IsAuthenticated needs to be true, if full it requires certain claims if (authorizeClaims != null && claims != null) { if (claims.IsAuthenticated && (!authorizeClaims.Any() || authorizeClaims.HasRequired(claims))) { return(true); } return(false); } return(true); }
/// <summary> /// Add any methods marked with GraphQLMutationAttribute in the given type to the schema. Names are added as lowerCaseCamel` /// </summary> /// <param name="mutationClassInstance"></param> /// <typeparam name="TType"></typeparam> public void AddMutationFrom <TType>(TType mutationClassInstance) { foreach (var method in mutationClassInstance.GetType().GetMethods()) { if (method.GetCustomAttribute(typeof(GraphQLMutationAttribute)) is GraphQLMutationAttribute attribute) { string name = SchemaGenerator.ToCamelCaseStartsLower(method.Name); var claims = method.GetCustomAttributes(typeof(GraphQLAuthorizeAttribute)).Cast <GraphQLAuthorizeAttribute>(); var requiredClaims = new RequiredClaims(claims); var mutationType = new MutationType(name, types[GetSchemaTypeNameForClrType(method.ReturnType)], mutationClassInstance, method, attribute.Description, requiredClaims); mutations[name] = mutationType; } } }
/// <summary> /// Replaces a field by Name and Argument Names (that is the key) /// </summary> /// <param name="name"></param> /// <param name="argTypes"></param> /// <param name="selectionExpression"></param> /// <param name="description"></param> /// <param name="returnSchemaType"></param> /// <typeparam name="TParams"></typeparam> /// <typeparam name="TReturn"></typeparam> /// <returns></returns> public void ReplaceField <TParams, TReturn>(string name, TParams argTypes, Expression <Func <TBaseType, TParams, TReturn> > selectionExpression, string description, string returnSchemaType = null) { RequiredClaims authorizeClaims = null; if (selectionExpression.Body.NodeType == ExpressionType.MemberAccess) { var attributes = ((MemberExpression)selectionExpression.Body).Member.GetCustomAttributes(typeof(GraphQLAuthorizeAttribute), true).Cast <GraphQLAuthorizeAttribute>(); authorizeClaims = new RequiredClaims(attributes); } var field = new Field(schema, name, selectionExpression, description, argTypes, new GqlTypeInfo(!string.IsNullOrEmpty(returnSchemaType) ? (Func <ISchemaType>)(() => schema.Type(returnSchemaType)) : () => schema.Type(typeof(TReturn).GetNonNullableOrEnumerableType()), typeof(TReturn)), authorizeClaims); _fieldsByName[field.Name] = field; }
internal SchemaType(ISchemaProvider schema, Type contextType, string name, string description, RequiredClaims authorizeClaims, bool isInput = false, bool isEnum = false, bool isScalar = false) { this.schema = schema; ContextType = contextType; Name = name; Description = description; IsInput = isInput; IsEnum = isEnum; IsScalar = isScalar; AuthorizeClaims = authorizeClaims; if (!isScalar) { AddField("__typename", t => name, "Type name", null).IsNullable(false); } }
public Field AddField <TService, TReturn>(string name, Expression <Func <TBaseType, TService, TReturn> > fieldSelection, string description, string returnSchemaType = null) { RequiredClaims authorizeClaims = null; if (fieldSelection.Body.NodeType == ExpressionType.MemberAccess) { var attributes = ((MemberExpression)fieldSelection.Body).Member.GetCustomAttributes(typeof(GraphQLAuthorizeAttribute), true).Cast <GraphQLAuthorizeAttribute>(); authorizeClaims = new RequiredClaims(attributes); } var field = new Field(schema, name, fieldSelection, description, null, new GqlTypeInfo(!string.IsNullOrEmpty(returnSchemaType) ? (Func <ISchemaType>)(() => schema.Type(returnSchemaType)) : () => schema.Type(typeof(TReturn).GetNonNullableOrEnumerableType()), typeof(TReturn)), authorizeClaims); this.AddField(field); return(field); }
/// <summary> /// Add any methods marked with GraphQLMutationAttribute in the given type to the schema. Names are added as lowerCaseCamel` /// </summary> /// <param name="mutationClassInstance"></param> /// <typeparam name="TType"></typeparam> public void AddMutationFrom <TType>(TType mutationClassInstance) { foreach (var method in mutationClassInstance.GetType().GetMethods()) { if (method.GetCustomAttribute(typeof(GraphQLMutationAttribute)) is GraphQLMutationAttribute attribute) { var isAsync = method.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null; string name = SchemaFieldNamer(method.Name); var claims = method.GetCustomAttributes(typeof(GraphQLAuthorizeAttribute)).Cast <GraphQLAuthorizeAttribute>(); var requiredClaims = new RequiredClaims(claims); var actualReturnType = GetTypeFromMutationReturn(isAsync ? method.ReturnType.GetGenericArguments()[0] : method.ReturnType); var typeName = GetSchemaTypeNameForDotnetType(actualReturnType); var returnType = new GqlTypeInfo(() => GetReturnType(typeName), actualReturnType); var mutationType = new MutationType(this, name, returnType, mutationClassInstance, method, attribute.Description, requiredClaims, isAsync, SchemaFieldNamer); mutations[name] = mutationType; } } }
internal Field(string name, LambdaExpression resolve, string description, string returnSchemaType, Type returnClrType, RequiredClaims authorizeClaims) { Name = name; Description = description; returnTypeSingle = returnSchemaType; ReturnTypeClr = returnClrType; AuthorizeClaims = authorizeClaims; if (resolve != null) { Resolve = resolve.Body; FieldParam = resolve.Parameters.First(); ReturnTypeClr = Resolve.Type; if (resolve.Body.NodeType == ExpressionType.MemberAccess) { ReturnTypeNotNullable = GraphQLNotNullAttribute.IsMemberMarkedNotNull(((MemberExpression)resolve.Body).Member); ReturnElementTypeNullable = GraphQLElementTypeNullable.IsMemberElementMarkedNullable(((MemberExpression)resolve.Body).Member); } } }
public MutationType(string methodName, ISchemaType returnType, object mutationClassInstance, MethodInfo method, string description, RequiredClaims authorizeClaims) { this.Description = description; this.ReturnType = returnType; this.mutationClassInstance = mutationClassInstance; this.method = method; Name = methodName; AuthorizeClaims = authorizeClaims; var methodArg = method.GetParameters().ElementAt(1); this.argInstanceType = methodArg.ParameterType; foreach (var item in argInstanceType.GetProperties()) { if (GraphQLIgnoreAttribute.ShouldIgnoreMemberFromInput(item)) { continue; } argumentTypes.Add(SchemaGenerator.ToCamelCaseStartsLower(item.Name), new ArgType { Type = item.PropertyType, TypeNotNullable = GraphQLNotNullAttribute.IsMemberMarkedNotNull(item) || item.PropertyType.GetTypeInfo().IsEnum }); } foreach (var item in argInstanceType.GetFields()) { if (GraphQLIgnoreAttribute.ShouldIgnoreMemberFromInput(item)) { continue; } argumentTypes.Add(SchemaGenerator.ToCamelCaseStartsLower(item.Name), new ArgType { Type = item.FieldType, TypeNotNullable = GraphQLNotNullAttribute.IsMemberMarkedNotNull(item) || item.FieldType.GetTypeInfo().IsEnum }); } }
/// <summary> /// Replaces a field by Name and Argument Names (that is the key) /// </summary> /// <param name="name"></param> /// <param name="argTypes"></param> /// <param name="selectionExpression"></param> /// <param name="description"></param> /// <param name="returnSchemaType"></param> /// <typeparam name="TParams"></typeparam> /// <typeparam name="TReturn"></typeparam> /// <returns></returns> public void ReplaceField <TParams, TReturn>(string name, TParams argTypes, Expression <Func <TBaseType, TParams, TReturn> > selectionExpression, string description, string returnSchemaType = null, RequiredClaims authorizeClaims = null) { var field = new Field(schema, name, selectionExpression, description, argTypes, new GqlTypeInfo(!string.IsNullOrEmpty(returnSchemaType) ? (Func <ISchemaType>)(() => schema.Type(returnSchemaType)) : () => schema.Type(typeof(TReturn).GetNonNullableOrEnumerableType()), typeof(TReturn)), authorizeClaims); _fieldsByName[field.Name] = field; }
internal SchemaType(ISchemaProvider schema, string name, string description, RequiredClaims authorizeClaims, bool isInput = false, bool isEnum = false, bool isScalar = false) : this(schema, typeof(TBaseType), name, description, authorizeClaims, isInput, isEnum, isScalar) { }
public Field(ISchemaProvider schema, string name, LambdaExpression resolve, string description, object argTypes, GqlTypeInfo returnType, RequiredClaims claims) : this(name, resolve, description, returnType, claims) { ArgumentTypesObject = argTypes; allArguments = argTypes.GetType().GetProperties().ToDictionary(p => p.Name, p => ArgType.FromProperty(schema, p)); argTypes.GetType().GetFields().ToDictionary(p => p.Name, p => ArgType.FromField(schema, p)).ToList().ForEach(kvp => allArguments.Add(kvp.Key, kvp.Value)); }
/// <summary> /// Replaces a field by Name and Argument Names (that is the key) /// </summary> /// <param name="name"></param> /// <param name="argTypes"></param> /// <param name="selectionExpression"></param> /// <param name="description"></param> /// <param name="returnSchemaType"></param> /// <typeparam name="TParams"></typeparam> /// <typeparam name="TReturn"></typeparam> /// <returns></returns> public void ReplaceField <TParams, TReturn>(string name, TParams argTypes, Expression <Func <TBaseType, TParams, TReturn> > selectionExpression, string description, string returnSchemaType = null, RequiredClaims authorizeClaims = null) { var field = new Field(name, selectionExpression, description, returnSchemaType, argTypes, authorizeClaims); _fieldsByName[field.Name] = field; }
public Field ReplaceField <TReturn>(string name, Expression <Func <TBaseType, TReturn> > selectionExpression, string description, string returnSchemaType = null, bool?isNullable = null, RequiredClaims authorizeClaims = null) { var field = new Field(name, selectionExpression, description, returnSchemaType, null, authorizeClaims); if (isNullable.HasValue) { field.ReturnTypeNotNullable = !isNullable.Value; } _fieldsByName[field.Name] = field; return(field); }
public Field ReplaceField <TReturn>(string name, Expression <Func <TBaseType, TReturn> > selectionExpression, string description, string returnSchemaType = null, bool?isNullable = null, RequiredClaims authorizeClaims = null) { var field = new Field(name, selectionExpression, description, new GqlTypeInfo(!string.IsNullOrEmpty(returnSchemaType) ? (Func <ISchemaType>)(() => schema.Type(returnSchemaType)) : () => schema.Type(typeof(TReturn).GetNonNullableOrEnumerableType()), typeof(TReturn)), authorizeClaims); if (isNullable.HasValue) { field.ReturnType.TypeNotNullable = !isNullable.Value; } _fieldsByName[field.Name] = field; return(field); }
/// <summary> /// Add a field from a type expression. The name to converted to lowerCamelCase /// </summary> /// <param name="fieldSelection"></param> /// <param name="description"></param> /// <param name="returnSchemaType"></param> /// <typeparam name="TReturn"></typeparam> public Field AddField <TReturn>(Expression <Func <TBaseType, TReturn> > fieldSelection, string description, string returnSchemaType = null, bool?isNullable = null, RequiredClaims authorizeClaims = null) { var exp = ExpressionUtil.CheckAndGetMemberExpression(fieldSelection); return(AddField(SchemaGenerator.ToCamelCaseStartsLower(exp.Member.Name), fieldSelection, description, returnSchemaType, isNullable, authorizeClaims)); }
public Field AddField <TParams, TService, TReturn>(string name, TParams argTypes, Expression <Func <TBaseType, TParams, TService, TReturn> > selectionExpression, string description, string returnSchemaType = null, bool?isNullable = null, RequiredClaims authorizeClaims = null) { var field = new Field(schema, name, selectionExpression, description, argTypes, new GqlTypeInfo(!string.IsNullOrEmpty(returnSchemaType) ? (Func <ISchemaType>)(() => schema.Type(returnSchemaType)) : () => schema.Type(typeof(TReturn).GetNonNullableOrEnumerableType()), typeof(TReturn)), authorizeClaims); if (isNullable.HasValue) { field.ReturnType.TypeNotNullable = !isNullable.Value; } this.AddField(field); return(field); }
public Field(string name, LambdaExpression resolve, string description, string returnSchemaType, object argTypes, RequiredClaims claims) : this(name, resolve, description, returnSchemaType, null, claims) { ArgumentTypesObject = argTypes; allArguments = argTypes.GetType().GetProperties().ToDictionary(p => p.Name, p => new ArgType { Type = p.PropertyType, TypeNotNullable = GraphQLNotNullAttribute.IsMemberMarkedNotNull(p), }); argTypes.GetType().GetFields().ToDictionary(p => p.Name, p => new ArgType { Type = p.FieldType, TypeNotNullable = GraphQLNotNullAttribute.IsMemberMarkedNotNull(p), }).ToList().ForEach(kvp => allArguments.Add(kvp.Key, kvp.Value)); }
public Field AddField <TParams, TService, TReturn>(string name, TParams argTypes, Expression <Func <TBaseType, TParams, TService, TReturn> > selectionExpression, string description, string returnSchemaType = null, bool?isNullable = null, RequiredClaims authorizeClaims = null) { var field = new Field(name, selectionExpression, description, returnSchemaType, argTypes, authorizeClaims); if (isNullable.HasValue) { field.ReturnTypeNotNullable = !isNullable.Value; } this.AddField(field); return(field); }