From a48e053de4b62b04adc1e0eda34039942e7c3fdb Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Sat, 11 May 2019 16:03:37 +0900 Subject: [PATCH] Implemented aero GraphQL server --- go.mod | 2 +- go.sum | 8 +++- graphql/graphql.go | 94 ++++++++++++++++++++++++++++++++++++++++++++++ main.go | 4 +- 4 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 graphql/graphql.go diff --git a/go.mod b/go.mod index 14026949..d82ceffa 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/aerogo/api v0.1.6 github.com/aerogo/codetree v1.2.2 // indirect github.com/aerogo/crawler v0.2.1 - github.com/aerogo/graphql v0.1.4 + github.com/aerogo/graphql v0.3.3 github.com/aerogo/http v1.0.3 github.com/aerogo/layout v0.1.5 github.com/aerogo/log v0.2.4 diff --git a/go.sum b/go.sum index fa1e1f26..9dc0ed02 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,10 @@ github.com/aerogo/csp v0.1.5 h1:4l8AaMWndSb0t/03onf4lc0th2zoaapmtKgysDIznW4= github.com/aerogo/csp v0.1.5/go.mod h1:KNqnTFffuDwIPJxBEFTl3baBx+x3Vw+9kcMfu5APFJA= github.com/aerogo/flow v0.1.2 h1:fZ3V7Bo7jwBjqnM1mWxYbg5O/FlQX2XovzMZU2D+o5M= github.com/aerogo/flow v0.1.2/go.mod h1:xXIb7GY0AKouhbp4/ViCsiOmvvgRGonqPG30d6FnACI= -github.com/aerogo/graphql v0.1.4 h1:NMMr0N5lTtaC8gfLhlKN46gVLCkrDHDZWPdjdmPRIYQ= -github.com/aerogo/graphql v0.1.4/go.mod h1:qAPqMXgv4ZUpDTIZzJT/AHDoWq7h6IMnDeaOCw52zyM= +github.com/aerogo/graphql v0.3.2 h1:M9tQw3nEp7NThL/IcYlrpwajLzkxuZi5OX0Oq/ox1hA= +github.com/aerogo/graphql v0.3.2/go.mod h1:bcAaQk3IGODFLF2gFwVszP3hyumWOhwKKuOh1xClSeI= +github.com/aerogo/graphql v0.3.3 h1:PyqTuEUErrLQWo80hKjVzO2YPbQBrYrRkJKARrUaRC0= +github.com/aerogo/graphql v0.3.3/go.mod h1:bcAaQk3IGODFLF2gFwVszP3hyumWOhwKKuOh1xClSeI= github.com/aerogo/http v1.0.0 h1:15a7Px8wGZbmgFqJMR1kBy3fWFkDfMZWexJzxhmFKe4= github.com/aerogo/http v1.0.0/go.mod h1:B1igUmMLpE6KabMpc9reHCJJNUOJ2U/PR9s1fF3TpPQ= github.com/aerogo/http v1.0.1 h1:KTzYarhp5yougurxuAhJKFh3YvZ7R7CfaDVwJv5+xIs= @@ -67,6 +69,8 @@ github.com/aerogo/mirror v0.1.3 h1:813FatCdChOvgWen2EcZNnRfxAeo9zmu/TgDNOnsDx0= github.com/aerogo/mirror v0.1.3/go.mod h1:Un87Jq8RIRrb2bU1CxVToJjVZgSMLUQXxVLCXln4rUU= github.com/aerogo/mirror v0.2.0 h1:iaQtEejSU3PytPOHrHSEWBYmAoM0Pc63YGFQUMTXWjY= github.com/aerogo/mirror v0.2.0/go.mod h1:Un87Jq8RIRrb2bU1CxVToJjVZgSMLUQXxVLCXln4rUU= +github.com/aerogo/mirror v0.2.2 h1:kASC9ZsTDBPwzZehb2o5qLbNv+bj8t9V167ExjEMRS0= +github.com/aerogo/mirror v0.2.2/go.mod h1:Un87Jq8RIRrb2bU1CxVToJjVZgSMLUQXxVLCXln4rUU= github.com/aerogo/nano v0.1.6 h1:FtWokAa8SZcm5kHlW10OkaUnqlFE4eQGvEfkiSBVsek= github.com/aerogo/nano v0.1.6/go.mod h1:NxWlxJWtm2s4gB4CcJGy5Lsofz1ZgvEGtv5dEQVNa94= github.com/aerogo/nano v0.2.0 h1:qcCdCsAtN1Qpw8DhZQXiLVJYsjmpQMmZ7TPFD2GkwVw= diff --git a/graphql/graphql.go b/graphql/graphql.go new file mode 100644 index 00000000..1b267208 --- /dev/null +++ b/graphql/graphql.go @@ -0,0 +1,94 @@ +package graphql + +import ( + "errors" + "fmt" + "reflect" + "strings" + + "github.com/aerogo/aero" + + "github.com/aerogo/graphql" + "github.com/animenotifier/arn" +) + +var ( + empty = struct{}{} + privateCollections = map[string]struct{}{ + "PayPalPayment": empty, + "Purchase": empty, + "EmailToUser": empty, + "Session": empty, + "EditLogEntry": empty, + } +) + +func Install(app *aero.Application) { + api := graphql.New(arn.DB) + + // Block private collections + api.AddRootResolver(func(name string, arguments graphql.Map) (interface{}, error, bool) { + typeName := strings.TrimPrefix(name, "all") + typeName = strings.TrimPrefix(typeName, "like") + _, private := privateCollections[typeName] + + if private { + return nil, fmt.Errorf("Type '%s' is private", typeName), true + } + + return nil, nil, false + }) + + // Like objects + api.AddRootResolver(func(name string, arguments graphql.Map) (interface{}, error, bool) { + if !strings.HasPrefix(name, "like") { + return nil, nil, false + } + + id, ok := arguments["ID"].(string) + + if !ok { + return nil, fmt.Errorf("'%s' needs to specify an ID", name), true + } + + typeName := strings.TrimPrefix(name, "like") + obj, err := arn.DB.Get(typeName, id) + + if err != nil { + return nil, err, true + } + + field := reflect.ValueOf(obj).Elem().FieldByName("IsDraft") + + if field.IsValid() && field.Bool() { + return nil, errors.New("Drafts need to be published before they can be liked"), true + } + + likeable, ok := obj.(arn.Likeable) + + if !ok { + return nil, fmt.Errorf("'%s' does not implement the Likeable interface", name), true + } + + // TODO: Authentication + // user := GetUserFromContext(ctx) + + // if user == nil { + // return errors.New("Not logged in") + // } + + // likeable.Like(user.ID) + + // Call OnLike if the object implements it + // receiver, ok := likeable.(LikeEventReceiver) + + // if ok { + // receiver.OnLike(user) + // } + + likeable.Save() + return obj, nil, true + }) + + app.Post("/graphql", api.Handler()) +} diff --git a/main.go b/main.go index f3cc8c2b..95dec19c 100644 --- a/main.go +++ b/main.go @@ -4,10 +4,10 @@ import ( "strings" "github.com/aerogo/aero" - "github.com/aerogo/graphql" nanostore "github.com/aerogo/session-store-nano" "github.com/animenotifier/arn" "github.com/animenotifier/notify.moe/auth" + "github.com/animenotifier/notify.moe/graphql" "github.com/animenotifier/notify.moe/middleware" "github.com/animenotifier/notify.moe/pages" "github.com/animenotifier/notify.moe/utils/routetests" @@ -61,7 +61,7 @@ func configure(app *aero.Application) *aero.Application { auth.Install(app) // GraphQL - app.Post("/graphql", graphql.Handler(arn.DB)) + graphql.Install(app) // Close the database node on shutdown app.OnEnd(arn.Node.Close)