Compare commits

..
Author SHA1 Message Date
gisle a5410dff2c Eugh.
the build was successful
2019-05-16 15:57:22 +02:00
gisle 7e3dc49635 Basic stuff, doesn't compile 2019-05-16 15:57:08 +02:00
54 changed files with 302 additions and 892 deletions
-8
View File
@@ -10,14 +10,12 @@ import (
"git.aiterp.net/rpdata/api/graph2" "git.aiterp.net/rpdata/api/graph2"
"git.aiterp.net/rpdata/api/internal/auth" "git.aiterp.net/rpdata/api/internal/auth"
"git.aiterp.net/rpdata/api/internal/instrumentation"
"git.aiterp.net/rpdata/api/internal/loader" "git.aiterp.net/rpdata/api/internal/loader"
"git.aiterp.net/rpdata/api/internal/store" "git.aiterp.net/rpdata/api/internal/store"
"git.aiterp.net/rpdata/api/models" "git.aiterp.net/rpdata/api/models"
"git.aiterp.net/rpdata/api/models/changes" "git.aiterp.net/rpdata/api/models/changes"
"git.aiterp.net/rpdata/api/models/logs" "git.aiterp.net/rpdata/api/models/logs"
"github.com/99designs/gqlgen/handler" "github.com/99designs/gqlgen/handler"
"github.com/prometheus/client_golang/prometheus/promhttp"
) )
func main() { func main() {
@@ -26,13 +24,9 @@ func main() {
log.Fatalln("Failed to init store:", err) log.Fatalln("Failed to init store:", err)
} }
instrumentation.Register()
http.Handle("/", handler.Playground("RPData API", "/graphql")) http.Handle("/", handler.Playground("RPData API", "/graphql"))
http.Handle("/graphql", queryHandler()) http.Handle("/graphql", queryHandler())
http.Handle("/metrics", promhttp.Handler())
go func() { go func() {
err := logs.RunFullUpdate() err := logs.RunFullUpdate()
if err != nil { if err != nil {
@@ -87,8 +81,6 @@ func queryHandler() http.HandlerFunc {
return fmt.Errorf("The server failed to serve your request due to an internal error, it has been logged") return fmt.Errorf("The server failed to serve your request due to an internal error, it has been logged")
}), }),
handler.ComplexityLimit(300), handler.ComplexityLimit(300),
handler.RequestMiddleware(instrumentation.RequestMiddleware()),
handler.ResolverMiddleware(instrumentation.ResolverMiddleware()),
) )
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
+7 -15
View File
@@ -3,16 +3,14 @@ module git.aiterp.net/rpdata/api
go 1.12 go 1.12
require ( require (
github.com/99designs/gqlgen v0.9.0 github.com/99designs/gqlgen v0.8.0
github.com/agnivade/levenshtein v1.0.1 github.com/agnivade/levenshtein v1.0.1
github.com/beorn7/perks v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew v1.1.1
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4
github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e
github.com/go-ini/ini v1.35.0 github.com/go-ini/ini v1.35.0
github.com/go-sql-driver/mysql v1.4.0 github.com/go-sql-driver/mysql v1.4.0
github.com/golang/protobuf v1.3.1 // indirect
github.com/gorilla/websocket v1.4.0 github.com/gorilla/websocket v1.4.0
github.com/graph-gophers/dataloader v0.0.0-20180104184831-78139374585c github.com/graph-gophers/dataloader v0.0.0-20180104184831-78139374585c
github.com/hashicorp/golang-lru v0.5.0 github.com/hashicorp/golang-lru v0.5.0
@@ -22,21 +20,15 @@ require (
github.com/opentracing/opentracing-go v1.0.2 github.com/opentracing/opentracing-go v1.0.2
github.com/pkg/errors v0.8.1 github.com/pkg/errors v0.8.1
github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib v1.0.0
github.com/prometheus/client_golang v0.9.1 github.com/sirupsen/logrus v1.0.5
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 // indirect
github.com/prometheus/common v0.4.0 // indirect
github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e // indirect
github.com/sirupsen/logrus v1.2.0
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.3.0
github.com/urfave/cli v1.20.0 github.com/urfave/cli v1.20.0
github.com/vektah/gqlparser v1.1.2 github.com/vektah/gqlparser v1.1.0
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06
golang.org/x/net v0.0.0-20190514140710-3ec191127204 golang.org/x/net v0.0.0-20180416171110-a35a21de978d
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a golang.org/x/sys v0.0.0-20180416112224-2f57af4873d0
golang.org/x/text v0.3.0 golang.org/x/text v0.3.0
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6
google.golang.org/appengine v1.1.0 google.golang.org/appengine v1.1.0
gopkg.in/yaml.v2 v2.2.2 gopkg.in/yaml.v2 v2.2.2
) )
replace golang.org/x/net => golang.org/x/net v0.0.0-20180416171110-a35a21de978d
-65
View File
@@ -4,42 +4,24 @@ github.com/99designs/gqlgen v0.8.0 h1:ZBteuSgeeFwn+mztjDqQZQdVa9pqslmPnDeCovcnc0
github.com/99designs/gqlgen v0.8.0/go.mod h1:st7qHA6ssU3uRZkmv+wzrzgX4srvIqEIdE5iuRW8GhE= github.com/99designs/gqlgen v0.8.0/go.mod h1:st7qHA6ssU3uRZkmv+wzrzgX4srvIqEIdE5iuRW8GhE=
github.com/99designs/gqlgen v0.8.3 h1:I6bMglXNKkn4KlvkSMzqZw53e1N2FF9Gud4NmsOxqiA= github.com/99designs/gqlgen v0.8.3 h1:I6bMglXNKkn4KlvkSMzqZw53e1N2FF9Gud4NmsOxqiA=
github.com/99designs/gqlgen v0.8.3/go.mod h1:aLyJw9xUgdJxZ8EqNQxo2pGFhXXJ/hq8t7J4yn8TgI4= github.com/99designs/gqlgen v0.8.3/go.mod h1:aLyJw9xUgdJxZ8EqNQxo2pGFhXXJ/hq8t7J4yn8TgI4=
github.com/99designs/gqlgen v0.9.0 h1:g1arBPML74Vqv0L3Q+TqIhGXLspV+2MYtRLkBxuZrlE=
github.com/99designs/gqlgen v0.9.0/go.mod h1:HrrG7ic9EgLPsULxsZh/Ti+p0HNWgR3XRuvnD0pb5KY=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/agnivade/levenshtein v1.0.0 h1:q+77q31bLT5jhN3BHKA1276nUEdbz7XjDa0o5dRKcZ0= github.com/agnivade/levenshtein v1.0.0 h1:q+77q31bLT5jhN3BHKA1276nUEdbz7XjDa0o5dRKcZ0=
github.com/agnivade/levenshtein v1.0.0/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/agnivade/levenshtein v1.0.0/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ= github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e h1:hmrbHva/wKD6X4M7pgHVbg/KfVV1wwgr1NEkQaVD3rU= github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e h1:hmrbHva/wKD6X4M7pgHVbg/KfVV1wwgr1NEkQaVD3rU=
github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-ini/ini v1.35.0 h1:D/my3+xOfqZMkJpciRcyqU7XMBUgiZa9qXjZIa8uv2k= github.com/go-ini/ini v1.35.0 h1:D/my3+xOfqZMkJpciRcyqU7XMBUgiZa9qXjZIa8uv2k=
github.com/go-ini/ini v1.35.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-ini/ini v1.35.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk= github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
@@ -51,21 +33,14 @@ github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCO
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0 h1:5B0uxl2lzNRVkJVg+uGHxWtRt4C0Wjc6kJKo5XYx8xE= github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0 h1:5B0uxl2lzNRVkJVg+uGHxWtRt4C0Wjc6kJKo5XYx8xE=
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU= github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/minio/minio-go v0.0.0-20180409193742-3d2d02921f05 h1:YEyFCqmHcmbcTLqZ7yEAg7VIUat6PuDzGbIctZy888k= github.com/minio/minio-go v0.0.0-20180409193742-3d2d02921f05 h1:YEyFCqmHcmbcTLqZ7yEAg7VIUat6PuDzGbIctZy888k=
github.com/minio/minio-go v0.0.0-20180409193742-3d2d02921f05/go.mod h1:7guKYtitv8dktvNUGrhzmNlA5wrAABTQXCoesZdFQO8= github.com/minio/minio-go v0.0.0-20180409193742-3d2d02921f05/go.mod h1:7guKYtitv8dktvNUGrhzmNlA5wrAABTQXCoesZdFQO8=
github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747 h1:eQox4Rh4ewJF+mqYPxCkmBAirRnPaHEB26UkNuPyjlk= github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747 h1:eQox4Rh4ewJF+mqYPxCkmBAirRnPaHEB26UkNuPyjlk=
github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
@@ -74,38 +49,18 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1 h1:K47Rk0v/fkEfwfQet2KWhscE0cJzjgCCDBG2KHZoVno=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e h1:zK8d1aZ+gw/Ne4uMfZTFRxj08PUOp+gGwm4HWUeGI1k=
github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/vektah/dataloaden v0.2.0/go.mod h1:vxM6NuRlgiR0M6wbVTJeKp9vQIs81ZMfCYO+4yq/jbE= github.com/vektah/dataloaden v0.2.0/go.mod h1:vxM6NuRlgiR0M6wbVTJeKp9vQIs81ZMfCYO+4yq/jbE=
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
github.com/vektah/gqlparser v0.0.0-20180831041411-14e83ae06ec1 h1:FYOXUtr3sYR9shto7Q/aQ1B0Onyk77aws9wGOORiz+I= github.com/vektah/gqlparser v0.0.0-20180831041411-14e83ae06ec1 h1:FYOXUtr3sYR9shto7Q/aQ1B0Onyk77aws9wGOORiz+I=
github.com/vektah/gqlparser v0.0.0-20180831041411-14e83ae06ec1/go.mod h1:K4QdSSpS2XiHHwzb18kWh3iBljB8rLC8okGXsnQy3Nc= github.com/vektah/gqlparser v0.0.0-20180831041411-14e83ae06ec1/go.mod h1:K4QdSSpS2XiHHwzb18kWh3iBljB8rLC8okGXsnQy3Nc=
github.com/vektah/gqlparser v1.1.0 h1:3668p2gUlO+PiS81x957Rpr3/FPRWG6cxgCXAvTS1hw= github.com/vektah/gqlparser v1.1.0 h1:3668p2gUlO+PiS81x957Rpr3/FPRWG6cxgCXAvTS1hw=
@@ -114,37 +69,17 @@ github.com/vektah/gqlparser v1.1.2 h1:ZsyLGn7/7jDNI+y4SEhI4yAxRChlv15pUHMjijT+e6
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06 h1:EOqG0JqGlLr+punVB69jvWCv/ErZKGlC7PMdyHfv+Bc= golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06 h1:EOqG0JqGlLr+punVB69jvWCv/ErZKGlC7PMdyHfv+Bc=
golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20180404174746-b3c676e531a6/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180404174746-b3c676e531a6/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180416171110-a35a21de978d h1:O2P57H5Cc+d+DJos+iweraI9rmzMYwV+45vkZdDY0Oo= golang.org/x/net v0.0.0-20180416171110-a35a21de978d h1:O2P57H5Cc+d+DJos+iweraI9rmzMYwV+45vkZdDY0Oo=
golang.org/x/net v0.0.0-20180416171110-a35a21de978d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180416171110-a35a21de978d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a h1:gOpx8G595UYyvj8UK4+OFyY4rx037g3fmfhe5SasG3U=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190514140710-3ec191127204 h1:4yG6GqBtw9C+UrLp6s2wtSniayy/Vd/3F7ffLE427XI=
golang.org/x/net v0.0.0-20190514140710-3ec191127204/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180416112224-2f57af4873d0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180416112224-2f57af4873d0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5 h1:mzjBh+S5frKOsOBobWIMAbXavqjmgO17k/2puhcFR94=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1 h1:dzEuQYa6+a3gROnSlgly5ERUm4SZKJt+dh+4iSbO+bI= golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1 h1:dzEuQYa6+a3gROnSlgly5ERUm4SZKJt+dh+4iSbO+bI=
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6 h1:iZgcI2DDp6zW5v9Z/5+f0NuqoxNdmzg4hivjk2WLXpY= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6 h1:iZgcI2DDp6zW5v9Z/5+f0NuqoxNdmzg4hivjk2WLXpY=
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd h1:oMEQDWVXVNpceQoVd1JN3CQ7LYJJzs5qWqZIUcxXHHw=
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
echo "# Generated by stiching together the files under schema/ – DO NOT EDIT" >generated.gql
cat schema/root.gql schema/**/*.gql >>generated.gql
+1 -3
View File
@@ -1,6 +1,4 @@
schema: schema: generated.gql
- schema/root.gql
- schema/types/*.gql
exec: exec:
filename: generated.go filename: generated.go
+5
View File
@@ -6,6 +6,7 @@ import (
graphql "github.com/99designs/gqlgen/graphql" graphql "github.com/99designs/gqlgen/graphql"
) )
//go:generate ./combine.sh
//go:generate go run github.com/99designs/gqlgen -v //go:generate go run github.com/99designs/gqlgen -v
// New creates a new GraphQL schema. // New creates a new GraphQL schema.
@@ -46,6 +47,10 @@ func (r *rootResolver) Story() StoryResolver {
return &types.StoryResolver return &types.StoryResolver
} }
func (r *rootResolver) File() FileResolver {
return &types.FileResolver
}
func (r *rootResolver) Change() ChangeResolver { func (r *rootResolver) Change() ChangeResolver {
return &types.ChangeResolver return &types.ChangeResolver
} }
+4 -19
View File
@@ -10,31 +10,16 @@ import (
/// Queries /// Queries
func (r *resolver) Changes(ctx context.Context, filter *changes.Filter) ([]*models.Change, error) { func (r *resolver) Changes(ctx context.Context, filter *changes.Filter) ([]models.Change, error) {
changes, err := changes.List(filter) return changes.List(filter)
if err != nil {
return nil, err
}
changes2 := make([]*models.Change, len(changes))
for i := range changes {
changes2[i] = &changes[i]
}
return changes2, nil
} }
/// Subscriptions /// Subscriptions
func (r *subscriptionResolver) Changes(ctx context.Context, keys []*models.ChangeKey) (<-chan *models.Change, error) { func (r *subscriptionResolver) Changes(ctx context.Context, keys []models.ChangeKey) (<-chan models.Change, error) {
if len(keys) == 0 { if len(keys) == 0 {
return nil, errors.New("At least one key is required for a subscription") return nil, errors.New("At least one key is required for a subscription")
} }
keys2 := make([]models.ChangeKey, len(keys)) return changes.Subscribe(ctx, keys, false), nil
for i := range keys {
keys2[i] = *keys[i]
}
return changes.Subscribe(ctx, keys2, false), nil
} }
+6 -21
View File
@@ -15,26 +15,11 @@ import (
// Queries // Queries
func (r *resolver) Channel(ctx context.Context, name string) (*models.Channel, error) { func (r *resolver) Channel(ctx context.Context, name string) (*models.Channel, error) {
channel, err := channels.FindName(name) return channels.FindName(name)
if err != nil {
return nil, err
} }
return &channel, nil func (r *resolver) Channels(ctx context.Context, filter *channels.Filter) ([]models.Channel, error) {
} return channels.List(filter)
func (r *resolver) Channels(ctx context.Context, filter *channels.Filter) ([]*models.Channel, error) {
channels, err := channels.List(filter)
if err != nil {
return nil, err
}
channels2 := make([]*models.Channel, len(channels))
for i := range channels {
channels2[i] = &channels[i]
}
return channels2, nil
} }
// Mutations // Mutations
@@ -69,7 +54,7 @@ func (r *mutationResolver) AddChannel(ctx context.Context, input input.ChannelAd
go changes.Submit("Channel", "add", token.UserID, true, changekeys.Listed(channel), channel) go changes.Submit("Channel", "add", token.UserID, true, changekeys.Listed(channel), channel)
return &channel, nil return channel, nil
} }
func (r *mutationResolver) EditChannel(ctx context.Context, input input.ChannelEditInput) (*models.Channel, error) { func (r *mutationResolver) EditChannel(ctx context.Context, input input.ChannelEditInput) (*models.Channel, error) {
@@ -83,12 +68,12 @@ func (r *mutationResolver) EditChannel(ctx context.Context, input input.ChannelE
return nil, errors.New("Channel not found") return nil, errors.New("Channel not found")
} }
channel, err = channels.Edit(channel, input.Logged, input.Hub, input.EventName, input.LocationName) channel, err = channels.Edit(*channel, input.Logged, input.Hub, input.EventName, input.LocationName)
if err != nil { if err != nil {
return nil, errors.New("Failed to edit channel: " + err.Error()) return nil, errors.New("Failed to edit channel: " + err.Error())
} }
go changes.Submit("Channel", "edit", token.UserID, true, changekeys.Listed(channel), channel) go changes.Submit("Channel", "edit", token.UserID, true, changekeys.Listed(channel), channel)
return &channel, nil return channel, nil
} }
+9 -12
View File
@@ -5,25 +5,22 @@ import (
"errors" "errors"
"time" "time"
"git.aiterp.net/rpdata/api/graph2/input"
"git.aiterp.net/rpdata/api/internal/auth"
"git.aiterp.net/rpdata/api/models"
"git.aiterp.net/rpdata/api/models/changekeys" "git.aiterp.net/rpdata/api/models/changekeys"
"git.aiterp.net/rpdata/api/models/changes" "git.aiterp.net/rpdata/api/models/changes"
"git.aiterp.net/rpdata/api/models/chapters"
"git.aiterp.net/rpdata/api/models/comments" "git.aiterp.net/rpdata/api/models/comments"
"git.aiterp.net/rpdata/api/internal/auth"
"git.aiterp.net/rpdata/api/models/stories" "git.aiterp.net/rpdata/api/models/stories"
"git.aiterp.net/rpdata/api/graph2/input"
"git.aiterp.net/rpdata/api/models"
"git.aiterp.net/rpdata/api/models/chapters"
) )
// Queries // Queries
func (r *resolver) Chapter(ctx context.Context, id string) (*models.Chapter, error) { func (r *resolver) Chapter(ctx context.Context, id string) (*models.Chapter, error) {
chapter, err := chapters.FindID(id) return chapters.FindID(id)
if err != nil {
return nil, err
}
return &chapter, nil
} }
// Mutations // Mutations
@@ -57,7 +54,7 @@ func (r *mutationResolver) AddChapter(ctx context.Context, input input.ChapterAd
commentMode = *input.CommentMode commentMode = *input.CommentMode
} }
chapter, err := chapters.Add(story, input.Title, author, input.Source, time.Now(), input.FictionalDate, commentMode) chapter, err := chapters.Add(*story, input.Title, author, input.Source, time.Now(), input.FictionalDate, commentMode)
if err != nil { if err != nil {
return nil, errors.New("Failed to create chapter: " + err.Error()) return nil, errors.New("Failed to create chapter: " + err.Error())
} }
@@ -88,7 +85,7 @@ func (r *mutationResolver) MoveChapter(ctx context.Context, input input.ChapterM
} }
oldStoryID := chapter.StoryID oldStoryID := chapter.StoryID
chapter, err = chapters.Move(chapter, target) chapter, err = chapters.Move(chapter, *target)
if err != nil { if err != nil {
return nil, errors.New("Failed to move chapter: " + err.Error()) return nil, errors.New("Failed to move chapter: " + err.Error())
} }
+35 -55
View File
@@ -16,49 +16,29 @@ import (
// Queries // Queries
func (r *resolver) Character(ctx context.Context, id *string, nick *string) (*models.Character, error) { func (r *resolver) Character(ctx context.Context, id *string, nick *string) (models.Character, error) {
if id != nil { if id != nil {
character, err := characters.FindID(*id) return characters.FindID(*id)
if err != nil {
return nil, err
}
return &character, nil
} else if nick != nil { } else if nick != nil {
character, err := characters.FindNick(*nick) return characters.FindNick(*nick)
if err != nil {
return nil, err
}
return &character, nil
} else { } else {
return nil, errors.New("You must specify either an ID or a nick") return models.Character{}, errors.New("You must specify either an ID or a nick")
} }
} }
func (r *resolver) Characters(ctx context.Context, filter *characters.Filter) ([]*models.Character, error) { func (r *resolver) Characters(ctx context.Context, filter *characters.Filter) ([]models.Character, error) {
characters, err := characters.List(filter) return characters.List(filter)
if err != nil {
return nil, err
}
characters2 := make([]*models.Character, len(characters))
for i := range characters {
characters2[i] = &characters[i]
}
return characters2, nil
} }
// Mutations // Mutations
func (r *mutationResolver) AddCharacter(ctx context.Context, input input.CharacterAddInput) (*models.Character, error) { func (r *mutationResolver) AddCharacter(ctx context.Context, input input.CharacterAddInput) (models.Character, error) {
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.Permitted("member", "character.add") { if !token.Permitted("member", "character.add") {
return nil, errors.New("You are not permitted to add characters") return models.Character{}, errors.New("You are not permitted to add characters")
} }
if len(input.Name) < 2 || len(input.Nick) < 2 { if len(input.Name) < 2 || len(input.Nick) < 2 {
return nil, errors.New("You need to provide a name and a nick (min length: 2)") return models.Character{}, errors.New("You need to provide a name and a nick (min length: 2)")
} }
shortName := "" shortName := ""
@@ -76,7 +56,7 @@ func (r *mutationResolver) AddCharacter(ctx context.Context, input input.Charact
author := token.UserID author := token.UserID
if input.Author != nil && *input.Author != author { if input.Author != nil && *input.Author != author {
if !token.Permitted("character.add") { if !token.Permitted("character.add") {
return nil, errors.New("You are only permitted to add your own characters") return models.Character{}, errors.New("You are only permitted to add your own characters")
} }
author = *input.Author author = *input.Author
@@ -86,109 +66,109 @@ func (r *mutationResolver) AddCharacter(ctx context.Context, input input.Charact
character, err := characters.Add(input.Nick, input.Name, shortName, author, description) character, err := characters.Add(input.Nick, input.Name, shortName, author, description)
if err != nil { if err != nil {
return nil, errors.New("Adding character failed: " + err.Error()) return models.Character{}, errors.New("Adding character failed: " + err.Error())
} }
go changes.Submit("Character", "add", token.UserID, true, changekeys.Listed(character), character) go changes.Submit("Character", "add", token.UserID, true, changekeys.Listed(character), character)
return &character, nil return character, nil
} }
func (r *mutationResolver) AddCharacterNick(ctx context.Context, input input.CharacterNickInput) (*models.Character, error) { func (r *mutationResolver) AddCharacterNick(ctx context.Context, input input.CharacterNickInput) (models.Character, error) {
character, err := characters.FindID(input.ID) character, err := characters.FindID(input.ID)
if err != nil { if err != nil {
return nil, errors.New("Character not found") return models.Character{}, errors.New("Character not found")
} }
if len(input.Nick) < 2 { if len(input.Nick) < 2 {
return nil, errors.New("You need to provide a valid nick (min length: 2)") return models.Character{}, errors.New("You need to provide a valid nick (min length: 2)")
} }
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.PermittedUser(character.Author, "member", "character.edit") { if !token.PermittedUser(character.Author, "member", "character.edit") {
return nil, errors.New("You are not permitted to edit this character") return models.Character{}, errors.New("You are not permitted to edit this character")
} }
logs.ScheduleFullUpdate() logs.ScheduleFullUpdate()
character, err = characters.AddNick(character, input.Nick) character, err = characters.AddNick(character, input.Nick)
if err != nil { if err != nil {
return nil, errors.New("Failed to add nick: " + err.Error()) return models.Character{}, errors.New("Failed to add nick: " + err.Error())
} }
go logs.ScheduleFullUpdate() go logs.ScheduleFullUpdate()
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character) go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
return &character, nil return character, nil
} }
func (r *mutationResolver) RemoveCharacterNick(ctx context.Context, input input.CharacterNickInput) (*models.Character, error) { func (r *mutationResolver) RemoveCharacterNick(ctx context.Context, input input.CharacterNickInput) (models.Character, error) {
character, err := characters.FindID(input.ID) character, err := characters.FindID(input.ID)
if err != nil { if err != nil {
return nil, errors.New("Character not found") return models.Character{}, errors.New("Character not found")
} }
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.PermittedUser(character.Author, "member", "character.edit") { if !token.PermittedUser(character.Author, "member", "character.edit") {
return nil, errors.New("You are not permitted to edit this character") return models.Character{}, errors.New("You are not permitted to edit this character")
} }
character, err = characters.RemoveNick(character, input.Nick) character, err = characters.RemoveNick(character, input.Nick)
if err != nil { if err != nil {
return nil, errors.New("Failed to remove nick: " + err.Error()) return models.Character{}, errors.New("Failed to remove nick: " + err.Error())
} }
go logs.ScheduleFullUpdate() go logs.ScheduleFullUpdate()
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character) go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
return &character, nil return character, nil
} }
func (r *mutationResolver) EditCharacter(ctx context.Context, input input.CharacterEditInput) (*models.Character, error) { func (r *mutationResolver) EditCharacter(ctx context.Context, input input.CharacterEditInput) (models.Character, error) {
character, err := characters.FindID(input.ID) character, err := characters.FindID(input.ID)
if err != nil { if err != nil {
return nil, errors.New("Character not found") return models.Character{}, errors.New("Character not found")
} }
if input.Name != nil && len(*input.Name) < 2 { if input.Name != nil && len(*input.Name) < 2 {
return nil, errors.New("You need to provide a valid name (min length: 2)") return models.Character{}, errors.New("You need to provide a valid name (min length: 2)")
} }
if input.ShortName != nil && len(*input.ShortName) < 2 { if input.ShortName != nil && len(*input.ShortName) < 2 {
return nil, errors.New("You need to provide a valid short name (min length: 2)") return models.Character{}, errors.New("You need to provide a valid short name (min length: 2)")
} }
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.PermittedUser(character.Author, "member", "character.edit") { if !token.PermittedUser(character.Author, "member", "character.edit") {
return nil, errors.New("You are not permitted to edit this character") return models.Character{}, errors.New("You are not permitted to edit this character")
} }
character, err = characters.Edit(character, input.Name, input.ShortName, input.Description) character, err = characters.Edit(character, input.Name, input.ShortName, input.Description)
if err != nil { if err != nil {
return nil, errors.New("Failed to edit character: " + err.Error()) return models.Character{}, errors.New("Failed to edit character: " + err.Error())
} }
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character) go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
return &character, nil return character, nil
} }
func (r *mutationResolver) RemoveCharacter(ctx context.Context, input input.CharacterRemoveInput) (*models.Character, error) { func (r *mutationResolver) RemoveCharacter(ctx context.Context, input input.CharacterRemoveInput) (models.Character, error) {
character, err := characters.FindID(input.ID) character, err := characters.FindID(input.ID)
if err != nil { if err != nil {
return nil, errors.New("Character not found") return models.Character{}, errors.New("Character not found")
} }
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.PermittedUser(character.Author, "member", "character.remove") { if !token.PermittedUser(character.Author, "member", "character.remove") {
return nil, errors.New("You are not permitted to remove this character") return models.Character{}, errors.New("You are not permitted to remove this character")
} }
character, err = characters.Remove(character) character, err = characters.Remove(character)
if err != nil { if err != nil {
return nil, errors.New("Failed to remove character: " + err.Error()) return models.Character{}, errors.New("Failed to remove character: " + err.Error())
} }
go changes.Submit("Character", "remove", token.UserID, true, changekeys.Listed(character), character) go changes.Submit("Character", "remove", token.UserID, true, changekeys.Listed(character), character)
return &character, nil return character, nil
} }
+26 -31
View File
@@ -24,39 +24,34 @@ import (
// Queries // Queries
func (r *resolver) Comment(ctx context.Context, id string) (*models.Comment, error) { func (r *resolver) Comment(ctx context.Context, id string) (models.Comment, error) {
comment, err := comments.Find(id) return comments.Find(id)
if err != nil {
return nil, err
}
return &comment, nil
} }
// Mutations // Mutations
func (r *mutationResolver) AddComment(ctx context.Context, input input.CommentAddInput) (*models.Comment, error) { func (r *mutationResolver) AddComment(ctx context.Context, input input.CommentAddInput) (models.Comment, error) {
chapter, err := chapters.FindID(input.ChapterID) chapter, err := chapters.FindID(input.ChapterID)
if err != nil { if err != nil {
return nil, errors.New("Chapter not found") return models.Comment{}, errors.New("Chapter not found")
} }
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.Permitted("member", "story.edit") { if !token.Permitted("member", "story.edit") {
return nil, errors.New("Unauthorized") return models.Comment{}, errors.New("Unauthorized")
} }
if !chapter.CanComment() { if !chapter.CanComment() {
return nil, errors.New("Comments are disabled or locked") return models.Comment{}, errors.New("Comments are disabled or locked")
} }
var characterPtr *models.Character var characterPtr *models.Character
if input.CharacterID != nil { if input.CharacterID != nil {
character, err := characters.FindID(*input.CharacterID) character, err := characters.FindID(*input.CharacterID)
if err != nil { if err != nil {
return nil, errors.New("Character not found") return models.Comment{}, errors.New("Character not found")
} else if character.Author != token.UserID { } else if character.Author != token.UserID {
return nil, errors.New("That is not your character") return models.Comment{}, errors.New("That is not your character")
} }
characterPtr = &character characterPtr = &character
@@ -74,7 +69,7 @@ func (r *mutationResolver) AddComment(ctx context.Context, input input.CommentAd
comment, err := comments.Add(chapter, subject, token.UserID, input.Source, input.CharacterName, characterPtr, time.Now(), fictionalDate) comment, err := comments.Add(chapter, subject, token.UserID, input.Source, input.CharacterName, characterPtr, time.Now(), fictionalDate)
if err != nil { if err != nil {
return nil, errors.New("Failed to add comment: " + err.Error()) return models.Comment{}, errors.New("Failed to add comment: " + err.Error())
} }
go func() { go func() {
@@ -87,27 +82,27 @@ func (r *mutationResolver) AddComment(ctx context.Context, input input.CommentAd
changes.Submit("Comment", "add", token.UserID, true, changekeys.Many(comment, chapter, models.Story{ID: chapter.StoryID}), comment, chapter, story) changes.Submit("Comment", "add", token.UserID, true, changekeys.Many(comment, chapter, models.Story{ID: chapter.StoryID}), comment, chapter, story)
}() }()
return &comment, nil return comment, nil
} }
func (r *mutationResolver) EditComment(ctx context.Context, input input.CommentEditInput) (*models.Comment, error) { func (r *mutationResolver) EditComment(ctx context.Context, input input.CommentEditInput) (models.Comment, error) {
comment, err := comments.Find(input.CommentID) comment, err := comments.Find(input.CommentID)
if err != nil { if err != nil {
return nil, errors.New("Comment not found") return models.Comment{}, errors.New("Comment not found")
} }
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.PermittedUser(comment.Author, "member", "story.edit") { if !token.PermittedUser(comment.Author, "member", "story.edit") {
return nil, errors.New("You cannot edit this comment") return models.Comment{}, errors.New("You cannot edit this comment")
} }
chapter, err := chapters.FindID(comment.ChapterID) chapter, err := chapters.FindID(comment.ChapterID)
if err != nil { if err != nil {
return nil, errors.New("Comment's chapter not found") return models.Comment{}, errors.New("Comment's chapter not found")
} }
if !chapter.CanComment() { if !chapter.CanComment() {
return nil, errors.New("Comments are disabled or locked") return models.Comment{}, errors.New("Comments are disabled or locked")
} }
if input.ClearFictionalDate != nil && *input.ClearFictionalDate == true { if input.ClearFictionalDate != nil && *input.ClearFictionalDate == true {
@@ -117,15 +112,15 @@ func (r *mutationResolver) EditComment(ctx context.Context, input input.CommentE
if input.CharacterID != nil && *input.CharacterID != "" { if input.CharacterID != nil && *input.CharacterID != "" {
character, err := characters.FindID(*input.CharacterID) character, err := characters.FindID(*input.CharacterID)
if err != nil { if err != nil {
return nil, errors.New("Character not found") return models.Comment{}, errors.New("Character not found")
} else if character.Author != token.UserID { } else if character.Author != token.UserID {
return nil, errors.New("That is not your character") return models.Comment{}, errors.New("That is not your character")
} }
} }
comment, err = comments.Edit(comment, input.Source, input.CharacterName, input.CharacterID, input.Subject, input.FictionalDate) comment, err = comments.Edit(comment, input.Source, input.CharacterName, input.CharacterID, input.Subject, input.FictionalDate)
if err != nil { if err != nil {
return nil, errors.New("Could not post comment: " + err.Error()) return models.Comment{}, errors.New("Could not post comment: " + err.Error())
} }
go func() { go func() {
@@ -138,32 +133,32 @@ func (r *mutationResolver) EditComment(ctx context.Context, input input.CommentE
changes.Submit("Comment", "edit", token.UserID, true, changekeys.Many(comment, chapter, models.Story{ID: chapter.StoryID}), comment, chapter, story) changes.Submit("Comment", "edit", token.UserID, true, changekeys.Many(comment, chapter, models.Story{ID: chapter.StoryID}), comment, chapter, story)
}() }()
return &comment, nil return comment, nil
} }
func (r *mutationResolver) RemoveComment(ctx context.Context, input input.CommentRemoveInput) (*models.Comment, error) { func (r *mutationResolver) RemoveComment(ctx context.Context, input input.CommentRemoveInput) (models.Comment, error) {
comment, err := comments.Find(input.CommentID) comment, err := comments.Find(input.CommentID)
if err != nil { if err != nil {
return nil, errors.New("Comment not found") return models.Comment{}, errors.New("Comment not found")
} }
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.PermittedUser(comment.Author, "member", "story.edit") { if !token.PermittedUser(comment.Author, "member", "story.edit") {
return nil, errors.New("You cannot remove this comment") return models.Comment{}, errors.New("You cannot remove this comment")
} }
chapter, err := chapters.FindID(comment.ChapterID) chapter, err := chapters.FindID(comment.ChapterID)
if err != nil { if err != nil {
return nil, errors.New("Comment's chapter not found") return models.Comment{}, errors.New("Comment's chapter not found")
} }
if !chapter.CanComment() { if !chapter.CanComment() {
return nil, errors.New("Comments are disabled or locked") return models.Comment{}, errors.New("Comments are disabled or locked")
} }
err = comments.Remove(comment) err = comments.Remove(comment)
if err != nil { if err != nil {
return nil, errors.New("Failed to remove comment: " + err.Error()) return models.Comment{}, errors.New("Failed to remove comment: " + err.Error())
} }
go func() { go func() {
@@ -176,5 +171,5 @@ func (r *mutationResolver) RemoveComment(ctx context.Context, input input.Commen
changes.Submit("Comment", "remove", token.UserID, true, changekeys.Many(comment, chapter, models.Story{ID: chapter.StoryID}), comment, chapter, story) changes.Submit("Comment", "remove", token.UserID, true, changekeys.Many(comment, chapter, models.Story{ID: chapter.StoryID}), comment, chapter, story)
}() }()
return &comment, nil return comment, nil
} }
+4 -19
View File
@@ -8,16 +8,11 @@ import (
"git.aiterp.net/rpdata/api/models/files" "git.aiterp.net/rpdata/api/models/files"
) )
func (r *resolver) File(ctx context.Context, id string) (*models.File, error) { func (r *resolver) File(ctx context.Context, id string) (models.File, error) {
file, err := files.FindID(id) return files.FindID(id)
if err != nil {
return nil, err
} }
return &file, nil func (r *resolver) Files(ctx context.Context, filter *files.Filter) ([]models.File, error) {
}
func (r *resolver) Files(ctx context.Context, filter *files.Filter) ([]*models.File, error) {
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if filter == nil { if filter == nil {
@@ -33,17 +28,7 @@ func (r *resolver) Files(ctx context.Context, filter *files.Filter) ([]*models.F
filter.Public = &trueValue filter.Public = &trueValue
} }
files, err := files.List(filter) return files.List(filter)
if err != nil {
return nil, err
}
files2 := make([]*models.File, len(files))
for i := range files {
files2[i] = &files[i]
}
return files2, nil
} }
var trueValue = true var trueValue = true
+21 -31
View File
@@ -20,16 +20,11 @@ import (
// Queries // Queries
func (r *resolver) Log(ctx context.Context, id string) (*models.Log, error) { func (r *resolver) Log(ctx context.Context, id string) (models.Log, error) {
log, err := logs.FindID(id) return logs.FindID(id)
if err != nil {
return nil, err
} }
return &log, nil func (r *resolver) Logs(ctx context.Context, filter *logs.Filter) ([]models.Log, error) {
}
func (r *resolver) Logs(ctx context.Context, filter *logs.Filter) ([]*models.Log, error) {
logs, err := logs.List(filter) logs, err := logs.List(filter)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -56,20 +51,15 @@ func (r *resolver) Logs(ctx context.Context, filter *logs.Filter) ([]*models.Log
} }
} }
logs2 := make([]*models.Log, len(logs)) return logs, nil
for i := range logs {
logs2[i] = &logs[i]
}
return logs2, nil
} }
// Mutations // Mutations
func (r *mutationResolver) AddLog(ctx context.Context, input input.LogAddInput) (*models.Log, error) { func (r *mutationResolver) AddLog(ctx context.Context, input input.LogAddInput) (models.Log, error) {
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("log.add") { if !token.Authenticated() || !token.Permitted("log.add") {
return nil, errors.New("You are not permitted to add logs") return models.Log{}, errors.New("You are not permitted to add logs")
} }
open := input.Open != nil && *input.Open == true open := input.Open != nil && *input.Open == true
@@ -90,7 +80,7 @@ func (r *mutationResolver) AddLog(ctx context.Context, input input.LogAddInput)
log, err := logs.Add(input.Date, input.Channel, title, event, description, open) log, err := logs.Add(input.Date, input.Channel, title, event, description, open)
if !token.Authenticated() || !token.Permitted("log.add") { if !token.Authenticated() || !token.Permitted("log.add") {
return nil, errors.New("Failed to create log: " + err.Error()) return models.Log{}, errors.New("Failed to create log: " + err.Error())
} }
go func() { go func() {
@@ -104,10 +94,10 @@ func (r *mutationResolver) AddLog(ctx context.Context, input input.LogAddInput)
changes.Submit("Log", "add", token.UserID, true, changekeys.Listed(log), log) changes.Submit("Log", "add", token.UserID, true, changekeys.Listed(log), log)
}() }()
return &log, nil return log, nil
} }
func (r *mutationResolver) ImportLog(ctx context.Context, input input.LogImportInput) ([]*models.Log, error) { func (r *mutationResolver) ImportLog(ctx context.Context, input input.LogImportInput) ([]models.Log, error) {
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("log.add") { if !token.Authenticated() || !token.Permitted("log.add") {
return nil, errors.New("You are not permitted to add logs") return nil, errors.New("You are not permitted to add logs")
@@ -133,7 +123,7 @@ func (r *mutationResolver) ImportLog(ctx context.Context, input input.LogImportI
return nil, err return nil, err
} }
newLogs := make([]*models.Log, 0, len(results)) newLogs := make([]models.Log, 0, len(results))
for _, result := range results { for _, result := range results {
go func(result logs.ImportedLog) { go func(result logs.ImportedLog) {
changes.Submit("Log", "add", token.UserID, true, changekeys.Many(result.Log), result.Log) changes.Submit("Log", "add", token.UserID, true, changekeys.Many(result.Log), result.Log)
@@ -145,50 +135,50 @@ func (r *mutationResolver) ImportLog(ctx context.Context, input input.LogImportI
log = result.Log log = result.Log
} }
newLogs = append(newLogs, &log) newLogs = append(newLogs, log)
} }
return newLogs, nil return newLogs, nil
} }
func (r *mutationResolver) EditLog(ctx context.Context, input input.LogEditInput) (*models.Log, error) { func (r *mutationResolver) EditLog(ctx context.Context, input input.LogEditInput) (models.Log, error) {
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("log.edit") { if !token.Authenticated() || !token.Permitted("log.edit") {
return nil, errors.New("You are not permitted to edit logs") return models.Log{}, errors.New("You are not permitted to edit logs")
} }
log, err := logs.FindID(input.ID) log, err := logs.FindID(input.ID)
if err != nil { if err != nil {
return nil, errors.New("Log not found") return models.Log{}, errors.New("Log not found")
} }
log, err = logs.Edit(log, input.Title, input.Event, input.Description, input.Open) log, err = logs.Edit(log, input.Title, input.Event, input.Description, input.Open)
if err != nil { if err != nil {
return nil, errors.New("Failed to edit log: " + err.Error()) return models.Log{}, errors.New("Failed to edit log: " + err.Error())
} }
go changes.Submit("Log", "edit", token.UserID, true, changekeys.Listed(log), log) go changes.Submit("Log", "edit", token.UserID, true, changekeys.Listed(log), log)
return &log, nil return log, nil
} }
func (r *mutationResolver) RemoveLog(ctx context.Context, input input.LogRemoveInput) (*models.Log, error) { func (r *mutationResolver) RemoveLog(ctx context.Context, input input.LogRemoveInput) (models.Log, error) {
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("log.remove") { if !token.Authenticated() || !token.Permitted("log.remove") {
return nil, errors.New("You are not permitted to remove logs") return models.Log{}, errors.New("You are not permitted to remove logs")
} }
log, err := logs.FindID(input.ID) log, err := logs.FindID(input.ID)
if err != nil { if err != nil {
return nil, errors.New("Log not found") return models.Log{}, errors.New("Log not found")
} }
log, err = logs.Remove(log) log, err = logs.Remove(log)
if err != nil { if err != nil {
return nil, errors.New("Failed to remove log: " + err.Error()) return models.Log{}, errors.New("Failed to remove log: " + err.Error())
} }
go changes.Submit("Log", "remove", token.UserID, true, changekeys.Listed(log), log) go changes.Submit("Log", "remove", token.UserID, true, changekeys.Listed(log), log)
return &log, nil return log, nil
} }
+21 -41
View File
@@ -16,16 +16,11 @@ import (
// Queries // Queries
func (r *resolver) Post(ctx context.Context, id string) (*models.Post, error) { func (r *resolver) Post(ctx context.Context, id string) (models.Post, error) {
post, err := posts.FindID(id) return posts.FindID(id)
if err != nil {
return nil, err
} }
return &post, nil func (r *resolver) Posts(ctx context.Context, filter *posts.Filter) ([]models.Post, error) {
}
func (r *resolver) Posts(ctx context.Context, filter *posts.Filter) ([]*models.Post, error) {
// Some sanity checks to avoid querying an insame amount of posts. // Some sanity checks to avoid querying an insame amount of posts.
if filter == nil { if filter == nil {
filter = &posts.Filter{Limit: 256} filter = &posts.Filter{Limit: 256}
@@ -43,52 +38,42 @@ func (r *resolver) Posts(ctx context.Context, filter *posts.Filter) ([]*models.P
} }
} }
posts, err := posts.List(filter) return posts.List(filter)
if err != nil {
return nil, err
}
posts2 := make([]*models.Post, len(posts))
for i := range posts {
posts2[i] = &posts[i]
}
return posts2, nil
} }
// Mutation // Mutation
func (r *mutationResolver) AddPost(ctx context.Context, input input.PostAddInput) (*models.Post, error) { func (r *mutationResolver) AddPost(ctx context.Context, input input.PostAddInput) (models.Post, error) {
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("post.add") { if !token.Authenticated() || !token.Permitted("post.add") {
return nil, errors.New("You are not permitted to edit logs") return models.Post{}, errors.New("You are not permitted to edit logs")
} }
log, err := logs.FindID(input.LogID) log, err := logs.FindID(input.LogID)
if err != nil { if err != nil {
return nil, err return models.Post{}, err
} }
post, err := posts.Add(log, input.Time, input.Kind, input.Nick, input.Text) post, err := posts.Add(log, input.Time, input.Kind, input.Nick, input.Text)
if err != nil { if err != nil {
return nil, err return models.Post{}, err
} }
go logs.UpdateCharacters(log, nil) go logs.UpdateCharacters(log, nil)
go changes.Submit("Post", "add", token.UserID, true, changekeys.Many(log, post), post) go changes.Submit("Post", "add", token.UserID, true, changekeys.Many(log, post), post)
return &post, nil return post, nil
} }
func (r *mutationResolver) EditPost(ctx context.Context, input input.PostEditInput) (*models.Post, error) { func (r *mutationResolver) EditPost(ctx context.Context, input input.PostEditInput) (models.Post, error) {
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("post.edit") { if !token.Authenticated() || !token.Permitted("post.edit") {
return nil, errors.New("You are not permitted to edit logs") return models.Post{}, errors.New("You are not permitted to edit logs")
} }
post, err := posts.FindID(input.ID) post, err := posts.FindID(input.ID)
if err != nil { if err != nil {
return nil, errors.New("Post not found") return models.Post{}, errors.New("Post not found")
} }
if input.Nick != nil { if input.Nick != nil {
@@ -104,7 +89,7 @@ func (r *mutationResolver) EditPost(ctx context.Context, input input.PostEditInp
post, err = posts.Edit(post, input.Time, input.Kind, input.Nick, input.Text) post, err = posts.Edit(post, input.Time, input.Kind, input.Nick, input.Text)
if err != nil { if err != nil {
return nil, errors.New("Adding post failed: " + err.Error()) return models.Post{}, errors.New("Adding post failed: " + err.Error())
} }
go func() { go func() {
@@ -116,10 +101,10 @@ func (r *mutationResolver) EditPost(ctx context.Context, input input.PostEditInp
changes.Submit("Post", "edit", token.UserID, true, changekeys.Many(log, post), post) changes.Submit("Post", "edit", token.UserID, true, changekeys.Many(log, post), post)
}() }()
return &post, nil return post, nil
} }
func (r *mutationResolver) MovePost(ctx context.Context, input input.PostMoveInput) ([]*models.Post, error) { func (r *mutationResolver) MovePost(ctx context.Context, input input.PostMoveInput) ([]models.Post, error) {
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("post.move") { if !token.Authenticated() || !token.Permitted("post.move") {
return nil, errors.New("You are not permitted to edit logs") return nil, errors.New("You are not permitted to edit logs")
@@ -144,28 +129,23 @@ func (r *mutationResolver) MovePost(ctx context.Context, input input.PostMoveInp
changes.Submit("Post", "move", token.UserID, true, changekeys.Many(log, posts), posts) changes.Submit("Post", "move", token.UserID, true, changekeys.Many(log, posts), posts)
}() }()
posts2 := make([]*models.Post, len(posts)) return posts, nil
for i := range posts {
posts2[i] = &posts[i]
} }
return posts2, nil func (r *mutationResolver) RemovePost(ctx context.Context, input input.PostRemoveInput) (models.Post, error) {
}
func (r *mutationResolver) RemovePost(ctx context.Context, input input.PostRemoveInput) (*models.Post, error) {
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.Authenticated() || !token.Permitted("post.remove") { if !token.Authenticated() || !token.Permitted("post.remove") {
return nil, errors.New("You are not permitted to edit logs") return models.Post{}, errors.New("You are not permitted to edit logs")
} }
post, err := posts.FindID(input.ID) post, err := posts.FindID(input.ID)
if err != nil { if err != nil {
return nil, errors.New("Post not found (before removing, of course)") return models.Post{}, errors.New("Post not found (before removing, of course)")
} }
post, err = posts.Remove(post) post, err = posts.Remove(post)
if err != nil { if err != nil {
return nil, errors.New("Could not remove post: " + err.Error()) return models.Post{}, errors.New("Could not remove post: " + err.Error())
} }
go func() { go func() {
@@ -178,5 +158,5 @@ func (r *mutationResolver) RemovePost(ctx context.Context, input input.PostRemov
changes.Submit("Post", "remove", token.UserID, true, changekeys.Many(log, post), post) changes.Submit("Post", "remove", token.UserID, true, changekeys.Many(log, post), post)
}() }()
return &post, nil return post, nil
} }
+14 -34
View File
@@ -16,15 +16,10 @@ import (
) )
func (r *resolver) Story(ctx context.Context, id string) (*models.Story, error) { func (r *resolver) Story(ctx context.Context, id string) (*models.Story, error) {
story, err := stories.FindID(id) return stories.FindID(id)
if err != nil {
return nil, err
} }
return &story, nil func (r *resolver) Stories(ctx context.Context, filter *stories.Filter) ([]models.Story, error) {
}
func (r *resolver) Stories(ctx context.Context, filter *stories.Filter) ([]*models.Story, error) {
if filter != nil { if filter != nil {
if filter.Unlisted != nil && *filter.Unlisted == true { if filter.Unlisted != nil && *filter.Unlisted == true {
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
@@ -38,17 +33,7 @@ func (r *resolver) Stories(ctx context.Context, filter *stories.Filter) ([]*mode
} }
} }
stories, err := stories.List(filter) return stories.List(filter)
if err != nil {
return nil, err
}
stories2 := make([]*models.Story, len(stories))
for i := range stories {
stories2[i] = &stories[i]
}
return stories2, nil
} }
// Mutations // Mutations
@@ -76,19 +61,14 @@ func (r *mutationResolver) AddStory(ctx context.Context, input input.StoryAddInp
listed := input.Listed != nil && *input.Listed listed := input.Listed != nil && *input.Listed
open := input.Open != nil && *input.Open open := input.Open != nil && *input.Open
tags := make([]models.Tag, len(input.Tags)) story, err := stories.Add(input.Name, author, input.Category, listed, open, input.Tags, time.Now(), fictionalDate)
for i := range input.Tags {
tags[i] = *input.Tags[i]
}
story, err := stories.Add(input.Name, author, input.Category, listed, open, tags, time.Now(), fictionalDate)
if err != nil { if err != nil {
return nil, errors.New("Failed to add story: " + err.Error()) return nil, errors.New("Failed to add story: " + err.Error())
} }
go changes.Submit("Story", "add", token.UserID, story.Listed, changekeys.Listed(story), story) go changes.Submit("Story", "add", token.UserID, story.Listed, changekeys.Listed(story), story)
return &story, nil return story, nil
} }
func (r *mutationResolver) AddStoryTag(ctx context.Context, input input.StoryTagAddInput) (*models.Story, error) { func (r *mutationResolver) AddStoryTag(ctx context.Context, input input.StoryTagAddInput) (*models.Story, error) {
@@ -109,14 +89,14 @@ func (r *mutationResolver) AddStoryTag(ctx context.Context, input input.StoryTag
} }
} }
story, err = stories.AddTag(story, *input.Tag) story, err = stories.AddTag(*story, input.Tag)
if err != nil { if err != nil {
return nil, errors.New("Failed to add story: " + err.Error()) return nil, errors.New("Failed to add story: " + err.Error())
} }
go changes.Submit("Story", "tag", token.UserID, story.Listed, changekeys.Listed(story), story, input.Tag) go changes.Submit("Story", "tag", token.UserID, story.Listed, changekeys.Listed(story), story, input.Tag)
return &story, nil return story, nil
} }
func (r *mutationResolver) RemoveStoryTag(ctx context.Context, input input.StoryTagRemoveInput) (*models.Story, error) { func (r *mutationResolver) RemoveStoryTag(ctx context.Context, input input.StoryTagRemoveInput) (*models.Story, error) {
@@ -137,14 +117,14 @@ func (r *mutationResolver) RemoveStoryTag(ctx context.Context, input input.Story
} }
} }
story, err = stories.RemoveTag(story, *input.Tag) story, err = stories.RemoveTag(*story, input.Tag)
if err != nil { if err != nil {
return nil, errors.New("Failed to add story: " + err.Error()) return nil, errors.New("Failed to add story: " + err.Error())
} }
go changes.Submit("Story", "untag", token.UserID, story.Listed, changekeys.Listed(story), story, input.Tag) go changes.Submit("Story", "untag", token.UserID, story.Listed, changekeys.Listed(story), story, input.Tag)
return &story, nil return story, nil
} }
func (r *mutationResolver) EditStory(ctx context.Context, input input.StoryEditInput) (*models.Story, error) { func (r *mutationResolver) EditStory(ctx context.Context, input input.StoryEditInput) (*models.Story, error) {
@@ -163,14 +143,14 @@ func (r *mutationResolver) EditStory(ctx context.Context, input input.StoryEditI
input.FictionalDate = &time.Time{} input.FictionalDate = &time.Time{}
} }
story, err = stories.Edit(story, input.Name, input.Category, input.Listed, input.Open, input.FictionalDate) story, err = stories.Edit(*story, input.Name, input.Category, input.Listed, input.Open, input.FictionalDate)
if err != nil { if err != nil {
return nil, errors.New("Failed to add story: " + err.Error()) return nil, errors.New("Failed to add story: " + err.Error())
} }
go changes.Submit("Story", "edit", token.UserID, story.Listed, changekeys.Listed(story), story) go changes.Submit("Story", "edit", token.UserID, story.Listed, changekeys.Listed(story), story)
return &story, nil return story, nil
} }
func (r *mutationResolver) RemoveStory(ctx context.Context, input input.StoryRemoveInput) (*models.Story, error) { func (r *mutationResolver) RemoveStory(ctx context.Context, input input.StoryRemoveInput) (*models.Story, error) {
@@ -185,17 +165,17 @@ func (r *mutationResolver) RemoveStory(ctx context.Context, input input.StoryRem
return nil, errors.New("You are not permitted to remove this story") return nil, errors.New("You are not permitted to remove this story")
} }
story, err = stories.Remove(story) story, err = stories.Remove(*story)
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = chapters.RemoveStory(story) err = chapters.RemoveStory(*story)
if err != nil { if err != nil {
return nil, errors.New("Failed to remove chapters, but story is removed: " + err.Error()) return nil, errors.New("Failed to remove chapters, but story is removed: " + err.Error())
} }
go changes.Submit("Story", "remove", token.UserID, story.Listed, changekeys.Listed(story), story) go changes.Submit("Story", "remove", token.UserID, story.Listed, changekeys.Listed(story), story)
return &story, nil return story, nil
} }
+2 -12
View File
@@ -7,16 +7,6 @@ import (
"git.aiterp.net/rpdata/api/models/tags" "git.aiterp.net/rpdata/api/models/tags"
) )
func (r *resolver) Tags(ctx context.Context) ([]*models.Tag, error) { func (r *resolver) Tags(ctx context.Context) ([]models.Tag, error) {
tags, err := tags.List() return tags.List()
if err != nil {
return nil, err
}
tags2 := make([]*models.Tag, len(tags))
for i := range tags {
tags2[i] = &tags[i]
}
return tags2, nil
} }
+3 -3
View File
@@ -8,11 +8,11 @@ import (
"git.aiterp.net/rpdata/api/models" "git.aiterp.net/rpdata/api/models"
) )
func (r *resolver) Token(ctx context.Context) (*models.Token, error) { func (r *resolver) Token(ctx context.Context) (models.Token, error) {
token := auth.TokenFromContext(ctx) token := auth.TokenFromContext(ctx)
if !token.Authenticated() { if !token.Authenticated() {
return nil, errors.New("No (valid) token") return models.Token{}, errors.New("No (valid) token")
} }
return token, nil return *token, nil
} }
+2 -12
View File
@@ -11,7 +11,7 @@ import (
/// Queries /// Queries
func (r *resolver) UnknownNicks(ctx context.Context, filter *input.UnknownNicksFilter) ([]*models.UnknownNick, error) { func (r *resolver) UnknownNicks(ctx context.Context, filter *input.UnknownNicksFilter) ([]models.UnknownNick, error) {
limit := 100 limit := 100
if filter != nil { if filter != nil {
if filter.Limit > 0 { if filter.Limit > 0 {
@@ -19,15 +19,5 @@ func (r *resolver) UnknownNicks(ctx context.Context, filter *input.UnknownNicksF
} }
} }
nicks, err := unknownnicks.List(limit) return unknownnicks.List(limit)
if err != nil {
return nil, err
}
nicks2 := make([]*models.UnknownNick, len(nicks))
for i := range nicks {
nicks2[i] = &nicks[i]
}
return nicks2, nil
} }
+3 -3
View File
@@ -15,10 +15,10 @@ func (r *changeResolver) Objects(ctx context.Context, obj *models.Change) ([]inp
results := make([]input.ChangeObject, 0, len(objects)) results := make([]input.ChangeObject, 0, len(objects))
for _, object := range objects { for _, object := range objects {
if changeObject, ok := object.(input.ChangeObject); ok { if cObj, ok := object.(input.ChangeObject); ok {
results = append(results, changeObject) results = append(results, cObj)
} else { } else {
log.Printf("Type %T needs ChangeObject impl", object) log.Printf("Warning: %T is not a change object", object)
} }
} }
+2 -12
View File
@@ -19,7 +19,7 @@ func (r *chapterResolver) FictionalDate(ctx context.Context, chapter *models.Cha
return &chapter.FictionalDate, nil return &chapter.FictionalDate, nil
} }
func (r *chapterResolver) Comments(ctx context.Context, chapter *models.Chapter, limit *int) ([]*models.Comment, error) { func (r *chapterResolver) Comments(ctx context.Context, chapter *models.Chapter, limit *int) ([]models.Comment, error) {
limitValue := 0 limitValue := 0
if limit != nil { if limit != nil {
if *limit < 0 { if *limit < 0 {
@@ -33,17 +33,7 @@ func (r *chapterResolver) Comments(ctx context.Context, chapter *models.Chapter,
return nil, nil return nil, nil
} }
comments, err := comments.ListChapterID(chapter.ID, limitValue) return comments.ListChapterID(chapter.ID, limitValue)
if err != nil {
return nil, err
}
comments2 := make([]*models.Comment, len(comments))
for i := range comments {
comments2[i] = &comments[i]
}
return comments2, nil
} }
// ChapterResolver is a resolver // ChapterResolver is a resolver
+16
View File
@@ -0,0 +1,16 @@
package types
import (
"context"
"git.aiterp.net/rpdata/api/models"
)
type fileResolver struct{}
func (r *fileResolver) Size(ctx context.Context, file *models.File) (int, error) {
return int(file.Size), nil
}
// FileResolver is a resolver
var FileResolver fileResolver
+10 -26
View File
@@ -11,46 +11,30 @@ import (
type logResolver struct{} type logResolver struct{}
func (r *logResolver) Channel(ctx context.Context, log *models.Log) (*models.Channel, error) { func (r *logResolver) Channel(ctx context.Context, log *models.Log) (models.Channel, error) {
loader := loader.FromContext(ctx) loader := loader.FromContext(ctx)
if loader == nil { if loader == nil {
return nil, errors.New("no loader") return models.Channel{}, errors.New("no loader")
} }
return loader.Channel("name", log.ChannelName) return loader.Channel("name", log.ChannelName)
} }
func (r *logResolver) Characters(ctx context.Context, log *models.Log) ([]*models.Character, error) { func (r *logResolver) Characters(ctx context.Context, log *models.Log) ([]models.Character, error) {
loader := loader.FromContext(ctx) loader := loader.FromContext(ctx)
if loader == nil { if loader == nil {
return nil, errors.New("no loader") return nil, errors.New("no loader")
} }
characters, err := loader.Characters("id", log.CharacterIDs...) return loader.Characters("id", log.CharacterIDs...)
if err != nil {
return nil, err
} }
characters2 := make([]*models.Character, len(characters)) func (r *logResolver) Posts(ctx context.Context, log *models.Log, kinds []string) ([]models.Post, error) {
for i := range characters { return posts.List(&posts.Filter{
characters2[i] = &characters[i] LogID: &log.ShortID,
} Kind: kinds,
Limit: 0,
return characters2, nil })
}
func (r *logResolver) Posts(ctx context.Context, log *models.Log, kinds []string) ([]*models.Post, error) {
posts, err := posts.List(&posts.Filter{LogID: &log.ShortID, Kind: kinds, Limit: 0})
if err != nil {
return nil, err
}
posts2 := make([]*models.Post, len(posts))
for i := range posts {
posts2[i] = &posts[i]
}
return posts2, nil
} }
// LogResolver is a resolver // LogResolver is a resolver
+2 -12
View File
@@ -19,18 +19,8 @@ func (r *storyResolver) FictionalDate(ctx context.Context, story *models.Story)
return &story.FictionalDate, nil return &story.FictionalDate, nil
} }
func (r *storyResolver) Chapters(ctx context.Context, story *models.Story) ([]*models.Chapter, error) { func (r *storyResolver) Chapters(ctx context.Context, story *models.Story) ([]models.Chapter, error) {
chapters, err := chapters.ListStoryID(story.ID) return chapters.ListStoryID(story.ID)
if err != nil {
return nil, err
}
chapters2 := make([]*models.Chapter, len(chapters))
for i := range chapters {
chapters2[i] = &chapters[i]
}
return chapters2, nil
} }
// StoryResolver is a resolver // StoryResolver is a resolver
+2 -7
View File
@@ -9,13 +9,8 @@ import (
type tokenResolver struct{} type tokenResolver struct{}
func (r *tokenResolver) User(ctx context.Context, token *models.Token) (*models.User, error) { func (r *tokenResolver) User(ctx context.Context, token *models.Token) (models.User, error) {
user, err := users.Find(token.UserID) return users.Find(token.UserID)
if err != nil {
return nil, err
}
return &user, nil
} }
// TokenResolver is a resolver // TokenResolver is a resolver
-346
View File
@@ -1,346 +0,0 @@
package instrumentation
import (
"context"
"reflect"
"sort"
"strings"
"sync"
"time"
"github.com/99designs/gqlgen/graphql"
prometheusclient "github.com/prometheus/client_golang/prometheus"
)
const (
existStatusFailure = "failure"
exitStatusSuccess = "success"
)
var latencyMapMutex sync.Mutex
var latencyMap = make(map[string]float64, 128)
type ctxKeyType string
var ctxKey = ctxKeyType("metricglobal")
var (
requestStartedCounter prometheusclient.Counter
requestCompletedCounter prometheusclient.Counter
requestFailureCounter *prometheusclient.CounterVec
requestSuccessCounter *prometheusclient.CounterVec
requestComplexityHisto prometheusclient.Histogram
resolverStartedCounter *prometheusclient.CounterVec
resolverCompletedCounter *prometheusclient.CounterVec
timeToResolveField *prometheusclient.HistogramVec
timeToHandleRequest *prometheusclient.HistogramVec
timeToHandleRequestQueryMAvg *prometheusclient.GaugeVec
timeToHandleRequestQueryTotal *prometheusclient.CounterVec
responseSizeMAvg *prometheusclient.GaugeVec
responseSizeTotal *prometheusclient.CounterVec
)
// Globals is monitoring data.
type Globals struct {
sync.Mutex
Queries []string
Failed bool
}
// Register registers the prometheus metrics.
func Register() {
requestStartedCounter = prometheusclient.NewCounter(
prometheusclient.CounterOpts{
Name: "graphql_request_started_total",
Help: "Total number of requests started on the graphql server.",
},
)
requestCompletedCounter = prometheusclient.NewCounter(
prometheusclient.CounterOpts{
Name: "graphql_request_completed_total",
Help: "Total number of requests completed on the graphql server.",
},
)
requestFailureCounter = prometheusclient.NewCounterVec(
prometheusclient.CounterOpts{
Name: "graphql_request_failures",
Help: "Number of requests with either success or failure status.",
},
[]string{"queries"},
)
requestSuccessCounter = prometheusclient.NewCounterVec(
prometheusclient.CounterOpts{
Name: "graphql_request_successes",
Help: "Number of requests with either success or failure status.",
},
[]string{"queries"},
)
requestComplexityHisto = prometheusclient.NewHistogram(
prometheusclient.HistogramOpts{
Name: "graphql_request_complexity",
Help: "The complexity value of incoming queries.",
Buckets: prometheusclient.LinearBuckets(100, 25, 9),
},
)
resolverStartedCounter = prometheusclient.NewCounterVec(
prometheusclient.CounterOpts{
Name: "graphql_resolver_started_total",
Help: "Total number of resolver started on the graphql server.",
},
[]string{"object", "field"},
)
resolverCompletedCounter = prometheusclient.NewCounterVec(
prometheusclient.CounterOpts{
Name: "graphql_resolver_completed_total",
Help: "Total number of resolver completed on the graphql server.",
},
[]string{"object", "field"},
)
timeToResolveField = prometheusclient.NewHistogramVec(prometheusclient.HistogramOpts{
Name: "graphql_resolver_duration_ms",
Help: "The time taken to resolve a field by graphql server.",
Buckets: prometheusclient.ExponentialBuckets(1, 2, 11),
}, []string{"exitStatus"})
timeToHandleRequest = prometheusclient.NewHistogramVec(prometheusclient.HistogramOpts{
Name: "graphql_request_duration_ms",
Help: "The time taken to handle a request by graphql server.",
Buckets: prometheusclient.ExponentialBuckets(1, 2, 11),
}, []string{"exitStatus"})
timeToHandleRequestQueryMAvg = prometheusclient.NewGaugeVec(
prometheusclient.GaugeOpts{
Name: "graphql_request_query_duration_mavg_ms",
Help: "Moving average of graphql request query duration for a query set.",
},
[]string{"queries"},
)
timeToHandleRequestQueryTotal = prometheusclient.NewCounterVec(
prometheusclient.CounterOpts{
Name: "graphql_request_query_duration_total_ms",
Help: "Total duration spent responding to a query.",
},
[]string{"queries"},
)
responseSizeMAvg = prometheusclient.NewGaugeVec(
prometheusclient.GaugeOpts{
Name: "graphql_response_size_mavg_bytes",
Help: "Moving average of graphql response size for a query set.",
},
[]string{"queries"},
)
responseSizeTotal = prometheusclient.NewCounterVec(
prometheusclient.CounterOpts{
Name: "graphql_response_size_total_bytes",
Help: "Total bytes of response data to a query.",
},
[]string{"queries"},
)
prometheusclient.MustRegister(
requestStartedCounter,
requestCompletedCounter,
requestSuccessCounter,
requestFailureCounter,
requestComplexityHisto,
resolverStartedCounter,
resolverCompletedCounter,
timeToResolveField,
timeToHandleRequest,
timeToHandleRequestQueryMAvg,
timeToHandleRequestQueryTotal,
responseSizeMAvg,
responseSizeTotal,
)
}
// UnRegister unregisters
func UnRegister() {
prometheusclient.Unregister(requestStartedCounter)
prometheusclient.Unregister(requestCompletedCounter)
prometheusclient.Unregister(requestSuccessCounter)
prometheusclient.Unregister(requestFailureCounter)
prometheusclient.Unregister(requestComplexityHisto)
prometheusclient.Unregister(resolverStartedCounter)
prometheusclient.Unregister(resolverCompletedCounter)
prometheusclient.Unregister(timeToResolveField)
prometheusclient.Unregister(timeToHandleRequest)
prometheusclient.Unregister(timeToHandleRequestQueryMAvg)
prometheusclient.Unregister(timeToHandleRequestQueryTotal)
prometheusclient.Unregister(responseSizeMAvg)
prometheusclient.Unregister(responseSizeTotal)
}
// ResolverMiddleware is a resolver middleware that logs metrics for prometheus.
func ResolverMiddleware() graphql.FieldMiddleware {
return func(ctx context.Context, next graphql.Resolver) (interface{}, error) {
rctx := graphql.GetResolverContext(ctx)
resolverStartedCounter.WithLabelValues(rctx.Object, rctx.Field.Name).Inc()
observerStart := time.Now()
path := rctx.Path()
if len(path) == 1 {
if globals, ok := ctx.Value(ctxKey).(*Globals); ok {
globals.Lock()
if rctx.Field.Field != nil {
globals.Queries = append(globals.Queries, rctx.Field.Name+"("+argsLabel(rctx.Args)+")")
} else if name, ok := path[0].(string); ok {
globals.Queries = append(globals.Queries, name)
}
globals.Unlock()
}
}
res, err := next(ctx)
var exitStatus string
if err != nil {
exitStatus = existStatusFailure
if globals, ok := ctx.Value(ctxKey).(*Globals); ok {
globals.Lock()
globals.Failed = true
globals.Unlock()
}
} else {
exitStatus = exitStatusSuccess
}
exitStatusLabel := prometheusclient.Labels{"exitStatus": exitStatus}
timeToResolveField.With(exitStatusLabel).Observe(float64(time.Since(observerStart).Nanoseconds() / int64(time.Millisecond)))
resolverCompletedCounter.WithLabelValues(rctx.Object, rctx.Field.Name).Inc()
return res, err
}
}
// RequestMiddleware is a request middleware that logs metrics for prometheus. It looks busy, but the
// overhead is less than 10µs.
func RequestMiddleware() graphql.RequestMiddleware {
return func(ctx context.Context, next func(ctx context.Context) []byte) []byte {
requestStartedCounter.Inc()
// Store some values in a global context.
globals := Globals{}
// Measure the time to serve the request
observerStart := time.Now()
res := next(context.WithValue(ctx, ctxKey, &globals))
observedDuration := time.Since(observerStart)
observedDurationMS := float64(observedDuration.Nanoseconds()) / float64(time.Millisecond)
reqCtx := graphql.GetRequestContext(ctx)
// exitStatus label
exitStatusLabel := prometheusclient.Labels{"exitStatus": exitStatusSuccess}
if globals.Failed {
exitStatusLabel["exitStatus"] = existStatusFailure
}
// queries label
sort.Strings(globals.Queries)
queriesStr := strings.Join(globals.Queries, ";")
queriesLabel := prometheusclient.Labels{
"queries": queriesStr,
}
// Write metrics
timeToHandleRequest.With(exitStatusLabel).Observe(observedDurationMS)
requestCompletedCounter.Inc()
if len(globals.Queries) > 0 {
if globals.Failed {
requestFailureCounter.With(queriesLabel).Inc()
} else {
requestSuccessCounter.With(queriesLabel).Inc()
}
timeToHandleRequestQueryMAvg.With(queriesLabel).Set(movingAvgLatency("ms:"+queriesStr, observedDurationMS))
timeToHandleRequestQueryTotal.With(queriesLabel).Add(observedDurationMS)
responseSizeMAvg.With(queriesLabel).Set(movingAvgLatency("bytes:"+queriesStr, float64(len(res))))
responseSizeTotal.With(queriesLabel).Add(float64(len(res)))
}
requestComplexityHisto.Observe(float64(reqCtx.OperationComplexity))
return res
}
}
func movingAvgLatency(key string, sample float64) float64 {
latencyMapMutex.Lock()
latency, ok := latencyMap[key]
if ok {
latency = (latency * 0.9) + (sample * 0.1)
latencyMap[key] = latency
} else {
latencyMap[key] = sample
latency = sample
}
latencyMapMutex.Unlock()
return latency
}
func argsLabel(args map[string]interface{}) string {
result := ""
for key, value := range args {
if len(result) > 0 {
result += ","
}
result = key
rv := reflect.ValueOf(value)
for rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
if rv.Kind() != reflect.Struct {
continue
}
result += "{"
first := true
for i := 0; i < rv.NumField(); i++ {
rf := rv.Field(i)
if (rf.Kind() == reflect.Ptr || rf.Kind() == reflect.Interface) && rf.IsNil() {
continue
}
rtf := rv.Type().Field(i)
// Empty limits are as good as no limit
if rtf.Name == "Limit" && rf.Type().Kind() == reflect.Int && rf.Int() <= 0 {
continue
}
if !first {
result += ","
}
first = false
jsonTag := rtf.Tag.Get("json")
if jsonTag != "" {
result += jsonTag
} else {
result += strings.ToLower(rtf.Name[0:1]) + rtf.Name[1:]
}
}
result += "}"
}
return result
}
+5 -5
View File
@@ -11,13 +11,13 @@ import (
) )
// Channel gets a character by key // Channel gets a character by key
func (loader *Loader) Channel(key, value string) (*models.Channel, error) { func (loader *Loader) Channel(key, value string) (models.Channel, error) {
if !strings.HasPrefix(key, "Channel.") { if !strings.HasPrefix(key, "Channel.") {
key = "Channel." + key key = "Channel." + key
} }
if loader.loaders[key] == nil { if loader.loaders[key] == nil {
return nil, errors.New("unsupported key") return models.Channel{}, errors.New("unsupported key")
} }
loader.loadPrimed(key) loader.loadPrimed(key)
@@ -25,15 +25,15 @@ func (loader *Loader) Channel(key, value string) (*models.Channel, error) {
thunk := loader.loaders[key].Load(loader.ctx, dataloader.StringKey(value)) thunk := loader.loaders[key].Load(loader.ctx, dataloader.StringKey(value))
res, err := thunk() res, err := thunk()
if err != nil { if err != nil {
return nil, err return models.Channel{}, err
} }
channel, ok := res.(models.Channel) channel, ok := res.(models.Channel)
if !ok { if !ok {
return nil, errors.New("incorrect type") return channel, errors.New("incorrect type")
} }
return &channel, nil return channel, nil
} }
// PrimeChannels primes channels for loading along with the first one. // PrimeChannels primes channels for loading along with the first one.
+8 -8
View File
@@ -33,28 +33,28 @@ func (change *Change) Objects() []interface{} {
data := make([]interface{}, 0, len(change.Logs)+len(change.Characters)+len(change.Channels)+len(change.Posts)+len(change.Stories)+len(change.Tags)+len(change.Chapters)+len(change.Comments)) data := make([]interface{}, 0, len(change.Logs)+len(change.Characters)+len(change.Channels)+len(change.Posts)+len(change.Stories)+len(change.Tags)+len(change.Chapters)+len(change.Comments))
for _, log := range change.Logs { for _, log := range change.Logs {
data = append(data, &log) data = append(data, log)
} }
for _, channel := range change.Channels { for _, channel := range change.Channels {
data = append(data, &channel) data = append(data, channel)
} }
for _, character := range change.Characters { for _, character := range change.Characters {
data = append(data, &character) data = append(data, character)
} }
for _, post := range change.Posts { for _, post := range change.Posts {
data = append(data, &post) data = append(data, post)
} }
for _, story := range change.Stories { for _, story := range change.Stories {
data = append(data, &story) data = append(data, story)
} }
for _, tag := range change.Tags { for _, tag := range change.Tags {
data = append(data, &tag) data = append(data, tag)
} }
for _, chapter := range change.Chapters { for _, chapter := range change.Chapters {
data = append(data, &chapter) data = append(data, chapter)
} }
for _, comment := range change.Comments { for _, comment := range change.Comments {
data = append(data, &comment) data = append(data, comment)
} }
return data return data
+5 -7
View File
@@ -12,13 +12,13 @@ var subList []*subscription
type subscription struct { type subscription struct {
Keys map[string]bool Keys map[string]bool
Channel chan<- *models.Change Channel chan<- models.Change
WildCard bool WildCard bool
} }
// Subscribe subscribes to all changes. // Subscribe subscribes to all changes.
func Subscribe(ctx context.Context, keys []models.ChangeKey, wildcard bool) <-chan *models.Change { func Subscribe(ctx context.Context, keys []models.ChangeKey, wildcard bool) <-chan models.Change {
channel := make(chan *models.Change, 64) channel := make(chan models.Change, 64)
sub := &subscription{ sub := &subscription{
Keys: make(map[string]bool, len(keys)), Keys: make(map[string]bool, len(keys)),
Channel: channel, Channel: channel,
@@ -58,18 +58,16 @@ func pushToSubscribers(change models.Change) {
subMutex.Lock() subMutex.Lock()
SubLoop: SubLoop:
for _, sub := range subList { for _, sub := range subList {
changeCopy := change
if sub.WildCard && change.Listed { if sub.WildCard && change.Listed {
select { select {
case sub.Channel <- &changeCopy: case sub.Channel <- change:
default: default:
} }
} else { } else {
for _, key := range keys { for _, key := range keys {
if sub.Keys[key] { if sub.Keys[key] {
select { select {
case sub.Channel <- &changeCopy: case sub.Channel <- change:
default: default:
} }
+2 -3
View File
@@ -9,8 +9,7 @@ type Channel struct {
LocationName string `bson:"locationName,omitempty"` LocationName string `bson:"locationName,omitempty"`
} }
// IsChangeObject is an interface implementation to identify it as a valid // IsChangeObject is a dummy interface implementation
// ChangeObject in GQL.
func (*Channel) IsChangeObject() { func (*Channel) IsChangeObject() {
panic("this method is a dummy, and so is its caller") // Dummy interface implementation
} }
+4 -4
View File
@@ -11,9 +11,9 @@ import (
var ErrInvalidName = errors.New("Invalid channel name") var ErrInvalidName = errors.New("Invalid channel name")
// Add creates a new channel. // Add creates a new channel.
func Add(name string, logged, hub bool, event, location string) (models.Channel, error) { func Add(name string, logged, hub bool, event, location string) (*models.Channel, error) {
if len(name) < 3 && !strings.HasPrefix(name, "#") { if len(name) < 3 && !strings.HasPrefix(name, "#") {
return models.Channel{}, ErrInvalidName return nil, ErrInvalidName
} }
channel := models.Channel{ channel := models.Channel{
@@ -26,8 +26,8 @@ func Add(name string, logged, hub bool, event, location string) (models.Channel,
err := collection.Insert(channel) err := collection.Insert(channel)
if err != nil { if err != nil {
return models.Channel{}, err return nil, err
} }
return channel, nil return &channel, nil
} }
+4 -4
View File
@@ -6,7 +6,7 @@ import (
) )
// Edit edits a channels // Edit edits a channels
func Edit(channel models.Channel, logged, hub *bool, eventName, locationName *string) (models.Channel, error) { func Edit(channel models.Channel, logged, hub *bool, eventName, locationName *string) (*models.Channel, error) {
mutation := bson.M{} mutation := bson.M{}
if logged != nil && *logged != channel.Logged { if logged != nil && *logged != channel.Logged {
@@ -27,13 +27,13 @@ func Edit(channel models.Channel, logged, hub *bool, eventName, locationName *st
} }
if len(mutation) == 0 { if len(mutation) == 0 {
return channel, nil return &channel, nil
} }
err := collection.UpdateId(channel.Name, bson.M{"$set": mutation}) err := collection.UpdateId(channel.Name, bson.M{"$set": mutation})
if err != nil { if err != nil {
return models.Channel{}, err return nil, err
} }
return channel, nil return &channel, nil
} }
+5 -5
View File
@@ -10,22 +10,22 @@ import (
// Ensure adds a channel if it doesn't exist. If logged is set and the found channel isn't logged, // Ensure adds a channel if it doesn't exist. If logged is set and the found channel isn't logged,
// that is changed. // that is changed.
func Ensure(name string, logged bool) (models.Channel, error) { func Ensure(name string, logged bool) (*models.Channel, error) {
if len(name) < 3 && !strings.HasPrefix(name, "#") { if len(name) < 3 && !strings.HasPrefix(name, "#") {
return models.Channel{}, ErrInvalidName return nil, ErrInvalidName
} }
channel, err := FindName(name) channel, err := FindName(name)
if err == mgo.ErrNotFound { if err == mgo.ErrNotFound {
return Add(name, logged, false, "", "") return Add(name, logged, false, "", "")
} else if err != nil { } else if err != nil {
return models.Channel{}, err return nil, err
} }
if logged && !channel.Logged { if logged && !channel.Logged {
channel, err = Edit(channel, &logged, nil, nil, nil) channel, err = Edit(*channel, &logged, nil, nil, nil)
if err != nil { if err != nil {
return models.Channel{}, err return nil, err
} }
} }
+5 -2
View File
@@ -3,9 +3,12 @@ package channels
import "git.aiterp.net/rpdata/api/models" import "git.aiterp.net/rpdata/api/models"
// FindName finds a channel by its id (its name). // FindName finds a channel by its id (its name).
func FindName(name string) (models.Channel, error) { func FindName(name string) (*models.Channel, error) {
channel := models.Channel{} channel := models.Channel{}
err := collection.FindId(name).One(&channel) err := collection.FindId(name).One(&channel)
if err != nil {
return nil, err
}
return channel, err return &channel, nil
} }
+2 -3
View File
@@ -21,8 +21,7 @@ func (chapter *Chapter) CanComment() bool {
return !chapter.CommentsLocked && chapter.CommentMode.IsEnabled() return !chapter.CommentsLocked && chapter.CommentMode.IsEnabled()
} }
// IsChangeObject is an interface implementation to identify it as a valid // IsChangeObject is a dummy interface implementation
// ChangeObject in GQL.
func (*Chapter) IsChangeObject() { func (*Chapter) IsChangeObject() {
panic("this method is a dummy, and so is its caller") // Dummy interface implementation
} }
+3 -3
View File
@@ -8,7 +8,7 @@ import (
) )
// Add adds a new chapter. // Add adds a new chapter.
func Add(story models.Story, title, author, source string, createdDate time.Time, finctionalDate *time.Time, commentMode models.ChapterCommentMode) (models.Chapter, error) { func Add(story models.Story, title, author, source string, createdDate time.Time, finctionalDate *time.Time, commentMode models.ChapterCommentMode) (*models.Chapter, error) {
chapter := models.Chapter{ chapter := models.Chapter{
ID: makeChapterID(), ID: makeChapterID(),
StoryID: story.ID, StoryID: story.ID,
@@ -27,7 +27,7 @@ func Add(story models.Story, title, author, source string, createdDate time.Time
err := collection.Insert(chapter) err := collection.Insert(chapter)
if err != nil { if err != nil {
return models.Chapter{}, err return nil, err
} }
if createdDate.After(story.UpdatedDate) { if createdDate.After(story.UpdatedDate) {
@@ -36,5 +36,5 @@ func Add(story models.Story, title, author, source string, createdDate time.Time
} }
} }
return chapter, nil return &chapter, nil
} }
+5 -2
View File
@@ -13,11 +13,14 @@ import (
var collection *mgo.Collection var collection *mgo.Collection
var storyCollection *mgo.Collection var storyCollection *mgo.Collection
func find(query interface{}) (models.Chapter, error) { func find(query interface{}) (*models.Chapter, error) {
chapter := models.Chapter{} chapter := models.Chapter{}
err := collection.Find(query).One(&chapter) err := collection.Find(query).One(&chapter)
if err != nil {
return nil, err
}
return chapter, err return &chapter, err
} }
func list(query interface{}) ([]models.Chapter, error) { func list(query interface{}) ([]models.Chapter, error) {
+3 -3
View File
@@ -9,7 +9,7 @@ import (
// Edit edits a chapter, and updates EditedDate. While many Edit functions cheat if there's nothing to // Edit edits a chapter, and updates EditedDate. While many Edit functions cheat if there's nothing to
// change, this functill will due to EditedDate. // change, this functill will due to EditedDate.
func Edit(chapter models.Chapter, title, source *string, fictionalDate *time.Time, commentMode *models.ChapterCommentMode, commentsLocked *bool) (models.Chapter, error) { func Edit(chapter models.Chapter, title, source *string, fictionalDate *time.Time, commentMode *models.ChapterCommentMode, commentsLocked *bool) (*models.Chapter, error) {
now := time.Now() now := time.Now()
changes := bson.M{"editedDate": now} changes := bson.M{"editedDate": now}
@@ -39,8 +39,8 @@ func Edit(chapter models.Chapter, title, source *string, fictionalDate *time.Tim
err := collection.UpdateId(chapter.ID, bson.M{"$set": changes}) err := collection.UpdateId(chapter.ID, bson.M{"$set": changes})
if err != nil { if err != nil {
return chapter, err return nil, err
} }
return edited, nil return &edited, nil
} }
+1 -1
View File
@@ -6,6 +6,6 @@ import (
) )
// FindID finds a chapter by ID // FindID finds a chapter by ID
func FindID(id string) (models.Chapter, error) { func FindID(id string) (*models.Chapter, error) {
return find(bson.M{"_id": id}) return find(bson.M{"_id": id})
} }
+3 -3
View File
@@ -8,12 +8,12 @@ import (
) )
// Move updates the chapter, moving it to the given story. // Move updates the chapter, moving it to the given story.
func Move(chapter models.Chapter, story models.Story) (models.Chapter, error) { func Move(chapter models.Chapter, story models.Story) (*models.Chapter, error) {
now := time.Now() now := time.Now()
err := collection.UpdateId(chapter.ID, bson.M{"$set": bson.M{"editedDate": now, "storyId": story.ID}}) err := collection.UpdateId(chapter.ID, bson.M{"$set": bson.M{"editedDate": now, "storyId": story.ID}})
if err != nil { if err != nil {
return models.Chapter{}, err return nil, err
} }
chapter.EditedDate = now chapter.EditedDate = now
@@ -24,5 +24,5 @@ func Move(chapter models.Chapter, story models.Story) (models.Chapter, error) {
} }
} }
return chapter, nil return &chapter, nil
} }
+2 -2
View File
@@ -6,9 +6,9 @@ import (
) )
// Remove removes a chapter. // Remove removes a chapter.
func Remove(chapter models.Chapter) (models.Chapter, error) { func Remove(chapter models.Chapter) (*models.Chapter, error) {
if err := collection.RemoveId(chapter.ID); err != nil { if err := collection.RemoveId(chapter.ID); err != nil {
return models.Chapter{}, err return nil, err
} }
return chapter, nil return chapter, nil
+2 -3
View File
@@ -30,8 +30,7 @@ func (character *Character) HasNick(nick string) bool {
return false return false
} }
// IsChangeObject is an interface implementation to identify it as a valid // IsChangeObject is a dummy interface implementation
// ChangeObject in GQL.
func (*Character) IsChangeObject() { func (*Character) IsChangeObject() {
panic("this method is a dummy, and so is its caller") // Dummy interface implementation
} }
+2 -3
View File
@@ -16,8 +16,7 @@ type Comment struct {
Source string `bson:"source"` Source string `bson:"source"`
} }
// IsChangeObject is an interface implementation to identify it as a valid // IsChangeObject is a dummy interface implementation
// ChangeObject in GQL.
func (*Comment) IsChangeObject() { func (*Comment) IsChangeObject() {
panic("this method is a dummy, and so is its caller") // Dummy interface implementation
} }
+2 -3
View File
@@ -15,8 +15,7 @@ type File struct {
URL string `bson:"url,omitempty" json:"url,omitempty"` URL string `bson:"url,omitempty" json:"url,omitempty"`
} }
// IsChangeObject is an interface implementation to identify it as a valid // IsChangeObject is a dummy interface implementation
// ChangeObject in GQL.
func (*File) IsChangeObject() { func (*File) IsChangeObject() {
panic("this method is a dummy, and so is its caller") // Dummy interface implementation
} }
+2 -3
View File
@@ -15,8 +15,7 @@ type Log struct {
CharacterIDs []string `bson:"characterIds"` CharacterIDs []string `bson:"characterIds"`
} }
// IsChangeObject is an interface implementation to identify it as a valid // IsChangeObject is a dummy interface implementation
// ChangeObject in GQL.
func (*Log) IsChangeObject() { func (*Log) IsChangeObject() {
panic("this method is a dummy, and so is its caller") // Dummy interface implementation
} }
+2 -3
View File
@@ -13,8 +13,7 @@ type Post struct {
Position int `bson:"position"` Position int `bson:"position"`
} }
// IsChangeObject is an interface implementation to identify it as a valid // IsChangeObject is a dummy interface implementation
// ChangeObject in GQL.
func (*Post) IsChangeObject() { func (*Post) IsChangeObject() {
panic("this method is a dummy, and so is its caller") // Dummy interface implementation
} }
+4 -4
View File
@@ -11,19 +11,19 @@ import (
var ErrTagAlreadyExists = errors.New("Tag already exists on story") var ErrTagAlreadyExists = errors.New("Tag already exists on story")
// AddTag adds a tag to the story. It returns ErrTagAlreadyExists if the tag is already there // AddTag adds a tag to the story. It returns ErrTagAlreadyExists if the tag is already there
func AddTag(story models.Story, tag models.Tag) (models.Story, error) { func AddTag(story models.Story, tag models.Tag) (*models.Story, error) {
for i := range story.Tags { for i := range story.Tags {
if story.Tags[i].Equal(tag) { if story.Tags[i].Equal(tag) {
return models.Story{}, ErrTagAlreadyExists return nil, ErrTagAlreadyExists
} }
} }
err := collection.UpdateId(story.ID, bson.M{"$push": bson.M{"tags": tag}}) err := collection.UpdateId(story.ID, bson.M{"$push": bson.M{"tags": tag}})
if err != nil { if err != nil {
return models.Story{}, err return nil, err
} }
story.Tags = append(story.Tags, tag) story.Tags = append(story.Tags, tag)
return story, nil return &story, nil
} }
+3 -3
View File
@@ -7,7 +7,7 @@ import (
) )
// Add creates a new story. // Add creates a new story.
func Add(name, author string, category models.StoryCategory, listed, open bool, tags []models.Tag, createdDate, fictionalDate time.Time) (models.Story, error) { func Add(name, author string, category models.StoryCategory, listed, open bool, tags []models.Tag, createdDate, fictionalDate time.Time) (*models.Story, error) {
story := models.Story{ story := models.Story{
ID: makeStoryID(), ID: makeStoryID(),
Name: name, Name: name,
@@ -23,8 +23,8 @@ func Add(name, author string, category models.StoryCategory, listed, open bool,
err := collection.Insert(story) err := collection.Insert(story)
if err != nil { if err != nil {
return models.Story{}, err return nil, err
} }
return story, nil return &story, nil
} }
+5 -2
View File
@@ -12,11 +12,14 @@ import (
var collection *mgo.Collection var collection *mgo.Collection
func find(query interface{}) (models.Story, error) { func find(query interface{}) (*models.Story, error) {
story := models.Story{} story := models.Story{}
err := collection.Find(query).One(&story) err := collection.Find(query).One(&story)
if err != nil {
return nil, err
}
return story, err return &story, err
} }
func list(query interface{}, limit int) ([]models.Story, error) { func list(query interface{}, limit int) ([]models.Story, error) {
+4 -4
View File
@@ -8,7 +8,7 @@ import (
) )
// Edit edits the story and returns the edited story if it succeeds. // Edit edits the story and returns the edited story if it succeeds.
func Edit(story models.Story, name *string, category *models.StoryCategory, listed, open *bool, fictionalDate *time.Time) (models.Story, error) { func Edit(story models.Story, name *string, category *models.StoryCategory, listed, open *bool, fictionalDate *time.Time) (*models.Story, error) {
changes := bson.M{} changes := bson.M{}
if name != nil && *name != story.Name { if name != nil && *name != story.Name {
@@ -33,13 +33,13 @@ func Edit(story models.Story, name *string, category *models.StoryCategory, list
} }
if len(changes) == 0 { if len(changes) == 0 {
return story, nil return &story, nil
} }
err := collection.UpdateId(story.ID, bson.M{"$set": changes}) err := collection.UpdateId(story.ID, bson.M{"$set": changes})
if err != nil { if err != nil {
return models.Story{}, err return nil, err
} }
return story, nil return &story, nil
} }
+1 -1
View File
@@ -6,6 +6,6 @@ import (
) )
// FindID finds a story by ID // FindID finds a story by ID
func FindID(id string) (models.Story, error) { func FindID(id string) (*models.Story, error) {
return find(bson.M{"_id": id}) return find(bson.M{"_id": id})
} }
+4 -4
View File
@@ -11,7 +11,7 @@ import (
var ErrTagNotExists = errors.New("Tag does not exist on story") var ErrTagNotExists = errors.New("Tag does not exist on story")
// RemoveTag removes a tag to the story. It returns ErrTagNotExists if the tag does not exist. // RemoveTag removes a tag to the story. It returns ErrTagNotExists if the tag does not exist.
func RemoveTag(story models.Story, tag models.Tag) (models.Story, error) { func RemoveTag(story models.Story, tag models.Tag) (*models.Story, error) {
index := -1 index := -1
for i := range story.Tags { for i := range story.Tags {
if story.Tags[i].Equal(tag) { if story.Tags[i].Equal(tag) {
@@ -20,15 +20,15 @@ func RemoveTag(story models.Story, tag models.Tag) (models.Story, error) {
} }
} }
if index == -1 { if index == -1 {
return models.Story{}, ErrTagNotExists return nil, ErrTagNotExists
} }
err := collection.UpdateId(story.ID, bson.M{"$pull": bson.M{"tags": tag}}) err := collection.UpdateId(story.ID, bson.M{"$pull": bson.M{"tags": tag}})
if err != nil { if err != nil {
return models.Story{}, err return nil, err
} }
story.Tags = append(story.Tags[:index], story.Tags[index+1:]...) story.Tags = append(story.Tags[:index], story.Tags[index+1:]...)
return story, nil return &story, nil
} }
+2 -2
View File
@@ -5,6 +5,6 @@ import (
) )
// Remove the story from the database // Remove the story from the database
func Remove(story models.Story) (models.Story, error) { func Remove(story models.Story) (*models.Story, error) {
return story, collection.RemoveId(story.ID) return &story, collection.RemoveId(story.ID)
} }
+2 -3
View File
@@ -17,8 +17,7 @@ type Story struct {
UpdatedDate time.Time `bson:"updatedDate"` UpdatedDate time.Time `bson:"updatedDate"`
} }
// IsChangeObject is an interface implementation to identify it as a valid // IsChangeObject is a dummy interface implementation
// ChangeObject in GQL.
func (*Story) IsChangeObject() { func (*Story) IsChangeObject() {
panic("this method is a dummy, and so is its caller") // Dummy interface implementation
} }
+2 -3
View File
@@ -11,8 +11,7 @@ func (tag *Tag) Equal(other Tag) bool {
return tag.Kind == other.Kind && tag.Name == other.Name return tag.Kind == other.Kind && tag.Name == other.Name
} }
// IsChangeObject is an interface implementation to identify it as a valid // IsChangeObject is a dummy interface implementation
// ChangeObject in GQL.
func (*Tag) IsChangeObject() { func (*Tag) IsChangeObject() {
panic("this method is a dummy, and so is its caller") // Dummy interface implementation
} }