api: Add graphql endpoint

This commit is contained in:
Kevin Kandlbinder 2022-03-17 00:24:30 +01:00
parent 9e05c54d81
commit 8256b70fcb
21 changed files with 9111 additions and 15 deletions

15
.graphqlconfig Normal file
View file

@ -0,0 +1,15 @@
{
"name": "Main Schema",
"schemaPath": "graph/schema.graphqls",
"extensions": {
"endpoints": {
"Default GraphQL Endpoint": {
"url": "http://localhost:8123/api/query",
"headers": {
"user-agent": "JS GraphQL"
},
"introspect": true
}
}
}
}

4
go.mod
View file

@ -4,13 +4,15 @@ go 1.16
require ( require (
github.com/766b/chi-prometheus v0.0.0-20211217152057-87afa9aa2ca8 github.com/766b/chi-prometheus v0.0.0-20211217152057-87afa9aa2ca8
github.com/99designs/gqlgen v0.17.1
github.com/go-chi/chi v1.5.4 // indirect github.com/go-chi/chi v1.5.4 // indirect
github.com/go-chi/chi/v5 v5.0.7 github.com/go-chi/chi/v5 v5.0.7
github.com/go-chi/cors v1.2.0 // indirect github.com/go-chi/cors v1.2.0
github.com/golang-jwt/jwt/v4 v4.3.0 github.com/golang-jwt/jwt/v4 v4.3.0
github.com/prometheus/client_golang v1.12.1 github.com/prometheus/client_golang v1.12.1
github.com/spf13/cobra v1.3.0 github.com/spf13/cobra v1.3.0
github.com/spf13/viper v1.10.1 github.com/spf13/viper v1.10.1
github.com/vektah/gqlparser/v2 v2.4.0
go.mongodb.org/mongo-driver v1.8.3 go.mongodb.org/mongo-driver v1.8.3
go.opentelemetry.io/otel v1.4.1 go.opentelemetry.io/otel v1.4.1
go.opentelemetry.io/otel/exporters/jaeger v1.4.1 go.opentelemetry.io/otel/exporters/jaeger v1.4.1

39
go.sum
View file

@ -48,17 +48,26 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/766b/chi-prometheus v0.0.0-20211217152057-87afa9aa2ca8 h1:hK1G69lDhhrGqJbRA5i1rmT2KI/W77MSdr7hEGHqWdQ= github.com/766b/chi-prometheus v0.0.0-20211217152057-87afa9aa2ca8 h1:hK1G69lDhhrGqJbRA5i1rmT2KI/W77MSdr7hEGHqWdQ=
github.com/766b/chi-prometheus v0.0.0-20211217152057-87afa9aa2ca8/go.mod h1:X/LhbmoBoRu8TxoGIOIraVNhfz3hhikJoaelrOuhdPY= github.com/766b/chi-prometheus v0.0.0-20211217152057-87afa9aa2ca8/go.mod h1:X/LhbmoBoRu8TxoGIOIraVNhfz3hhikJoaelrOuhdPY=
github.com/99designs/gqlgen v0.17.1 h1:i2qQMPKHQjHgBWYIpO4TsaQpPqMHCPK1+h95ipvH8VU=
github.com/99designs/gqlgen v0.17.1/go.mod h1:K5fzLKwtph+FFgh9j7nFbRUdBKvTcGnsta51fsMTn3o=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/agnivade/levenshtein v1.1.0 h1:n6qGwyHG61v3ABce1rPVZklEYRT8NFpCMrpZdBUbYGM=
github.com/agnivade/levenshtein v1.1.0/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
@ -104,11 +113,15 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
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/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g=
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@ -230,6 +243,7 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
@ -254,6 +268,7 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
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/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
@ -282,6 +297,7 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kevinmbeaulieu/eq-go v1.0.0/go.mod h1:G3S8ajA56gKBZm4UB9AOyoOS37JO3roToPzKNM8dtdM=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
@ -298,9 +314,12 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
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/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc=
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/matryer/moq v0.2.3 h1:Q06vEqnBYjjfx5KKgHfYRKE/lvlRu+Nj+xodG4YdHnU=
github.com/matryer/moq v0.2.3/go.mod h1:9RtPYjTnH1bSBIkpvtHkFN7nbWAnO7oRpdJkEIn6UtE=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
@ -323,6 +342,7 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.2.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -376,11 +396,16 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM= github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
@ -418,6 +443,10 @@ github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/sjson v1.1.5/go.mod h1:VuJzsZnTowhSxWdOgsAnb886i4AjEyTkk7tNtsL7EYE= github.com/tidwall/sjson v1.1.5/go.mod h1:VuJzsZnTowhSxWdOgsAnb886i4AjEyTkk7tNtsL7EYE=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/vektah/gqlparser/v2 v2.4.0 h1:EmA4dw9mqHm0j6Xzb9T21hOrp3oXmxnS40vwki70DZU=
github.com/vektah/gqlparser/v2 v2.4.0/go.mod h1:flJWIR04IMQPGz+BXLrORkrARBxv/rtyIAFvd/MceW0=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w= github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
@ -431,6 +460,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
@ -506,6 +536,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -549,8 +581,9 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -650,6 +683,7 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -713,6 +747,7 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200815165600-90abf76919f3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
@ -726,6 +761,8 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

57
gqlgen.yml Normal file
View file

@ -0,0 +1,57 @@
# Where are all the schema files located? globs are supported eg src/**/*.graphqls
schema:
- graph/*.graphqls
# Where should the generated server code go?
exec:
filename: graph/generated/generated.go
package: generated
# Uncomment to enable federation
# federation:
# filename: graph/generated/federation.go
# package: generated
# Where should any generated models go?
model:
filename: graph/model/models_gen.go
package: model
# Where should the resolver implementations go?
resolver:
layout: follow-schema
dir: graph
package: graph
# Optional: turn on use ` + "`" + `gqlgen:"fieldName"` + "`" + ` tags in your models
# struct_tag: json
# Optional: turn on to use []Thing instead of []*Thing
# omit_slice_element_pointers: false
# Optional: set to speed up generation time by not performing a final validation pass.
# skip_validation: true
# gqlgen will search for any type names in the schema in these go packages
# if they match it will use them, otherwise it will generate them.
autobind:
- "github.com/Unkn0wnCat/matrix-veles/internal/db/model"
- "github.com/Unkn0wnCat/matrix-veles/graph/model"
# This section declares type mapping between the GraphQL and go type systems
#
# The first line in each type will be used as defaults for resolver arguments and
# modelgen, the others will be allowed when binding to fields. Configure them to
# your liking
models:
ID:
model:
- github.com/99designs/gqlgen/graphql.ID
- github.com/99designs/gqlgen/graphql.Int
- github.com/99designs/gqlgen/graphql.Int64
- github.com/99designs/gqlgen/graphql.Int32
Int:
model:
- github.com/99designs/gqlgen/graphql.Int
- github.com/99designs/gqlgen/graphql.Int64
- github.com/99designs/gqlgen/graphql.Int32

View file

@ -0,0 +1,42 @@
query {
entries(first:2) {
pageInfo {
hasPreviousPage
hasNextPage
startCursor
endCursor
}
edges {
node {
id
tags
timestamp
comments {
edges {
node {
author {
id
}
content
timestamp
}
}
}
partOf {
edges {
node {
id
maintainers {
edges {
node {
username
}
}
}
}
}
}
}
}
}
}

7217
graph/generated/generated.go Normal file

File diff suppressed because it is too large Load diff

454
graph/helpers.go Normal file
View file

@ -0,0 +1,454 @@
package graph
import (
"github.com/Unkn0wnCat/matrix-veles/graph/model"
model2 "github.com/Unkn0wnCat/matrix-veles/internal/db/model"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"log"
"time"
)
func buildStringFilter(filter *model.StringFilter) bson.M {
compiledFilter := bson.M{}
if filter != nil {
if filter.Eq != nil {
compiledFilter["$eq"] = *filter.Eq
}
if filter.Neq != nil {
compiledFilter["$ne"] = *filter.Eq
}
if filter.Regex != nil {
compiledFilter["$regex"] = *filter.Regex
}
}
return compiledFilter
}
func buildTimestampFilter(filter *model.TimestampFilter) (*bson.M, error) {
compiledFilter := bson.M{}
if filter != nil {
if filter.After != nil {
compiledFilter["$gt"] = *filter.After
}
if filter.Before != nil {
compiledFilter["$lt"] = *filter.Before
}
}
return &compiledFilter, nil
}
func buildIntFilter(filter *model.IntFilter) bson.M {
compiledFilter := bson.M{}
if filter != nil {
if filter.Eq != nil {
compiledFilter["$eq"] = *filter.Eq
}
if filter.Neq != nil {
compiledFilter["$ne"] = *filter.Neq
}
if filter.Gt != nil {
compiledFilter["$gt"] = *filter.Gt
}
if filter.Lt != nil {
compiledFilter["$lt"] = *filter.Lt
}
}
return compiledFilter
}
func buildStringArrayFilter(filter *model.StringArrayFilter) bson.M {
compiledFilter := bson.M{}
if filter != nil {
if filter.ElemMatch != nil {
compiledFilter["$elemMatch"] = buildStringFilter(filter.ElemMatch)
}
if filter.ContainsAll != nil {
compiledFilter["$all"] = filter.ContainsAll
}
if filter.Length != nil {
compiledFilter["$size"] = *filter.Length
}
}
return compiledFilter
}
func idArrayToPrimitiveID(ids []*string) ([]primitive.ObjectID, error) {
var pIds []primitive.ObjectID
for _, id := range ids {
pId, err := primitive.ObjectIDFromHex(*id)
if err != nil {
return nil, err
}
pIds = append(pIds, pId)
}
return pIds, nil
}
func buildIDArrayFilter(filter *model.IDArrayFilter) (bson.M, error) {
compiledFilter := bson.M{}
var err error
if filter != nil {
if filter.ContainsAll != nil {
compiledFilter["$all"], err = idArrayToPrimitiveID(filter.ContainsAll)
if err != nil {
return nil, err
}
}
if filter.Length != nil {
compiledFilter["$size"] = *filter.Length
}
}
return compiledFilter, nil
}
func buildSortRule(sort *model.SortRule) interface{} {
if sort.Direction == "ASC" {
return 1
}
return -1
}
func buildDBUserFilter(first *int, after *string, filter *model.UserFilter, sort *model.UserSort) (*bson.M, *bson.M, *int64, error) {
compiledFilter := bson.M{}
compiledSort := bson.M{}
var filterBson *bson.M
var cursorBson *bson.M
limit := 25
if sort != nil {
if sort.ID != nil {
compiledSort["_id"] = buildSortRule(sort.ID)
}
if sort.Username != nil {
compiledSort["username"] = buildSortRule(sort.Username)
}
if sort.Admin != nil {
compiledSort["admin"] = buildSortRule(sort.Admin)
}
}
if first != nil {
limit = *first
}
if after != nil {
cursorBsonW := bson.M{}
afterID, err := primitive.ObjectIDFromHex(*after)
if err != nil {
return nil, nil, nil, err
}
cursorBsonW["_id"] = bson.M{"$gt": afterID}
cursorBson = &cursorBsonW
}
if filter != nil {
filterBsonW := bson.M{}
if filter.ID != nil {
filterBsonW["_id"] = *filter.ID
}
if filter.Username != nil {
filterBsonW["username"] = buildStringFilter(filter.Username)
}
if filter.Admin != nil {
filterBsonW["admin"] = *filter.Admin
}
if filter.MatrixLinks != nil {
filterBsonW["matrix_links"] = buildStringArrayFilter(filter.MatrixLinks)
}
if filter.PendingMatrixLinks != nil {
filterBsonW["pending_matrix_links"] = buildStringArrayFilter(filter.PendingMatrixLinks)
}
filterBson = &filterBsonW
}
if filterBson != nil && cursorBson != nil {
compiledFilter["$and"] = bson.A{*cursorBson, *filterBson}
}
if filterBson == nil && cursorBson != nil {
compiledFilter = *cursorBson
}
if filterBson != nil && cursorBson == nil {
compiledFilter = *filterBson
}
convLimit := int64(limit)
return &compiledFilter, &compiledSort, &convLimit, nil
}
func buildDBListFilter(first *int, after *string, filter *model.ListFilter, sort *model.ListSort) (*bson.M, *bson.M, *int64, error) {
compiledFilter := bson.M{}
compiledSort := bson.M{}
var filterBson *bson.M
var cursorBson *bson.M
limit := 25
var err error
if sort != nil {
if sort.ID != nil {
compiledSort["_id"] = buildSortRule(sort.ID)
}
if sort.Name != nil {
compiledSort["name"] = buildSortRule(sort.Name)
}
}
if first != nil {
limit = *first
}
if after != nil {
cursorBsonW := bson.M{}
afterID, err := primitive.ObjectIDFromHex(*after)
if err != nil {
return nil, nil, nil, err
}
cursorBsonW["_id"] = bson.M{"$gt": afterID}
cursorBson = &cursorBsonW
}
if filter != nil {
filterBsonW := bson.M{}
if filter.ID != nil {
filterBsonW["_id"] = *filter.ID
}
if filter.Name != nil {
filterBsonW["name"] = buildStringFilter(filter.Name)
}
if filter.Tags != nil {
filterBsonW["tags"] = buildStringArrayFilter(filter.Tags)
}
if filter.Maintainers != nil {
filterBsonW["maintainers"], err = buildIDArrayFilter(filter.Maintainers)
if err != nil {
return nil, nil, nil, err
}
}
filterBson = &filterBsonW
}
if filterBson != nil && cursorBson != nil {
compiledFilter["$and"] = bson.A{*cursorBson, *filterBson}
}
if filterBson == nil && cursorBson != nil {
compiledFilter = *cursorBson
}
if filterBson != nil && cursorBson == nil {
compiledFilter = *filterBson
}
convLimit := int64(limit)
return &compiledFilter, &compiledSort, &convLimit, nil
}
func buildDBEntryFilter(first *int, after *string, filter *model.EntryFilter, sort *model.EntrySort) (*bson.M, *bson.M, *int64, error) {
compiledFilter := bson.M{}
compiledSort := bson.M{}
var filterBson *bson.M
var cursorBson *bson.M
limit := 25
var err error
if sort != nil {
if sort.ID != nil {
compiledSort["_id"] = buildSortRule(sort.ID)
}
if sort.Timestamp != nil {
compiledSort["timestamp"] = buildSortRule(sort.Timestamp)
}
if sort.AddedBy != nil {
compiledSort["added_by"] = buildSortRule(sort.AddedBy)
}
if sort.HashValue != nil {
compiledSort["hash_value"] = buildSortRule(sort.HashValue)
}
}
if first != nil {
limit = *first
}
if after != nil {
cursorBsonW := bson.M{}
afterID, err := primitive.ObjectIDFromHex(*after)
if err != nil {
return nil, nil, nil, err
}
cursorBsonW["_id"] = bson.M{"$gt": afterID}
cursorBson = &cursorBsonW
}
if filter != nil {
filterBsonW := bson.M{}
if filter.ID != nil {
filterBsonW["_id"] = *filter.ID
}
if filter.HashValue != nil {
filterBsonW["hash_value"] = buildStringFilter(filter.HashValue)
}
if filter.Tags != nil {
filterBsonW["tags"] = buildStringArrayFilter(filter.Tags)
}
if filter.AddedBy != nil {
dbId, err := primitive.ObjectIDFromHex(*filter.AddedBy)
if err != nil {
return nil, nil, nil, err
}
filterBsonW["added_by"] = dbId
}
if filter.Timestamp != nil {
filterBsonW["timestamp"], err = buildTimestampFilter(filter.Timestamp)
if err != nil {
return nil, nil, nil, err
}
}
if filter.FileURL != nil {
filterBsonW["file_url"] = buildStringFilter(filter.FileURL)
}
if filter.PartOf != nil {
filterBsonW["part_of"], err = buildIDArrayFilter(filter.PartOf)
if err != nil {
return nil, nil, nil, err
}
}
filterBson = &filterBsonW
}
if filterBson != nil && cursorBson != nil {
compiledFilter["$and"] = bson.A{*cursorBson, *filterBson}
}
if filterBson == nil && cursorBson != nil {
compiledFilter = *cursorBson
}
if filterBson != nil && cursorBson == nil {
compiledFilter = *filterBson
}
convLimit := int64(limit)
return &compiledFilter, &compiledSort, &convLimit, nil
}
func ResolveComments(comments []*model2.DBComment, first *int, after *string) (*model.CommentConnection, error) {
if len(comments) == 0 {
return nil, nil
}
startIndex := 0
if after != nil {
afterTs, err := time.Parse(time.RFC3339Nano, *after)
if err != nil {
return nil, err
}
set := false
for i, comment := range comments {
if afterTs.Before(comment.Timestamp) {
startIndex = i
set = true
break
}
}
if !set {
return nil, nil
}
}
if startIndex >= len(comments) {
return nil, nil
}
comments = comments[startIndex:]
length := 25
if first != nil {
length = *first
}
cut := false
if len(comments) > length {
cut = true
comments = comments[:length]
}
var edges []*model.CommentEdge
for _, comment := range comments {
edges = append(edges, &model.CommentEdge{
Node: model.MakeComment(comment),
Cursor: comment.Timestamp.Format(time.RFC3339Nano),
})
}
log.Println(edges)
return &model.CommentConnection{
PageInfo: &model.PageInfo{
HasPreviousPage: startIndex > 0,
HasNextPage: cut,
StartCursor: edges[0].Cursor,
EndCursor: edges[len(edges)-1].Cursor,
},
Edges: nil,
}, nil
}

21
graph/model/comment.go Normal file
View file

@ -0,0 +1,21 @@
package model
import (
"github.com/Unkn0wnCat/matrix-veles/internal/db/model"
"go.mongodb.org/mongo-driver/bson/primitive"
"time"
)
type Comment struct {
Timestamp time.Time `json:"timestamp"`
AuthorID *primitive.ObjectID
Content string `json:"content"`
}
func MakeComment(dbComment *model.DBComment) *Comment {
return &Comment{
Timestamp: dbComment.Timestamp,
AuthorID: dbComment.CommentedBy,
Content: dbComment.Content,
}
}

31
graph/model/entry.go Normal file
View file

@ -0,0 +1,31 @@
package model
import (
"github.com/Unkn0wnCat/matrix-veles/internal/db/model"
"go.mongodb.org/mongo-driver/bson/primitive"
"time"
)
type Entry struct {
ID string `json:"id"`
Tags []string `json:"tags"`
PartOfIDs []*primitive.ObjectID
HashValue string `json:"hashValue"`
FileURL *string `json:"fileUrl"`
Timestamp time.Time `json:"timestamp"`
AddedByID primitive.ObjectID
RawComments []*model.DBComment
}
func MakeEntry(dbEntry *model.DBEntry) *Entry {
return &Entry{
ID: dbEntry.ID.Hex(),
Tags: dbEntry.Tags,
PartOfIDs: dbEntry.PartOf,
HashValue: dbEntry.HashValue,
FileURL: &dbEntry.FileURL,
Timestamp: dbEntry.Timestamp,
AddedByID: *dbEntry.AddedBy,
RawComments: dbEntry.Comments,
}
}

24
graph/model/list.go Normal file
View file

@ -0,0 +1,24 @@
package model
import (
"github.com/Unkn0wnCat/matrix-veles/internal/db/model"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type List struct {
ID string `json:"id"`
Name string `json:"name"`
Tags []string `json:"tags"`
RawComments []*model.DBComment
MaintainerIDs []*primitive.ObjectID
}
func MakeList(dbList *model.DBHashList) *List {
return &List{
ID: dbList.ID.Hex(),
Name: dbList.Name,
Tags: dbList.Tags,
RawComments: dbList.Comments,
MaintainerIDs: dbList.Maintainers,
}
}

197
graph/model/models_gen.go Normal file
View file

@ -0,0 +1,197 @@
// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
package model
import (
"fmt"
"io"
"strconv"
"time"
)
type CommentConnection struct {
PageInfo *PageInfo `json:"pageInfo"`
Edges []*CommentEdge `json:"edges"`
}
type CommentEdge struct {
Node *Comment `json:"node"`
Cursor string `json:"cursor"`
}
type EntryArrayFilter struct {
ContainsAll []*EntryFilter `json:"containsAll"`
ContainsOne []*EntryFilter `json:"containsOne"`
Length *int `json:"length"`
}
type EntryConnection struct {
PageInfo *PageInfo `json:"pageInfo"`
Edges []*EntryEdge `json:"edges"`
}
type EntryEdge struct {
Node *Entry `json:"node"`
Cursor string `json:"cursor"`
}
type EntryFilter struct {
ID *string `json:"id"`
HashValue *StringFilter `json:"hashValue"`
Tags *StringArrayFilter `json:"tags"`
AddedBy *string `json:"addedBy"`
FileURL *StringFilter `json:"fileUrl"`
Timestamp *TimestampFilter `json:"timestamp"`
PartOf *IDArrayFilter `json:"partOf"`
}
type EntrySort struct {
ID *SortRule `json:"id"`
HashValue *SortRule `json:"hashValue"`
Timestamp *SortRule `json:"timestamp"`
AddedBy *SortRule `json:"addedBy"`
}
type IDArrayFilter struct {
ContainsAll []*string `json:"containsAll"`
Length *int `json:"length"`
}
type IntFilter struct {
Gt *int `json:"gt"`
Lt *int `json:"lt"`
Eq *int `json:"eq"`
Neq *int `json:"neq"`
}
type ListArrayFilter struct {
ContainsAll []*ListFilter `json:"containsAll"`
ContainsOne []*ListFilter `json:"containsOne"`
Length *int `json:"length"`
}
type ListConnection struct {
PageInfo *PageInfo `json:"pageInfo"`
Edges []*ListEdge `json:"edges"`
}
type ListEdge struct {
Node *List `json:"node"`
Cursor string `json:"cursor"`
}
type ListFilter struct {
ID *string `json:"id"`
Name *StringFilter `json:"name"`
Tags *StringArrayFilter `json:"tags"`
Maintainers *IDArrayFilter `json:"maintainers"`
}
type ListSort struct {
ID *SortRule `json:"id"`
Name *SortRule `json:"name"`
}
type Login struct {
Username string `json:"username"`
Password string `json:"password"`
}
type PageInfo struct {
HasPreviousPage bool `json:"hasPreviousPage"`
HasNextPage bool `json:"hasNextPage"`
StartCursor string `json:"startCursor"`
EndCursor string `json:"endCursor"`
}
type SortRule struct {
Direction SortDirection `json:"direction"`
}
type StringArrayFilter struct {
ContainsAll []*string `json:"containsAll"`
ElemMatch *StringFilter `json:"elemMatch"`
Length *int `json:"length"`
}
type StringFilter struct {
Eq *string `json:"eq"`
Neq *string `json:"neq"`
Regex *string `json:"regex"`
}
type TimestampFilter struct {
After *time.Time `json:"after"`
Before *time.Time `json:"before"`
}
type UserArrayFilter struct {
ContainsAll []*UserFilter `json:"containsAll"`
ContainsOne []*UserFilter `json:"containsOne"`
Length *int `json:"length"`
}
type UserConnection struct {
PageInfo *PageInfo `json:"pageInfo"`
Edges []*UserEdge `json:"edges"`
}
type UserEdge struct {
Node *User `json:"node"`
Cursor string `json:"cursor"`
}
type UserFilter struct {
ID *string `json:"id"`
Username *StringFilter `json:"username"`
MatrixLinks *StringArrayFilter `json:"matrixLinks"`
PendingMatrixLinks *StringArrayFilter `json:"pendingMatrixLinks"`
Admin *bool `json:"admin"`
}
type UserSort struct {
ID *SortRule `json:"id"`
Username *SortRule `json:"username"`
Admin *SortRule `json:"admin"`
}
type SortDirection string
const (
SortDirectionAsc SortDirection = "ASC"
SortDirectionDesc SortDirection = "DESC"
)
var AllSortDirection = []SortDirection{
SortDirectionAsc,
SortDirectionDesc,
}
func (e SortDirection) IsValid() bool {
switch e {
case SortDirectionAsc, SortDirectionDesc:
return true
}
return false
}
func (e SortDirection) String() string {
return string(e)
}
func (e *SortDirection) UnmarshalGQL(v interface{}) error {
str, ok := v.(string)
if !ok {
return fmt.Errorf("enums must be strings")
}
*e = SortDirection(str)
if !e.IsValid() {
return fmt.Errorf("%s is not a valid SortDirection", str)
}
return nil
}
func (e SortDirection) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(e.String()))
}

21
graph/model/user.go Normal file
View file

@ -0,0 +1,21 @@
package model
import model "github.com/Unkn0wnCat/matrix-veles/internal/db/model"
type User struct {
ID string `json:"id"`
Username string `json:"username"`
Admin *bool `json:"admin"`
MatrixLinks []*string `json:"matrixLinks"`
PendingMatrixLinks []*string `json:"pendingMatrixLinks"`
}
func MakeUser(dbUser *model.DBUser) *User {
return &User{
ID: dbUser.ID.Hex(),
Username: dbUser.Username,
Admin: dbUser.Admin,
MatrixLinks: dbUser.MatrixLinks,
PendingMatrixLinks: dbUser.PendingMatrixLinks,
}
}

7
graph/resolver.go Normal file
View file

@ -0,0 +1,7 @@
package graph
// This file will not be regenerated automatically.
//
// It serves as dependency injection for your app, add any dependencies you require here.
type Resolver struct{}

210
graph/schema.graphqls Normal file
View file

@ -0,0 +1,210 @@
# GraphQL schema example
#
# https://gqlgen.com/getting-started/
scalar Time
directive @loggedIn on FIELD_DEFINITION
enum SortDirection {
ASC
DESC
}
type PageInfo {
hasPreviousPage: Boolean!
hasNextPage: Boolean!
startCursor: String!
endCursor: String!
}
input SortRule {
direction: SortDirection!
}
type User {
id: ID!
username: String!
admin: Boolean
matrixLinks: [String!]
pendingMatrixLinks: [String!]
}
type UserConnection {
pageInfo: PageInfo!
edges: [UserEdge!]!
}
type UserEdge {
node: User!
cursor: String!
}
type Entry {
id: ID!
tags: [String!]
partOf(first: Int, after: String): ListConnection
hashValue: String!
fileUrl: String
timestamp: Time!
addedBy: User!
comments(first: Int, after: String): CommentConnection
}
type EntryConnection {
pageInfo: PageInfo!
edges: [EntryEdge!]!
}
type EntryEdge {
node: Entry!
cursor: String!
}
type List {
id: ID!
name: String!
tags: [String!]
comments(first: Int, after: String): CommentConnection
maintainers(first: Int, after: String): UserConnection!
entries(first: Int, after: String): EntryConnection
}
type ListConnection {
pageInfo: PageInfo!
edges: [ListEdge!]!
}
type ListEdge {
node: List!
cursor: String!
}
type Comment {
timestamp: Time!
author: User!
content: String!
}
type CommentConnection {
pageInfo: PageInfo!
edges: [CommentEdge!]!
}
type CommentEdge {
node: Comment!
cursor: String!
}
input IntFilter {
gt: Int
lt: Int
eq: Int
neq: Int
}
input TimestampFilter {
after: Time
before: Time
}
input StringFilter {
eq: String # Equal
neq: String # Not Equal
regex: String # Regex Check
}
input StringArrayFilter {
containsAll: [String]
elemMatch: StringFilter
length: Int
}
input UserFilter {
id: ID
username: StringFilter
matrixLinks: StringArrayFilter
pendingMatrixLinks: StringArrayFilter
admin: Boolean
}
input UserArrayFilter {
containsAll: [UserFilter]
containsOne: [UserFilter]
length: Int
}
input UserSort {
id: SortRule
username: SortRule
admin: SortRule
}
input ListFilter {
id: ID
name: StringFilter
tags: StringArrayFilter
maintainers: IDArrayFilter
# entries: EntryArrayFilter
}
input IDArrayFilter {
containsAll: [ID]
length: Int
}
input ListArrayFilter {
containsAll: [ListFilter]
containsOne: [ListFilter]
length: Int
}
input ListSort {
id: SortRule
name: SortRule
}
input EntryFilter {
id: ID
hashValue: StringFilter
tags: StringArrayFilter
addedBy: ID
fileUrl: StringFilter
timestamp: TimestampFilter
partOf: IDArrayFilter
}
input EntryArrayFilter {
containsAll: [EntryFilter]
containsOne: [EntryFilter]
length: Int
}
input EntrySort {
id: SortRule
hashValue: SortRule
timestamp: SortRule
addedBy: SortRule
}
type Query {
users(first: Int, after: String, filter: UserFilter, sort: UserSort): UserConnection! @loggedIn
lists(first: Int, after: String, filter: ListFilter, sort: ListSort): ListConnection! @loggedIn
entries(first: Int, after: String, filter: EntryFilter, sort: EntrySort): EntryConnection! @loggedIn
user(id: ID, username: String): User! @loggedIn
entry(id: ID, hashValue: String): Entry! @loggedIn
list(id: ID, name: String): List! @loggedIn
}
input Login {
username: String!
password: String!
}
type Mutation {
login(input: Login!): String!
}

687
graph/schema.resolvers.go Normal file
View file

@ -0,0 +1,687 @@
package graph
// This file will be automatically regenerated based on the schema, any resolver implementations
// will be copied through when generating and any unknown code will be moved to the end.
import (
"context"
"errors"
"fmt"
"math/big"
"time"
"github.com/Unkn0wnCat/matrix-veles/graph/generated"
"github.com/Unkn0wnCat/matrix-veles/graph/model"
"github.com/Unkn0wnCat/matrix-veles/internal/db"
model2 "github.com/Unkn0wnCat/matrix-veles/internal/db/model"
jwt "github.com/golang-jwt/jwt/v4"
"github.com/spf13/viper"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func (r *commentResolver) Author(ctx context.Context, obj *model.Comment) (*model.User, error) {
user, err := db.GetUserByID(*obj.AuthorID)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, errors.New("not found")
}
return nil, errors.New("database error")
}
return model.MakeUser(user), nil
}
func (r *entryResolver) PartOf(ctx context.Context, obj *model.Entry, first *int, after *string) (*model.ListConnection, error) {
ids := obj.PartOfIDs
if len(ids) == 0 {
return nil, nil
}
startIndex := 0
if after != nil {
afterInt := new(big.Int)
afterInt.SetString(*after, 16)
idInt := new(big.Int)
set := false
for i, id := range obj.PartOfIDs {
idInt.SetString(id.Hex(), 16)
if idInt.Cmp(afterInt) > 0 {
startIndex = i
set = true
break
}
}
if !set {
return nil, nil
}
}
if startIndex >= len(ids) {
return nil, nil
}
ids = ids[startIndex:]
length := 25
if first != nil {
length = *first
}
cut := false
if len(ids) > length {
cut = true
ids = ids[:length]
}
var edges []*model.ListEdge
for _, id := range ids {
dbList, err := db.GetListByID(*id)
if err != nil {
return nil, err
}
edges = append(edges, &model.ListEdge{
Node: model.MakeList(dbList),
Cursor: dbList.ID.Hex(),
})
}
return &model.ListConnection{
PageInfo: &model.PageInfo{
HasPreviousPage: startIndex > 0,
HasNextPage: cut,
StartCursor: edges[0].Cursor,
EndCursor: edges[len(edges)-1].Cursor,
},
Edges: edges,
}, nil
}
func (r *entryResolver) AddedBy(ctx context.Context, obj *model.Entry) (*model.User, error) {
user, err := db.GetUserByID(obj.AddedByID)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, errors.New("not found")
}
return nil, errors.New("database error")
}
return model.MakeUser(user), nil
}
func (r *entryResolver) Comments(ctx context.Context, obj *model.Entry, first *int, after *string) (*model.CommentConnection, error) {
comments := obj.RawComments
return ResolveComments(comments, first, after)
}
func (r *listResolver) Comments(ctx context.Context, obj *model.List, first *int, after *string) (*model.CommentConnection, error) {
comments := obj.RawComments
return ResolveComments(comments, first, after)
}
func (r *listResolver) Maintainers(ctx context.Context, obj *model.List, first *int, after *string) (*model.UserConnection, error) {
ids := obj.MaintainerIDs
if len(ids) == 0 {
return nil, nil
}
startIndex := 0
if after != nil {
afterInt := new(big.Int)
afterInt.SetString(*after, 16)
idInt := new(big.Int)
set := false
for i, id := range ids {
idInt.SetString(id.Hex(), 16)
if idInt.Cmp(afterInt) > 0 {
startIndex = i
set = true
break
}
}
if !set {
return nil, nil
}
}
if startIndex >= len(ids) {
return nil, nil
}
ids = ids[startIndex:]
length := 25
if first != nil {
length = *first
}
cut := false
if len(ids) > length {
cut = true
ids = ids[:length]
}
var edges []*model.UserEdge
for _, id := range ids {
dbUser, err := db.GetUserByID(*id)
if err != nil {
return nil, err
}
edges = append(edges, &model.UserEdge{
Node: model.MakeUser(dbUser),
Cursor: dbUser.ID.Hex(),
})
}
return &model.UserConnection{
PageInfo: &model.PageInfo{
HasPreviousPage: startIndex > 0,
HasNextPage: cut,
StartCursor: edges[0].Cursor,
EndCursor: edges[len(edges)-1].Cursor,
},
Edges: edges,
}, nil
}
func (r *listResolver) Entries(ctx context.Context, obj *model.List, first *int, after *string) (*model.EntryConnection, error) {
coll := db.Db.Collection(viper.GetString("bot.mongo.collection.entries"))
dbFilter, _, dbLimit, err := buildDBEntryFilter(first, after, &model.EntryFilter{
PartOf: &model.IDArrayFilter{
ContainsAll: []*string{&obj.ID},
},
}, nil)
if err != nil {
return nil, err
}
newLimit := *dbLimit + 1
findOpts := options.FindOptions{
Limit: &newLimit,
}
res, err := coll.Find(ctx, *dbFilter, &findOpts)
if err != nil {
return nil, errors.New("database error")
}
var rawEntries []model2.DBEntry
err = res.All(ctx, &rawEntries)
if err != nil {
return nil, errors.New("database error")
}
if len(rawEntries) == 0 {
return nil, nil
}
lastEntryI := len(rawEntries) - 1
if lastEntryI > 0 {
lastEntryI--
}
firstEntry := rawEntries[0]
lastEntry := rawEntries[lastEntryI]
isAfter := false
if after != nil {
isAfter = true
}
hasMore := false
if int64(len(rawEntries)) > *dbLimit {
hasMore = true
}
var edges []*model.EntryEdge
for i, rawEntry := range rawEntries {
if int64(i) == *dbLimit {
continue
}
edges = append(edges, &model.EntryEdge{
Node: model.MakeEntry(&rawEntry),
Cursor: rawEntry.ID.Hex(),
})
}
return &model.EntryConnection{
PageInfo: &model.PageInfo{
HasPreviousPage: isAfter,
HasNextPage: hasMore,
StartCursor: firstEntry.ID.Hex(),
EndCursor: lastEntry.ID.Hex(),
},
Edges: edges,
}, nil
}
func (r *mutationResolver) Login(ctx context.Context, input model.Login) (string, error) {
user, err := db.GetUserByUsername(input.Username)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return "", errors.New("invalid credentials")
}
return "", errors.New("database error")
}
err = user.CheckPassword(input.Password)
if err != nil {
return "", errors.New("invalid credentials")
}
jwtSigningKey := []byte(viper.GetString("bot.web.secret"))
claims := model2.JwtClaims{
Username: user.Username,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24 * 365 * 100)),
IssuedAt: jwt.NewNumericDate(time.Now()),
NotBefore: jwt.NewNumericDate(time.Now()),
Issuer: "veles-api",
Subject: user.ID.Hex(),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
ss, err := token.SignedString(jwtSigningKey)
if err != nil {
return "", errors.New("unable to create token")
}
return ss, nil
}
func (r *queryResolver) Users(ctx context.Context, first *int, after *string, filter *model.UserFilter, sort *model.UserSort) (*model.UserConnection, error) {
dbFilter, dbSort, dbLimit, err := buildDBUserFilter(first, after, filter, sort)
if err != nil {
return nil, err
}
coll := db.Db.Collection(viper.GetString("bot.mongo.collection.users"))
newLimit := *dbLimit + 1
findOpts := options.FindOptions{
Limit: &newLimit,
Sort: *dbSort,
}
res, err := coll.Find(ctx, *dbFilter, &findOpts)
if err != nil {
return nil, errors.New("database error")
}
var rawUsers []model2.DBUser
err = res.All(ctx, &rawUsers)
if err != nil {
return nil, errors.New("database error")
}
if len(rawUsers) == 0 {
return nil, errors.New("not found")
}
lastUserI := len(rawUsers) - 1
if lastUserI > 0 {
lastUserI--
}
firstUser := rawUsers[0]
lastUser := rawUsers[lastUserI]
isAfter := false
if after != nil {
isAfter = true
}
hasMore := false
if int64(len(rawUsers)) > *dbLimit {
hasMore = true
}
var edges []*model.UserEdge
for i, rawUser := range rawUsers {
if int64(i) == *dbLimit {
continue
}
edges = append(edges, &model.UserEdge{
Node: model.MakeUser(&rawUser),
Cursor: rawUser.ID.Hex(),
})
}
return &model.UserConnection{
PageInfo: &model.PageInfo{
HasPreviousPage: isAfter,
HasNextPage: hasMore,
StartCursor: firstUser.ID.Hex(),
EndCursor: lastUser.ID.Hex(),
},
Edges: edges,
}, nil
}
func (r *queryResolver) Lists(ctx context.Context, first *int, after *string, filter *model.ListFilter, sort *model.ListSort) (*model.ListConnection, error) {
dbFilter, dbSort, dbLimit, err := buildDBListFilter(first, after, filter, sort)
if err != nil {
return nil, err
}
coll := db.Db.Collection(viper.GetString("bot.mongo.collection.lists"))
newLimit := *dbLimit + 1
findOpts := options.FindOptions{
Limit: &newLimit,
Sort: *dbSort,
}
res, err := coll.Find(ctx, *dbFilter, &findOpts)
if err != nil {
return nil, errors.New("database error")
}
var rawLists []model2.DBHashList
err = res.All(ctx, &rawLists)
if err != nil {
return nil, errors.New("database error")
}
if len(rawLists) == 0 {
return nil, errors.New("not found")
}
lastListI := len(rawLists) - 1
if lastListI > 0 {
lastListI--
}
firstList := rawLists[0]
lastList := rawLists[lastListI]
isAfter := false
if after != nil {
isAfter = true
}
hasMore := false
if int64(len(rawLists)) > *dbLimit {
hasMore = true
}
var edges []*model.ListEdge
for i, rawList := range rawLists {
if int64(i) == *dbLimit {
continue
}
edges = append(edges, &model.ListEdge{
Node: model.MakeList(&rawList),
Cursor: rawList.ID.Hex(),
})
}
return &model.ListConnection{
PageInfo: &model.PageInfo{
HasPreviousPage: isAfter,
HasNextPage: hasMore,
StartCursor: firstList.ID.Hex(),
EndCursor: lastList.ID.Hex(),
},
Edges: edges,
}, nil
}
func (r *queryResolver) Entries(ctx context.Context, first *int, after *string, filter *model.EntryFilter, sort *model.EntrySort) (*model.EntryConnection, error) {
dbFilter, dbSort, dbLimit, err := buildDBEntryFilter(first, after, filter, sort)
if err != nil {
return nil, err
}
coll := db.Db.Collection(viper.GetString("bot.mongo.collection.entries"))
newLimit := *dbLimit + 1
findOpts := options.FindOptions{
Limit: &newLimit,
Sort: *dbSort,
}
res, err := coll.Find(ctx, *dbFilter, &findOpts)
if err != nil {
return nil, errors.New("database error")
}
var rawEntries []model2.DBEntry
err = res.All(ctx, &rawEntries)
if err != nil {
return nil, errors.New("database error")
}
if len(rawEntries) == 0 {
return nil, errors.New("not found")
}
lastEntryI := len(rawEntries) - 1
if lastEntryI > 0 {
lastEntryI--
}
firstEntry := rawEntries[0]
lastEntry := rawEntries[lastEntryI]
isAfter := false
if after != nil {
isAfter = true
}
hasMore := false
if int64(len(rawEntries)) > *dbLimit {
hasMore = true
}
var edges []*model.EntryEdge
for i, rawEntry := range rawEntries {
if int64(i) == *dbLimit {
continue
}
edges = append(edges, &model.EntryEdge{
Node: model.MakeEntry(&rawEntry),
Cursor: rawEntry.ID.Hex(),
})
}
return &model.EntryConnection{
PageInfo: &model.PageInfo{
HasPreviousPage: isAfter,
HasNextPage: hasMore,
StartCursor: firstEntry.ID.Hex(),
EndCursor: lastEntry.ID.Hex(),
},
Edges: edges,
}, nil
}
func (r *queryResolver) User(ctx context.Context, id *string, username *string) (*model.User, error) {
if id != nil {
dbId, err := primitive.ObjectIDFromHex(*id)
if err != nil {
return nil, err
}
rawUser, err := db.GetUserByID(dbId)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, errors.New("not found")
}
return nil, errors.New("database error")
}
return model.MakeUser(rawUser), nil
}
if username != nil {
rawUser, err := db.GetUserByUsername(*username)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, errors.New("not found")
}
return nil, errors.New("database error")
}
return model.MakeUser(rawUser), nil
}
return nil, errors.New("not found")
}
func (r *queryResolver) Entry(ctx context.Context, id *string, hashValue *string) (*model.Entry, error) {
if id != nil {
dbId, err := primitive.ObjectIDFromHex(*id)
if err != nil {
return nil, err
}
rawEntry, err := db.GetEntryByID(dbId)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, errors.New("not found")
}
return nil, errors.New("database error")
}
return model.MakeEntry(rawEntry), nil
}
if hashValue != nil {
rawEntry, err := db.GetEntryByHash(*hashValue)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, errors.New("not found")
}
return nil, errors.New("database error")
}
return model.MakeEntry(rawEntry), nil
}
return nil, errors.New("not found")
}
func (r *queryResolver) List(ctx context.Context, id *string, name *string) (*model.List, error) {
if id != nil {
dbId, err := primitive.ObjectIDFromHex(*id)
if err != nil {
return nil, err
}
rawList, err := db.GetListByID(dbId)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, errors.New("not found")
}
return nil, errors.New("database error")
}
return model.MakeList(rawList), nil
}
if name != nil {
rawList, err := db.GetListByName(*name)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, errors.New("not found")
}
return nil, errors.New("database error")
}
return model.MakeList(rawList), nil
}
return nil, errors.New("not found")
}
// Comment returns generated.CommentResolver implementation.
func (r *Resolver) Comment() generated.CommentResolver { return &commentResolver{r} }
// Entry returns generated.EntryResolver implementation.
func (r *Resolver) Entry() generated.EntryResolver { return &entryResolver{r} }
// List returns generated.ListResolver implementation.
func (r *Resolver) List() generated.ListResolver { return &listResolver{r} }
// Mutation returns generated.MutationResolver implementation.
func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} }
// Query returns generated.QueryResolver implementation.
func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} }
type commentResolver struct{ *Resolver }
type entryResolver struct{ *Resolver }
type listResolver struct{ *Resolver }
type mutationResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }
// !!! WARNING !!!
// The code below was going to be deleted when updating resolvers. It has been copied here so you have
// one last chance to move it out of harms way if you want. There are two reasons this happens:
// - When renaming or deleting a resolver the old code will be put in here. You can safely delete
// it when you're done.
// - You have helper methods in this file. Move them out to keep these resolver files clean.
func (r *commentResolver) Timestamp(ctx context.Context, obj *model.Comment) (*time.Time, error) {
panic(fmt.Errorf("not implemented"))
}
func (r *entryResolver) Timestamp(ctx context.Context, obj *model.Entry) (*time.Time, error) {
panic(fmt.Errorf("not implemented"))
}

View file

@ -6,6 +6,7 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/event"
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/options"
"log" "log"
@ -13,6 +14,7 @@ import (
) )
var DbClient *mongo.Client var DbClient *mongo.Client
var Db *mongo.Database
func Connect() { func Connect() {
if viper.GetString("bot.mongo.uri") == "" { if viper.GetString("bot.mongo.uri") == "" {
@ -20,15 +22,22 @@ func Connect() {
return return
} }
cmdMonitor := &event.CommandMonitor{
Started: func(_ context.Context, evt *event.CommandStartedEvent) {
log.Print(evt.Command)
},
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() defer cancel()
newClient, err := mongo.Connect(ctx, options.Client().ApplyURI(viper.GetString("bot.mongo.uri"))) newClient, err := mongo.Connect(ctx, options.Client().ApplyURI(viper.GetString("bot.mongo.uri")).SetMonitor(cmdMonitor))
if err != nil { if err != nil {
log.Println("Could not connect to DB") log.Println("Could not connect to DB")
log.Panicln(err) log.Panicln(err)
} }
DbClient = newClient DbClient = newClient
Db = DbClient.Database(viper.GetString("bot.mongo.database"))
} }
func SaveEntry(entry *model.DBEntry) error { func SaveEntry(entry *model.DBEntry) error {

View file

@ -0,0 +1,8 @@
package model
import "github.com/golang-jwt/jwt/v4"
type JwtClaims struct {
Username string `json:"username"`
jwt.RegisteredClaims
}

View file

@ -5,6 +5,12 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
chiprometheus "github.com/766b/chi-prometheus" chiprometheus "github.com/766b/chi-prometheus"
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/playground"
"github.com/Unkn0wnCat/matrix-veles/graph"
"github.com/Unkn0wnCat/matrix-veles/graph/generated"
"github.com/Unkn0wnCat/matrix-veles/internal/db/model"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/go-chi/cors" "github.com/go-chi/cors"
"net/http" "net/http"
@ -25,10 +31,30 @@ func SetupAPI() chi.Router {
m := chiprometheus.NewMiddleware("api") m := chiprometheus.NewMiddleware("api")
router.Use(m) router.Use(m)
router.Use(decodeAuthMiddleware)
router.NotFound(notFoundHandler) router.NotFound(notFoundHandler)
router.MethodNotAllowed(methodNotAllowedHandler) router.MethodNotAllowed(methodNotAllowedHandler)
router.Handle("/", playground.Handler("GraphQL playground", "/api/query"))
c := generated.Config{Resolvers: &graph.Resolver{}}
c.Directives.LoggedIn = func(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) {
claimsVal := ctx.Value("claims")
var claims model.JwtClaims
if claimsVal != nil {
claims = claimsVal.(model.JwtClaims)
if claims.Valid() == nil {
return next(ctx)
}
}
return nil, errors.New("authentication required")
}
srv := handler.NewDefaultServer(generated.NewExecutableSchema(c))
router.Handle("/query", srv)
//router.NotFoundHandler = NotFoundHandler{} //router.NotFoundHandler = NotFoundHandler{}
//router.MethodNotAllowedHandler = MethodNotAllowedHandler{} //router.MethodNotAllowedHandler = MethodNotAllowedHandler{}
@ -72,7 +98,7 @@ func SetupAPI() chi.Router {
r.Get("/", func(writer http.ResponseWriter, request *http.Request) { r.Get("/", func(writer http.ResponseWriter, request *http.Request) {
writer.WriteHeader(200) writer.WriteHeader(200)
claims := request.Context().Value("claims").(jwtClaims) claims := request.Context().Value("claims").(model.JwtClaims)
writer.Write([]byte(`hello ` + claims.Username)) writer.Write([]byte(`hello ` + claims.Username))
}) })
@ -81,12 +107,38 @@ func SetupAPI() chi.Router {
return router return router
} }
func getClaims(request *http.Request) jwtClaims { func getClaims(request *http.Request) model.JwtClaims {
claims := request.Context().Value("claims").(jwtClaims) claims := request.Context().Value("claims").(model.JwtClaims)
return claims return claims
} }
func decodeAuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
token := req.Header.Get("Authorization")
tokenSplit := strings.Split(token, " ")
if token == "" || len(tokenSplit) < 2 {
next.ServeHTTP(res, req)
return
}
token = tokenSplit[1]
claims, _, err := parseToken(token)
if err != nil {
next.ServeHTTP(res, req)
return
}
ctx := context.WithValue(req.Context(), "claims", *claims)
req = req.WithContext(ctx)
next.ServeHTTP(res, req)
})
}
func checkAuthMiddleware(next http.Handler) http.Handler { func checkAuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
token := req.Header.Get("Authorization") token := req.Header.Get("Authorization")

View file

@ -18,13 +18,8 @@ type apiAuthRequestBody struct {
Password string `json:"password"` Password string `json:"password"`
} }
type jwtClaims struct { func parseToken(tokenString string) (*model.JwtClaims, *jwt.Token, error) {
Username string `json:"username"` claims := model.JwtClaims{}
jwt.RegisteredClaims
}
func parseToken(tokenString string) (*jwtClaims, *jwt.Token, error) {
claims := jwtClaims{}
jwtSigningKey := []byte(viper.GetString("bot.web.secret")) jwtSigningKey := []byte(viper.GetString("bot.web.secret"))
token, err := jwt.ParseWithClaims(tokenString, &claims, func(token *jwt.Token) (interface{}, error) { token, err := jwt.ParseWithClaims(tokenString, &claims, func(token *jwt.Token) (interface{}, error) {
@ -67,7 +62,7 @@ func apiHandleAuthLogin(res http.ResponseWriter, req *http.Request) {
jwtSigningKey := []byte(viper.GetString("bot.web.secret")) jwtSigningKey := []byte(viper.GetString("bot.web.secret"))
claims := jwtClaims{ claims := model.JwtClaims{
Username: user.Username, Username: user.Username,
RegisteredClaims: jwt.RegisteredClaims{ RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24 * 365 * 100)), ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24 * 365 * 100)),
@ -143,7 +138,7 @@ func apiHandleAuthRegister(res http.ResponseWriter, req *http.Request) {
jwtSigningKey := viper.GetString("bot.web.secret") jwtSigningKey := viper.GetString("bot.web.secret")
claims := jwtClaims{ claims := model.JwtClaims{
Username: user.Username, Username: user.Username,
RegisteredClaims: jwt.RegisteredClaims{ RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24)), ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24)),

View file

@ -17,6 +17,8 @@
package main package main
//go:generate gqlgen generate
import ( import (
"github.com/Unkn0wnCat/matrix-veles/cmd" "github.com/Unkn0wnCat/matrix-veles/cmd"
) )

8
tools.go Normal file
View file

@ -0,0 +1,8 @@
//go:build tools
// +build tools
package main
import (
_ "github.com/99designs/gqlgen"
)