Skip to content

Commit f8435b1

Browse files
authored
Merge pull request #48 from fossapps/gql
Gql
2 parents b87de29 + adbea70 commit f8435b1

17 files changed

Lines changed: 303 additions & 4 deletions

Micro.Auth.Api/GraphQL/AuthSchema.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using System;
2-
using GraphQL.Types;
2+
using Micro.Auth.Api.GraphQL.Federation;
33
using Micro.Auth.Api.GraphQL.Directives;
44

55
namespace Micro.Auth.Api.GraphQL

Micro.Auth.Api/GraphQL/Directives/AuthorizeDirective.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using GraphQL;
2+
using GraphQL.Resolvers;
23
using GraphQL.Types;
34
using GraphQL.Utilities;
45
using Micro.Auth.Api.GraphQL.Directives.Exceptions;
@@ -9,6 +10,8 @@ namespace Micro.Auth.Api.GraphQL.Directives
910
public class AuthorizeDirective : DirectiveGraphType
1011
{
1112
public const string DirectiveName = "authorize";
13+
public override bool? Introspectable => true;
14+
1215
public AuthorizeDirective() : base(
1316
DirectiveName,
1417
DirectiveLocation.Field,
@@ -41,7 +44,10 @@ public override void VisitObjectFieldDefinition(FieldType field, IObjectGraphTyp
4144
return;
4245
}
4346

44-
throw new NotAuthorizedException();
47+
field.Resolver = new AsyncFieldResolver<object>(async context =>
48+
{
49+
throw new NotAuthorizedException();
50+
});
4551
}
4652
}
4753
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using GraphQL.Types;
2+
using Micro.Auth.Api.GraphQL.Types;
3+
4+
namespace Micro.Auth.Api.GraphQL.Federation
5+
{
6+
public class EntityType : UnionGraphType
7+
{
8+
public EntityType(ISchema schema)
9+
{
10+
Name = "_Entity";
11+
Type<UserType>();
12+
}
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using GraphQL.Types;
2+
3+
namespace Micro.Auth.Api.GraphQL.Federation
4+
{
5+
public class ExtendsDirective : DirectiveGraphType
6+
{
7+
public const string DirectiveName = "external";
8+
public override bool? Introspectable => true;
9+
10+
public ExtendsDirective() : base(DirectiveName, DirectiveLocation.Object, DirectiveLocation.Interface)
11+
{
12+
}
13+
}
14+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System.Collections.Generic;
2+
using GraphQL.Builders;
3+
using GraphQL.Types;
4+
using GraphQLParser.AST;
5+
6+
namespace Micro.Auth.Api.GraphQL.Federation
7+
{
8+
public static class Extensions
9+
{
10+
private static FieldBuilder<TSourceType, TReturnType> BuildAstMeta<TSourceType, TReturnType>(FieldBuilder<TSourceType, TReturnType> fieldBuilder, string name, string value = null)
11+
{
12+
fieldBuilder.FieldType.BuildAstMeta(name, value);
13+
return fieldBuilder;
14+
}
15+
public static FieldBuilder<TSourceType, TReturnType> Requires<TSourceType, TReturnType>(this FieldBuilder<TSourceType, TReturnType> fieldBuilder, string fields) => BuildAstMeta(fieldBuilder, "requires", fields);
16+
public static FieldBuilder<TSourceType, TReturnType> Provides<TSourceType, TReturnType>(this FieldBuilder<TSourceType, TReturnType> fieldBuilder, string fields) => BuildAstMeta(fieldBuilder, "provides", fields);
17+
public static FieldBuilder<TSourceType, TReturnType> External<TSourceType, TReturnType>(this FieldBuilder<TSourceType, TReturnType> fieldBuilder) => BuildAstMeta(fieldBuilder, "external");
18+
public static void BuildAstMeta(this IProvideMetadata type, string name, string value = null)
19+
{
20+
var definition = (GraphQLObjectTypeDefinition)type.GetMetadata<ASTNode>("__AST_MetaField__", () => BuildGraphQLObjectTypeDefinition());
21+
var directive = BuildGraphQLDirective(name, value);
22+
AddDirective(definition, directive);
23+
//type.SetAstType(definition);
24+
type.Metadata["__AST_MetaField__"] = definition;
25+
}
26+
private static void AddDirective(GraphQLObjectTypeDefinition definition, GraphQLDirective directive) => ((List<GraphQLDirective>)definition.Directives).Add(directive);
27+
private static GraphQLObjectTypeDefinition BuildGraphQLObjectTypeDefinition() => new GraphQLObjectTypeDefinition
28+
{
29+
Directives = new List<GraphQLDirective>(),
30+
Location = new GraphQLLocation(),
31+
Fields = new List<GraphQLFieldDefinition>()
32+
};
33+
private static GraphQLDirective BuildGraphQLDirective(string name, string value = null, ASTNodeKind kind = ASTNodeKind.StringValue) => new GraphQLDirective
34+
{
35+
Name = new GraphQLName
36+
{
37+
Value = name,
38+
Location = new GraphQLLocation()
39+
},
40+
Arguments = string.IsNullOrEmpty(value) ? new List<GraphQLArgument>() : new List<GraphQLArgument>() {
41+
new GraphQLArgument
42+
{
43+
Name = new GraphQLName {
44+
Value = "fields",
45+
Location = new GraphQLLocation()
46+
},
47+
Value = new GraphQLScalarValue(kind) {
48+
Value = value,
49+
Location = new GraphQLLocation()
50+
},
51+
Location = new GraphQLLocation()
52+
}
53+
},
54+
Location = new GraphQLLocation()
55+
};
56+
}
57+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using GraphQL.Types;
2+
3+
namespace Micro.Auth.Api.GraphQL.Federation
4+
{
5+
public class ExternalDirective : DirectiveGraphType
6+
{
7+
8+
public const string DirectiveName = "external";
9+
public override bool? Introspectable => true;
10+
11+
public ExternalDirective() : base(DirectiveName, DirectiveLocation.FieldDefinition)
12+
{
13+
}
14+
}
15+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using GraphQL.Types;
4+
using GraphQL.Utilities.Federation;
5+
6+
namespace Micro.Auth.Api.GraphQL.Federation
7+
{
8+
public class FederatedObjectGraphType<TSource> : ObjectGraphType<TSource>
9+
{
10+
protected void ResolveReferenceAsync(Func<FederatedResolveContext, Task<TSource>> resolver)
11+
{
12+
ResolveReferenceAsync(new FuncFederatedResolver<TSource>(resolver));
13+
}
14+
15+
protected void Key(string fields)
16+
{
17+
this.BuildAstMeta("key", fields);
18+
}
19+
20+
private void ResolveReferenceAsync(IFederatedResolver resolver)
21+
{
22+
// Metadata[FederatedSchemaBuilder.RESOLVER_METADATA_FIELD] = resolver;
23+
Metadata["__FedResolver__"] = resolver;
24+
}
25+
}
26+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System.Collections.Generic;
2+
using System.Threading.Tasks;
3+
using GraphQL;
4+
using GraphQL.Types;
5+
using GraphQL.Utilities.Federation;
6+
7+
namespace Micro.Auth.Api.GraphQL.Federation
8+
{
9+
public class FederatedQuery : ObjectGraphType
10+
{
11+
public FederatedQuery()
12+
{
13+
Field<NonNullGraphType<ServiceGraphType>>().Name("_service").Resolve(x => new { });
14+
Field<NonNullGraphType<ListGraphType<EntityType>>>()
15+
.Name("_entities")
16+
.Argument<NonNullGraphType<ListGraphType<NonNullGraphType<AnyScalarGraphType>>>>("representations")
17+
.ResolveAsync(context =>
18+
{
19+
var representations = context.GetArgument<List<Dictionary<string, object>>>("representations");
20+
var results = new List<Task<object>>();
21+
22+
foreach (var representation in representations)
23+
{
24+
var typeName = representation["__typename"].ToString();
25+
var type = context.Schema.AllTypes[typeName];
26+
27+
if (type != null)
28+
{
29+
// execute resolver
30+
var resolver = type.GetMetadata<IFederatedResolver>("__FedResolver__");
31+
if (resolver != null)
32+
{
33+
var resolveContext = new FederatedResolveContext
34+
{
35+
Arguments = representation,
36+
ParentFieldContext = context
37+
};
38+
var result = resolver.Resolve(resolveContext);
39+
results.Add(result);
40+
}
41+
else
42+
{
43+
results.Add(Task.FromResult((object)representation));
44+
}
45+
}
46+
else
47+
{
48+
// otherwise return the representation
49+
results.Add(Task.FromResult((object)representation));
50+
}
51+
}
52+
53+
var tasks = Task.WhenAll(results).ContinueWith(results => (object)results.Result);
54+
tasks.ConfigureAwait(false);
55+
return tasks;
56+
});
57+
}
58+
}
59+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using GraphQL.Types;
2+
3+
namespace Micro.Auth.Api.GraphQL.Federation
4+
{
5+
public class KeyDirective : DirectiveGraphType
6+
{
7+
public const string DirectiveName = "key";
8+
public override bool? Introspectable => true;
9+
10+
public KeyDirective() : base(DirectiveName, DirectiveLocation.Object, DirectiveLocation.Interface)
11+
{
12+
Repeatable = true;
13+
Arguments = new QueryArguments(new QueryArgument<NonNullGraphType<StringGraphType>>
14+
{
15+
Name = "fields",
16+
Description = "_FieldSet"
17+
});
18+
}
19+
}
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using GraphQL.Types;
2+
3+
namespace Micro.Auth.Api.GraphQL.Federation
4+
{
5+
public class ProvidesDirective : DirectiveGraphType
6+
{
7+
public const string DirectiveName = "provides";
8+
public override bool? Introspectable => true;
9+
10+
public ProvidesDirective() : base(DirectiveName, DirectiveLocation.FieldDefinition)
11+
{
12+
Arguments = new QueryArguments(new QueryArgument<NonNullGraphType<StringGraphType>>
13+
{
14+
Name = "fields",
15+
Description = "_FieldSet"
16+
});
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)