From 7e6454c5935b8d39958835992ebd8adb8d32d021 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Tue, 2 Feb 2021 15:34:10 -0500 Subject: [PATCH 1/8] GraphQL Framework --- cmd/main.go | 32 +- go.mod | 2 + go.sum | 51 + gqlgen.yml | 56 + graph/generated/generated.go | 9341 ++++++++++++++++++++++++++++++++++ graph/model/models_gen.go | 397 ++ graph/resolver.go | 13 + graph/schema.graphqls | 356 ++ graph/schema.resolvers.go | 81 + internal/api/albums.go | 9 - internal/api/auth.go | 51 +- internal/api/devices.go | 9 - internal/api/info.go | 9 - internal/api/media_items.go | 327 -- internal/api/routes.go | 50 +- internal/api/tags.go | 9 - internal/api/upload.go | 9 - internal/api/users.go | 30 - internal/auth/auth.go | 48 +- internal/auth/ldap.go | 4 +- internal/auth/local.go | 6 +- internal/db/db.go | 29 +- internal/db/devices.go | 15 +- internal/db/media_items.go | 8 +- internal/db/users.go | 17 +- internal/models/db.go | 96 - plugin/models.go | 240 + plugin/models.gotpl | 85 + 28 files changed, 10764 insertions(+), 616 deletions(-) create mode 100644 gqlgen.yml create mode 100644 graph/generated/generated.go create mode 100644 graph/model/models_gen.go create mode 100644 graph/resolver.go create mode 100644 graph/schema.graphqls create mode 100644 graph/schema.resolvers.go delete mode 100644 internal/api/albums.go delete mode 100644 internal/api/devices.go delete mode 100644 internal/api/info.go delete mode 100644 internal/api/media_items.go delete mode 100644 internal/api/tags.go delete mode 100644 internal/api/upload.go delete mode 100644 internal/api/users.go delete mode 100644 internal/models/db.go create mode 100644 plugin/models.go create mode 100644 plugin/models.gotpl diff --git a/cmd/main.go b/cmd/main.go index c662467..d5ff9ab 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -7,6 +7,10 @@ import ( log "github.com/sirupsen/logrus" "reichard.io/imagini/cmd/server" + + "reichard.io/imagini/plugin" + "github.com/99designs/gqlgen/api" + "github.com/99designs/gqlgen/codegen/config" ) type UTCFormatter struct { @@ -21,7 +25,6 @@ func (u UTCFormatter) Format(e *log.Entry) ([]byte, error) { func main() { log.SetFormatter(UTCFormatter{&log.TextFormatter{FullTimestamp: true}}) - log.Info("Starting Imagini") app := &cli.App{ Name: "Imagini", Usage: "A self hosted photo library.", @@ -32,6 +35,11 @@ func main() { Usage: "Start Imagini web server.", Action: cmdServer, }, + { + Name: "generate", + Usage: "generate graphql schema", + Action: cmdGenerate, + }, }, } err := app.Run(os.Args) @@ -41,6 +49,7 @@ func main() { } func cmdServer(ctx *cli.Context) error { + log.Info("Starting Imagini Server") server := server.NewServer() server.StartServer() @@ -53,3 +62,24 @@ func cmdServer(ctx *cli.Context) error { return nil } + +func cmdGenerate(ctx *cli.Context) error { + log.Info("Generating Imagini Models") + gqlgenConf, err := config.LoadConfigFromDefaultLocations() + if err != nil { + log.Panic("Failed to load config", err.Error()) + os.Exit(2) + } + + log.Info("Generating Schema...") + err = api.Generate(gqlgenConf, + api.AddPlugin(plugin.New()), + ) + log.Info("Schema Generation Done") + if err != nil { + log.Panic(err.Error()) + os.Exit(3) + } + os.Exit(0) + return nil +} diff --git a/go.mod b/go.mod index 1758010..810144d 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module reichard.io/imagini go 1.15 require ( + github.com/99designs/gqlgen v0.13.0 github.com/codeon/govips v0.0.0-20200329201227-415341c0ce33 // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/disintegration/imaging v1.6.2 // indirect @@ -14,6 +15,7 @@ require ( github.com/sirupsen/logrus v1.7.0 github.com/tus/tusd v1.4.0 github.com/urfave/cli/v2 v2.3.0 + github.com/vektah/gqlparser/v2 v2.1.0 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect gorm.io/driver/sqlite v1.1.4 diff --git a/go.sum b/go.sum index dd43da0..fee82df 100644 --- a/go.sum +++ b/go.sum @@ -2,9 +2,16 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.40.0/go.mod h1:Tk58MuI9rbLMKlAjeO/bDnteAx7tX2gJIXw4T5Jwlro= +github.com/99designs/gqlgen v0.13.0 h1:haLTcUp3Vwp80xMVEg5KRNwzfUrgFdRmtBY8fuB8scA= +github.com/99designs/gqlgen v0.13.0/go.mod h1:NV130r6f4tpRWuAI+zsrSdooO/eWUv+Gyyoi3rEfXIk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0= +github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs= 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/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/aws/aws-sdk-go v1.20.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -22,6 +29,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/dgrijalva/jwt-go v1.0.2 h1:KPldsxuKGsS2FPWsNeg9ZO18aCrGKujPoWXn2yo+KQM= 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/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= github.com/dsoprea/go-exif v0.0.0-20201216222538-db167117f483 h1:zJb7OUzMMSul61UUhYXWNOXc9nO1lexj3jsAgoDtCqg= @@ -41,6 +49,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/gabriel-vasile/mimetype v1.1.2 h1:gaPnPcNor5aZSVCJVSGipcpbgMWiAAj9z182ocSGbHU= github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To= +github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= github.com/go-errors/errors v1.1.1 h1:ljK/pL5ltg3qoN+OtN6yCv9HWSfMwxSx90GJCZQxYNg= @@ -52,6 +61,7 @@ github.com/go-macaron/gzip v0.0.0-20200329073552-98214d7a897e/go.mod h1:1if9hBU2 github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 h1:NjHlg70DuOkcAMqgt0+XA+NHwtu66MkTVVgR4fFWbcI= github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191/go.mod h1:VFI2o2q9kYsC4o7VP1HrEVosiZZTd+MVT3YZx4gqvJw= 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.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= @@ -77,9 +87,14 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +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/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -98,6 +113,9 @@ github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eT github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= 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/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/lestrrat-go/backoff/v2 v2.0.3 h1:2ABaTa5ifB1L90aoRMjaPa97p0WzzVe93Vggv8oZftw= github.com/lestrrat-go/backoff/v2 v2.0.3/go.mod h1:mU93bMXuG27/Y5erI5E9weqavpTX5qiVFZI4uXAX0xk= github.com/lestrrat-go/httpcc v0.0.0-20210101035852-e7e8fea419e3 h1:e52qvXxpJPV/Kb2ovtuYgcRFjNmf9ntcn8BPIbpRM4k= @@ -109,14 +127,24 @@ github.com/lestrrat-go/jwx v1.0.8/go.mod h1:6XJ5sxHF5U116AxYxeHfTnfsZRMgmeKY214z github.com/lestrrat-go/option v0.0.0-20210103042652-6f1ecfceda35 h1:lea8Wt+1ePkVrI2/WD+NgQT5r/XsLAzxeqtyFLcEs10= github.com/lestrrat-go/option v0.0.0-20210103042652-6f1ecfceda35/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lestrrat-go/pdebug/v3 v3.0.0-20210111091911-ec4f5c88c087/go.mod h1:za+m+Ve24yCxTEhR59N7UlnJomWwCiIqbJRmKeiADU4= +github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 h1:reVOUXwnhsYv/8UqjvhrMOu5CNT9UapHFLbQ2JcXsmg= +github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8= +github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -131,11 +159,15 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/common v0.4.1/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.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sethgrid/pester v0.0.0-20190127155807-68a33a018ad0/go.mod h1:Ad7IjTpvzZO8Fl0vh9AzQ+j/jYZfyp2diGwI8m5q+ns= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= 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.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= @@ -148,6 +180,7 @@ github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:s github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 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.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -159,8 +192,13 @@ github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e h1:GSGeB9EAKY2spCABz6x github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= 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/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWpEAyDlU1eKOuk5twTjAjuevXqcJJw8hrg= +github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U= +github.com/vektah/gqlparser/v2 v2.1.0 h1:uiKJ+T5HMGGQM2kRKQ8Pxw8+Zq9qhhZhz/lieYvCMns= +github.com/vektah/gqlparser/v2 v2.1.0/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms= github.com/vimeo/go-util v1.2.0/go.mod h1:s13SMDTSO7AjH1nbgp707mfN5JFIWUFDU5MDDuRRtKs= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -186,6 +224,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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= @@ -215,11 +255,13 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -230,17 +272,22 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/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-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200417140056-c07e33ef3290 h1:NXNmtp0ToD36cui5IqWy95LC4Y6vT/4y3RnPxlQPinU= golang.org/x/tools v0.0.0-20200417140056-c07e33ef3290/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 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-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= @@ -261,6 +308,7 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa gopkg.in/Acconut/lockfile.v1 v1.1.0/go.mod h1:6UCz3wJ8tSFUsPR6uP/j8uegEtDuEEqFxlpi0JI4Umw= 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 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/h2non/gock.v1 v1.0.14/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= gopkg.in/ini.v1 v1.46.0 h1:VeDZbLYGaupuvIrsYCEOe/L/2Pcs5n7hdO1ZTjporag= gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -270,6 +318,7 @@ gopkg.in/macaron.v1 v1.4.0/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -284,3 +333,5 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k= diff --git a/gqlgen.yml b/gqlgen.yml new file mode 100644 index 0000000..5673aaa --- /dev/null +++ b/gqlgen.yml @@ -0,0 +1,56 @@ +# 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: + - "reichard.io/imagini/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 diff --git a/graph/generated/generated.go b/graph/generated/generated.go new file mode 100644 index 0000000..c7823df --- /dev/null +++ b/graph/generated/generated.go @@ -0,0 +1,9341 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package generated + +import ( + "bytes" + "context" + "errors" + "fmt" + "strconv" + "sync" + "sync/atomic" + "time" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/introspection" + gqlparser "github.com/vektah/gqlparser/v2" + "github.com/vektah/gqlparser/v2/ast" + "reichard.io/imagini/graph/model" +) + +// region ************************** generated!.gotpl ************************** + +// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. +func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { + return &executableSchema{ + resolvers: cfg.Resolvers, + directives: cfg.Directives, + complexity: cfg.Complexity, + } +} + +type Config struct { + Resolvers ResolverRoot + Directives DirectiveRoot + Complexity ComplexityRoot +} + +type ResolverRoot interface { + Mutation() MutationResolver + Query() QueryResolver +} + +type DirectiveRoot struct { + HasRole func(ctx context.Context, obj interface{}, next graphql.Resolver, role model.Role) (res interface{}, err error) + Meta func(ctx context.Context, obj interface{}, next graphql.Resolver, gorm *string) (res interface{}, err error) +} + +type ComplexityRoot struct { + Album struct { + CreatedAt func(childComplexity int) int + ID func(childComplexity int) int + Name func(childComplexity int) int + UpdatedAt func(childComplexity int) int + } + + AlbumResponse struct { + Data func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + Device struct { + CreatedAt func(childComplexity int) int + ID func(childComplexity int) int + Name func(childComplexity int) int + RefreshKey func(childComplexity int) int + Type func(childComplexity int) int + UpdatedAt func(childComplexity int) int + User func(childComplexity int) int + } + + DeviceResponse struct { + Data func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + MediaItem struct { + Albums func(childComplexity int) int + CreatedAt func(childComplexity int) int + ExifDate func(childComplexity int) int + FileName func(childComplexity int) int + ID func(childComplexity int) int + IsVideo func(childComplexity int) int + Latitude func(childComplexity int) int + Longitude func(childComplexity int) int + OrigName func(childComplexity int) int + Tags func(childComplexity int) int + UpdatedAt func(childComplexity int) int + User func(childComplexity int) int + } + + MediaItemResponse struct { + Data func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + Mutation struct { + CreateAlbum func(childComplexity int, input model.NewAlbum) int + CreateDevice func(childComplexity int, input model.NewDevice) int + CreateMediaItem func(childComplexity int, input model.NewMediaItem) int + CreateTag func(childComplexity int, input model.NewTag) int + CreateUser func(childComplexity int, input model.NewUser) int + } + + PageInfo struct { + Count func(childComplexity int) int + Page func(childComplexity int) int + Total func(childComplexity int) int + } + + Query struct { + Album func(childComplexity int, id string) int + Albums func(childComplexity int, filter *model.AlbumFilter, count *int, page *int) int + Device func(childComplexity int, id string) int + Devices func(childComplexity int, filter *model.DeviceFilter, count *int, page *int) int + MediaItem func(childComplexity int, id string) int + MediaItems func(childComplexity int, filter *model.MediaItemFilter, count *int, page *int) int + Tag func(childComplexity int, id string) int + Tags func(childComplexity int, filter *model.TagFilter, count *int, page *int) int + User func(childComplexity int, id string) int + Users func(childComplexity int, filter *model.UserFilter, count *int, page *int) int + } + + Tag struct { + CreatedAt func(childComplexity int) int + ID func(childComplexity int) int + Name func(childComplexity int) int + UpdatedAt func(childComplexity int) int + } + + TagResponse struct { + Data func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + User struct { + AuthType func(childComplexity int) int + CreatedAt func(childComplexity int) int + Email func(childComplexity int) int + FirstName func(childComplexity int) int + ID func(childComplexity int) int + LastName func(childComplexity int) int + Password func(childComplexity int) int + Role func(childComplexity int) int + UpdatedAt func(childComplexity int) int + Username func(childComplexity int) int + } + + UserResponse struct { + Data func(childComplexity int) int + PageInfo func(childComplexity int) int + } +} + +type MutationResolver interface { + CreateMediaItem(ctx context.Context, input model.NewMediaItem) (*model.MediaItem, error) + CreateDevice(ctx context.Context, input model.NewDevice) (*model.Device, error) + CreateAlbum(ctx context.Context, input model.NewAlbum) (*model.Album, error) + CreateTag(ctx context.Context, input model.NewTag) (*model.Tag, error) + CreateUser(ctx context.Context, input model.NewUser) (*model.User, error) +} +type QueryResolver interface { + MediaItem(ctx context.Context, id string) (*model.MediaItem, error) + Device(ctx context.Context, id string) (*model.Device, error) + Album(ctx context.Context, id string) (*model.Album, error) + Tag(ctx context.Context, id string) (*model.Tag, error) + User(ctx context.Context, id string) (*model.User, error) + MediaItems(ctx context.Context, filter *model.MediaItemFilter, count *int, page *int) (*model.MediaItemResponse, error) + Devices(ctx context.Context, filter *model.DeviceFilter, count *int, page *int) (*model.DeviceResponse, error) + Albums(ctx context.Context, filter *model.AlbumFilter, count *int, page *int) (*model.AlbumResponse, error) + Tags(ctx context.Context, filter *model.TagFilter, count *int, page *int) (*model.TagResponse, error) + Users(ctx context.Context, filter *model.UserFilter, count *int, page *int) (*model.UserResponse, error) +} + +type executableSchema struct { + resolvers ResolverRoot + directives DirectiveRoot + complexity ComplexityRoot +} + +func (e *executableSchema) Schema() *ast.Schema { + return parsedSchema +} + +func (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) { + ec := executionContext{nil, e} + _ = ec + switch typeName + "." + field { + + case "Album.createdAt": + if e.complexity.Album.CreatedAt == nil { + break + } + + return e.complexity.Album.CreatedAt(childComplexity), true + + case "Album.id": + if e.complexity.Album.ID == nil { + break + } + + return e.complexity.Album.ID(childComplexity), true + + case "Album.name": + if e.complexity.Album.Name == nil { + break + } + + return e.complexity.Album.Name(childComplexity), true + + case "Album.updatedAt": + if e.complexity.Album.UpdatedAt == nil { + break + } + + return e.complexity.Album.UpdatedAt(childComplexity), true + + case "AlbumResponse.data": + if e.complexity.AlbumResponse.Data == nil { + break + } + + return e.complexity.AlbumResponse.Data(childComplexity), true + + case "AlbumResponse.pageInfo": + if e.complexity.AlbumResponse.PageInfo == nil { + break + } + + return e.complexity.AlbumResponse.PageInfo(childComplexity), true + + case "Device.createdAt": + if e.complexity.Device.CreatedAt == nil { + break + } + + return e.complexity.Device.CreatedAt(childComplexity), true + + case "Device.id": + if e.complexity.Device.ID == nil { + break + } + + return e.complexity.Device.ID(childComplexity), true + + case "Device.name": + if e.complexity.Device.Name == nil { + break + } + + return e.complexity.Device.Name(childComplexity), true + + case "Device.refreshKey": + if e.complexity.Device.RefreshKey == nil { + break + } + + return e.complexity.Device.RefreshKey(childComplexity), true + + case "Device.type": + if e.complexity.Device.Type == nil { + break + } + + return e.complexity.Device.Type(childComplexity), true + + case "Device.updatedAt": + if e.complexity.Device.UpdatedAt == nil { + break + } + + return e.complexity.Device.UpdatedAt(childComplexity), true + + case "Device.user": + if e.complexity.Device.User == nil { + break + } + + return e.complexity.Device.User(childComplexity), true + + case "DeviceResponse.data": + if e.complexity.DeviceResponse.Data == nil { + break + } + + return e.complexity.DeviceResponse.Data(childComplexity), true + + case "DeviceResponse.pageInfo": + if e.complexity.DeviceResponse.PageInfo == nil { + break + } + + return e.complexity.DeviceResponse.PageInfo(childComplexity), true + + case "MediaItem.albums": + if e.complexity.MediaItem.Albums == nil { + break + } + + return e.complexity.MediaItem.Albums(childComplexity), true + + case "MediaItem.createdAt": + if e.complexity.MediaItem.CreatedAt == nil { + break + } + + return e.complexity.MediaItem.CreatedAt(childComplexity), true + + case "MediaItem.exifDate": + if e.complexity.MediaItem.ExifDate == nil { + break + } + + return e.complexity.MediaItem.ExifDate(childComplexity), true + + case "MediaItem.fileName": + if e.complexity.MediaItem.FileName == nil { + break + } + + return e.complexity.MediaItem.FileName(childComplexity), true + + case "MediaItem.id": + if e.complexity.MediaItem.ID == nil { + break + } + + return e.complexity.MediaItem.ID(childComplexity), true + + case "MediaItem.isVideo": + if e.complexity.MediaItem.IsVideo == nil { + break + } + + return e.complexity.MediaItem.IsVideo(childComplexity), true + + case "MediaItem.latitude": + if e.complexity.MediaItem.Latitude == nil { + break + } + + return e.complexity.MediaItem.Latitude(childComplexity), true + + case "MediaItem.longitude": + if e.complexity.MediaItem.Longitude == nil { + break + } + + return e.complexity.MediaItem.Longitude(childComplexity), true + + case "MediaItem.origName": + if e.complexity.MediaItem.OrigName == nil { + break + } + + return e.complexity.MediaItem.OrigName(childComplexity), true + + case "MediaItem.tags": + if e.complexity.MediaItem.Tags == nil { + break + } + + return e.complexity.MediaItem.Tags(childComplexity), true + + case "MediaItem.updatedAt": + if e.complexity.MediaItem.UpdatedAt == nil { + break + } + + return e.complexity.MediaItem.UpdatedAt(childComplexity), true + + case "MediaItem.user": + if e.complexity.MediaItem.User == nil { + break + } + + return e.complexity.MediaItem.User(childComplexity), true + + case "MediaItemResponse.data": + if e.complexity.MediaItemResponse.Data == nil { + break + } + + return e.complexity.MediaItemResponse.Data(childComplexity), true + + case "MediaItemResponse.pageInfo": + if e.complexity.MediaItemResponse.PageInfo == nil { + break + } + + return e.complexity.MediaItemResponse.PageInfo(childComplexity), true + + case "Mutation.createAlbum": + if e.complexity.Mutation.CreateAlbum == nil { + break + } + + args, err := ec.field_Mutation_createAlbum_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.CreateAlbum(childComplexity, args["input"].(model.NewAlbum)), true + + case "Mutation.createDevice": + if e.complexity.Mutation.CreateDevice == nil { + break + } + + args, err := ec.field_Mutation_createDevice_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.CreateDevice(childComplexity, args["input"].(model.NewDevice)), true + + case "Mutation.createMediaItem": + if e.complexity.Mutation.CreateMediaItem == nil { + break + } + + args, err := ec.field_Mutation_createMediaItem_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.CreateMediaItem(childComplexity, args["input"].(model.NewMediaItem)), true + + case "Mutation.createTag": + if e.complexity.Mutation.CreateTag == nil { + break + } + + args, err := ec.field_Mutation_createTag_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.CreateTag(childComplexity, args["input"].(model.NewTag)), true + + case "Mutation.createUser": + if e.complexity.Mutation.CreateUser == nil { + break + } + + args, err := ec.field_Mutation_createUser_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.CreateUser(childComplexity, args["input"].(model.NewUser)), true + + case "PageInfo.count": + if e.complexity.PageInfo.Count == nil { + break + } + + return e.complexity.PageInfo.Count(childComplexity), true + + case "PageInfo.page": + if e.complexity.PageInfo.Page == nil { + break + } + + return e.complexity.PageInfo.Page(childComplexity), true + + case "PageInfo.total": + if e.complexity.PageInfo.Total == nil { + break + } + + return e.complexity.PageInfo.Total(childComplexity), true + + case "Query.album": + if e.complexity.Query.Album == nil { + break + } + + args, err := ec.field_Query_album_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Album(childComplexity, args["id"].(string)), true + + case "Query.albums": + if e.complexity.Query.Albums == nil { + break + } + + args, err := ec.field_Query_albums_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Albums(childComplexity, args["filter"].(*model.AlbumFilter), args["count"].(*int), args["page"].(*int)), true + + case "Query.device": + if e.complexity.Query.Device == nil { + break + } + + args, err := ec.field_Query_device_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Device(childComplexity, args["id"].(string)), true + + case "Query.devices": + if e.complexity.Query.Devices == nil { + break + } + + args, err := ec.field_Query_devices_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Devices(childComplexity, args["filter"].(*model.DeviceFilter), args["count"].(*int), args["page"].(*int)), true + + case "Query.mediaItem": + if e.complexity.Query.MediaItem == nil { + break + } + + args, err := ec.field_Query_mediaItem_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.MediaItem(childComplexity, args["id"].(string)), true + + case "Query.mediaItems": + if e.complexity.Query.MediaItems == nil { + break + } + + args, err := ec.field_Query_mediaItems_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.MediaItems(childComplexity, args["filter"].(*model.MediaItemFilter), args["count"].(*int), args["page"].(*int)), true + + case "Query.tag": + if e.complexity.Query.Tag == nil { + break + } + + args, err := ec.field_Query_tag_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Tag(childComplexity, args["id"].(string)), true + + case "Query.tags": + if e.complexity.Query.Tags == nil { + break + } + + args, err := ec.field_Query_tags_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Tags(childComplexity, args["filter"].(*model.TagFilter), args["count"].(*int), args["page"].(*int)), true + + case "Query.user": + if e.complexity.Query.User == nil { + break + } + + args, err := ec.field_Query_user_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.User(childComplexity, args["id"].(string)), true + + case "Query.users": + if e.complexity.Query.Users == nil { + break + } + + args, err := ec.field_Query_users_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Users(childComplexity, args["filter"].(*model.UserFilter), args["count"].(*int), args["page"].(*int)), true + + case "Tag.createdAt": + if e.complexity.Tag.CreatedAt == nil { + break + } + + return e.complexity.Tag.CreatedAt(childComplexity), true + + case "Tag.id": + if e.complexity.Tag.ID == nil { + break + } + + return e.complexity.Tag.ID(childComplexity), true + + case "Tag.name": + if e.complexity.Tag.Name == nil { + break + } + + return e.complexity.Tag.Name(childComplexity), true + + case "Tag.updatedAt": + if e.complexity.Tag.UpdatedAt == nil { + break + } + + return e.complexity.Tag.UpdatedAt(childComplexity), true + + case "TagResponse.data": + if e.complexity.TagResponse.Data == nil { + break + } + + return e.complexity.TagResponse.Data(childComplexity), true + + case "TagResponse.pageInfo": + if e.complexity.TagResponse.PageInfo == nil { + break + } + + return e.complexity.TagResponse.PageInfo(childComplexity), true + + case "User.authType": + if e.complexity.User.AuthType == nil { + break + } + + return e.complexity.User.AuthType(childComplexity), true + + case "User.createdAt": + if e.complexity.User.CreatedAt == nil { + break + } + + return e.complexity.User.CreatedAt(childComplexity), true + + case "User.email": + if e.complexity.User.Email == nil { + break + } + + return e.complexity.User.Email(childComplexity), true + + case "User.firstName": + if e.complexity.User.FirstName == nil { + break + } + + return e.complexity.User.FirstName(childComplexity), true + + case "User.id": + if e.complexity.User.ID == nil { + break + } + + return e.complexity.User.ID(childComplexity), true + + case "User.lastName": + if e.complexity.User.LastName == nil { + break + } + + return e.complexity.User.LastName(childComplexity), true + + case "User.password": + if e.complexity.User.Password == nil { + break + } + + return e.complexity.User.Password(childComplexity), true + + case "User.role": + if e.complexity.User.Role == nil { + break + } + + return e.complexity.User.Role(childComplexity), true + + case "User.updatedAt": + if e.complexity.User.UpdatedAt == nil { + break + } + + return e.complexity.User.UpdatedAt(childComplexity), true + + case "User.username": + if e.complexity.User.Username == nil { + break + } + + return e.complexity.User.Username(childComplexity), true + + case "UserResponse.data": + if e.complexity.UserResponse.Data == nil { + break + } + + return e.complexity.UserResponse.Data(childComplexity), true + + case "UserResponse.pageInfo": + if e.complexity.UserResponse.PageInfo == nil { + break + } + + return e.complexity.UserResponse.PageInfo(childComplexity), true + + } + return 0, false +} + +func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { + rc := graphql.GetOperationContext(ctx) + ec := executionContext{rc, e} + first := true + + switch rc.Operation.Operation { + case ast.Query: + return func(ctx context.Context) *graphql.Response { + if !first { + return nil + } + first = false + data := ec._Query(ctx, rc.Operation.SelectionSet) + var buf bytes.Buffer + data.MarshalGQL(&buf) + + return &graphql.Response{ + Data: buf.Bytes(), + } + } + case ast.Mutation: + return func(ctx context.Context) *graphql.Response { + if !first { + return nil + } + first = false + data := ec._Mutation(ctx, rc.Operation.SelectionSet) + var buf bytes.Buffer + data.MarshalGQL(&buf) + + return &graphql.Response{ + Data: buf.Bytes(), + } + } + + default: + return graphql.OneShot(graphql.ErrorResponse(ctx, "unsupported GraphQL operation")) + } +} + +type executionContext struct { + *graphql.OperationContext + *executableSchema +} + +func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { + if ec.DisableIntrospection { + return nil, errors.New("introspection disabled") + } + return introspection.WrapSchema(parsedSchema), nil +} + +func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { + if ec.DisableIntrospection { + return nil, errors.New("introspection disabled") + } + return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil +} + +var sources = []*ast.Source{ + {Name: "graph/schema.graphqls", Input: ` +# https://gqlgen.com/reference/scalars/ +scalar Time +scalar Upload + +# https://gqlgen.com/reference/directives/ +directive @hasRole(role: Role!) on FIELD_DEFINITION + +directive @meta( + gorm: String, +) on OBJECT | FIELD_DEFINITION | ENUM_VALUE | INPUT_FIELD_DEFINITION | ENUM | INPUT_OBJECT | ARGUMENT_DEFINITION + +enum Role { + Admin + User +} + +enum DeviceType { + iOS + Android + Chrome + Firefox + InternetExplorer + Edge + Safari + Unknown +} + +enum AuthType { + Local + LDAP +} + +# ------------------------------------------------------------ +# ----------------------- Type Filters ----------------------- +# ------------------------------------------------------------ + +input TimeFilter { + equalTo: Time + notEqualTo: Time + lessThan: Time + lessThanOrEqualTo: Time + moreThan: Time + moreThanOrEqualTo: Time +} + +input IntFilter { + equalTo: Int + notEqualTo: Int + lessThan: Int + lessThanOrEqualTo: Int + moreThan: Int + moreThanOrEqualTo: Int + in: [Int!] + notIn: [Int!] +} + +input FloatFilter { + equalTo: Float + notEqualTo: Float + lessThan: Float + lessThanOrEqualTo: Float + moreThan: Float + moreThanOrEqualTo: Float + in: [Float!] + notIn: [Float!] +} + +input BooleanFilter { + equalTo: Boolean + notEqualTo: Boolean +} + +input IDFilter { + equalTo: ID + notEqualTo: ID + in: [ID!] + notIn: [ID!] +} + +input StringFilter { + equalTo: String + notEqualTo: String + startWith: String + notStartWith: String + endWith: String + notEndWith: String + contain: String + notContain: String + in: [String!] + notIn: [String!] + + startWithStrict: String + notStartWithStrict: String + endWithStrict: String + notEndWithStrict: String + containStrict: String + notContainStrict: String +} + +input RoleFilter { + equalTo: Role + notEqualTo: Role + in: [Role!] + notIn: [Role!] +} + +input DeviceTypeFilter { + equalTo: DeviceType + notEqualTo: DeviceType + in: [DeviceType!] + notIn: [DeviceType!] +} + +input AuthTypeFilter { + equalTo: AuthType + notEqualTo: AuthType + in: [AuthType!] + notIn: [AuthType!] +} + +# ------------------------------------------------------------ +# -------------------- Object Definitions -------------------- +# ------------------------------------------------------------ + +type Device { + id: ID @meta(gorm: "primarykey;not null") + createdAt: Time + updatedAt: Time + name: String! @meta(gorm: "not null") + type: DeviceType! @meta(gorm: "default:Unknown;not null") + user: User @meta(gorm: "ForeignKey:ID;not null") + refreshKey: String +} + +type User { + id: ID @meta(gorm: "primarykey;not null") + createdAt: Time + updatedAt: Time + email: String! @meta(gorm: "not null;unique") + username: String! @meta(gorm: "not null;unique") + firstName: String + lastName: String + role: Role! @meta(gorm: "default:User;not null") + authType: AuthType! @meta(gorm: "default:Local;not null") + password: String +} + +type MediaItem { + id: ID @meta(gorm: "primarykey;not null") + createdAt: Time + updatedAt: Time + exifDate: Time + latitude: Float + longitude: Float + isVideo: Boolean! @meta(gorm: "default:false;not null") + fileName: String! @meta(gorm: "not null") + origName: String! @meta(gorm: "not null") + tags: [Tag] @meta(gorm: "many2many:media_tags") + albums: [Album] @meta(gorm: "many2many:media_albums") + user: User @meta(gorm: "ForeignKey:ID;not null") +} + +type Tag { + id: ID @meta(gorm: "primarykey;not null") + createdAt: Time + updatedAt: Time + name: String! @meta(gorm: "unique;not null") +} + +type Album { + id: ID @meta(gorm: "primarykey;not null") + createdAt: Time + updatedAt: Time + name: String! @meta(gorm: "unique;not null") +} + +# ------------------------------------------------------------ +# ---------------------- Object Filters ---------------------- +# ------------------------------------------------------------ + +input UserFilter { + id: IDFilter + createdAt: TimeFilter + updatedAt: TimeFilter + username: StringFilter + firstName: StringFilter + lastName: StringFilter + role: RoleFilter + authType: AuthTypeFilter + + and: UserFilter + or: UserFilter +} + +input MediaItemFilter { + id: IDFilter + createdAt: TimeFilter + updatedAt: TimeFilter + exifDate: TimeFilter + latitude: FloatFilter + longitude: FloatFilter + isVideo: BooleanFilter + origName: StringFilter + tags: TagFilter + albums: AlbumFilter + + and: MediaItemFilter + or: MediaItemFilter +} + +input DeviceFilter { + id: IDFilter + createdAt: TimeFilter + updatedAt: TimeFilter + name: StringFilter + type: DeviceTypeFilter + + and: MediaItemFilter + or: MediaItemFilter +} + +input TagFilter { + id: IDFilter + createdAt: TimeFilter + updatedAt: TimeFilter + name: StringFilter + + and: MediaItemFilter + or: MediaItemFilter +} + +input AlbumFilter { + id: IDFilter + createdAt: TimeFilter + updatedAt: TimeFilter + name: StringFilter + + and: MediaItemFilter + or: MediaItemFilter +} + +# ------------------------------------------------------------ +# -------------------------- Inputs -------------------------- +# ------------------------------------------------------------ + +input NewUser { + email: String! + username: String! + firstName: String + lastName: String + role: Role! + authType: AuthType! + password: String +} + +input NewDevice { + name: String! +} + +input NewMediaItem { + file: Upload! + tags: [ID!] + albums: [ID!] +} + +input NewTag { + name: String! +} + +input NewAlbum { + name: String! +} + +# ------------------------------------------------------------ +# ------------------------ Responses ------------------------- +# ------------------------------------------------------------ + +type PageInfo { + count: Int! + page: Int! + total: Int! +} + +type MediaItemResponse { + data: [MediaItem] + pageInfo: PageInfo! +} + +type UserResponse { + data: [User] + pageInfo: PageInfo! +} + +type DeviceResponse { + data: [Device] + pageInfo: PageInfo! +} + +type TagResponse { + data: [Tag] + pageInfo: PageInfo! +} + +type AlbumResponse { + data: [Album] + pageInfo: PageInfo! +} + +# ------------------------------------------------------------ +# --------------------- Query & Mutations -------------------- +# ------------------------------------------------------------ + +type Query { + # Single Item + mediaItem(id: ID!): MediaItem! @hasRole(role: User) + device(id: ID!): Device! @hasRole(role: User) + album(id: ID!): Album! @hasRole(role: User) + tag(id: ID!): Tag! @hasRole(role: User) + user(id: ID!): User! @hasRole(role: Admin) + + # All + mediaItems( + filter: MediaItemFilter + count: Int + page: Int + ): MediaItemResponse! @hasRole(role: User) + devices( + filter: DeviceFilter + count: Int + page: Int + ): DeviceResponse! @hasRole(role: User) + albums( + filter: AlbumFilter + count: Int + page: Int + ): AlbumResponse! @hasRole(role: User) + tags( + filter: TagFilter + count: Int + page: Int + ): TagResponse! @hasRole(role: User) + users( + filter: UserFilter + count: Int + page: Int + ): UserResponse! @hasRole(role: Admin) +} + +type Mutation { + createMediaItem(input: NewMediaItem!): MediaItem! @hasRole(role: User) + createDevice(input: NewDevice!): Device! @hasRole(role: User) + createAlbum(input: NewAlbum!): Album! @hasRole(role: User) + createTag(input: NewTag!): Tag! @hasRole(role: User) + createUser(input: NewUser!): User! @hasRole(role: Admin) +} +`, BuiltIn: false}, +} +var parsedSchema = gqlparser.MustLoadSchema(sources...) + +// endregion ************************** generated!.gotpl ************************** + +// region ***************************** args.gotpl ***************************** + +func (ec *executionContext) dir_hasRole_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.Role + if tmp, ok := rawArgs["role"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("role")) + arg0, err = ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, tmp) + if err != nil { + return nil, err + } + } + args["role"] = arg0 + return args, nil +} + +func (ec *executionContext) dir_meta_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *string + if tmp, ok := rawArgs["gorm"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("gorm")) + arg0, err = ec.unmarshalOString2ᚖstring(ctx, tmp) + if err != nil { + return nil, err + } + } + args["gorm"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_createAlbum_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.NewAlbum + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNNewAlbum2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewAlbum(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_createDevice_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.NewDevice + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNNewDevice2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewDevice(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_createMediaItem_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.NewMediaItem + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNNewMediaItem2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewMediaItem(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_createTag_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.NewTag + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNNewTag2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewTag(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_createUser_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.NewUser + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNNewUser2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewUser(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["name"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + arg0, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["name"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_album_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_albums_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *model.AlbumFilter + if tmp, ok := rawArgs["filter"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) + arg0, err = ec.unmarshalOAlbumFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbumFilter(ctx, tmp) + if err != nil { + return nil, err + } + } + args["filter"] = arg0 + var arg1 *int + if tmp, ok := rawArgs["count"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) + arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["count"] = arg1 + var arg2 *int + if tmp, ok := rawArgs["page"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) + arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["page"] = arg2 + return args, nil +} + +func (ec *executionContext) field_Query_device_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_devices_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *model.DeviceFilter + if tmp, ok := rawArgs["filter"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) + arg0, err = ec.unmarshalODeviceFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceFilter(ctx, tmp) + if err != nil { + return nil, err + } + } + args["filter"] = arg0 + var arg1 *int + if tmp, ok := rawArgs["count"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) + arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["count"] = arg1 + var arg2 *int + if tmp, ok := rawArgs["page"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) + arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["page"] = arg2 + return args, nil +} + +func (ec *executionContext) field_Query_mediaItem_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_mediaItems_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *model.MediaItemFilter + if tmp, ok := rawArgs["filter"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) + arg0, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, tmp) + if err != nil { + return nil, err + } + } + args["filter"] = arg0 + var arg1 *int + if tmp, ok := rawArgs["count"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) + arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["count"] = arg1 + var arg2 *int + if tmp, ok := rawArgs["page"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) + arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["page"] = arg2 + return args, nil +} + +func (ec *executionContext) field_Query_tag_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_tags_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *model.TagFilter + if tmp, ok := rawArgs["filter"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) + arg0, err = ec.unmarshalOTagFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTagFilter(ctx, tmp) + if err != nil { + return nil, err + } + } + args["filter"] = arg0 + var arg1 *int + if tmp, ok := rawArgs["count"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) + arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["count"] = arg1 + var arg2 *int + if tmp, ok := rawArgs["page"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) + arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["page"] = arg2 + return args, nil +} + +func (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_users_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *model.UserFilter + if tmp, ok := rawArgs["filter"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) + arg0, err = ec.unmarshalOUserFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserFilter(ctx, tmp) + if err != nil { + return nil, err + } + } + args["filter"] = arg0 + var arg1 *int + if tmp, ok := rawArgs["count"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) + arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["count"] = arg1 + var arg2 *int + if tmp, ok := rawArgs["page"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) + arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["page"] = arg2 + return args, nil +} + +func (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 bool + if tmp, ok := rawArgs["includeDeprecated"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) + arg0, err = ec.unmarshalOBoolean2bool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["includeDeprecated"] = arg0 + return args, nil +} + +func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 bool + if tmp, ok := rawArgs["includeDeprecated"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) + arg0, err = ec.unmarshalOBoolean2bool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["includeDeprecated"] = arg0 + return args, nil +} + +// endregion ***************************** args.gotpl ***************************** + +// region ************************** directives.gotpl ************************** + +// endregion ************************** directives.gotpl ************************** + +// region **************************** field.gotpl ***************************** + +func (ec *executionContext) _Album_id(ctx context.Context, field graphql.CollectedField, obj *model.Album) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Album", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ID, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primarykey;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOID2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _Album_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.Album) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Album", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.CreatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _Album_updatedAt(ctx context.Context, field graphql.CollectedField, obj *model.Album) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Album", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UpdatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _Album_name(ctx context.Context, field graphql.CollectedField, obj *model.Album) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Album", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "unique;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) _AlbumResponse_data(ctx context.Context, field graphql.CollectedField, obj *model.AlbumResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "AlbumResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Data, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.Album) + fc.Result = res + return ec.marshalOAlbum2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbum(ctx, field.Selections, res) +} + +func (ec *executionContext) _AlbumResponse_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.AlbumResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "AlbumResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PageInfo, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.PageInfo) + fc.Result = res + return ec.marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) +} + +func (ec *executionContext) _Device_id(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Device", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ID, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primarykey;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOID2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _Device_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Device", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.CreatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _Device_updatedAt(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Device", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UpdatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _Device_name(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Device", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) _Device_type(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Device", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Type, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "default:Unknown;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(model.DeviceType); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be reichard.io/imagini/graph/model.DeviceType`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(model.DeviceType) + fc.Result = res + return ec.marshalNDeviceType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx, field.Selections, res) +} + +func (ec *executionContext) _Device_user(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Device", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.User, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "ForeignKey:ID;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.User); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.User`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.User) + fc.Result = res + return ec.marshalOUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) +} + +func (ec *executionContext) _Device_refreshKey(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Device", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.RefreshKey, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _DeviceResponse_data(ctx context.Context, field graphql.CollectedField, obj *model.DeviceResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "DeviceResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Data, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.Device) + fc.Result = res + return ec.marshalODevice2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx, field.Selections, res) +} + +func (ec *executionContext) _DeviceResponse_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.DeviceResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "DeviceResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PageInfo, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.PageInfo) + fc.Result = res + return ec.marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItem_id(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ID, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primarykey;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOID2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItem_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.CreatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItem_updatedAt(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UpdatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItem_exifDate(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ExifDate, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItem_latitude(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Latitude, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*float64) + fc.Result = res + return ec.marshalOFloat2ᚖfloat64(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItem_longitude(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Longitude, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*float64) + fc.Result = res + return ec.marshalOFloat2ᚖfloat64(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItem_isVideo(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsVideo, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "default:false;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(bool); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be bool`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItem_fileName(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.FileName, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItem_origName(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.OrigName, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItem_tags(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Tags, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "many2many:media_tags") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.([]*model.Tag); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be []*reichard.io/imagini/graph/model.Tag`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.Tag) + fc.Result = res + return ec.marshalOTag2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTag(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItem_albums(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Albums, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "many2many:media_albums") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.([]*model.Album); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be []*reichard.io/imagini/graph/model.Album`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.Album) + fc.Result = res + return ec.marshalOAlbum2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbum(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItem_user(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.User, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "ForeignKey:ID;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.User); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.User`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.User) + fc.Result = res + return ec.marshalOUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItemResponse_data(ctx context.Context, field graphql.CollectedField, obj *model.MediaItemResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItemResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Data, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.MediaItem) + fc.Result = res + return ec.marshalOMediaItem2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItem(ctx, field.Selections, res) +} + +func (ec *executionContext) _MediaItemResponse_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.MediaItemResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItemResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PageInfo, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.PageInfo) + fc.Result = res + return ec.marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_createMediaItem(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_createMediaItem_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().CreateMediaItem(rctx, args["input"].(model.NewMediaItem)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.MediaItem); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.MediaItem`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.MediaItem) + fc.Result = res + return ec.marshalNMediaItem2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItem(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_createDevice(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_createDevice_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().CreateDevice(rctx, args["input"].(model.NewDevice)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.Device); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.Device`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Device) + fc.Result = res + return ec.marshalNDevice2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_createAlbum(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_createAlbum_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().CreateAlbum(rctx, args["input"].(model.NewAlbum)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.Album); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.Album`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Album) + fc.Result = res + return ec.marshalNAlbum2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbum(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_createTag(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_createTag_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().CreateTag(rctx, args["input"].(model.NewTag)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.Tag); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.Tag`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Tag) + fc.Result = res + return ec.marshalNTag2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTag(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_createUser(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_createUser_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().CreateUser(rctx, args["input"].(model.NewUser)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "Admin") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.User); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.User`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.User) + fc.Result = res + return ec.marshalNUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) +} + +func (ec *executionContext) _PageInfo_count(ctx context.Context, field graphql.CollectedField, obj *model.PageInfo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "PageInfo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Count, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _PageInfo_page(ctx context.Context, field graphql.CollectedField, obj *model.PageInfo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "PageInfo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Page, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _PageInfo_total(ctx context.Context, field graphql.CollectedField, obj *model.PageInfo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "PageInfo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Total, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_mediaItem(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_mediaItem_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().MediaItem(rctx, args["id"].(string)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.MediaItem); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.MediaItem`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.MediaItem) + fc.Result = res + return ec.marshalNMediaItem2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItem(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_device(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_device_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Device(rctx, args["id"].(string)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.Device); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.Device`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Device) + fc.Result = res + return ec.marshalNDevice2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_album(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_album_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Album(rctx, args["id"].(string)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.Album); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.Album`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Album) + fc.Result = res + return ec.marshalNAlbum2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbum(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_tag(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_tag_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Tag(rctx, args["id"].(string)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.Tag); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.Tag`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Tag) + fc.Result = res + return ec.marshalNTag2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTag(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_user(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_user_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().User(rctx, args["id"].(string)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "Admin") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.User); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.User`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.User) + fc.Result = res + return ec.marshalNUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_mediaItems(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_mediaItems_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().MediaItems(rctx, args["filter"].(*model.MediaItemFilter), args["count"].(*int), args["page"].(*int)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.MediaItemResponse); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.MediaItemResponse`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.MediaItemResponse) + fc.Result = res + return ec.marshalNMediaItemResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemResponse(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_devices(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_devices_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Devices(rctx, args["filter"].(*model.DeviceFilter), args["count"].(*int), args["page"].(*int)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.DeviceResponse); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.DeviceResponse`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.DeviceResponse) + fc.Result = res + return ec.marshalNDeviceResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceResponse(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_albums(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_albums_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Albums(rctx, args["filter"].(*model.AlbumFilter), args["count"].(*int), args["page"].(*int)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.AlbumResponse); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.AlbumResponse`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.AlbumResponse) + fc.Result = res + return ec.marshalNAlbumResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbumResponse(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_tags(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_tags_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Tags(rctx, args["filter"].(*model.TagFilter), args["count"].(*int), args["page"].(*int)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.TagResponse); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.TagResponse`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.TagResponse) + fc.Result = res + return ec.marshalNTagResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTagResponse(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_users(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_users_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Users(rctx, args["filter"].(*model.UserFilter), args["count"].(*int), args["page"].(*int)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "Admin") + if err != nil { + return nil, err + } + if ec.directives.HasRole == nil { + return nil, errors.New("directive hasRole is not implemented") + } + return ec.directives.HasRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.UserResponse); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.UserResponse`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.UserResponse) + fc.Result = res + return ec.marshalNUserResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserResponse(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query___type_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.introspectType(args["name"].(string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.introspectSchema() + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Schema) + fc.Result = res + return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res) +} + +func (ec *executionContext) _Tag_id(ctx context.Context, field graphql.CollectedField, obj *model.Tag) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Tag", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ID, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primarykey;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOID2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _Tag_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.Tag) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Tag", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.CreatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _Tag_updatedAt(ctx context.Context, field graphql.CollectedField, obj *model.Tag) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Tag", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UpdatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _Tag_name(ctx context.Context, field graphql.CollectedField, obj *model.Tag) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Tag", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "unique;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) _TagResponse_data(ctx context.Context, field graphql.CollectedField, obj *model.TagResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "TagResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Data, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.Tag) + fc.Result = res + return ec.marshalOTag2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTag(ctx, field.Selections, res) +} + +func (ec *executionContext) _TagResponse_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.TagResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "TagResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PageInfo, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.PageInfo) + fc.Result = res + return ec.marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ID, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primarykey;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOID2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.CreatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_updatedAt(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UpdatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_email(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Email, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "not null;unique") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_username(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Username, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "not null;unique") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_firstName(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.FirstName, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_lastName(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.LastName, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_role(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Role, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "default:User;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(model.Role); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be reichard.io/imagini/graph/model.Role`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(model.Role) + fc.Result = res + return ec.marshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_authType(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.AuthType, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "default:Local;not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(model.AuthType); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be reichard.io/imagini/graph/model.AuthType`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(model.AuthType) + fc.Result = res + return ec.marshalNAuthType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_password(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Password, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _UserResponse_data(ctx context.Context, field graphql.CollectedField, obj *model.UserResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "UserResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Data, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.User) + fc.Result = res + return ec.marshalOUser2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) +} + +func (ec *executionContext) _UserResponse_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.UserResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "UserResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PageInfo, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.PageInfo) + fc.Result = res + return ec.marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Locations, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]string) + fc.Result = res + return ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Args, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]introspection.InputValue) + fc.Result = res + return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsDeprecated(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DeprecationReason(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Args, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]introspection.InputValue) + fc.Result = res + return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Type, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsDeprecated(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DeprecationReason(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Type, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DefaultValue, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Types(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.QueryType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MutationType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.SubscriptionType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Directives(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]introspection.Directive) + fc.Result = res + return ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Kind(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalN__TypeKind2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field___Type_fields_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Fields(args["includeDeprecated"].(bool)), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Field) + fc.Result = res + return ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Interfaces(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PossibleTypes(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field___Type_enumValues_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.EnumValues(args["includeDeprecated"].(bool)), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.EnumValue) + fc.Result = res + return ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.InputFields(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.InputValue) + fc.Result = res + return ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.OfType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +// endregion **************************** field.gotpl ***************************** + +// region **************************** input.gotpl ***************************** + +func (ec *executionContext) unmarshalInputAlbumFilter(ctx context.Context, obj interface{}) (model.AlbumFilter, error) { + var it model.AlbumFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalOIDFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐIDFilter(ctx, v) + if err != nil { + return it, err + } + case "createdAt": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAt")) + it.CreatedAt, err = ec.unmarshalOTimeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTimeFilter(ctx, v) + if err != nil { + return it, err + } + case "updatedAt": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("updatedAt")) + it.UpdatedAt, err = ec.unmarshalOTimeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTimeFilter(ctx, v) + if err != nil { + return it, err + } + case "name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + it.Name, err = ec.unmarshalOStringFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐStringFilter(ctx, v) + if err != nil { + return it, err + } + case "and": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + it.And, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) + if err != nil { + return it, err + } + case "or": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + it.Or, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputAuthTypeFilter(ctx context.Context, obj interface{}) (model.AuthTypeFilter, error) { + var it model.AuthTypeFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "equalTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("equalTo")) + it.EqualTo, err = ec.unmarshalOAuthType2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx, v) + if err != nil { + return it, err + } + case "notEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEqualTo")) + it.NotEqualTo, err = ec.unmarshalOAuthType2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx, v) + if err != nil { + return it, err + } + case "in": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) + it.In, err = ec.unmarshalOAuthType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthTypeᚄ(ctx, v) + if err != nil { + return it, err + } + case "notIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) + it.NotIn, err = ec.unmarshalOAuthType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthTypeᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputBooleanFilter(ctx context.Context, obj interface{}) (model.BooleanFilter, error) { + var it model.BooleanFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "equalTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("equalTo")) + it.EqualTo, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "notEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEqualTo")) + it.NotEqualTo, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputDeviceFilter(ctx context.Context, obj interface{}) (model.DeviceFilter, error) { + var it model.DeviceFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalOIDFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐIDFilter(ctx, v) + if err != nil { + return it, err + } + case "createdAt": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAt")) + it.CreatedAt, err = ec.unmarshalOTimeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTimeFilter(ctx, v) + if err != nil { + return it, err + } + case "updatedAt": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("updatedAt")) + it.UpdatedAt, err = ec.unmarshalOTimeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTimeFilter(ctx, v) + if err != nil { + return it, err + } + case "name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + it.Name, err = ec.unmarshalOStringFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐStringFilter(ctx, v) + if err != nil { + return it, err + } + case "type": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("type")) + it.Type, err = ec.unmarshalODeviceTypeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceTypeFilter(ctx, v) + if err != nil { + return it, err + } + case "and": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + it.And, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) + if err != nil { + return it, err + } + case "or": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + it.Or, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputDeviceTypeFilter(ctx context.Context, obj interface{}) (model.DeviceTypeFilter, error) { + var it model.DeviceTypeFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "equalTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("equalTo")) + it.EqualTo, err = ec.unmarshalODeviceType2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx, v) + if err != nil { + return it, err + } + case "notEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEqualTo")) + it.NotEqualTo, err = ec.unmarshalODeviceType2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx, v) + if err != nil { + return it, err + } + case "in": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) + it.In, err = ec.unmarshalODeviceType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceTypeᚄ(ctx, v) + if err != nil { + return it, err + } + case "notIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) + it.NotIn, err = ec.unmarshalODeviceType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceTypeᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputFloatFilter(ctx context.Context, obj interface{}) (model.FloatFilter, error) { + var it model.FloatFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "equalTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("equalTo")) + it.EqualTo, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) + if err != nil { + return it, err + } + case "notEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEqualTo")) + it.NotEqualTo, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) + if err != nil { + return it, err + } + case "lessThan": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lessThan")) + it.LessThan, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) + if err != nil { + return it, err + } + case "lessThanOrEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lessThanOrEqualTo")) + it.LessThanOrEqualTo, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) + if err != nil { + return it, err + } + case "moreThan": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("moreThan")) + it.MoreThan, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) + if err != nil { + return it, err + } + case "moreThanOrEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("moreThanOrEqualTo")) + it.MoreThanOrEqualTo, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) + if err != nil { + return it, err + } + case "in": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) + it.In, err = ec.unmarshalOFloat2ᚕfloat64ᚄ(ctx, v) + if err != nil { + return it, err + } + case "notIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) + it.NotIn, err = ec.unmarshalOFloat2ᚕfloat64ᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputIDFilter(ctx context.Context, obj interface{}) (model.IDFilter, error) { + var it model.IDFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "equalTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("equalTo")) + it.EqualTo, err = ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "notEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEqualTo")) + it.NotEqualTo, err = ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "in": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) + it.In, err = ec.unmarshalOID2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "notIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) + it.NotIn, err = ec.unmarshalOID2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputIntFilter(ctx context.Context, obj interface{}) (model.IntFilter, error) { + var it model.IntFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "equalTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("equalTo")) + it.EqualTo, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "notEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEqualTo")) + it.NotEqualTo, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "lessThan": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lessThan")) + it.LessThan, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "lessThanOrEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lessThanOrEqualTo")) + it.LessThanOrEqualTo, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "moreThan": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("moreThan")) + it.MoreThan, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "moreThanOrEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("moreThanOrEqualTo")) + it.MoreThanOrEqualTo, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "in": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) + it.In, err = ec.unmarshalOInt2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "notIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) + it.NotIn, err = ec.unmarshalOInt2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputMediaItemFilter(ctx context.Context, obj interface{}) (model.MediaItemFilter, error) { + var it model.MediaItemFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalOIDFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐIDFilter(ctx, v) + if err != nil { + return it, err + } + case "createdAt": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAt")) + it.CreatedAt, err = ec.unmarshalOTimeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTimeFilter(ctx, v) + if err != nil { + return it, err + } + case "updatedAt": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("updatedAt")) + it.UpdatedAt, err = ec.unmarshalOTimeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTimeFilter(ctx, v) + if err != nil { + return it, err + } + case "exifDate": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("exifDate")) + it.ExifDate, err = ec.unmarshalOTimeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTimeFilter(ctx, v) + if err != nil { + return it, err + } + case "latitude": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("latitude")) + it.Latitude, err = ec.unmarshalOFloatFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐFloatFilter(ctx, v) + if err != nil { + return it, err + } + case "longitude": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("longitude")) + it.Longitude, err = ec.unmarshalOFloatFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐFloatFilter(ctx, v) + if err != nil { + return it, err + } + case "isVideo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("isVideo")) + it.IsVideo, err = ec.unmarshalOBooleanFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐBooleanFilter(ctx, v) + if err != nil { + return it, err + } + case "origName": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("origName")) + it.OrigName, err = ec.unmarshalOStringFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐStringFilter(ctx, v) + if err != nil { + return it, err + } + case "tags": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("tags")) + it.Tags, err = ec.unmarshalOTagFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTagFilter(ctx, v) + if err != nil { + return it, err + } + case "albums": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("albums")) + it.Albums, err = ec.unmarshalOAlbumFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbumFilter(ctx, v) + if err != nil { + return it, err + } + case "and": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + it.And, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) + if err != nil { + return it, err + } + case "or": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + it.Or, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputNewAlbum(ctx context.Context, obj interface{}) (model.NewAlbum, error) { + var it model.NewAlbum + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + it.Name, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputNewDevice(ctx context.Context, obj interface{}) (model.NewDevice, error) { + var it model.NewDevice + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + it.Name, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputNewMediaItem(ctx context.Context, obj interface{}) (model.NewMediaItem, error) { + var it model.NewMediaItem + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "file": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("file")) + it.File, err = ec.unmarshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx, v) + if err != nil { + return it, err + } + case "tags": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("tags")) + it.Tags, err = ec.unmarshalOID2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "albums": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("albums")) + it.Albums, err = ec.unmarshalOID2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputNewTag(ctx context.Context, obj interface{}) (model.NewTag, error) { + var it model.NewTag + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + it.Name, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputNewUser(ctx context.Context, obj interface{}) (model.NewUser, error) { + var it model.NewUser + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "email": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email")) + it.Email, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "username": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("username")) + it.Username, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "firstName": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("firstName")) + it.FirstName, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "lastName": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lastName")) + it.LastName, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "role": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("role")) + it.Role, err = ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, v) + if err != nil { + return it, err + } + case "authType": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authType")) + it.AuthType, err = ec.unmarshalNAuthType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx, v) + if err != nil { + return it, err + } + case "password": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("password")) + it.Password, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputRoleFilter(ctx context.Context, obj interface{}) (model.RoleFilter, error) { + var it model.RoleFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "equalTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("equalTo")) + it.EqualTo, err = ec.unmarshalORole2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, v) + if err != nil { + return it, err + } + case "notEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEqualTo")) + it.NotEqualTo, err = ec.unmarshalORole2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, v) + if err != nil { + return it, err + } + case "in": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) + it.In, err = ec.unmarshalORole2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRoleᚄ(ctx, v) + if err != nil { + return it, err + } + case "notIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) + it.NotIn, err = ec.unmarshalORole2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRoleᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputStringFilter(ctx context.Context, obj interface{}) (model.StringFilter, error) { + var it model.StringFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "equalTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("equalTo")) + it.EqualTo, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "notEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEqualTo")) + it.NotEqualTo, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "startWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("startWith")) + it.StartWith, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "notStartWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notStartWith")) + it.NotStartWith, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "endWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("endWith")) + it.EndWith, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "notEndWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEndWith")) + it.NotEndWith, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "contain": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("contain")) + it.Contain, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "notContain": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notContain")) + it.NotContain, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "in": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) + it.In, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "notIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) + it.NotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "startWithStrict": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("startWithStrict")) + it.StartWithStrict, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "notStartWithStrict": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notStartWithStrict")) + it.NotStartWithStrict, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "endWithStrict": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("endWithStrict")) + it.EndWithStrict, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "notEndWithStrict": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEndWithStrict")) + it.NotEndWithStrict, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "containStrict": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("containStrict")) + it.ContainStrict, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "notContainStrict": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notContainStrict")) + it.NotContainStrict, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputTagFilter(ctx context.Context, obj interface{}) (model.TagFilter, error) { + var it model.TagFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalOIDFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐIDFilter(ctx, v) + if err != nil { + return it, err + } + case "createdAt": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAt")) + it.CreatedAt, err = ec.unmarshalOTimeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTimeFilter(ctx, v) + if err != nil { + return it, err + } + case "updatedAt": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("updatedAt")) + it.UpdatedAt, err = ec.unmarshalOTimeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTimeFilter(ctx, v) + if err != nil { + return it, err + } + case "name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + it.Name, err = ec.unmarshalOStringFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐStringFilter(ctx, v) + if err != nil { + return it, err + } + case "and": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + it.And, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) + if err != nil { + return it, err + } + case "or": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + it.Or, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputTimeFilter(ctx context.Context, obj interface{}) (model.TimeFilter, error) { + var it model.TimeFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "equalTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("equalTo")) + it.EqualTo, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + if err != nil { + return it, err + } + case "notEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEqualTo")) + it.NotEqualTo, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + if err != nil { + return it, err + } + case "lessThan": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lessThan")) + it.LessThan, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + if err != nil { + return it, err + } + case "lessThanOrEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lessThanOrEqualTo")) + it.LessThanOrEqualTo, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + if err != nil { + return it, err + } + case "moreThan": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("moreThan")) + it.MoreThan, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + if err != nil { + return it, err + } + case "moreThanOrEqualTo": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("moreThanOrEqualTo")) + it.MoreThanOrEqualTo, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputUserFilter(ctx context.Context, obj interface{}) (model.UserFilter, error) { + var it model.UserFilter + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalOIDFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐIDFilter(ctx, v) + if err != nil { + return it, err + } + case "createdAt": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAt")) + it.CreatedAt, err = ec.unmarshalOTimeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTimeFilter(ctx, v) + if err != nil { + return it, err + } + case "updatedAt": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("updatedAt")) + it.UpdatedAt, err = ec.unmarshalOTimeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTimeFilter(ctx, v) + if err != nil { + return it, err + } + case "username": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("username")) + it.Username, err = ec.unmarshalOStringFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐStringFilter(ctx, v) + if err != nil { + return it, err + } + case "firstName": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("firstName")) + it.FirstName, err = ec.unmarshalOStringFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐStringFilter(ctx, v) + if err != nil { + return it, err + } + case "lastName": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lastName")) + it.LastName, err = ec.unmarshalOStringFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐStringFilter(ctx, v) + if err != nil { + return it, err + } + case "role": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("role")) + it.Role, err = ec.unmarshalORoleFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRoleFilter(ctx, v) + if err != nil { + return it, err + } + case "authType": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authType")) + it.AuthType, err = ec.unmarshalOAuthTypeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthTypeFilter(ctx, v) + if err != nil { + return it, err + } + case "and": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + it.And, err = ec.unmarshalOUserFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserFilter(ctx, v) + if err != nil { + return it, err + } + case "or": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + it.Or, err = ec.unmarshalOUserFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserFilter(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +// endregion **************************** input.gotpl ***************************** + +// region ************************** interface.gotpl *************************** + +// endregion ************************** interface.gotpl *************************** + +// region **************************** object.gotpl **************************** + +var albumImplementors = []string{"Album"} + +func (ec *executionContext) _Album(ctx context.Context, sel ast.SelectionSet, obj *model.Album) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, albumImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Album") + case "id": + out.Values[i] = ec._Album_id(ctx, field, obj) + case "createdAt": + out.Values[i] = ec._Album_createdAt(ctx, field, obj) + case "updatedAt": + out.Values[i] = ec._Album_updatedAt(ctx, field, obj) + case "name": + out.Values[i] = ec._Album_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var albumResponseImplementors = []string{"AlbumResponse"} + +func (ec *executionContext) _AlbumResponse(ctx context.Context, sel ast.SelectionSet, obj *model.AlbumResponse) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, albumResponseImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("AlbumResponse") + case "data": + out.Values[i] = ec._AlbumResponse_data(ctx, field, obj) + case "pageInfo": + out.Values[i] = ec._AlbumResponse_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var deviceImplementors = []string{"Device"} + +func (ec *executionContext) _Device(ctx context.Context, sel ast.SelectionSet, obj *model.Device) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, deviceImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Device") + case "id": + out.Values[i] = ec._Device_id(ctx, field, obj) + case "createdAt": + out.Values[i] = ec._Device_createdAt(ctx, field, obj) + case "updatedAt": + out.Values[i] = ec._Device_updatedAt(ctx, field, obj) + case "name": + out.Values[i] = ec._Device_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "type": + out.Values[i] = ec._Device_type(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "user": + out.Values[i] = ec._Device_user(ctx, field, obj) + case "refreshKey": + out.Values[i] = ec._Device_refreshKey(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var deviceResponseImplementors = []string{"DeviceResponse"} + +func (ec *executionContext) _DeviceResponse(ctx context.Context, sel ast.SelectionSet, obj *model.DeviceResponse) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, deviceResponseImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DeviceResponse") + case "data": + out.Values[i] = ec._DeviceResponse_data(ctx, field, obj) + case "pageInfo": + out.Values[i] = ec._DeviceResponse_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var mediaItemImplementors = []string{"MediaItem"} + +func (ec *executionContext) _MediaItem(ctx context.Context, sel ast.SelectionSet, obj *model.MediaItem) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, mediaItemImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("MediaItem") + case "id": + out.Values[i] = ec._MediaItem_id(ctx, field, obj) + case "createdAt": + out.Values[i] = ec._MediaItem_createdAt(ctx, field, obj) + case "updatedAt": + out.Values[i] = ec._MediaItem_updatedAt(ctx, field, obj) + case "exifDate": + out.Values[i] = ec._MediaItem_exifDate(ctx, field, obj) + case "latitude": + out.Values[i] = ec._MediaItem_latitude(ctx, field, obj) + case "longitude": + out.Values[i] = ec._MediaItem_longitude(ctx, field, obj) + case "isVideo": + out.Values[i] = ec._MediaItem_isVideo(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "fileName": + out.Values[i] = ec._MediaItem_fileName(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "origName": + out.Values[i] = ec._MediaItem_origName(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "tags": + out.Values[i] = ec._MediaItem_tags(ctx, field, obj) + case "albums": + out.Values[i] = ec._MediaItem_albums(ctx, field, obj) + case "user": + out.Values[i] = ec._MediaItem_user(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var mediaItemResponseImplementors = []string{"MediaItemResponse"} + +func (ec *executionContext) _MediaItemResponse(ctx context.Context, sel ast.SelectionSet, obj *model.MediaItemResponse) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, mediaItemResponseImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("MediaItemResponse") + case "data": + out.Values[i] = ec._MediaItemResponse_data(ctx, field, obj) + case "pageInfo": + out.Values[i] = ec._MediaItemResponse_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var mutationImplementors = []string{"Mutation"} + +func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors) + + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Mutation", + }) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Mutation") + case "createMediaItem": + out.Values[i] = ec._Mutation_createMediaItem(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "createDevice": + out.Values[i] = ec._Mutation_createDevice(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "createAlbum": + out.Values[i] = ec._Mutation_createAlbum(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "createTag": + out.Values[i] = ec._Mutation_createTag(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "createUser": + out.Values[i] = ec._Mutation_createUser(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var pageInfoImplementors = []string{"PageInfo"} + +func (ec *executionContext) _PageInfo(ctx context.Context, sel ast.SelectionSet, obj *model.PageInfo) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, pageInfoImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("PageInfo") + case "count": + out.Values[i] = ec._PageInfo_count(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "page": + out.Values[i] = ec._PageInfo_page(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "total": + out.Values[i] = ec._PageInfo_total(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var queryImplementors = []string{"Query"} + +func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, queryImplementors) + + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Query", + }) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Query") + case "mediaItem": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_mediaItem(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "device": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_device(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "album": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_album(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "tag": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_tag(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "user": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_user(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "mediaItems": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_mediaItems(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "devices": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_devices(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "albums": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_albums(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "tags": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_tags(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "users": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_users(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "__type": + out.Values[i] = ec._Query___type(ctx, field) + case "__schema": + out.Values[i] = ec._Query___schema(ctx, field) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var tagImplementors = []string{"Tag"} + +func (ec *executionContext) _Tag(ctx context.Context, sel ast.SelectionSet, obj *model.Tag) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, tagImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Tag") + case "id": + out.Values[i] = ec._Tag_id(ctx, field, obj) + case "createdAt": + out.Values[i] = ec._Tag_createdAt(ctx, field, obj) + case "updatedAt": + out.Values[i] = ec._Tag_updatedAt(ctx, field, obj) + case "name": + out.Values[i] = ec._Tag_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var tagResponseImplementors = []string{"TagResponse"} + +func (ec *executionContext) _TagResponse(ctx context.Context, sel ast.SelectionSet, obj *model.TagResponse) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, tagResponseImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("TagResponse") + case "data": + out.Values[i] = ec._TagResponse_data(ctx, field, obj) + case "pageInfo": + out.Values[i] = ec._TagResponse_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var userImplementors = []string{"User"} + +func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *model.User) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, userImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("User") + case "id": + out.Values[i] = ec._User_id(ctx, field, obj) + case "createdAt": + out.Values[i] = ec._User_createdAt(ctx, field, obj) + case "updatedAt": + out.Values[i] = ec._User_updatedAt(ctx, field, obj) + case "email": + out.Values[i] = ec._User_email(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "username": + out.Values[i] = ec._User_username(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "firstName": + out.Values[i] = ec._User_firstName(ctx, field, obj) + case "lastName": + out.Values[i] = ec._User_lastName(ctx, field, obj) + case "role": + out.Values[i] = ec._User_role(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "authType": + out.Values[i] = ec._User_authType(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "password": + out.Values[i] = ec._User_password(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var userResponseImplementors = []string{"UserResponse"} + +func (ec *executionContext) _UserResponse(ctx context.Context, sel ast.SelectionSet, obj *model.UserResponse) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, userResponseImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("UserResponse") + case "data": + out.Values[i] = ec._UserResponse_data(ctx, field, obj) + case "pageInfo": + out.Values[i] = ec._UserResponse_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __DirectiveImplementors = []string{"__Directive"} + +func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __DirectiveImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Directive") + case "name": + out.Values[i] = ec.___Directive_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + out.Values[i] = ec.___Directive_description(ctx, field, obj) + case "locations": + out.Values[i] = ec.___Directive_locations(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "args": + out.Values[i] = ec.___Directive_args(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __EnumValueImplementors = []string{"__EnumValue"} + +func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__EnumValue") + case "name": + out.Values[i] = ec.___EnumValue_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + out.Values[i] = ec.___EnumValue_description(ctx, field, obj) + case "isDeprecated": + out.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "deprecationReason": + out.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __FieldImplementors = []string{"__Field"} + +func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __FieldImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Field") + case "name": + out.Values[i] = ec.___Field_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + out.Values[i] = ec.___Field_description(ctx, field, obj) + case "args": + out.Values[i] = ec.___Field_args(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "type": + out.Values[i] = ec.___Field_type(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "isDeprecated": + out.Values[i] = ec.___Field_isDeprecated(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "deprecationReason": + out.Values[i] = ec.___Field_deprecationReason(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __InputValueImplementors = []string{"__InputValue"} + +func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __InputValueImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__InputValue") + case "name": + out.Values[i] = ec.___InputValue_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + out.Values[i] = ec.___InputValue_description(ctx, field, obj) + case "type": + out.Values[i] = ec.___InputValue_type(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "defaultValue": + out.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __SchemaImplementors = []string{"__Schema"} + +func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __SchemaImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Schema") + case "types": + out.Values[i] = ec.___Schema_types(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "queryType": + out.Values[i] = ec.___Schema_queryType(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "mutationType": + out.Values[i] = ec.___Schema_mutationType(ctx, field, obj) + case "subscriptionType": + out.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj) + case "directives": + out.Values[i] = ec.___Schema_directives(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __TypeImplementors = []string{"__Type"} + +func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Type") + case "kind": + out.Values[i] = ec.___Type_kind(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "name": + out.Values[i] = ec.___Type_name(ctx, field, obj) + case "description": + out.Values[i] = ec.___Type_description(ctx, field, obj) + case "fields": + out.Values[i] = ec.___Type_fields(ctx, field, obj) + case "interfaces": + out.Values[i] = ec.___Type_interfaces(ctx, field, obj) + case "possibleTypes": + out.Values[i] = ec.___Type_possibleTypes(ctx, field, obj) + case "enumValues": + out.Values[i] = ec.___Type_enumValues(ctx, field, obj) + case "inputFields": + out.Values[i] = ec.___Type_inputFields(ctx, field, obj) + case "ofType": + out.Values[i] = ec.___Type_ofType(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +// endregion **************************** object.gotpl **************************** + +// region ***************************** type.gotpl ***************************** + +func (ec *executionContext) marshalNAlbum2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbum(ctx context.Context, sel ast.SelectionSet, v model.Album) graphql.Marshaler { + return ec._Album(ctx, sel, &v) +} + +func (ec *executionContext) marshalNAlbum2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbum(ctx context.Context, sel ast.SelectionSet, v *model.Album) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._Album(ctx, sel, v) +} + +func (ec *executionContext) marshalNAlbumResponse2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbumResponse(ctx context.Context, sel ast.SelectionSet, v model.AlbumResponse) graphql.Marshaler { + return ec._AlbumResponse(ctx, sel, &v) +} + +func (ec *executionContext) marshalNAlbumResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbumResponse(ctx context.Context, sel ast.SelectionSet, v *model.AlbumResponse) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._AlbumResponse(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNAuthType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx context.Context, v interface{}) (model.AuthType, error) { + var res model.AuthType + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNAuthType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx context.Context, sel ast.SelectionSet, v model.AuthType) graphql.Marshaler { + return v +} + +func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + res := graphql.MarshalBoolean(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + +func (ec *executionContext) marshalNDevice2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx context.Context, sel ast.SelectionSet, v model.Device) graphql.Marshaler { + return ec._Device(ctx, sel, &v) +} + +func (ec *executionContext) marshalNDevice2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx context.Context, sel ast.SelectionSet, v *model.Device) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._Device(ctx, sel, v) +} + +func (ec *executionContext) marshalNDeviceResponse2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceResponse(ctx context.Context, sel ast.SelectionSet, v model.DeviceResponse) graphql.Marshaler { + return ec._DeviceResponse(ctx, sel, &v) +} + +func (ec *executionContext) marshalNDeviceResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceResponse(ctx context.Context, sel ast.SelectionSet, v *model.DeviceResponse) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._DeviceResponse(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNDeviceType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx context.Context, v interface{}) (model.DeviceType, error) { + var res model.DeviceType + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNDeviceType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx context.Context, sel ast.SelectionSet, v model.DeviceType) graphql.Marshaler { + return v +} + +func (ec *executionContext) unmarshalNFloat2float64(ctx context.Context, v interface{}) (float64, error) { + res, err := graphql.UnmarshalFloat(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.SelectionSet, v float64) graphql.Marshaler { + res := graphql.MarshalFloat(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + +func (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalID(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalID(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + +func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) { + res, err := graphql.UnmarshalInt(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { + res := graphql.MarshalInt(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + +func (ec *executionContext) marshalNMediaItem2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItem(ctx context.Context, sel ast.SelectionSet, v model.MediaItem) graphql.Marshaler { + return ec._MediaItem(ctx, sel, &v) +} + +func (ec *executionContext) marshalNMediaItem2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItem(ctx context.Context, sel ast.SelectionSet, v *model.MediaItem) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._MediaItem(ctx, sel, v) +} + +func (ec *executionContext) marshalNMediaItemResponse2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemResponse(ctx context.Context, sel ast.SelectionSet, v model.MediaItemResponse) graphql.Marshaler { + return ec._MediaItemResponse(ctx, sel, &v) +} + +func (ec *executionContext) marshalNMediaItemResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemResponse(ctx context.Context, sel ast.SelectionSet, v *model.MediaItemResponse) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._MediaItemResponse(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNNewAlbum2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewAlbum(ctx context.Context, v interface{}) (model.NewAlbum, error) { + res, err := ec.unmarshalInputNewAlbum(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalNNewDevice2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewDevice(ctx context.Context, v interface{}) (model.NewDevice, error) { + res, err := ec.unmarshalInputNewDevice(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalNNewMediaItem2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewMediaItem(ctx context.Context, v interface{}) (model.NewMediaItem, error) { + res, err := ec.unmarshalInputNewMediaItem(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalNNewTag2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewTag(ctx context.Context, v interface{}) (model.NewTag, error) { + res, err := ec.unmarshalInputNewTag(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalNNewUser2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewUser(ctx context.Context, v interface{}) (model.NewUser, error) { + res, err := ec.unmarshalInputNewUser(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx context.Context, sel ast.SelectionSet, v *model.PageInfo) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._PageInfo(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx context.Context, v interface{}) (model.Role, error) { + var res model.Role + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx context.Context, sel ast.SelectionSet, v model.Role) graphql.Marshaler { + return v +} + +func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + +func (ec *executionContext) marshalNTag2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐTag(ctx context.Context, sel ast.SelectionSet, v model.Tag) graphql.Marshaler { + return ec._Tag(ctx, sel, &v) +} + +func (ec *executionContext) marshalNTag2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTag(ctx context.Context, sel ast.SelectionSet, v *model.Tag) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._Tag(ctx, sel, v) +} + +func (ec *executionContext) marshalNTagResponse2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐTagResponse(ctx context.Context, sel ast.SelectionSet, v model.TagResponse) graphql.Marshaler { + return ec._TagResponse(ctx, sel, &v) +} + +func (ec *executionContext) marshalNTagResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTagResponse(ctx context.Context, sel ast.SelectionSet, v *model.TagResponse) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._TagResponse(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx context.Context, v interface{}) (graphql.Upload, error) { + res, err := graphql.UnmarshalUpload(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx context.Context, sel ast.SelectionSet, v graphql.Upload) graphql.Marshaler { + res := graphql.MarshalUpload(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + +func (ec *executionContext) marshalNUser2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx context.Context, sel ast.SelectionSet, v model.User) graphql.Marshaler { + return ec._User(ctx, sel, &v) +} + +func (ec *executionContext) marshalNUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx context.Context, sel ast.SelectionSet, v *model.User) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._User(ctx, sel, v) +} + +func (ec *executionContext) marshalNUserResponse2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserResponse(ctx context.Context, sel ast.SelectionSet, v model.UserResponse) graphql.Marshaler { + return ec._UserResponse(ctx, sel, &v) +} + +func (ec *executionContext) marshalNUserResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserResponse(ctx context.Context, sel ast.SelectionSet, v *model.UserResponse) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._UserResponse(ctx, sel, v) +} + +func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { + return ec.___Directive(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + +func (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { + var vSlice []interface{} + if v != nil { + if tmp1, ok := v.([]interface{}); ok { + vSlice = tmp1 + } else { + vSlice = []interface{}{v} + } + } + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler { + return ec.___EnumValue(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler { + return ec.___Field(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler { + return ec.___InputValue(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler { + return ec.___Type(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec.___Type(ctx, sel, v) +} + +func (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + +func (ec *executionContext) marshalOAlbum2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbum(ctx context.Context, sel ast.SelectionSet, v []*model.Album) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalOAlbum2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbum(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalOAlbum2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbum(ctx context.Context, sel ast.SelectionSet, v *model.Album) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Album(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOAlbumFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbumFilter(ctx context.Context, v interface{}) (*model.AlbumFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputAlbumFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOAuthType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthTypeᚄ(ctx context.Context, v interface{}) ([]model.AuthType, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + if tmp1, ok := v.([]interface{}); ok { + vSlice = tmp1 + } else { + vSlice = []interface{}{v} + } + } + var err error + res := make([]model.AuthType, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNAuthType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalOAuthType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []model.AuthType) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNAuthType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) unmarshalOAuthType2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx context.Context, v interface{}) (*model.AuthType, error) { + if v == nil { + return nil, nil + } + var res = new(model.AuthType) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOAuthType2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx context.Context, sel ast.SelectionSet, v *model.AuthType) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return v +} + +func (ec *executionContext) unmarshalOAuthTypeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthTypeFilter(ctx context.Context, v interface{}) (*model.AuthTypeFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputAuthTypeFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + return graphql.MarshalBoolean(v) +} + +func (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalBoolean(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return graphql.MarshalBoolean(*v) +} + +func (ec *executionContext) unmarshalOBooleanFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐBooleanFilter(ctx context.Context, v interface{}) (*model.BooleanFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputBooleanFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalODevice2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx context.Context, sel ast.SelectionSet, v []*model.Device) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalODevice2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalODevice2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx context.Context, sel ast.SelectionSet, v *model.Device) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Device(ctx, sel, v) +} + +func (ec *executionContext) unmarshalODeviceFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceFilter(ctx context.Context, v interface{}) (*model.DeviceFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputDeviceFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalODeviceType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceTypeᚄ(ctx context.Context, v interface{}) ([]model.DeviceType, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + if tmp1, ok := v.([]interface{}); ok { + vSlice = tmp1 + } else { + vSlice = []interface{}{v} + } + } + var err error + res := make([]model.DeviceType, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNDeviceType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalODeviceType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []model.DeviceType) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNDeviceType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) unmarshalODeviceType2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx context.Context, v interface{}) (*model.DeviceType, error) { + if v == nil { + return nil, nil + } + var res = new(model.DeviceType) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalODeviceType2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx context.Context, sel ast.SelectionSet, v *model.DeviceType) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return v +} + +func (ec *executionContext) unmarshalODeviceTypeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceTypeFilter(ctx context.Context, v interface{}) (*model.DeviceTypeFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputDeviceTypeFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOFloat2ᚕfloat64ᚄ(ctx context.Context, v interface{}) ([]float64, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + if tmp1, ok := v.([]interface{}); ok { + vSlice = tmp1 + } else { + vSlice = []interface{}{v} + } + } + var err error + res := make([]float64, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNFloat2float64(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalOFloat2ᚕfloat64ᚄ(ctx context.Context, sel ast.SelectionSet, v []float64) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNFloat2float64(ctx, sel, v[i]) + } + + return ret +} + +func (ec *executionContext) unmarshalOFloat2ᚖfloat64(ctx context.Context, v interface{}) (*float64, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalFloat(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOFloat2ᚖfloat64(ctx context.Context, sel ast.SelectionSet, v *float64) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return graphql.MarshalFloat(*v) +} + +func (ec *executionContext) unmarshalOFloatFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐFloatFilter(ctx context.Context, v interface{}) (*model.FloatFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputFloatFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOID2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + if tmp1, ok := v.([]interface{}); ok { + vSlice = tmp1 + } else { + vSlice = []interface{}{v} + } + } + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNID2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalOID2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNID2string(ctx, sel, v[i]) + } + + return ret +} + +func (ec *executionContext) unmarshalOID2ᚖstring(ctx context.Context, v interface{}) (*string, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalID(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOID2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return graphql.MarshalID(*v) +} + +func (ec *executionContext) unmarshalOIDFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐIDFilter(ctx context.Context, v interface{}) (*model.IDFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputIDFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOInt2ᚕintᚄ(ctx context.Context, v interface{}) ([]int, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + if tmp1, ok := v.([]interface{}); ok { + vSlice = tmp1 + } else { + vSlice = []interface{}{v} + } + } + var err error + res := make([]int, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNInt2int(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalOInt2ᚕintᚄ(ctx context.Context, sel ast.SelectionSet, v []int) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNInt2int(ctx, sel, v[i]) + } + + return ret +} + +func (ec *executionContext) unmarshalOInt2ᚖint(ctx context.Context, v interface{}) (*int, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalInt(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.SelectionSet, v *int) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return graphql.MarshalInt(*v) +} + +func (ec *executionContext) marshalOMediaItem2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItem(ctx context.Context, sel ast.SelectionSet, v []*model.MediaItem) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalOMediaItem2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItem(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalOMediaItem2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItem(ctx context.Context, sel ast.SelectionSet, v *model.MediaItem) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._MediaItem(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx context.Context, v interface{}) (*model.MediaItemFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputMediaItemFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalORole2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRoleᚄ(ctx context.Context, v interface{}) ([]model.Role, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + if tmp1, ok := v.([]interface{}); ok { + vSlice = tmp1 + } else { + vSlice = []interface{}{v} + } + } + var err error + res := make([]model.Role, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalORole2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRoleᚄ(ctx context.Context, sel ast.SelectionSet, v []model.Role) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) unmarshalORole2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx context.Context, v interface{}) (*model.Role, error) { + if v == nil { + return nil, nil + } + var res = new(model.Role) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalORole2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx context.Context, sel ast.SelectionSet, v *model.Role) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return v +} + +func (ec *executionContext) unmarshalORoleFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRoleFilter(ctx context.Context, v interface{}) (*model.RoleFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputRoleFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + return graphql.MarshalString(v) +} + +func (ec *executionContext) unmarshalOString2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + if tmp1, ok := v.([]interface{}); ok { + vSlice = tmp1 + } else { + vSlice = []interface{}{v} + } + } + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNString2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalOString2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNString2string(ctx, sel, v[i]) + } + + return ret +} + +func (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalString(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return graphql.MarshalString(*v) +} + +func (ec *executionContext) unmarshalOStringFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐStringFilter(ctx context.Context, v interface{}) (*model.StringFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputStringFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOTag2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTag(ctx context.Context, sel ast.SelectionSet, v []*model.Tag) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalOTag2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTag(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalOTag2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTag(ctx context.Context, sel ast.SelectionSet, v *model.Tag) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Tag(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOTagFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTagFilter(ctx context.Context, v interface{}) (*model.TagFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputTagFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOTime2ᚖtimeᚐTime(ctx context.Context, v interface{}) (*time.Time, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalTime(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOTime2ᚖtimeᚐTime(ctx context.Context, sel ast.SelectionSet, v *time.Time) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return graphql.MarshalTime(*v) +} + +func (ec *executionContext) unmarshalOTimeFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTimeFilter(ctx context.Context, v interface{}) (*model.TimeFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputTimeFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOUser2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx context.Context, sel ast.SelectionSet, v []*model.User) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalOUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalOUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx context.Context, sel ast.SelectionSet, v *model.User) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._User(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOUserFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserFilter(ctx context.Context, v interface{}) (*model.UserFilter, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputUserFilter(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec.___Schema(ctx, sel, v) +} + +func (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec.___Type(ctx, sel, v) +} + +// endregion ***************************** type.gotpl ***************************** diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go new file mode 100644 index 0000000..695b3f4 --- /dev/null +++ b/graph/model/models_gen.go @@ -0,0 +1,397 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package model + +import ( + "fmt" + "io" + "strconv" + "time" + + "github.com/99designs/gqlgen/graphql" +) + +type Album struct { + ID *string `json:"id" gorm:"primarykey;not null"` + CreatedAt *time.Time `json:"createdAt" ` + UpdatedAt *time.Time `json:"updatedAt" ` + Name string `json:"name" gorm:"unique;not null"` +} + +type AlbumFilter struct { + ID *IDFilter `json:"id" ` + CreatedAt *TimeFilter `json:"createdAt" ` + UpdatedAt *TimeFilter `json:"updatedAt" ` + Name *StringFilter `json:"name" ` + And *MediaItemFilter `json:"and" ` + Or *MediaItemFilter `json:"or" ` +} + +type AlbumResponse struct { + Data []*Album `json:"data" ` + PageInfo *PageInfo `json:"pageInfo" ` +} + +type AuthTypeFilter struct { + EqualTo *AuthType `json:"equalTo" ` + NotEqualTo *AuthType `json:"notEqualTo" ` + In []AuthType `json:"in" ` + NotIn []AuthType `json:"notIn" ` +} + +type BooleanFilter struct { + EqualTo *bool `json:"equalTo" ` + NotEqualTo *bool `json:"notEqualTo" ` +} + +type Device struct { + ID *string `json:"id" gorm:"primarykey;not null"` + CreatedAt *time.Time `json:"createdAt" ` + UpdatedAt *time.Time `json:"updatedAt" ` + Name string `json:"name" gorm:"not null"` + Type DeviceType `json:"type" gorm:"default:Unknown;not null"` + User *User `json:"user" gorm:"ForeignKey:ID;not null"` + RefreshKey *string `json:"refreshKey" ` +} + +type DeviceFilter struct { + ID *IDFilter `json:"id" ` + CreatedAt *TimeFilter `json:"createdAt" ` + UpdatedAt *TimeFilter `json:"updatedAt" ` + Name *StringFilter `json:"name" ` + Type *DeviceTypeFilter `json:"type" ` + And *MediaItemFilter `json:"and" ` + Or *MediaItemFilter `json:"or" ` +} + +type DeviceResponse struct { + Data []*Device `json:"data" ` + PageInfo *PageInfo `json:"pageInfo" ` +} + +type DeviceTypeFilter struct { + EqualTo *DeviceType `json:"equalTo" ` + NotEqualTo *DeviceType `json:"notEqualTo" ` + In []DeviceType `json:"in" ` + NotIn []DeviceType `json:"notIn" ` +} + +type FloatFilter struct { + EqualTo *float64 `json:"equalTo" ` + NotEqualTo *float64 `json:"notEqualTo" ` + LessThan *float64 `json:"lessThan" ` + LessThanOrEqualTo *float64 `json:"lessThanOrEqualTo" ` + MoreThan *float64 `json:"moreThan" ` + MoreThanOrEqualTo *float64 `json:"moreThanOrEqualTo" ` + In []float64 `json:"in" ` + NotIn []float64 `json:"notIn" ` +} + +type IDFilter struct { + EqualTo *string `json:"equalTo" ` + NotEqualTo *string `json:"notEqualTo" ` + In []string `json:"in" ` + NotIn []string `json:"notIn" ` +} + +type IntFilter struct { + EqualTo *int `json:"equalTo" ` + NotEqualTo *int `json:"notEqualTo" ` + LessThan *int `json:"lessThan" ` + LessThanOrEqualTo *int `json:"lessThanOrEqualTo" ` + MoreThan *int `json:"moreThan" ` + MoreThanOrEqualTo *int `json:"moreThanOrEqualTo" ` + In []int `json:"in" ` + NotIn []int `json:"notIn" ` +} + +type MediaItem struct { + ID *string `json:"id" gorm:"primarykey;not null"` + CreatedAt *time.Time `json:"createdAt" ` + UpdatedAt *time.Time `json:"updatedAt" ` + ExifDate *time.Time `json:"exifDate" ` + Latitude *float64 `json:"latitude" ` + Longitude *float64 `json:"longitude" ` + IsVideo bool `json:"isVideo" gorm:"default:false;not null"` + FileName string `json:"fileName" gorm:"not null"` + OrigName string `json:"origName" gorm:"not null"` + Tags []*Tag `json:"tags" gorm:"many2many:media_tags"` + Albums []*Album `json:"albums" gorm:"many2many:media_albums"` + User *User `json:"user" gorm:"ForeignKey:ID;not null"` +} + +type MediaItemFilter struct { + ID *IDFilter `json:"id" ` + CreatedAt *TimeFilter `json:"createdAt" ` + UpdatedAt *TimeFilter `json:"updatedAt" ` + ExifDate *TimeFilter `json:"exifDate" ` + Latitude *FloatFilter `json:"latitude" ` + Longitude *FloatFilter `json:"longitude" ` + IsVideo *BooleanFilter `json:"isVideo" ` + OrigName *StringFilter `json:"origName" ` + Tags *TagFilter `json:"tags" ` + Albums *AlbumFilter `json:"albums" ` + And *MediaItemFilter `json:"and" ` + Or *MediaItemFilter `json:"or" ` +} + +type MediaItemResponse struct { + Data []*MediaItem `json:"data" ` + PageInfo *PageInfo `json:"pageInfo" ` +} + +type NewAlbum struct { + Name string `json:"name" ` +} + +type NewDevice struct { + Name string `json:"name" ` +} + +type NewMediaItem struct { + File graphql.Upload `json:"file" ` + Tags []string `json:"tags" ` + Albums []string `json:"albums" ` +} + +type NewTag struct { + Name string `json:"name" ` +} + +type NewUser struct { + Email string `json:"email" ` + Username string `json:"username" ` + FirstName *string `json:"firstName" ` + LastName *string `json:"lastName" ` + Role Role `json:"role" ` + AuthType AuthType `json:"authType" ` + Password *string `json:"password" ` +} + +type PageInfo struct { + Count int `json:"count" ` + Page int `json:"page" ` + Total int `json:"total" ` +} + +type RoleFilter struct { + EqualTo *Role `json:"equalTo" ` + NotEqualTo *Role `json:"notEqualTo" ` + In []Role `json:"in" ` + NotIn []Role `json:"notIn" ` +} + +type StringFilter struct { + EqualTo *string `json:"equalTo" ` + NotEqualTo *string `json:"notEqualTo" ` + StartWith *string `json:"startWith" ` + NotStartWith *string `json:"notStartWith" ` + EndWith *string `json:"endWith" ` + NotEndWith *string `json:"notEndWith" ` + Contain *string `json:"contain" ` + NotContain *string `json:"notContain" ` + In []string `json:"in" ` + NotIn []string `json:"notIn" ` + StartWithStrict *string `json:"startWithStrict" ` + NotStartWithStrict *string `json:"notStartWithStrict" ` + EndWithStrict *string `json:"endWithStrict" ` + NotEndWithStrict *string `json:"notEndWithStrict" ` + ContainStrict *string `json:"containStrict" ` + NotContainStrict *string `json:"notContainStrict" ` +} + +type Tag struct { + ID *string `json:"id" gorm:"primarykey;not null"` + CreatedAt *time.Time `json:"createdAt" ` + UpdatedAt *time.Time `json:"updatedAt" ` + Name string `json:"name" gorm:"unique;not null"` +} + +type TagFilter struct { + ID *IDFilter `json:"id" ` + CreatedAt *TimeFilter `json:"createdAt" ` + UpdatedAt *TimeFilter `json:"updatedAt" ` + Name *StringFilter `json:"name" ` + And *MediaItemFilter `json:"and" ` + Or *MediaItemFilter `json:"or" ` +} + +type TagResponse struct { + Data []*Tag `json:"data" ` + PageInfo *PageInfo `json:"pageInfo" ` +} + +type TimeFilter struct { + EqualTo *time.Time `json:"equalTo" ` + NotEqualTo *time.Time `json:"notEqualTo" ` + LessThan *time.Time `json:"lessThan" ` + LessThanOrEqualTo *time.Time `json:"lessThanOrEqualTo" ` + MoreThan *time.Time `json:"moreThan" ` + MoreThanOrEqualTo *time.Time `json:"moreThanOrEqualTo" ` +} + +type User struct { + ID *string `json:"id" gorm:"primarykey;not null"` + CreatedAt *time.Time `json:"createdAt" ` + UpdatedAt *time.Time `json:"updatedAt" ` + Email string `json:"email" gorm:"not null;unique"` + Username string `json:"username" gorm:"not null;unique"` + FirstName *string `json:"firstName" ` + LastName *string `json:"lastName" ` + Role Role `json:"role" gorm:"default:User;not null"` + AuthType AuthType `json:"authType" gorm:"default:Local;not null"` + Password *string `json:"password" ` +} + +type UserFilter struct { + ID *IDFilter `json:"id" ` + CreatedAt *TimeFilter `json:"createdAt" ` + UpdatedAt *TimeFilter `json:"updatedAt" ` + Username *StringFilter `json:"username" ` + FirstName *StringFilter `json:"firstName" ` + LastName *StringFilter `json:"lastName" ` + Role *RoleFilter `json:"role" ` + AuthType *AuthTypeFilter `json:"authType" ` + And *UserFilter `json:"and" ` + Or *UserFilter `json:"or" ` +} + +type UserResponse struct { + Data []*User `json:"data" ` + PageInfo *PageInfo `json:"pageInfo" ` +} + +type AuthType string + +const ( + AuthTypeLocal AuthType = "Local" + AuthTypeLdap AuthType = "LDAP" +) + +var AllAuthType = []AuthType{ + AuthTypeLocal, + AuthTypeLdap, +} + +func (e AuthType) IsValid() bool { + switch e { + case AuthTypeLocal, AuthTypeLdap: + return true + } + return false +} + +func (e AuthType) String() string { + return string(e) +} + +func (e *AuthType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = AuthType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid AuthType", str) + } + return nil +} + +func (e AuthType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type DeviceType string + +const ( + DeviceTypeIOs DeviceType = "iOS" + DeviceTypeAndroid DeviceType = "Android" + DeviceTypeChrome DeviceType = "Chrome" + DeviceTypeFirefox DeviceType = "Firefox" + DeviceTypeInternetExplorer DeviceType = "InternetExplorer" + DeviceTypeEdge DeviceType = "Edge" + DeviceTypeSafari DeviceType = "Safari" + DeviceTypeUnknown DeviceType = "Unknown" +) + +var AllDeviceType = []DeviceType{ + DeviceTypeIOs, + DeviceTypeAndroid, + DeviceTypeChrome, + DeviceTypeFirefox, + DeviceTypeInternetExplorer, + DeviceTypeEdge, + DeviceTypeSafari, + DeviceTypeUnknown, +} + +func (e DeviceType) IsValid() bool { + switch e { + case DeviceTypeIOs, DeviceTypeAndroid, DeviceTypeChrome, DeviceTypeFirefox, DeviceTypeInternetExplorer, DeviceTypeEdge, DeviceTypeSafari, DeviceTypeUnknown: + return true + } + return false +} + +func (e DeviceType) String() string { + return string(e) +} + +func (e *DeviceType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = DeviceType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid DeviceType", str) + } + return nil +} + +func (e DeviceType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type Role string + +const ( + RoleAdmin Role = "Admin" + RoleUser Role = "User" +) + +var AllRole = []Role{ + RoleAdmin, + RoleUser, +} + +func (e Role) IsValid() bool { + switch e { + case RoleAdmin, RoleUser: + return true + } + return false +} + +func (e Role) String() string { + return string(e) +} + +func (e *Role) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = Role(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid Role", str) + } + return nil +} + +func (e Role) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} diff --git a/graph/resolver.go b/graph/resolver.go new file mode 100644 index 0000000..e7fdab5 --- /dev/null +++ b/graph/resolver.go @@ -0,0 +1,13 @@ +package graph + +import ( + "reichard.io/imagini/internal/db" +) + +// This file will not be regenerated automatically. +// +// It serves as dependency injection for your app, add any dependencies you require here. + +type Resolver struct{ + DB *db.DBManager +} diff --git a/graph/schema.graphqls b/graph/schema.graphqls new file mode 100644 index 0000000..a53c070 --- /dev/null +++ b/graph/schema.graphqls @@ -0,0 +1,356 @@ + +# https://gqlgen.com/reference/scalars/ +scalar Time +scalar Upload + +# https://gqlgen.com/reference/directives/ +directive @hasRole(role: Role!) on FIELD_DEFINITION + +directive @meta( + gorm: String, +) on OBJECT | FIELD_DEFINITION | ENUM_VALUE | INPUT_FIELD_DEFINITION | ENUM | INPUT_OBJECT | ARGUMENT_DEFINITION + +enum Role { + Admin + User +} + +enum DeviceType { + iOS + Android + Chrome + Firefox + InternetExplorer + Edge + Safari + Unknown +} + +enum AuthType { + Local + LDAP +} + +# ------------------------------------------------------------ +# ----------------------- Type Filters ----------------------- +# ------------------------------------------------------------ + +input TimeFilter { + equalTo: Time + notEqualTo: Time + lessThan: Time + lessThanOrEqualTo: Time + moreThan: Time + moreThanOrEqualTo: Time +} + +input IntFilter { + equalTo: Int + notEqualTo: Int + lessThan: Int + lessThanOrEqualTo: Int + moreThan: Int + moreThanOrEqualTo: Int + in: [Int!] + notIn: [Int!] +} + +input FloatFilter { + equalTo: Float + notEqualTo: Float + lessThan: Float + lessThanOrEqualTo: Float + moreThan: Float + moreThanOrEqualTo: Float + in: [Float!] + notIn: [Float!] +} + +input BooleanFilter { + equalTo: Boolean + notEqualTo: Boolean +} + +input IDFilter { + equalTo: ID + notEqualTo: ID + in: [ID!] + notIn: [ID!] +} + +input StringFilter { + equalTo: String + notEqualTo: String + startWith: String + notStartWith: String + endWith: String + notEndWith: String + contain: String + notContain: String + in: [String!] + notIn: [String!] + + startWithStrict: String + notStartWithStrict: String + endWithStrict: String + notEndWithStrict: String + containStrict: String + notContainStrict: String +} + +input RoleFilter { + equalTo: Role + notEqualTo: Role + in: [Role!] + notIn: [Role!] +} + +input DeviceTypeFilter { + equalTo: DeviceType + notEqualTo: DeviceType + in: [DeviceType!] + notIn: [DeviceType!] +} + +input AuthTypeFilter { + equalTo: AuthType + notEqualTo: AuthType + in: [AuthType!] + notIn: [AuthType!] +} + +# ------------------------------------------------------------ +# -------------------- Object Definitions -------------------- +# ------------------------------------------------------------ + +type Device { + id: ID @meta(gorm: "primarykey;not null") + createdAt: Time + updatedAt: Time + name: String! @meta(gorm: "not null") + type: DeviceType! @meta(gorm: "default:Unknown;not null") + user: User @meta(gorm: "ForeignKey:ID;not null") + refreshKey: String +} + +type User { + id: ID @meta(gorm: "primarykey;not null") + createdAt: Time + updatedAt: Time + email: String! @meta(gorm: "not null;unique") + username: String! @meta(gorm: "not null;unique") + firstName: String + lastName: String + role: Role! @meta(gorm: "default:User;not null") + authType: AuthType! @meta(gorm: "default:Local;not null") + password: String +} + +type MediaItem { + id: ID @meta(gorm: "primarykey;not null") + createdAt: Time + updatedAt: Time + exifDate: Time + latitude: Float + longitude: Float + isVideo: Boolean! @meta(gorm: "default:false;not null") + fileName: String! @meta(gorm: "not null") + origName: String! @meta(gorm: "not null") + tags: [Tag] @meta(gorm: "many2many:media_tags") + albums: [Album] @meta(gorm: "many2many:media_albums") + user: User @meta(gorm: "ForeignKey:ID;not null") +} + +type Tag { + id: ID @meta(gorm: "primarykey;not null") + createdAt: Time + updatedAt: Time + name: String! @meta(gorm: "unique;not null") +} + +type Album { + id: ID @meta(gorm: "primarykey;not null") + createdAt: Time + updatedAt: Time + name: String! @meta(gorm: "unique;not null") +} + +# ------------------------------------------------------------ +# ---------------------- Object Filters ---------------------- +# ------------------------------------------------------------ + +input UserFilter { + id: IDFilter + createdAt: TimeFilter + updatedAt: TimeFilter + username: StringFilter + firstName: StringFilter + lastName: StringFilter + role: RoleFilter + authType: AuthTypeFilter + + and: UserFilter + or: UserFilter +} + +input MediaItemFilter { + id: IDFilter + createdAt: TimeFilter + updatedAt: TimeFilter + exifDate: TimeFilter + latitude: FloatFilter + longitude: FloatFilter + isVideo: BooleanFilter + origName: StringFilter + tags: TagFilter + albums: AlbumFilter + + and: MediaItemFilter + or: MediaItemFilter +} + +input DeviceFilter { + id: IDFilter + createdAt: TimeFilter + updatedAt: TimeFilter + name: StringFilter + type: DeviceTypeFilter + + and: MediaItemFilter + or: MediaItemFilter +} + +input TagFilter { + id: IDFilter + createdAt: TimeFilter + updatedAt: TimeFilter + name: StringFilter + + and: MediaItemFilter + or: MediaItemFilter +} + +input AlbumFilter { + id: IDFilter + createdAt: TimeFilter + updatedAt: TimeFilter + name: StringFilter + + and: MediaItemFilter + or: MediaItemFilter +} + +# ------------------------------------------------------------ +# -------------------------- Inputs -------------------------- +# ------------------------------------------------------------ + +input NewUser { + email: String! + username: String! + firstName: String + lastName: String + role: Role! + authType: AuthType! + password: String +} + +input NewDevice { + name: String! +} + +input NewMediaItem { + file: Upload! + tags: [ID!] + albums: [ID!] +} + +input NewTag { + name: String! +} + +input NewAlbum { + name: String! +} + +# ------------------------------------------------------------ +# ------------------------ Responses ------------------------- +# ------------------------------------------------------------ + +type PageInfo { + count: Int! + page: Int! + total: Int! +} + +type MediaItemResponse { + data: [MediaItem] + pageInfo: PageInfo! +} + +type UserResponse { + data: [User] + pageInfo: PageInfo! +} + +type DeviceResponse { + data: [Device] + pageInfo: PageInfo! +} + +type TagResponse { + data: [Tag] + pageInfo: PageInfo! +} + +type AlbumResponse { + data: [Album] + pageInfo: PageInfo! +} + +# ------------------------------------------------------------ +# --------------------- Query & Mutations -------------------- +# ------------------------------------------------------------ + +type Query { + # Single Item + mediaItem(id: ID!): MediaItem! @hasRole(role: User) + device(id: ID!): Device! @hasRole(role: User) + album(id: ID!): Album! @hasRole(role: User) + tag(id: ID!): Tag! @hasRole(role: User) + user(id: ID!): User! @hasRole(role: Admin) + + # All + mediaItems( + filter: MediaItemFilter + count: Int + page: Int + ): MediaItemResponse! @hasRole(role: User) + devices( + filter: DeviceFilter + count: Int + page: Int + ): DeviceResponse! @hasRole(role: User) + albums( + filter: AlbumFilter + count: Int + page: Int + ): AlbumResponse! @hasRole(role: User) + tags( + filter: TagFilter + count: Int + page: Int + ): TagResponse! @hasRole(role: User) + users( + filter: UserFilter + count: Int + page: Int + ): UserResponse! @hasRole(role: Admin) +} + +type Mutation { + createMediaItem(input: NewMediaItem!): MediaItem! @hasRole(role: User) + createDevice(input: NewDevice!): Device! @hasRole(role: User) + createAlbum(input: NewAlbum!): Album! @hasRole(role: User) + createTag(input: NewTag!): Tag! @hasRole(role: User) + createUser(input: NewUser!): User! @hasRole(role: Admin) +} diff --git a/graph/schema.resolvers.go b/graph/schema.resolvers.go new file mode 100644 index 0000000..d539daf --- /dev/null +++ b/graph/schema.resolvers.go @@ -0,0 +1,81 @@ +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" + "fmt" + + "reichard.io/imagini/graph/generated" + "reichard.io/imagini/graph/model" +) + +func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewMediaItem) (*model.MediaItem, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *mutationResolver) CreateDevice(ctx context.Context, input model.NewDevice) (*model.Device, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *mutationResolver) CreateAlbum(ctx context.Context, input model.NewAlbum) (*model.Album, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *mutationResolver) CreateTag(ctx context.Context, input model.NewTag) (*model.Tag, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser) (*model.User, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *queryResolver) MediaItem(ctx context.Context, id string) (*model.MediaItem, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *queryResolver) Device(ctx context.Context, id string) (*model.Device, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *queryResolver) Album(ctx context.Context, id string) (*model.Album, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *queryResolver) Tag(ctx context.Context, id string) (*model.Tag, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *queryResolver) MediaItems(ctx context.Context, filter *model.MediaItemFilter, count *int, page *int) (*model.MediaItemResponse, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *queryResolver) Devices(ctx context.Context, filter *model.DeviceFilter, count *int, page *int) (*model.DeviceResponse, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *queryResolver) Albums(ctx context.Context, filter *model.AlbumFilter, count *int, page *int) (*model.AlbumResponse, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *queryResolver) Tags(ctx context.Context, filter *model.TagFilter, count *int, page *int) (*model.TagResponse, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *queryResolver) Users(ctx context.Context, filter *model.UserFilter, count *int, page *int) (*model.UserResponse, error) { + panic(fmt.Errorf("not implemented")) +} + +// 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 mutationResolver struct{ *Resolver } +type queryResolver struct{ *Resolver } diff --git a/internal/api/albums.go b/internal/api/albums.go deleted file mode 100644 index 9f71175..0000000 --- a/internal/api/albums.go +++ /dev/null @@ -1,9 +0,0 @@ -package api - -import ( - "net/http" -) - -func (api *API) albumsHandler(w http.ResponseWriter, r *http.Request) { - -} diff --git a/internal/api/auth.go b/internal/api/auth.go index 6121f3c..db67217 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -11,6 +11,7 @@ import ( "github.com/lestrrat-go/jwx/jwt" "reichard.io/imagini/internal/models" + graphql "reichard.io/imagini/graph/model" ) func (api *API) loginHandler(w http.ResponseWriter, r *http.Request) { @@ -81,47 +82,47 @@ func (api *API) logoutHandler(w http.ResponseWriter, r *http.Request) { /** * This will find or create the requested device based on ID and User. **/ -func (api *API) upsertRequestedDevice(user models.User, r *http.Request) (models.Device, error) { +func (api *API) upsertRequestedDevice(user graphql.User, r *http.Request) (graphql.Device, error) { requestedDevice := deriveRequestedDevice(r) requestedDevice.Type = deriveDeviceType(r) - requestedDevice.UserUUID = user.UUID + requestedDevice.User.ID = user.ID - if requestedDevice.UUID == uuid.Nil { + if *requestedDevice.ID == "" { err := api.DB.CreateDevice(&requestedDevice) createdDevice, err := api.DB.Device(&requestedDevice) return createdDevice, err } - foundDevice, err := api.DB.Device(&models.Device{ - Base: models.Base{ UUID: requestedDevice.UUID }, - User: user, + foundDevice, err := api.DB.Device(&graphql.Device{ + ID: requestedDevice.ID, + User: &user, }) return foundDevice, err } -func deriveDeviceType(r *http.Request) string { +func deriveDeviceType(r *http.Request) graphql.DeviceType { userAgent := strings.ToLower(r.Header.Get("User-Agent")) if strings.HasPrefix(userAgent, "ios-imagini"){ - return "iOS" + return graphql.DeviceTypeIOs } else if strings.HasPrefix(userAgent, "android-imagini"){ - return "Android" + return graphql.DeviceTypeAndroid } else if strings.HasPrefix(userAgent, "chrome"){ - return "Chrome" + return graphql.DeviceTypeChrome } else if strings.HasPrefix(userAgent, "firefox"){ - return "Firefox" + return graphql.DeviceTypeFirefox } else if strings.HasPrefix(userAgent, "msie"){ - return "Internet Explorer" + return graphql.DeviceTypeInternetExplorer } else if strings.HasPrefix(userAgent, "edge"){ - return "Edge" + return graphql.DeviceTypeEdge } else if strings.HasPrefix(userAgent, "safari"){ - return "Safari" + return graphql.DeviceTypeSafari } - return "Unknown" + return graphql.DeviceTypeUnknown } -func deriveRequestedDevice(r *http.Request) models.Device { - deviceSkeleton := models.Device{} +func deriveRequestedDevice(r *http.Request) graphql.Device { + deviceSkeleton := graphql.Device{} authHeader := r.Header.Get("X-Imagini-Authorization") splitAuthInfo := strings.Split(authHeader, ",") @@ -137,19 +138,20 @@ func deriveRequestedDevice(r *http.Request) models.Device { // Derive Key key := strings.ToLower(strings.TrimSpace(splitItem[0])) - if key != "deviceuuid" && key != "devicename" { + if key != "deviceid" && key != "devicename" { continue } // Derive Value val := trimQuotes(strings.TrimSpace(splitItem[1])) - if key == "deviceuuid" { + if key == "deviceid" { parsedDeviceUUID, err := uuid.Parse(val) if err != nil { log.Warn("[auth] deriveRequestedDevice - Unable to parse requested DeviceUUID: ", val) continue } - deviceSkeleton.Base = models.Base{UUID: parsedDeviceUUID} + stringDeviceUUID := parsedDeviceUUID.String() + deviceSkeleton.ID = &stringDeviceUUID } else if key == "devicename" { deviceSkeleton.Name = val } @@ -157,7 +159,7 @@ func deriveRequestedDevice(r *http.Request) models.Device { // If name not set, set to type if deviceSkeleton.Name == "" { - deviceSkeleton.Name = deviceSkeleton.Type + deviceSkeleton.Name = deviceSkeleton.Type.String() } return deviceSkeleton @@ -196,9 +198,12 @@ func (api *API) refreshAccessToken(w http.ResponseWriter, r *http.Request) (jwt. return nil, err } + stringUserUUID := userUUID.String() + stringDeviceUUID := deviceUUID.String() + // Device & User Skeleton - user := models.User{Base: models.Base{UUID: userUUID}} - device := models.Device{Base: models.Base{UUID: deviceUUID}} + user := graphql.User{ID: &stringUserUUID} + device := graphql.Device{ID: &stringDeviceUUID} // Update token accessTokenString, err := api.Auth.CreateJWTAccessToken(user, device) diff --git a/internal/api/devices.go b/internal/api/devices.go deleted file mode 100644 index 70a718e..0000000 --- a/internal/api/devices.go +++ /dev/null @@ -1,9 +0,0 @@ -package api - -import ( - "net/http" -) - -func (api *API) devicesHandler(w http.ResponseWriter, r *http.Request) { - -} diff --git a/internal/api/info.go b/internal/api/info.go deleted file mode 100644 index 4958078..0000000 --- a/internal/api/info.go +++ /dev/null @@ -1,9 +0,0 @@ -package api - -import ( - "net/http" -) - -func (api *API) infoHandler(w http.ResponseWriter, r *http.Request) { - -} diff --git a/internal/api/media_items.go b/internal/api/media_items.go deleted file mode 100644 index 9b288ec..0000000 --- a/internal/api/media_items.go +++ /dev/null @@ -1,327 +0,0 @@ -package api - -import ( - "io" - "os" - "fmt" - "path" - "time" - "regexp" - "strings" - "errors" - "net/url" - "net/http" - "encoding/json" - - "github.com/google/uuid" - "github.com/dsoprea/go-exif/v3" - log "github.com/sirupsen/logrus" - "github.com/gabriel-vasile/mimetype" - "github.com/dsoprea/go-exif/v3/common" - - "reichard.io/imagini/internal/models" -) - -// GET -// - /api/v1/MediaItems/ -// - JSON Struct -// - /api/v1/MediaItems//content -// - The raw file -func (api *API) mediaItemsHandler(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodPost { - // CREATE - api.mediaItemPOSTHandler(w, r) - } else if r.Method == http.MethodPut { - // UPDATE / REPLACE - } else if r.Method == http.MethodPatch { - // UPDATE / MODIFY - } else if r.Method == http.MethodDelete { - // DELETE - } else if r.Method == http.MethodGet { - // GET - api.mediaItemGETHandler(w, r) - } else { - errorJSON(w, "Method is not supported.", http.StatusMethodNotAllowed) - return - } -} - -// Paging: -// - Regular Pagination: -// - /api/v1/MediaItems?page[limit]=50&page=2 -// - Meta Count Only -// - /api/v1/MediaItems?page[limit]=0 - -// Sorting: -// - Ascending Sort: -// - /api/v1/MediaItems?sort=created_at -// - Descending Sort: -// - /api/v1/MediaItems?sort=-created_at - -// Filters: -// - Greater Than / Less Than (created_at, updated_at, exif_date) -// - /api/v1/MediaItems?filter[created_at]>=2020-01-01&filter[created_at]<=2021-01-01 -// - Long / Lat Range (latitude, longitude) -// - /api/v1/MediaItems?filter[latitude]>=71.1827&filter[latitude]<=72.0000&filter[longitude]>=100.000&filter[longitude]<=101.0000 -// - Image / Video (media_type) -// - /api/v1/MediaItems?filter[media_type]=Image -// - Tags (tags) -// - /api/v1/MediaItems?filter[tags]=id1,id2,id3 -// - Albums (albums) -// - /api/v1/MediaItems?filter[albums]=id1 -func (api *API) mediaItemGETHandler(w http.ResponseWriter, r *http.Request) { - if err := r.ParseForm(); err != nil { - // Handle error - } - - testObj := models.MediaItem{} - json.NewDecoder().Decode(&testObj) - fmt.Printf("Result: %+v\n", testObj) - - // allParams, err := json.Marshal(r.Form) - // if err != nil { - // // Handle error - // } - - // filter := &models.MediaItem{} - // if err = json.Unmarshal(allParams, filter); err != nil { - // // Handle error - // fmt.Printf("Fuck: %s\n", err) - // } - - // fmt.Printf("Result: %+v\n", filter) - - // err = normalizeForm(r.Form, models.MediaItem{}) - // if err != nil { - // fmt.Printf("Error: %s\n", err) - // } - - // var testItems []models.MediaItem - // api.DB.QueryBuilder(&testItems, allParams) - - // fmt.Printf("\n\nItems: %+v", testItems) - - - // Pull out UUIDs - reqInfo := r.Context().Value("uuids").(map[string]string) - uid := reqInfo["uid"] - userUUID, _ := uuid.Parse(uid) - - // TODO: Can apply multiple filters based on query parameters - mediaItemFilter := &models.MediaItem{UserUUID: userUUID} - mediaItemFilter.UserUUID = userUUID - - mediaItems, count, _ := api.DB.MediaItems(mediaItemFilter) - response := &models.APIResponse{ - Data: &mediaItems, - Meta: &models.APIMeta{Count: count}, - } - responseJSON(w, &response, http.StatusOK) -} - -func (api *API) mediaItemPOSTHandler(w http.ResponseWriter, r *http.Request) { - // 64MB limit (TODO: Change this - video) - r.ParseMultipartForm(64 << 20) - - // Open form file - formFile, multipartFileHeader, err := r.FormFile("file") - if err != nil { - errorJSON(w, "Upload failed.", http.StatusInternalServerError) - return - } - defer formFile.Close() - - // File header placeholder - fileHeader := make([]byte, 64) - - // Copy headers into the buffer - if _, err := formFile.Read(fileHeader); err != nil { - errorJSON(w, "Upload failed.", http.StatusInternalServerError) - return - } - - // Reset position - if _, err := formFile.Seek(0, 0); err != nil { - errorJSON(w, "Upload failed.", http.StatusInternalServerError) - return - } - - // Determine media type - fileMime := mimetype.Detect(fileHeader) - contentType := fileMime.String() - var mediaType string - if strings.HasPrefix(contentType, "image/") { - mediaType = "Image" - } else if strings.HasPrefix(contentType, "video/") { - mediaType = "Video" - } else { - errorJSON(w, "Invalid filetype.", http.StatusUnsupportedMediaType) - return - } - - // Pull out UUIDs - reqInfo := r.Context().Value("uuids").(map[string]string) - uid := reqInfo["uid"] - - // Derive Folder & File Path - mediaItemUUID := uuid.New() - fileName := mediaItemUUID.String() + fileMime.Extension() - folderPath := path.Join("/" + api.Config.DataPath + "/media/" + uid) - os.MkdirAll(folderPath, 0700) - filePath := path.Join(folderPath + "/" + fileName) - - // Create File - f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0600) - if err != nil { - log.Warn("[api] createMediaItem - Unable to open file: ", filePath) - errorJSON(w, "Upload failed.", http.StatusInternalServerError) - return - } - defer f.Close() - - // Copy data to file - _, err = io.Copy(f, formFile) - if err != nil { - errorJSON(w, "Upload failed.", http.StatusInternalServerError) - return - } - - // Create MediaItem From EXIF Data - mediaItem, err := mediaItemFromEXIFData(filePath) - if err != nil { - errorJSON(w, "Upload failed.", http.StatusInternalServerError) - return - } - - // Add Additional MediaItem Fields - mediaItem.Base.UUID = mediaItemUUID - mediaItem.UserUUID, err = uuid.Parse(uid) - mediaItem.MediaType = mediaType - mediaItem.FileName = fileName - mediaItem.OrigName = multipartFileHeader.Filename - - // Create MediaItem in DB - err = api.DB.CreateMediaItem(mediaItem) - if err != nil { - errorJSON(w, "Upload failed.", http.StatusInternalServerError) - return - } - - successJSON(w, "Upload succeeded.", http.StatusCreated) -} - -func mediaItemFromEXIFData(filePath string) (*models.MediaItem, error) { - rawExif, err := exif.SearchFileAndExtractExif(filePath) - entries, _, err := exif.GetFlatExifData(rawExif, nil) - - decLong := float32(1) - decLat := float32(1) - - mediaItem := &models.MediaItem{} - for _, v := range entries { - if v.TagName == "DateTimeOriginal" { - formattedTime, _ := time.Parse("2006:01:02 15:04:05", v.Formatted) - mediaItem.EXIFDate = formattedTime - } else if v.TagName == "GPSLatitude" { - latStruct := v.Value.([]exifcommon.Rational) - decLat *= deriveDecimalCoordinate( - latStruct[0].Numerator / latStruct[0].Denominator, - latStruct[1].Numerator / latStruct[1].Denominator, - float32(latStruct[2].Numerator) / float32(latStruct[2].Denominator), - ) - } else if v.TagName == "GPSLongitude" { - longStruct := v.Value.([]exifcommon.Rational) - decLong *= deriveDecimalCoordinate( - longStruct[0].Numerator / longStruct[0].Denominator, - longStruct[1].Numerator / longStruct[1].Denominator, - float32(longStruct[2].Numerator) / float32(longStruct[2].Denominator), - ) - } else if v.TagName == "GPSLatitudeRef" && v.Formatted == "S" { - decLat *= -1 - } else if v.TagName == "GPSLongitudeRef" && v.Formatted == "W" { - decLong *= -1 - } - } - - mediaItem.Latitude = &decLat - mediaItem.Longitude = &decLong - - return mediaItem, err -} - -func deriveDecimalCoordinate(degrees, minutes uint32, seconds float32) float32 { - return float32(degrees) + (float32(minutes) / 60) + (seconds / 3600) -} - -// { -// filters: [ -// { field: "", operator: ""}, -// { field: "", operator: ""}, -// { field: "", operator: ""}, -// ], -// sort: "" -// page: {} -// } -func normalizeForm(form url.Values, typeObj interface{}) error { - allowedFields := models.JSONFields(typeObj) - - for key, val := range form { - key = strings.ToLower(key) - - re := regexp.MustCompile(`^(filter|page)\[(\w*)]($|>|<)$`) - matches := re.FindStringSubmatch(key) - - if len(matches) == 4 { - cmd := strings.ToLower(matches[1]) - field := strings.ToLower(matches[2]) - operator := strings.ToLower(matches[3]) - - if cmd == "page" && field == "limit" { - fmt.Printf("cmd: %s field: %s op: %s\n", cmd, field, operator) - continue - } - - // Validate field - _, ok := allowedFields[field] - if !ok { - return errors.New("Invalid field.") - } - - // Val assertions - tempObj := make(map[string]string) - tempObj[field] = val[0] - - mi, err := json.Marshal(tempObj) - if err != nil { - // Handle error - fmt.Printf("1 Type Assertion Failed For Field: [%s] with value: [%s]\n", field, val) - } - fmt.Printf("String JSON: %s", string(mi)) - refObj := &models.MediaItem{} - if err = json.Unmarshal(mi, refObj); err != nil { - // Handle error - fmt.Printf("2 Type Assertion Failed For Field: [%s] with value: [%s]\n", field, val[0]) - fmt.Println(err) - } - - fmt.Printf("Result: %+v\n", refObj) - - fmt.Printf("cmd: %s field: %s op: %s\n", cmd, field, operator) - } else if key == "sort" { - field := strings.ToLower(val[0]) - - // Validate field - _, ok := allowedFields[field] - if !ok { - return errors.New("Invalid field.") - } - - // TODO: Validate val - - fmt.Printf("cmd: %s\n", key) - } else { - return errors.New("Invalid parameter(s)") - } - } - return nil -} diff --git a/internal/api/routes.go b/internal/api/routes.go index a9a7210..9c2603e 100644 --- a/internal/api/routes.go +++ b/internal/api/routes.go @@ -5,53 +5,27 @@ import ( "net/http" "reichard.io/imagini/internal/models" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/playground" + "reichard.io/imagini/graph" + "reichard.io/imagini/graph/generated" ) func (api *API) registerRoutes() { + srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}})) + + // TODO: Provide Authentication for srv + api.Router.Handle("/playground", playground.Handler("GraphQL playground", "/query")) + api.Router.Handle("/query", srv) + api.Router.HandleFunc("/media/", multipleMiddleware( api.mediaHandler, api.authMiddleware, )) - api.Router.HandleFunc("/api/v1/MediaItems", multipleMiddleware( - api.mediaItemsHandler, - api.authMiddleware, - )) - api.Router.HandleFunc("/api/v1/Devices", multipleMiddleware( - api.devicesHandler, - api.authMiddleware, - )) - api.Router.HandleFunc("/api/v1/Upload", multipleMiddleware( - api.uploadHandler, - api.authMiddleware, - )) - api.Router.HandleFunc("/api/v1/Albums", multipleMiddleware( - api.albumsHandler, - api.authMiddleware, - )) - api.Router.HandleFunc("/api/v1/Users", multipleMiddleware( - api.usersHandler, - api.authMiddleware, - )) - api.Router.HandleFunc("/api/v1/Tags", multipleMiddleware( - api.tagsHandler, - api.authMiddleware, - )) - api.Router.HandleFunc("/api/v1/Info", multipleMiddleware( - api.infoHandler, - api.authMiddleware, - )) - api.Router.HandleFunc("/api/v1/Me", multipleMiddleware( - api.meHandler, - api.authMiddleware, - )) - - api.Router.HandleFunc("/api/v1/Logout", api.logoutHandler) - api.Router.HandleFunc("/api/v1/Login", api.loginHandler) + api.Router.HandleFunc("/logout", api.logoutHandler) + api.Router.HandleFunc("/login", api.loginHandler) } - - -// https://stackoverflow.com/a/59764037 func errorJSON(w http.ResponseWriter, err string, code int) { errStruct := &models.APIResponse{Error: &models.APIError{Message: err, Code: int64(code)}} responseJSON(w, errStruct, code) diff --git a/internal/api/tags.go b/internal/api/tags.go deleted file mode 100644 index fe7c7e2..0000000 --- a/internal/api/tags.go +++ /dev/null @@ -1,9 +0,0 @@ -package api - -import ( - "net/http" -) - -func (api *API) tagsHandler(w http.ResponseWriter, r *http.Request) { - -} diff --git a/internal/api/upload.go b/internal/api/upload.go deleted file mode 100644 index c9767a1..0000000 --- a/internal/api/upload.go +++ /dev/null @@ -1,9 +0,0 @@ -package api - -import ( - "net/http" -) - -func (api *API) uploadHandler(w http.ResponseWriter, r *http.Request) { - -} diff --git a/internal/api/users.go b/internal/api/users.go deleted file mode 100644 index 4c28349..0000000 --- a/internal/api/users.go +++ /dev/null @@ -1,30 +0,0 @@ -package api - -import ( - "net/http" - // log "github.com/sirupsen/logrus" -) - -func (api *API) usersHandler(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodPost { - // CREATE - } else if r.Method == http.MethodPut { - // UPDATE / REPLACE - } else if r.Method == http.MethodPatch { - // UPDATE / MODIFY - } else if r.Method == http.MethodDelete { - // DELETE - } else if r.Method == http.MethodGet { - // GET - } else { - errorJSON(w, "Method is not supported.", http.StatusMethodNotAllowed) - return - } -} - -func (api *API) meHandler(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodGet { - errorJSON(w, "Method is not supported.", http.StatusMethodNotAllowed) - return - } -} diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 46e225c..213dfc7 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -14,6 +14,8 @@ import ( "reichard.io/imagini/internal/db" "reichard.io/imagini/internal/config" + + graphql "reichard.io/imagini/graph/model" "reichard.io/imagini/internal/models" "reichard.io/imagini/internal/session" ) @@ -33,11 +35,16 @@ func NewMgr(db *db.DBManager, c *config.Config) *AuthManager { } } -func (auth *AuthManager) AuthenticateUser(creds models.APICredentials) (bool, models.User) { - // By Username - foundUser, err := auth.DB.User(&models.User{Username: creds.User}) +func (auth *AuthManager) AuthenticateUser(creds models.APICredentials) (bool, graphql.User) { + // Search Objects + userByName := &graphql.User{} + userByName.Username = creds.User + + foundUser, err := auth.DB.User(userByName) if errors.Is(err, gorm.ErrRecordNotFound) { - foundUser, err = auth.DB.User(&models.User{Email: creds.User}) + userByEmail := &graphql.User{} + userByEmail.Email = creds.User + foundUser, err = auth.DB.User(userByEmail) } // Error Checking @@ -62,7 +69,7 @@ func (auth *AuthManager) AuthenticateUser(creds models.APICredentials) (bool, mo } } -func (auth *AuthManager) getRole(user models.User) string { +func (auth *AuthManager) getRole(user graphql.User) string { // TODO: Lookup role of user return "User" } @@ -80,7 +87,8 @@ func (auth *AuthManager) ValidateJWTRefreshToken(refreshJWT string) (jwt.Token, if err != nil { return nil, errors.New("did does not parse") } - device, err := auth.DB.Device(&models.Device{Base: models.Base{UUID: deviceID}}) + stringDeviceID := deviceID.String() + device, err := auth.DB.Device(&graphql.Device{ID: &stringDeviceID}) if err != nil { return nil, err } @@ -88,7 +96,7 @@ func (auth *AuthManager) ValidateJWTRefreshToken(refreshJWT string) (jwt.Token, // Verify & Validate Token verifiedToken, err := jwt.ParseBytes(byteRefreshJWT, jwt.WithValidate(true), - jwt.WithVerify(jwa.HS256, []byte(device.RefreshKey)), + jwt.WithVerify(jwa.HS256, []byte(*device.RefreshKey)), ) if err != nil { fmt.Println("failed to parse payload: ", err) @@ -111,17 +119,17 @@ func (auth *AuthManager) ValidateJWTAccessToken(accessJWT string) (jwt.Token, er return verifiedToken, nil } -func (auth *AuthManager) CreateJWTRefreshToken(user models.User, device models.Device) (string, error) { +func (auth *AuthManager) CreateJWTRefreshToken(user graphql.User, device graphql.Device) (string, error) { // Acquire Refresh Key - byteKey := []byte(device.RefreshKey) + byteKey := []byte(*device.RefreshKey) // Create New Token tm := time.Now() t := jwt.New() - t.Set(`did`, device.UUID.String()) // Device ID - t.Set(jwt.SubjectKey, user.UUID.String()) // User ID - t.Set(jwt.AudienceKey, `imagini`) // App ID - t.Set(jwt.IssuedAtKey, tm) // Issued At + t.Set(`did`, device.ID) // Device ID + t.Set(jwt.SubjectKey, user.ID) // User ID + t.Set(jwt.AudienceKey, `imagini`) // App ID + t.Set(jwt.IssuedAtKey, tm) // Issued At // iOS & Android = Never Expiring Refresh Token if device.Type != "iOS" && device.Type != "Android" { @@ -146,16 +154,16 @@ func (auth *AuthManager) CreateJWTRefreshToken(user models.User, device models.D return string(signed), nil } -func (auth *AuthManager) CreateJWTAccessToken(user models.User, device models.Device) (string, error) { +func (auth *AuthManager) CreateJWTAccessToken(user graphql.User, device graphql.Device) (string, error) { // Create New Token tm := time.Now() t := jwt.New() - t.Set(`did`, device.UUID.String()) // Device ID - t.Set(`role`, auth.getRole(user)) // User Role (Admin / User) - t.Set(jwt.SubjectKey, user.UUID.String()) // User ID - t.Set(jwt.AudienceKey, `imagini`) // App ID - t.Set(jwt.IssuedAtKey, tm) // Issued At - t.Set(jwt.ExpirationKey, tm.Add(time.Hour * 2)) // 2 Hour Access Key + t.Set(`did`, device.ID) // Device ID + t.Set(`role`, auth.getRole(user)) // User Role (Admin / User) + t.Set(jwt.SubjectKey, user.ID) // User ID + t.Set(jwt.AudienceKey, `imagini`) // App ID + t.Set(jwt.IssuedAtKey, tm) // Issued At + t.Set(jwt.ExpirationKey, tm.Add(time.Hour * 2)) // 2 Hour Access Key // Validate Token Creation _, err := json.MarshalIndent(t, "", " ") diff --git a/internal/auth/ldap.go b/internal/auth/ldap.go index db9a9e6..0de965b 100644 --- a/internal/auth/ldap.go +++ b/internal/auth/ldap.go @@ -1,9 +1,9 @@ package auth import ( - "reichard.io/imagini/internal/models" + "reichard.io/imagini/graph/model" ) -func authenticateLDAPUser(user models.User, pw string) bool { +func authenticateLDAPUser(user model.User, pw string) bool { return false } diff --git a/internal/auth/local.go b/internal/auth/local.go index 5fc1b0d..b5f06c9 100644 --- a/internal/auth/local.go +++ b/internal/auth/local.go @@ -3,12 +3,12 @@ package auth import ( "golang.org/x/crypto/bcrypt" log "github.com/sirupsen/logrus" - "reichard.io/imagini/internal/models" + "reichard.io/imagini/graph/model" ) -func authenticateLocalUser(user models.User, pw string) bool { +func authenticateLocalUser(user model.User, pw string) bool { bPassword :=[]byte(pw) - err := bcrypt.CompareHashAndPassword([]byte(user.Password), bPassword) + err := bcrypt.CompareHashAndPassword([]byte(*user.Password), bPassword) if err == nil { log.Info("[auth] Authentication successfull: ", user.Username) return true diff --git a/internal/db/db.go b/internal/db/db.go index 619f04c..67994dd 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -11,7 +11,7 @@ import ( log "github.com/sirupsen/logrus" "reichard.io/imagini/internal/config" - "reichard.io/imagini/internal/models" + "reichard.io/imagini/graph/model" ) type DBManager struct { @@ -35,16 +35,15 @@ func NewMgr(c *config.Config) *DBManager { } // Initialize database - dbm.db.AutoMigrate(&models.ServerSetting{}) - dbm.db.AutoMigrate(&models.Device{}) - dbm.db.AutoMigrate(&models.User{}) - dbm.db.AutoMigrate(&models.MediaItem{}) - dbm.db.AutoMigrate(&models.Tag{}) - dbm.db.AutoMigrate(&models.Album{}) + dbm.db.AutoMigrate(&model.Device{}) + dbm.db.AutoMigrate(&model.User{}) + dbm.db.AutoMigrate(&model.MediaItem{}) + dbm.db.AutoMigrate(&model.Tag{}) + dbm.db.AutoMigrate(&model.Album{}) // Determine whether to bootstrap var count int64 - dbm.db.Model(&models.User{}).Count(&count) + dbm.db.Model(&model.User{}).Count(&count) if count == 0 { dbm.bootstrapDatabase() } @@ -54,17 +53,23 @@ func NewMgr(c *config.Config) *DBManager { func (dbm *DBManager) bootstrapDatabase() { log.Info("[query] Bootstrapping database.") - err := dbm.CreateUser(&models.User{ + + password := "admin" + user := &model.User{ Username: "admin", - Password: "admin", AuthType: "Local", - }) + Password: &password, + } + + err := dbm.CreateUser(user) if err != nil { log.Fatal("[query] Unable to bootstrap database.") } } +// func (dmb *DBManager) {} + func (dbm *DBManager) QueryBuilder(dest interface{}, params []byte) (int64, error) { // TODO: // - Where Filters @@ -72,7 +77,7 @@ func (dbm *DBManager) QueryBuilder(dest interface{}, params []byte) (int64, erro // - Paging Filters objType := fmt.Sprintf("%T", dest) - if objType == "*[]models.MediaItem" { + if objType == "*[]model.MediaItem" { // TODO: Validate MediaItem Type } else { // Return Error diff --git a/internal/db/devices.go b/internal/db/devices.go index c64abf7..9bb6d35 100644 --- a/internal/db/devices.go +++ b/internal/db/devices.go @@ -4,27 +4,28 @@ import ( "github.com/google/uuid" log "github.com/sirupsen/logrus" - "reichard.io/imagini/internal/models" + "reichard.io/imagini/graph/model" ) -func (dbm *DBManager) CreateDevice (device *models.Device) error { +func (dbm *DBManager) CreateDevice (device *model.Device) error { log.Info("[db] Creating device: ", device.Name) - device.RefreshKey = uuid.New().String() + refreshKey := uuid.New().String() + device.RefreshKey = &refreshKey err := dbm.db.Create(&device).Error return err } -func (dbm *DBManager) Device (device *models.Device) (models.Device, error) { - var foundDevice models.Device +func (dbm *DBManager) Device (device *model.Device) (model.Device, error) { + var foundDevice model.Device var count int64 err := dbm.db.Where(&device).First(&foundDevice).Count(&count).Error return foundDevice, err } -func (dbm *DBManager) DeleteDevice (user *models.Device) error { +func (dbm *DBManager) DeleteDevice (user *model.Device) error { return nil } -func (dbm *DBManager) UpdateRefreshToken (device *models.Device, refreshToken string) error { +func (dbm *DBManager) UpdateRefreshToken (device *model.Device, refreshToken string) error { return nil } diff --git a/internal/db/media_items.go b/internal/db/media_items.go index a67f9b8..6e65c27 100644 --- a/internal/db/media_items.go +++ b/internal/db/media_items.go @@ -3,17 +3,17 @@ package db import ( log "github.com/sirupsen/logrus" - "reichard.io/imagini/internal/models" + "reichard.io/imagini/graph/model" ) -func (dbm *DBManager) CreateMediaItem (mediaItem *models.MediaItem) error { +func (dbm *DBManager) CreateMediaItem (mediaItem *model.MediaItem) error { log.Info("[db] Creating media item: ", mediaItem.FileName) err := dbm.db.Create(&mediaItem).Error return err } -func (dbm *DBManager) MediaItems(mediaItemFilter *models.MediaItem) ([]models.MediaItem, int64, error) { - var mediaItems []models.MediaItem +func (dbm *DBManager) MediaItems(mediaItemFilter *model.MediaItem) ([]model.MediaItem, int64, error) { + var mediaItems []model.MediaItem var count int64 err := dbm.db.Where(&mediaItemFilter).Find(&mediaItems).Count(&count).Error; diff --git a/internal/db/users.go b/internal/db/users.go index 3ba521f..1d644d6 100644 --- a/internal/db/users.go +++ b/internal/db/users.go @@ -4,32 +4,33 @@ import ( "golang.org/x/crypto/bcrypt" log "github.com/sirupsen/logrus" - "reichard.io/imagini/internal/models" + "reichard.io/imagini/graph/model" ) -func (dbm *DBManager) CreateUser(user *models.User) error { +func (dbm *DBManager) CreateUser(user *model.User) error { log.Info("[db] Creating user: ", user.Username) - hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost) + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(*user.Password), bcrypt.DefaultCost) if err != nil { log.Error(err) return err } - user.Password = string(hashedPassword) + stringHashedPassword := string(hashedPassword) + user.Password = &stringHashedPassword err = dbm.db.Create(&user).Error return err } -func (dbm *DBManager) User (user *models.User) (models.User, error) { - var foundUser models.User +func (dbm *DBManager) User (user *model.User) (model.User, error) { + var foundUser model.User var count int64 err := dbm.db.Where(&user).First(&foundUser).Count(&count).Error return foundUser, err } -func (dbm *DBManager) DeleteUser (user models.User) error { +func (dbm *DBManager) DeleteUser (user model.User) error { return nil } -func (dbm *DBManager) UpdatePassword (user models.User, pw string) { +func (dbm *DBManager) UpdatePassword (user model.User, pw string) { } diff --git a/internal/models/db.go b/internal/models/db.go deleted file mode 100644 index 00de761..0000000 --- a/internal/models/db.go +++ /dev/null @@ -1,96 +0,0 @@ -package models - -import ( - "time" - "strings" - "reflect" - "gorm.io/gorm" - "github.com/google/uuid" -) - -type Base struct { - UUID uuid.UUID `json:"uuid" gorm:"type:uuid;primarykey"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` -} - -func (base *Base) BeforeCreate(tx *gorm.DB) (err error) { - base.UUID = uuid.New() - return -} - -type ServerSetting struct { - Base - Name string `json:"name" gorm:"not null"` - Description string `json:"description" gorm:"not null"` - Value string `json:"value" gorm:"not null"` -} - -type Device struct { - Base - UserUUID uuid.UUID `json:"-" gorm:"not null"` - User User `json:"user" gorm:"ForeignKey:UUID;References:UserUUID;not null"` // User - Name string `json:"name" gorm:"not null"` // Name of Device - Type string `json:"type" gorm:"not null"` // Android, iOS, Chrome, FireFox, Edge - RefreshKey string `json:"-"` // Device Specific Refresh Key -} - -type User struct { - Base - Email string `json:"email" gorm:"unique"` // Email - Username string `json:"username" gorm:"unique"` // Username - FirstName string `json:"first_name"` // First Name - LastName string `json:"last_name"` // Last Name - Role string `json:"role"` // Role - AuthType string `json:"auth_type" gorm:"default:Local;not null"` // Auth Type (E.g. Local, LDAP) - Password string `json:"-"` // Hased & Salted Password -} - -type MediaItem struct { - Base - UserUUID uuid.UUID `json:"-" gorm:"not null"` - User User `json:"-" gorm:"ForeignKey:UUID;References:UserUUID;not null"` // User - EXIFDate time.Time `json:"exif_date"` // EXIF Date - Latitude *float32 `json:"latitude" gorm:"type:decimal(10,2)"` // Decimal Latitude - Longitude *float32 `json:"longitude" gorm:"type:decimal(10,2)"` // Decimal Longitude - MediaType string `json:"media_type" gorm:"default:Image;not null"` // Image, Video - OrigName string `json:"orig_name" gorm:"not null"` // Original Name - FileName string `json:"file_name" gorm:"not null"` // File Name - Tags []Tag `json:"tags" gorm:"many2many:media_tags;"` // Associated Tag UUIDs - Albums []Album `json:"albums" gorm:"many2many:media_albums;"` // Associated Album UUIDs -} - -type Tag struct { - Base - Name string `json:"name" gorm:"not null"` // Tag Name -} - -type Album struct { - Base - Name string `json:"name" gorm:"not null"` // Album Name -} - -func JSONFields(model interface{}) map[string]struct{} { - jsonFields := make(map[string]struct{}) - val := reflect.ValueOf(model) - t := val.Type() - for i := 0; i < t.NumField(); i++ { - jsonField := strings.TrimSpace(t.Field(i).Tag.Get("json")) - - if jsonField == "" { - continue - } - - jsonSplit := strings.Split(jsonField, ",") - fieldVal := strings.TrimSpace(jsonSplit[0]) - - if fieldVal == "" || fieldVal == "-" { - continue - } - - jsonFields[fieldVal] = struct{}{} - } - - return jsonFields -} diff --git a/plugin/models.go b/plugin/models.go new file mode 100644 index 0000000..3682a2d --- /dev/null +++ b/plugin/models.go @@ -0,0 +1,240 @@ +package plugin + +import ( + "fmt" + "go/types" + "sort" + + "github.com/99designs/gqlgen/codegen/config" + "github.com/99designs/gqlgen/codegen/templates" + "github.com/99designs/gqlgen/plugin" + "github.com/vektah/gqlparser/v2/ast" +) + +type BuildMutateHook = func(b *ModelBuild) *ModelBuild + +func defaultBuildMutateHook(b *ModelBuild) *ModelBuild { + return b +} + +type ModelBuild struct { + PackageName string + Interfaces []*Interface + Models []*Object + Enums []*Enum + Scalars []string +} + +type Interface struct { + Description string + Name string +} + +type Object struct { + Description string + Name string + Fields []*Field + Implements []string +} + +type Field struct { + Description string + Name string + Type types.Type + Tag string + Gorm string +} + +type Enum struct { + Description string + Name string + Values []*EnumValue +} + +type EnumValue struct { + Description string + Name string +} + +func New() plugin.Plugin { + return &Plugin{ + MutateHook: defaultBuildMutateHook, + } +} + +type Plugin struct { + MutateHook BuildMutateHook +} + +var _ plugin.ConfigMutator = &Plugin{} + +func (m *Plugin) Name() string { + return "imaginimodel" +} + +func (m *Plugin) MutateConfig(cfg *config.Config) error { + binder := cfg.NewBinder() + + b := &ModelBuild{ + PackageName: cfg.Model.Package, + } + + for _, schemaType := range cfg.Schema.Types { + if schemaType.BuiltIn { + continue + } + switch schemaType.Kind { + case ast.Interface, ast.Union: + it := &Interface{ + Description: schemaType.Description, + Name: schemaType.Name, + } + + b.Interfaces = append(b.Interfaces, it) + case ast.Object, ast.InputObject: + if schemaType == cfg.Schema.Query || schemaType == cfg.Schema.Mutation || schemaType == cfg.Schema.Subscription { + continue + } + it := &Object{ + Description: schemaType.Description, + Name: schemaType.Name, + } + for _, implementor := range cfg.Schema.GetImplements(schemaType) { + it.Implements = append(it.Implements, implementor.Name) + } + + for _, field := range schemaType.Fields { + var typ types.Type + fieldDef := cfg.Schema.Types[field.Type.Name()] + + if cfg.Models.UserDefined(field.Type.Name()) { + var err error + typ, err = binder.FindTypeFromName(cfg.Models[field.Type.Name()].Model[0]) + if err != nil { + return err + } + } else { + switch fieldDef.Kind { + case ast.Scalar: + // no user defined model, referencing a default scalar + typ = types.NewNamed( + types.NewTypeName(0, cfg.Model.Pkg(), "string", nil), + nil, + nil, + ) + + case ast.Interface, ast.Union: + // no user defined model, referencing a generated interface type + typ = types.NewNamed( + types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil), + types.NewInterfaceType([]*types.Func{}, []types.Type{}), + nil, + ) + + case ast.Enum: + // no user defined model, must reference a generated enum + typ = types.NewNamed( + types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil), + nil, + nil, + ) + + case ast.Object, ast.InputObject: + // no user defined model, must reference a generated struct + typ = types.NewNamed( + types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil), + types.NewStruct(nil, nil), + nil, + ) + + default: + panic(fmt.Errorf("unknown ast type %s", fieldDef.Kind)) + } + } + + name := field.Name + if nameOveride := cfg.Models[schemaType.Name].Fields[field.Name].FieldName; nameOveride != "" { + name = nameOveride + } + + typ = binder.CopyModifiersFromAst(field.Type, typ) + + if isStruct(typ) && (fieldDef.Kind == ast.Object || fieldDef.Kind == ast.InputObject) { + typ = types.NewPointer(typ) + } + + gormType := "" + directive := field.Directives.ForName("meta") + if directive != nil { + arg := directive.Arguments.ForName("gorm") + if arg != nil { + gormType = fmt.Sprintf("gorm:\"%s\"", arg.Value.Raw) + } + } + + it.Fields = append(it.Fields, &Field{ + Name: name, + Type: typ, + Description: field.Description, + Tag: `json:"` + field.Name + `"`, + Gorm: gormType, + }) + } + + b.Models = append(b.Models, it) + case ast.Enum: + it := &Enum{ + Name: schemaType.Name, + Description: schemaType.Description, + } + + for _, v := range schemaType.EnumValues { + it.Values = append(it.Values, &EnumValue{ + Name: v.Name, + Description: v.Description, + }) + } + + b.Enums = append(b.Enums, it) + case ast.Scalar: + b.Scalars = append(b.Scalars, schemaType.Name) + } + } + sort.Slice(b.Enums, func(i, j int) bool { return b.Enums[i].Name < b.Enums[j].Name }) + sort.Slice(b.Models, func(i, j int) bool { return b.Models[i].Name < b.Models[j].Name }) + sort.Slice(b.Interfaces, func(i, j int) bool { return b.Interfaces[i].Name < b.Interfaces[j].Name }) + + for _, it := range b.Enums { + cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+templates.ToGo(it.Name)) + } + for _, it := range b.Models { + cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+templates.ToGo(it.Name)) + } + for _, it := range b.Interfaces { + cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+templates.ToGo(it.Name)) + } + for _, it := range b.Scalars { + cfg.Models.Add(it, "github.com/99designs/gqlgen/graphql.String") + } + + if len(b.Models) == 0 && len(b.Enums) == 0 && len(b.Interfaces) == 0 && len(b.Scalars) == 0 { + return nil + } + + if m.MutateHook != nil { + b = m.MutateHook(b) + } + + return templates.Render(templates.Options{ + PackageName: cfg.Model.Package, + Filename: cfg.Model.Filename, + Data: b, + GeneratedHeader: true, + Packages: cfg.Packages, + }) +} + +func isStruct(t types.Type) bool { + _, is := t.Underlying().(*types.Struct) + return is +} diff --git a/plugin/models.gotpl b/plugin/models.gotpl new file mode 100644 index 0000000..b468faa --- /dev/null +++ b/plugin/models.gotpl @@ -0,0 +1,85 @@ +{{ reserveImport "context" }} +{{ reserveImport "fmt" }} +{{ reserveImport "io" }} +{{ reserveImport "strconv" }} +{{ reserveImport "time" }} +{{ reserveImport "sync" }} +{{ reserveImport "errors" }} +{{ reserveImport "bytes" }} + +{{ reserveImport "github.com/vektah/gqlparser/v2" }} +{{ reserveImport "github.com/vektah/gqlparser/v2/ast" }} +{{ reserveImport "github.com/99designs/gqlgen/graphql" }} +{{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }} + +{{- range $model := .Interfaces }} + {{ with .Description }} {{.|prefixLines "// "}} {{ end }} + type {{.Name|go }} interface { + Is{{.Name|go }}() + } +{{- end }} + +{{ range $model := .Models }} + {{with .Description }} {{.|prefixLines "// "}} {{end}} + type {{ .Name|go }} struct { + {{- range $field := .Fields }} + {{- with .Description }} + {{.|prefixLines "// "}} + {{- end}} + {{ $field.Name|go }} {{$field.Type | ref}} `{{$field.Tag}} {{$field.Gorm}}` + {{- end }} + } + + {{- range $iface := .Implements }} + func ({{ $model.Name|go }}) Is{{ $iface|go }}() {} + {{- end }} +{{- end}} + +{{ range $enum := .Enums }} + {{ with .Description }} {{.|prefixLines "// "}} {{end}} + type {{.Name|go }} string + const ( + {{- range $value := .Values}} + {{- with .Description}} + {{.|prefixLines "// "}} + {{- end}} + {{ $enum.Name|go }}{{ .Name|go }} {{$enum.Name|go }} = {{.Name|quote}} + {{- end }} + ) + + var All{{.Name|go }} = []{{ .Name|go }}{ + {{- range $value := .Values}} + {{$enum.Name|go }}{{ .Name|go }}, + {{- end }} + } + + func (e {{.Name|go }}) IsValid() bool { + switch e { + case {{ range $index, $element := .Values}}{{if $index}},{{end}}{{ $enum.Name|go }}{{ $element.Name|go }}{{end}}: + return true + } + return false + } + + func (e {{.Name|go }}) String() string { + return string(e) + } + + func (e *{{.Name|go }}) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = {{ .Name|go }}(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid {{ .Name }}", str) + } + return nil + } + + func (e {{.Name|go }}) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) + } + +{{- end }} From c39fe6ec24714224dcf2815f8511e224a7583a3a Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Tue, 2 Feb 2021 22:55:35 -0500 Subject: [PATCH 2/8] Basic Auth Context --- graph/generated/generated.go | 666 +++++++++++++++++----- graph/model/models_auth.go | 12 + graph/model/models_db.go | 36 ++ graph/model/models_gen.go | 46 ++ graph/schema.graphqls | 55 +- graph/schema.resolvers.go | 53 +- internal/api/auth.go | 54 +- internal/api/middlewares.go | 37 +- internal/{models/api.go => api/models.go} | 2 +- internal/api/routes.go | 21 +- internal/auth/auth.go | 28 +- internal/db/db.go | 11 +- internal/db/users.go | 9 +- 13 files changed, 828 insertions(+), 202 deletions(-) create mode 100644 graph/model/models_auth.go create mode 100644 graph/model/models_db.go rename internal/{models/api.go => api/models.go} (97%) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index c7823df..bcf5285 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -42,8 +42,8 @@ type ResolverRoot interface { } type DirectiveRoot struct { - HasRole func(ctx context.Context, obj interface{}, next graphql.Resolver, role model.Role) (res interface{}, err error) - Meta func(ctx context.Context, obj interface{}, next graphql.Resolver, gorm *string) (res interface{}, err error) + HasMinRole func(ctx context.Context, obj interface{}, next graphql.Resolver, role model.Role) (res interface{}, err error) + Meta func(ctx context.Context, obj interface{}, next graphql.Resolver, gorm *string) (res interface{}, err error) } type ComplexityRoot struct { @@ -59,6 +59,11 @@ type ComplexityRoot struct { PageInfo func(childComplexity int) int } + AuthResponse struct { + Error func(childComplexity int) int + Result func(childComplexity int) int + } + Device struct { CreatedAt func(childComplexity int) int ID func(childComplexity int) int @@ -113,6 +118,9 @@ type ComplexityRoot struct { Albums func(childComplexity int, filter *model.AlbumFilter, count *int, page *int) int Device func(childComplexity int, id string) int Devices func(childComplexity int, filter *model.DeviceFilter, count *int, page *int) int + Login func(childComplexity int, user string, password string) int + Logout func(childComplexity int) int + Me func(childComplexity int) int MediaItem func(childComplexity int, id string) int MediaItems func(childComplexity int, filter *model.MediaItemFilter, count *int, page *int) int Tag func(childComplexity int, id string) int @@ -160,11 +168,14 @@ type MutationResolver interface { CreateUser(ctx context.Context, input model.NewUser) (*model.User, error) } type QueryResolver interface { + Login(ctx context.Context, user string, password string) (model.AuthResult, error) + Logout(ctx context.Context) (model.AuthResult, error) MediaItem(ctx context.Context, id string) (*model.MediaItem, error) Device(ctx context.Context, id string) (*model.Device, error) Album(ctx context.Context, id string) (*model.Album, error) - Tag(ctx context.Context, id string) (*model.Tag, error) User(ctx context.Context, id string) (*model.User, error) + Tag(ctx context.Context, id string) (*model.Tag, error) + Me(ctx context.Context) (*model.User, error) MediaItems(ctx context.Context, filter *model.MediaItemFilter, count *int, page *int) (*model.MediaItemResponse, error) Devices(ctx context.Context, filter *model.DeviceFilter, count *int, page *int) (*model.DeviceResponse, error) Albums(ctx context.Context, filter *model.AlbumFilter, count *int, page *int) (*model.AlbumResponse, error) @@ -229,6 +240,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.AlbumResponse.PageInfo(childComplexity), true + case "AuthResponse.Error": + if e.complexity.AuthResponse.Error == nil { + break + } + + return e.complexity.AuthResponse.Error(childComplexity), true + + case "AuthResponse.Result": + if e.complexity.AuthResponse.Result == nil { + break + } + + return e.complexity.AuthResponse.Result(childComplexity), true + case "Device.createdAt": if e.complexity.Device.CreatedAt == nil { break @@ -519,6 +544,32 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.Devices(childComplexity, args["filter"].(*model.DeviceFilter), args["count"].(*int), args["page"].(*int)), true + case "Query.login": + if e.complexity.Query.Login == nil { + break + } + + args, err := ec.field_Query_login_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Login(childComplexity, args["user"].(string), args["password"].(string)), true + + case "Query.logout": + if e.complexity.Query.Logout == nil { + break + } + + return e.complexity.Query.Logout(childComplexity), true + + case "Query.me": + if e.complexity.Query.Me == nil { + break + } + + return e.complexity.Query.Me(childComplexity), true + case "Query.mediaItem": if e.complexity.Query.MediaItem == nil { break @@ -787,7 +838,7 @@ scalar Time scalar Upload # https://gqlgen.com/reference/directives/ -directive @hasRole(role: Role!) on FIELD_DEFINITION +directive @hasMinRole(role: Role!) on FIELD_DEFINITION directive @meta( gorm: String, @@ -814,6 +865,20 @@ enum AuthType { LDAP } +# ------------------------------------------------------------ +# ---------------------- Authentication ---------------------- +# ------------------------------------------------------------ + +enum AuthResult { + Success + Failure +} + +type AuthResponse { + Result: AuthResult! + Error: String +} + # ------------------------------------------------------------ # ----------------------- Type Filters ----------------------- # ------------------------------------------------------------ @@ -1095,47 +1160,56 @@ type AlbumResponse { # ------------------------------------------------------------ type Query { + + # Authentication + login( + user: String! + password: String! + ): AuthResult! + logout: AuthResult! @hasMinRole(role: User) + # Single Item - mediaItem(id: ID!): MediaItem! @hasRole(role: User) - device(id: ID!): Device! @hasRole(role: User) - album(id: ID!): Album! @hasRole(role: User) - tag(id: ID!): Tag! @hasRole(role: User) - user(id: ID!): User! @hasRole(role: Admin) + mediaItem(id: ID!): MediaItem! @hasMinRole(role: User) + device(id: ID!): Device! @hasMinRole(role: User) + album(id: ID!): Album! @hasMinRole(role: User) + user(id: ID!): User! @hasMinRole(role: Admin) + tag(id: ID!): Tag! @hasMinRole(role: User) + me: User! @hasMinRole(role: User) # All mediaItems( filter: MediaItemFilter count: Int page: Int - ): MediaItemResponse! @hasRole(role: User) + ): MediaItemResponse! @hasMinRole(role: User) devices( filter: DeviceFilter count: Int page: Int - ): DeviceResponse! @hasRole(role: User) + ): DeviceResponse! @hasMinRole(role: User) albums( filter: AlbumFilter count: Int page: Int - ): AlbumResponse! @hasRole(role: User) + ): AlbumResponse! @hasMinRole(role: User) tags( filter: TagFilter count: Int page: Int - ): TagResponse! @hasRole(role: User) + ): TagResponse! @hasMinRole(role: User) users( filter: UserFilter count: Int page: Int - ): UserResponse! @hasRole(role: Admin) + ): UserResponse! @hasMinRole(role: Admin) } type Mutation { - createMediaItem(input: NewMediaItem!): MediaItem! @hasRole(role: User) - createDevice(input: NewDevice!): Device! @hasRole(role: User) - createAlbum(input: NewAlbum!): Album! @hasRole(role: User) - createTag(input: NewTag!): Tag! @hasRole(role: User) - createUser(input: NewUser!): User! @hasRole(role: Admin) + createMediaItem(input: NewMediaItem!): MediaItem! @hasMinRole(role: User) + createDevice(input: NewDevice!): Device! @hasMinRole(role: User) + createAlbum(input: NewAlbum!): Album! @hasMinRole(role: User) + createTag(input: NewTag!): Tag! @hasMinRole(role: User) + createUser(input: NewUser!): User! @hasMinRole(role: Admin) } `, BuiltIn: false}, } @@ -1145,7 +1219,7 @@ var parsedSchema = gqlparser.MustLoadSchema(sources...) // region ***************************** args.gotpl ***************************** -func (ec *executionContext) dir_hasRole_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { +func (ec *executionContext) dir_hasMinRole_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} var arg0 model.Role @@ -1361,6 +1435,30 @@ func (ec *executionContext) field_Query_devices_args(ctx context.Context, rawArg return args, nil } +func (ec *executionContext) field_Query_login_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["user"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("user")) + arg0, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["user"] = arg0 + var arg1 string + if tmp, ok := rawArgs["password"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("password")) + arg1, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["password"] = arg1 + return args, nil +} + func (ec *executionContext) field_Query_mediaItem_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -1789,6 +1887,73 @@ func (ec *executionContext) _AlbumResponse_pageInfo(ctx context.Context, field g return ec.marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) } +func (ec *executionContext) _AuthResponse_Result(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "AuthResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Result, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(model.AuthResult) + fc.Result = res + return ec.marshalNAuthResult2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResult(ctx, field.Selections, res) +} + +func (ec *executionContext) _AuthResponse_Error(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "AuthResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Error, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + func (ec *executionContext) _Device_id(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -2843,10 +3008,10 @@ func (ec *executionContext) _Mutation_createMediaItem(ctx context.Context, field if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -2909,10 +3074,10 @@ func (ec *executionContext) _Mutation_createDevice(ctx context.Context, field gr if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -2975,10 +3140,10 @@ func (ec *executionContext) _Mutation_createAlbum(ctx context.Context, field gra if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -3041,10 +3206,10 @@ func (ec *executionContext) _Mutation_createTag(ctx context.Context, field graph if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -3107,10 +3272,10 @@ func (ec *executionContext) _Mutation_createUser(ctx context.Context, field grap if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -3245,6 +3410,107 @@ func (ec *executionContext) _PageInfo_total(ctx context.Context, field graphql.C return ec.marshalNInt2int(ctx, field.Selections, res) } +func (ec *executionContext) _Query_login(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_login_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Login(rctx, args["user"].(string), args["password"].(string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(model.AuthResult) + fc.Result = res + return ec.marshalNAuthResult2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResult(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_logout(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Logout(rctx) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") + } + return ec.directives.HasMinRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(model.AuthResult); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be reichard.io/imagini/graph/model.AuthResult`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(model.AuthResult) + fc.Result = res + return ec.marshalNAuthResult2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResult(ctx, field.Selections, res) +} + func (ec *executionContext) _Query_mediaItem(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -3278,10 +3544,10 @@ func (ec *executionContext) _Query_mediaItem(ctx context.Context, field graphql. if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -3344,10 +3610,10 @@ func (ec *executionContext) _Query_device(ctx context.Context, field graphql.Col if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -3410,10 +3676,10 @@ func (ec *executionContext) _Query_album(ctx context.Context, field graphql.Coll if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -3443,72 +3709,6 @@ func (ec *executionContext) _Query_album(ctx context.Context, field graphql.Coll return ec.marshalNAlbum2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbum(ctx, field.Selections, res) } -func (ec *executionContext) _Query_tag(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - fc := &graphql.FieldContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, - IsResolver: true, - } - - ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_tag_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - directive0 := func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Tag(rctx, args["id"].(string)) - } - directive1 := func(ctx context.Context) (interface{}, error) { - role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") - if err != nil { - return nil, err - } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") - } - return ec.directives.HasRole(ctx, nil, directive0, role) - } - - tmp, err := directive1(rctx) - if err != nil { - return nil, graphql.ErrorOnPath(ctx, err) - } - if tmp == nil { - return nil, nil - } - if data, ok := tmp.(*model.Tag); ok { - return data, nil - } - return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.Tag`, tmp) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(*model.Tag) - fc.Result = res - return ec.marshalNTag2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTag(ctx, field.Selections, res) -} - func (ec *executionContext) _Query_user(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -3542,10 +3742,135 @@ func (ec *executionContext) _Query_user(ctx context.Context, field graphql.Colle if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.User); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.User`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.User) + fc.Result = res + return ec.marshalNUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_tag(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_tag_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Tag(rctx, args["id"].(string)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") + } + return ec.directives.HasMinRole(ctx, nil, directive0, role) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*model.Tag); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.Tag`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Tag) + fc.Result = res + return ec.marshalNTag2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTag(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_me(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Me(rctx) + } + directive1 := func(ctx context.Context) (interface{}, error) { + role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") + if err != nil { + return nil, err + } + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") + } + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -3608,10 +3933,10 @@ func (ec *executionContext) _Query_mediaItems(ctx context.Context, field graphql if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -3674,10 +3999,10 @@ func (ec *executionContext) _Query_devices(ctx context.Context, field graphql.Co if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -3740,10 +4065,10 @@ func (ec *executionContext) _Query_albums(ctx context.Context, field graphql.Col if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -3806,10 +4131,10 @@ func (ec *executionContext) _Query_tags(ctx context.Context, field graphql.Colle if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -3872,10 +4197,10 @@ func (ec *executionContext) _Query_users(ctx context.Context, field graphql.Coll if err != nil { return nil, err } - if ec.directives.HasRole == nil { - return nil, errors.New("directive hasRole is not implemented") + if ec.directives.HasMinRole == nil { + return nil, errors.New("directive hasMinRole is not implemented") } - return ec.directives.HasRole(ctx, nil, directive0, role) + return ec.directives.HasMinRole(ctx, nil, directive0, role) } tmp, err := directive1(rctx) @@ -7006,6 +7331,35 @@ func (ec *executionContext) _AlbumResponse(ctx context.Context, sel ast.Selectio return out } +var authResponseImplementors = []string{"AuthResponse"} + +func (ec *executionContext) _AuthResponse(ctx context.Context, sel ast.SelectionSet, obj *model.AuthResponse) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, authResponseImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("AuthResponse") + case "Result": + out.Values[i] = ec._AuthResponse_Result(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "Error": + out.Values[i] = ec._AuthResponse_Error(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var deviceImplementors = []string{"Device"} func (ec *executionContext) _Device(ctx context.Context, sel ast.SelectionSet, obj *model.Device) graphql.Marshaler { @@ -7264,6 +7618,34 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") + case "login": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_login(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "logout": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_logout(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "mediaItem": field := field out.Concurrently(i, func() (res graphql.Marshaler) { @@ -7306,6 +7688,20 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } return res }) + case "user": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_user(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "tag": field := field out.Concurrently(i, func() (res graphql.Marshaler) { @@ -7320,7 +7716,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } return res }) - case "user": + case "me": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { @@ -7328,7 +7724,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_user(ctx, field) + res = ec._Query_me(ctx, field) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } @@ -7837,6 +8233,16 @@ func (ec *executionContext) marshalNAlbumResponse2ᚖreichardᚗioᚋimaginiᚋg return ec._AlbumResponse(ctx, sel, v) } +func (ec *executionContext) unmarshalNAuthResult2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResult(ctx context.Context, v interface{}) (model.AuthResult, error) { + var res model.AuthResult + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNAuthResult2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResult(ctx context.Context, sel ast.SelectionSet, v model.AuthResult) graphql.Marshaler { + return v +} + func (ec *executionContext) unmarshalNAuthType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx context.Context, v interface{}) (model.AuthType, error) { var res model.AuthType err := res.UnmarshalGQL(v) diff --git a/graph/model/models_auth.go b/graph/model/models_auth.go new file mode 100644 index 0000000..5c77bd9 --- /dev/null +++ b/graph/model/models_auth.go @@ -0,0 +1,12 @@ +package model + +import ( + "net/http" +) + +type AuthContext struct { + AccessToken string + RefreshToken string + AuthResponse *http.ResponseWriter + AuthRequest *http.Request +} diff --git a/graph/model/models_db.go b/graph/model/models_db.go new file mode 100644 index 0000000..cd46621 --- /dev/null +++ b/graph/model/models_db.go @@ -0,0 +1,36 @@ +package model + +import ( + "gorm.io/gorm" + "github.com/google/uuid" +) + +func (u *User) BeforeCreate(tx *gorm.DB) (err error) { + newID := uuid.New().String() + u.ID = &newID + return +} + +func (a *Album) BeforeCreate(tx *gorm.DB) (err error) { + newID := uuid.New().String() + a.ID = &newID + return +} + +func (m *MediaItem) BeforeCreate(tx *gorm.DB) (err error) { + newID := uuid.New().String() + m.ID = &newID + return +} + +func (t *Tag) BeforeCreate(tx *gorm.DB) (err error) { + newID := uuid.New().String() + t.ID = &newID + return +} + +func (d *Device) BeforeCreate(tx *gorm.DB) (err error) { + newID := uuid.New().String() + d.ID = &newID + return +} diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 695b3f4..ed064a7 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -32,6 +32,11 @@ type AlbumResponse struct { PageInfo *PageInfo `json:"pageInfo" ` } +type AuthResponse struct { + Result AuthResult `json:"Result" ` + Error *string `json:"Error" ` +} + type AuthTypeFilter struct { EqualTo *AuthType `json:"equalTo" ` NotEqualTo *AuthType `json:"notEqualTo" ` @@ -261,6 +266,47 @@ type UserResponse struct { PageInfo *PageInfo `json:"pageInfo" ` } +type AuthResult string + +const ( + AuthResultSuccess AuthResult = "Success" + AuthResultFailure AuthResult = "Failure" +) + +var AllAuthResult = []AuthResult{ + AuthResultSuccess, + AuthResultFailure, +} + +func (e AuthResult) IsValid() bool { + switch e { + case AuthResultSuccess, AuthResultFailure: + return true + } + return false +} + +func (e AuthResult) String() string { + return string(e) +} + +func (e *AuthResult) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = AuthResult(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid AuthResult", str) + } + return nil +} + +func (e AuthResult) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + type AuthType string const ( diff --git a/graph/schema.graphqls b/graph/schema.graphqls index a53c070..3d90eb0 100644 --- a/graph/schema.graphqls +++ b/graph/schema.graphqls @@ -4,7 +4,7 @@ scalar Time scalar Upload # https://gqlgen.com/reference/directives/ -directive @hasRole(role: Role!) on FIELD_DEFINITION +directive @hasMinRole(role: Role!) on FIELD_DEFINITION directive @meta( gorm: String, @@ -31,6 +31,20 @@ enum AuthType { LDAP } +# ------------------------------------------------------------ +# ---------------------- Authentication ---------------------- +# ------------------------------------------------------------ + +enum AuthResult { + Success + Failure +} + +type AuthResponse { + Result: AuthResult! + Error: String +} + # ------------------------------------------------------------ # ----------------------- Type Filters ----------------------- # ------------------------------------------------------------ @@ -312,45 +326,54 @@ type AlbumResponse { # ------------------------------------------------------------ type Query { + + # Authentication + login( + user: String! + password: String! + ): AuthResult! + logout: AuthResult! @hasMinRole(role: User) + # Single Item - mediaItem(id: ID!): MediaItem! @hasRole(role: User) - device(id: ID!): Device! @hasRole(role: User) - album(id: ID!): Album! @hasRole(role: User) - tag(id: ID!): Tag! @hasRole(role: User) - user(id: ID!): User! @hasRole(role: Admin) + mediaItem(id: ID!): MediaItem! @hasMinRole(role: User) + device(id: ID!): Device! @hasMinRole(role: User) + album(id: ID!): Album! @hasMinRole(role: User) + user(id: ID!): User! @hasMinRole(role: Admin) + tag(id: ID!): Tag! @hasMinRole(role: User) + me: User! @hasMinRole(role: User) # All mediaItems( filter: MediaItemFilter count: Int page: Int - ): MediaItemResponse! @hasRole(role: User) + ): MediaItemResponse! @hasMinRole(role: User) devices( filter: DeviceFilter count: Int page: Int - ): DeviceResponse! @hasRole(role: User) + ): DeviceResponse! @hasMinRole(role: User) albums( filter: AlbumFilter count: Int page: Int - ): AlbumResponse! @hasRole(role: User) + ): AlbumResponse! @hasMinRole(role: User) tags( filter: TagFilter count: Int page: Int - ): TagResponse! @hasRole(role: User) + ): TagResponse! @hasMinRole(role: User) users( filter: UserFilter count: Int page: Int - ): UserResponse! @hasRole(role: Admin) + ): UserResponse! @hasMinRole(role: Admin) } type Mutation { - createMediaItem(input: NewMediaItem!): MediaItem! @hasRole(role: User) - createDevice(input: NewDevice!): Device! @hasRole(role: User) - createAlbum(input: NewAlbum!): Album! @hasRole(role: User) - createTag(input: NewTag!): Tag! @hasRole(role: User) - createUser(input: NewUser!): User! @hasRole(role: Admin) + createMediaItem(input: NewMediaItem!): MediaItem! @hasMinRole(role: User) + createDevice(input: NewDevice!): Device! @hasMinRole(role: User) + createAlbum(input: NewAlbum!): Album! @hasMinRole(role: User) + createTag(input: NewTag!): Tag! @hasMinRole(role: User) + createUser(input: NewUser!): User! @hasMinRole(role: Admin) } diff --git a/graph/schema.resolvers.go b/graph/schema.resolvers.go index d539daf..3f72070 100644 --- a/graph/schema.resolvers.go +++ b/graph/schema.resolvers.go @@ -4,6 +4,7 @@ package graph // will be copied through when generating and any unknown code will be moved to the end. import ( + "net/http" "context" "fmt" @@ -28,7 +29,38 @@ func (r *mutationResolver) CreateTag(ctx context.Context, input model.NewTag) (* } func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser) (*model.User, error) { - panic(fmt.Errorf("not implemented")) + user := &model.User{ + Email: input.Email, + Username: input.Username, + FirstName: input.FirstName, + LastName: input.LastName, + Role: input.Role, + AuthType: input.AuthType, + Password: input.Password, + } + + err := r.DB.CreateUser(user) + if err != nil { + panic(fmt.Errorf("DB Error")) + } + + return user, nil +} + +func (r *queryResolver) Login(ctx context.Context, user string, password string) (model.AuthResult, error) { + + // Set Cookie From Context + authContext := ctx.Value("auth").(*model.AuthContext) + resp := *authContext.AuthResponse + testCookie := http.Cookie{Name: "TestCookie", Value: "Test123", Path: "/", HttpOnly: true} + http.SetCookie(resp, &testCookie) + + return model.AuthResultSuccess, nil +} + +func (r *queryResolver) Logout(ctx context.Context) (model.AuthResult, error) { + // panic(fmt.Errorf("not implemented")) + return model.AuthResultSuccess, nil } func (r *queryResolver) MediaItem(ctx context.Context, id string) (*model.MediaItem, error) { @@ -43,11 +75,15 @@ func (r *queryResolver) Album(ctx context.Context, id string) (*model.Album, err panic(fmt.Errorf("not implemented")) } +func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) { + panic(fmt.Errorf("not implemented")) +} + func (r *queryResolver) Tag(ctx context.Context, id string) (*model.Tag, error) { panic(fmt.Errorf("not implemented")) } -func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) { +func (r *queryResolver) Me(ctx context.Context) (*model.User, error) { panic(fmt.Errorf("not implemented")) } @@ -68,7 +104,18 @@ func (r *queryResolver) Tags(ctx context.Context, filter *model.TagFilter, count } func (r *queryResolver) Users(ctx context.Context, filter *model.UserFilter, count *int, page *int) (*model.UserResponse, error) { - panic(fmt.Errorf("not implemented")) + resp, totalCount, err := r.DB.Users() + if err != nil { + panic(fmt.Errorf("DB Error")) + } + return &model.UserResponse{ + Data: resp, + PageInfo: &model.PageInfo{ + Count: int(totalCount), + Page: 0, + Total: int(totalCount), + }, + }, nil } // Mutation returns generated.MutationResolver implementation. diff --git a/internal/api/auth.go b/internal/api/auth.go index db67217..81ef498 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -4,14 +4,16 @@ import ( "fmt" "time" "strings" + "context" "net/http" "encoding/json" + "github.com/google/uuid" log "github.com/sirupsen/logrus" "github.com/lestrrat-go/jwx/jwt" + "github.com/99designs/gqlgen/graphql" - "reichard.io/imagini/internal/models" - graphql "reichard.io/imagini/graph/model" + "reichard.io/imagini/graph/model" ) func (api *API) loginHandler(w http.ResponseWriter, r *http.Request) { @@ -22,7 +24,7 @@ func (api *API) loginHandler(w http.ResponseWriter, r *http.Request) { } // Decode into Struct - var creds models.APICredentials + var creds APICredentials err := json.NewDecoder(r.Body).Decode(&creds) if err != nil { errorJSON(w, "Invalid parameters.", http.StatusBadRequest) @@ -36,7 +38,7 @@ func (api *API) loginHandler(w http.ResponseWriter, r *http.Request) { } // Do login - resp, user := api.Auth.AuthenticateUser(creds) + resp, user := api.Auth.AuthenticateUser(creds.User, creds.Password) if !resp { errorJSON(w, "Invalid credentials.", http.StatusUnauthorized) return @@ -82,7 +84,7 @@ func (api *API) logoutHandler(w http.ResponseWriter, r *http.Request) { /** * This will find or create the requested device based on ID and User. **/ -func (api *API) upsertRequestedDevice(user graphql.User, r *http.Request) (graphql.Device, error) { +func (api *API) upsertRequestedDevice(user model.User, r *http.Request) (model.Device, error) { requestedDevice := deriveRequestedDevice(r) requestedDevice.Type = deriveDeviceType(r) requestedDevice.User.ID = user.ID @@ -93,7 +95,7 @@ func (api *API) upsertRequestedDevice(user graphql.User, r *http.Request) (graph return createdDevice, err } - foundDevice, err := api.DB.Device(&graphql.Device{ + foundDevice, err := api.DB.Device(&model.Device{ ID: requestedDevice.ID, User: &user, }) @@ -101,28 +103,28 @@ func (api *API) upsertRequestedDevice(user graphql.User, r *http.Request) (graph return foundDevice, err } -func deriveDeviceType(r *http.Request) graphql.DeviceType { +func deriveDeviceType(r *http.Request) model.DeviceType { userAgent := strings.ToLower(r.Header.Get("User-Agent")) if strings.HasPrefix(userAgent, "ios-imagini"){ - return graphql.DeviceTypeIOs + return model.DeviceTypeIOs } else if strings.HasPrefix(userAgent, "android-imagini"){ - return graphql.DeviceTypeAndroid + return model.DeviceTypeAndroid } else if strings.HasPrefix(userAgent, "chrome"){ - return graphql.DeviceTypeChrome + return model.DeviceTypeChrome } else if strings.HasPrefix(userAgent, "firefox"){ - return graphql.DeviceTypeFirefox + return model.DeviceTypeFirefox } else if strings.HasPrefix(userAgent, "msie"){ - return graphql.DeviceTypeInternetExplorer + return model.DeviceTypeInternetExplorer } else if strings.HasPrefix(userAgent, "edge"){ - return graphql.DeviceTypeEdge + return model.DeviceTypeEdge } else if strings.HasPrefix(userAgent, "safari"){ - return graphql.DeviceTypeSafari + return model.DeviceTypeSafari } - return graphql.DeviceTypeUnknown + return model.DeviceTypeUnknown } -func deriveRequestedDevice(r *http.Request) graphql.Device { - deviceSkeleton := graphql.Device{} +func deriveRequestedDevice(r *http.Request) model.Device { + deviceSkeleton := model.Device{} authHeader := r.Header.Get("X-Imagini-Authorization") splitAuthInfo := strings.Split(authHeader, ",") @@ -202,8 +204,8 @@ func (api *API) refreshAccessToken(w http.ResponseWriter, r *http.Request) (jwt. stringDeviceUUID := deviceUUID.String() // Device & User Skeleton - user := graphql.User{ID: &stringUserUUID} - device := graphql.Device{ID: &stringDeviceUUID} + user := model.User{ID: &stringUserUUID} + device := model.Device{ID: &stringDeviceUUID} // Update token accessTokenString, err := api.Auth.CreateJWTAccessToken(user, device) @@ -230,3 +232,17 @@ func trimQuotes(s string) string { } return s } + +func hasMinRoleDirective(ctx context.Context, obj interface{}, next graphql.Resolver, role model.Role) (res interface{}, err error) { + // if !getCurrentUser(ctx).HasRole(role) { + // // block calling the next resolver + // return nil, fmt.Errorf("Access denied") + // } + + // or let it pass through + return next(ctx) +} + +func metaDirective(ctx context.Context, obj interface{}, next graphql.Resolver, gorm *string) (res interface{}, err error){ + return next(ctx) +} diff --git a/internal/api/middlewares.go b/internal/api/middlewares.go index d168fd7..6edb91b 100644 --- a/internal/api/middlewares.go +++ b/internal/api/middlewares.go @@ -1,10 +1,12 @@ package api import ( - "os" - "context" - "net/http" log "github.com/sirupsen/logrus" + "net/http" + "context" + "os" + + "reichard.io/imagini/graph/model" ) type Middleware func(http.Handler) http.HandlerFunc @@ -20,6 +22,35 @@ func multipleMiddleware(h http.HandlerFunc, m ...Middleware) http.HandlerFunc { return wrapped } +func (api *API) injectContextMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + log.Info("[middleware] Entering testMiddleware...") + authContext := &model.AuthContext{ + AuthResponse: &w, + AuthRequest: r, + } + accessCookie, err := r.Cookie("AccessToken") + if err != nil { + log.Warn("[middleware] AccessToken not found") + } else { + authContext.AccessToken = accessCookie.Value + } + refreshCookie, err := r.Cookie("RefreshToken") + if err != nil { + log.Warn("[middleware] RefreshToken not found") + } else { + authContext.RefreshToken = refreshCookie.Value + } + + // Add context + ctx := context.WithValue(r.Context(), "auth", authContext) + r = r.WithContext(ctx) + + log.Info("[middleware] Exiting testMiddleware...") + next.ServeHTTP(w, r) + }) +} + func (api *API) authMiddleware(next http.Handler) http.HandlerFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/internal/models/api.go b/internal/api/models.go similarity index 97% rename from internal/models/api.go rename to internal/api/models.go index 47654a0..8a2345b 100644 --- a/internal/models/api.go +++ b/internal/api/models.go @@ -1,4 +1,4 @@ -package models +package api type APICredentials struct { User string `json:"user"` diff --git a/internal/api/routes.go b/internal/api/routes.go index 9c2603e..41bb097 100644 --- a/internal/api/routes.go +++ b/internal/api/routes.go @@ -1,33 +1,38 @@ package api import ( - "encoding/json" "net/http" + "encoding/json" - "reichard.io/imagini/internal/models" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/playground" + "reichard.io/imagini/graph" "reichard.io/imagini/graph/generated" ) func (api *API) registerRoutes() { - srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}})) - // TODO: Provide Authentication for srv + // Set up Directives + c := generated.Config{ Resolvers: &graph.Resolver{ DB: api.DB } } + c.Directives.HasMinRole = hasMinRoleDirective + c.Directives.Meta = metaDirective + srv := handler.NewDefaultServer(generated.NewExecutableSchema(c)) + + // Handle GraphQL api.Router.Handle("/playground", playground.Handler("GraphQL playground", "/query")) - api.Router.Handle("/query", srv) + api.Router.Handle("/query", api.injectContextMiddleware(srv)) + // Handle Resource Route api.Router.HandleFunc("/media/", multipleMiddleware( api.mediaHandler, api.authMiddleware, )) - api.Router.HandleFunc("/logout", api.logoutHandler) - api.Router.HandleFunc("/login", api.loginHandler) + } func errorJSON(w http.ResponseWriter, err string, code int) { - errStruct := &models.APIResponse{Error: &models.APIError{Message: err, Code: int64(code)}} + errStruct := &APIResponse{Error: &APIError{Message: err, Code: int64(code)}} responseJSON(w, errStruct, code) } diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 213dfc7..a4dfd8c 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -12,11 +12,9 @@ import ( "github.com/lestrrat-go/jwx/jwa" "github.com/lestrrat-go/jwx/jwt" + "reichard.io/imagini/graph/model" "reichard.io/imagini/internal/db" "reichard.io/imagini/internal/config" - - graphql "reichard.io/imagini/graph/model" - "reichard.io/imagini/internal/models" "reichard.io/imagini/internal/session" ) @@ -35,21 +33,21 @@ func NewMgr(db *db.DBManager, c *config.Config) *AuthManager { } } -func (auth *AuthManager) AuthenticateUser(creds models.APICredentials) (bool, graphql.User) { +func (auth *AuthManager) AuthenticateUser(user, password string) (bool, model.User) { // Search Objects - userByName := &graphql.User{} - userByName.Username = creds.User + userByName := &model.User{} + userByName.Username = user foundUser, err := auth.DB.User(userByName) if errors.Is(err, gorm.ErrRecordNotFound) { - userByEmail := &graphql.User{} - userByEmail.Email = creds.User + userByEmail := &model.User{} + userByEmail.Email = user foundUser, err = auth.DB.User(userByEmail) } // Error Checking if errors.Is(err, gorm.ErrRecordNotFound) { - log.Warn("[auth] User not found: ", creds.User) + log.Warn("[auth] User not found: ", user) return false, foundUser } else if err != nil { log.Error(err) @@ -61,15 +59,15 @@ func (auth *AuthManager) AuthenticateUser(creds models.APICredentials) (bool, gr // Determine Type switch foundUser.AuthType { case "Local": - return authenticateLocalUser(foundUser, creds.Password), foundUser + return authenticateLocalUser(foundUser, password), foundUser case "LDAP": - return authenticateLDAPUser(foundUser, creds.Password), foundUser + return authenticateLDAPUser(foundUser, password), foundUser default: return false, foundUser } } -func (auth *AuthManager) getRole(user graphql.User) string { +func (auth *AuthManager) getRole(user model.User) string { // TODO: Lookup role of user return "User" } @@ -88,7 +86,7 @@ func (auth *AuthManager) ValidateJWTRefreshToken(refreshJWT string) (jwt.Token, return nil, errors.New("did does not parse") } stringDeviceID := deviceID.String() - device, err := auth.DB.Device(&graphql.Device{ID: &stringDeviceID}) + device, err := auth.DB.Device(&model.Device{ID: &stringDeviceID}) if err != nil { return nil, err } @@ -119,7 +117,7 @@ func (auth *AuthManager) ValidateJWTAccessToken(accessJWT string) (jwt.Token, er return verifiedToken, nil } -func (auth *AuthManager) CreateJWTRefreshToken(user graphql.User, device graphql.Device) (string, error) { +func (auth *AuthManager) CreateJWTRefreshToken(user model.User, device model.Device) (string, error) { // Acquire Refresh Key byteKey := []byte(*device.RefreshKey) @@ -154,7 +152,7 @@ func (auth *AuthManager) CreateJWTRefreshToken(user graphql.User, device graphql return string(signed), nil } -func (auth *AuthManager) CreateJWTAccessToken(user graphql.User, device graphql.Device) (string, error) { +func (auth *AuthManager) CreateJWTAccessToken(user model.User, device model.Device) (string, error) { // Create New Token tm := time.Now() t := jwt.New() diff --git a/internal/db/db.go b/internal/db/db.go index 67994dd..1873598 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -1,14 +1,14 @@ package db import ( - "fmt" - "path" "errors" + "path" + "fmt" - "gorm.io/gorm" + log "github.com/sirupsen/logrus" // "gorm.io/gorm/logger" "gorm.io/driver/sqlite" - log "github.com/sirupsen/logrus" + "gorm.io/gorm" "reichard.io/imagini/internal/config" "reichard.io/imagini/graph/model" @@ -59,6 +59,7 @@ func (dbm *DBManager) bootstrapDatabase() { Username: "admin", AuthType: "Local", Password: &password, + Role: model.RoleAdmin, } err := dbm.CreateUser(user) @@ -68,8 +69,6 @@ func (dbm *DBManager) bootstrapDatabase() { } } -// func (dmb *DBManager) {} - func (dbm *DBManager) QueryBuilder(dest interface{}, params []byte) (int64, error) { // TODO: // - Where Filters diff --git a/internal/db/users.go b/internal/db/users.go index 1d644d6..8853789 100644 --- a/internal/db/users.go +++ b/internal/db/users.go @@ -7,7 +7,7 @@ import ( "reichard.io/imagini/graph/model" ) -func (dbm *DBManager) CreateUser(user *model.User) error { +func (dbm *DBManager) CreateUser (user *model.User) error { log.Info("[db] Creating user: ", user.Username) hashedPassword, err := bcrypt.GenerateFromPassword([]byte(*user.Password), bcrypt.DefaultCost) if err != nil { @@ -27,6 +27,13 @@ func (dbm *DBManager) User (user *model.User) (model.User, error) { return foundUser, err } +func (dbm *DBManager) Users () ([]*model.User, int64, error) { + var foundUsers []*model.User + var count int64 + err := dbm.db.Find(&foundUsers).Count(&count).Error + return foundUsers, count, err +} + func (dbm *DBManager) DeleteUser (user model.User) error { return nil } From 082f9234829fd3f74522784482ce5eba002c3f64 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Thu, 4 Feb 2021 05:16:13 -0500 Subject: [PATCH 3/8] Wooo API! --- cmd/main.go | 113 +++++------ graph/generated/generated.go | 353 ++++++++++++++++++++++++++++++----- graph/model/models_auth.go | 11 +- graph/model/models_db.go | 34 ++-- graph/model/models_gen.go | 17 +- graph/resolver.go | 8 +- graph/schema.graphqls | 22 ++- graph/schema.resolvers.go | 90 +++++++-- internal/api/auth.go | 320 ++++++++++--------------------- internal/api/media.go | 71 +++---- internal/api/middlewares.go | 133 ++++++------- internal/api/routes.go | 53 +++--- internal/auth/auth.go | 274 +++++++++++++-------------- internal/db/db.go | 164 ++++++++-------- internal/db/devices.go | 35 ++-- internal/db/errors.go | 2 +- internal/db/media_items.go | 20 +- internal/db/users.go | 52 +++--- 18 files changed, 977 insertions(+), 795 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index d5ff9ab..0d9c8e4 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,85 +1,86 @@ package main import ( - "os" - "os/signal" - "github.com/urfave/cli/v2" - log "github.com/sirupsen/logrus" + "os" + "os/signal" - "reichard.io/imagini/cmd/server" + log "github.com/sirupsen/logrus" + "github.com/urfave/cli/v2" - "reichard.io/imagini/plugin" - "github.com/99designs/gqlgen/api" + "reichard.io/imagini/cmd/server" + + "github.com/99designs/gqlgen/api" "github.com/99designs/gqlgen/codegen/config" + "reichard.io/imagini/plugin" ) type UTCFormatter struct { - log.Formatter + log.Formatter } func (u UTCFormatter) Format(e *log.Entry) ([]byte, error) { - e.Time = e.Time.UTC() - return u.Formatter.Format(e) + e.Time = e.Time.UTC() + return u.Formatter.Format(e) } func main() { - log.SetFormatter(UTCFormatter{&log.TextFormatter{FullTimestamp: true}}) + log.SetFormatter(UTCFormatter{&log.TextFormatter{FullTimestamp: true}}) - app := &cli.App{ - Name: "Imagini", - Usage: "A self hosted photo library.", - Commands: []*cli.Command{ - { - Name: "serve", - Aliases: []string{"s"}, - Usage: "Start Imagini web server.", - Action: cmdServer, - }, - { - Name: "generate", - Usage: "generate graphql schema", + app := &cli.App{ + Name: "Imagini", + Usage: "A self hosted photo library.", + Commands: []*cli.Command{ + { + Name: "serve", + Aliases: []string{"s"}, + Usage: "Start Imagini web server.", + Action: cmdServer, + }, + { + Name: "generate", + Usage: "generate graphql schema", Action: cmdGenerate, }, - }, - } - err := app.Run(os.Args) - if err != nil { - log.Fatal(err) - } + }, + } + err := app.Run(os.Args) + if err != nil { + log.Fatal(err) + } } func cmdServer(ctx *cli.Context) error { - log.Info("Starting Imagini Server") - server := server.NewServer() - server.StartServer() + log.Info("Starting Imagini Server") + server := server.NewServer() + server.StartServer() - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) - <-c + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + <-c - server.StopServer() - os.Exit(0) + server.StopServer() + os.Exit(0) - return nil + return nil } func cmdGenerate(ctx *cli.Context) error { - log.Info("Generating Imagini Models") - gqlgenConf, err := config.LoadConfigFromDefaultLocations() - if err != nil { - log.Panic("Failed to load config", err.Error()) - os.Exit(2) - } + log.Info("Generating Imagini Models") + gqlgenConf, err := config.LoadConfigFromDefaultLocations() + if err != nil { + log.Panic("Failed to load config", err.Error()) + os.Exit(2) + } - log.Info("Generating Schema...") - err = api.Generate(gqlgenConf, - api.AddPlugin(plugin.New()), - ) - log.Info("Schema Generation Done") - if err != nil { - log.Panic(err.Error()) - os.Exit(3) - } - os.Exit(0) - return nil + log.Info("Generating Schema...") + err = api.Generate(gqlgenConf, + api.AddPlugin(plugin.New()), + ) + log.Info("Schema Generation Done") + if err != nil { + log.Panic(err.Error()) + os.Exit(3) + } + os.Exit(0) + return nil } diff --git a/graph/generated/generated.go b/graph/generated/generated.go index bcf5285..dee8a1b 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -60,6 +60,7 @@ type ComplexityRoot struct { } AuthResponse struct { + Device func(childComplexity int) int Error func(childComplexity int) int Result func(childComplexity int) int } @@ -72,6 +73,7 @@ type ComplexityRoot struct { Type func(childComplexity int) int UpdatedAt func(childComplexity int) int User func(childComplexity int) int + UserID func(childComplexity int) int } DeviceResponse struct { @@ -92,6 +94,7 @@ type ComplexityRoot struct { Tags func(childComplexity int) int UpdatedAt func(childComplexity int) int User func(childComplexity int) int + UserID func(childComplexity int) int } MediaItemResponse struct { @@ -118,7 +121,7 @@ type ComplexityRoot struct { Albums func(childComplexity int, filter *model.AlbumFilter, count *int, page *int) int Device func(childComplexity int, id string) int Devices func(childComplexity int, filter *model.DeviceFilter, count *int, page *int) int - Login func(childComplexity int, user string, password string) int + Login func(childComplexity int, user string, password string, deviceID *string) int Logout func(childComplexity int) int Me func(childComplexity int) int MediaItem func(childComplexity int, id string) int @@ -168,8 +171,8 @@ type MutationResolver interface { CreateUser(ctx context.Context, input model.NewUser) (*model.User, error) } type QueryResolver interface { - Login(ctx context.Context, user string, password string) (model.AuthResult, error) - Logout(ctx context.Context) (model.AuthResult, error) + Login(ctx context.Context, user string, password string, deviceID *string) (*model.AuthResponse, error) + Logout(ctx context.Context) (*model.AuthResponse, error) MediaItem(ctx context.Context, id string) (*model.MediaItem, error) Device(ctx context.Context, id string) (*model.Device, error) Album(ctx context.Context, id string) (*model.Album, error) @@ -240,6 +243,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.AlbumResponse.PageInfo(childComplexity), true + case "AuthResponse.Device": + if e.complexity.AuthResponse.Device == nil { + break + } + + return e.complexity.AuthResponse.Device(childComplexity), true + case "AuthResponse.Error": if e.complexity.AuthResponse.Error == nil { break @@ -303,6 +313,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Device.User(childComplexity), true + case "Device.userID": + if e.complexity.Device.UserID == nil { + break + } + + return e.complexity.Device.UserID(childComplexity), true + case "DeviceResponse.data": if e.complexity.DeviceResponse.Data == nil { break @@ -401,6 +418,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.MediaItem.User(childComplexity), true + case "MediaItem.userID": + if e.complexity.MediaItem.UserID == nil { + break + } + + return e.complexity.MediaItem.UserID(childComplexity), true + case "MediaItemResponse.data": if e.complexity.MediaItemResponse.Data == nil { break @@ -554,7 +578,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Login(childComplexity, args["user"].(string), args["password"].(string)), true + return e.complexity.Query.Login(childComplexity, args["user"].(string), args["password"].(string), args["deviceID"].(*string)), true case "Query.logout": if e.complexity.Query.Logout == nil { @@ -876,6 +900,7 @@ enum AuthResult { type AuthResponse { Result: AuthResult! + Device: Device Error: String } @@ -972,17 +997,18 @@ input AuthTypeFilter { # ------------------------------------------------------------ type Device { - id: ID @meta(gorm: "primarykey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time name: String! @meta(gorm: "not null") type: DeviceType! @meta(gorm: "default:Unknown;not null") - user: User @meta(gorm: "ForeignKey:ID;not null") + userID: ID! @meta(gorm: "not null") + user: User! @meta(gorm: "foreignKey:ID;references:UserID;not null") refreshKey: String } type User { - id: ID @meta(gorm: "primarykey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time email: String! @meta(gorm: "not null;unique") @@ -995,7 +1021,7 @@ type User { } type MediaItem { - id: ID @meta(gorm: "primarykey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time exifDate: Time @@ -1006,18 +1032,19 @@ type MediaItem { origName: String! @meta(gorm: "not null") tags: [Tag] @meta(gorm: "many2many:media_tags") albums: [Album] @meta(gorm: "many2many:media_albums") - user: User @meta(gorm: "ForeignKey:ID;not null") + userID: ID! @meta(gorm: "not null") + user: User! @meta(gorm: "foreignKey:ID;references:UserID;not null") } type Tag { - id: ID @meta(gorm: "primarykey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time name: String! @meta(gorm: "unique;not null") } type Album { - id: ID @meta(gorm: "primarykey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time name: String! @meta(gorm: "unique;not null") @@ -1165,8 +1192,9 @@ type Query { login( user: String! password: String! - ): AuthResult! - logout: AuthResult! @hasMinRole(role: User) + deviceID: ID + ): AuthResponse! + logout: AuthResponse! @hasMinRole(role: User) # Single Item mediaItem(id: ID!): MediaItem! @hasMinRole(role: User) @@ -1456,6 +1484,15 @@ func (ec *executionContext) field_Query_login_args(ctx context.Context, rawArgs } } args["password"] = arg1 + var arg2 *string + if tmp, ok := rawArgs["deviceID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("deviceID")) + arg2, err = ec.unmarshalOID2ᚖstring(ctx, tmp) + if err != nil { + return nil, err + } + } + args["deviceID"] = arg2 return args, nil } @@ -1663,7 +1700,7 @@ func (ec *executionContext) _Album_id(ctx context.Context, field graphql.Collect return obj.ID, nil } directive1 := func(ctx context.Context) (interface{}, error) { - gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primarykey;not null") + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primaryKey;not null") if err != nil { return nil, err } @@ -1680,21 +1717,24 @@ func (ec *executionContext) _Album_id(ctx context.Context, field graphql.Collect if tmp == nil { return nil, nil } - if data, ok := tmp.(*string); ok { + if data, ok := tmp.(string); ok { return data, nil } - return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*string) + res := resTmp.(string) fc.Result = res - return ec.marshalOID2ᚖstring(ctx, field.Selections, res) + return ec.marshalNID2string(ctx, field.Selections, res) } func (ec *executionContext) _Album_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.Album) (ret graphql.Marshaler) { @@ -1922,6 +1962,38 @@ func (ec *executionContext) _AuthResponse_Result(ctx context.Context, field grap return ec.marshalNAuthResult2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResult(ctx, field.Selections, res) } +func (ec *executionContext) _AuthResponse_Device(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "AuthResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Device, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.Device) + fc.Result = res + return ec.marshalODevice2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx, field.Selections, res) +} + func (ec *executionContext) _AuthResponse_Error(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -1976,7 +2048,7 @@ func (ec *executionContext) _Device_id(ctx context.Context, field graphql.Collec return obj.ID, nil } directive1 := func(ctx context.Context) (interface{}, error) { - gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primarykey;not null") + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primaryKey;not null") if err != nil { return nil, err } @@ -1993,21 +2065,24 @@ func (ec *executionContext) _Device_id(ctx context.Context, field graphql.Collec if tmp == nil { return nil, nil } - if data, ok := tmp.(*string); ok { + if data, ok := tmp.(string); ok { return data, nil } - return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*string) + res := resTmp.(string) fc.Result = res - return ec.marshalOID2ᚖstring(ctx, field.Selections, res) + return ec.marshalNID2string(ctx, field.Selections, res) } func (ec *executionContext) _Device_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { @@ -2192,6 +2267,65 @@ func (ec *executionContext) _Device_type(ctx context.Context, field graphql.Coll return ec.marshalNDeviceType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx, field.Selections, res) } +func (ec *executionContext) _Device_userID(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Device", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UserID, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + func (ec *executionContext) _Device_user(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -2214,7 +2348,7 @@ func (ec *executionContext) _Device_user(ctx context.Context, field graphql.Coll return obj.User, nil } directive1 := func(ctx context.Context) (interface{}, error) { - gorm, err := ec.unmarshalOString2ᚖstring(ctx, "ForeignKey:ID;not null") + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "foreignKey:ID;references:UserID;not null") if err != nil { return nil, err } @@ -2241,11 +2375,14 @@ func (ec *executionContext) _Device_user(ctx context.Context, field graphql.Coll return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } res := resTmp.(*model.User) fc.Result = res - return ec.marshalOUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) + return ec.marshalNUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) } func (ec *executionContext) _Device_refreshKey(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { @@ -2369,7 +2506,7 @@ func (ec *executionContext) _MediaItem_id(ctx context.Context, field graphql.Col return obj.ID, nil } directive1 := func(ctx context.Context) (interface{}, error) { - gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primarykey;not null") + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primaryKey;not null") if err != nil { return nil, err } @@ -2386,21 +2523,24 @@ func (ec *executionContext) _MediaItem_id(ctx context.Context, field graphql.Col if tmp == nil { return nil, nil } - if data, ok := tmp.(*string); ok { + if data, ok := tmp.(string); ok { return data, nil } - return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*string) + res := resTmp.(string) fc.Result = res - return ec.marshalOID2ᚖstring(ctx, field.Selections, res) + return ec.marshalNID2string(ctx, field.Selections, res) } func (ec *executionContext) _MediaItem_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { @@ -2852,6 +2992,65 @@ func (ec *executionContext) _MediaItem_albums(ctx context.Context, field graphql return ec.marshalOAlbum2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbum(ctx, field.Selections, res) } +func (ec *executionContext) _MediaItem_userID(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MediaItem", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UserID, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + func (ec *executionContext) _MediaItem_user(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -2874,7 +3073,7 @@ func (ec *executionContext) _MediaItem_user(ctx context.Context, field graphql.C return obj.User, nil } directive1 := func(ctx context.Context) (interface{}, error) { - gorm, err := ec.unmarshalOString2ᚖstring(ctx, "ForeignKey:ID;not null") + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "foreignKey:ID;references:UserID;not null") if err != nil { return nil, err } @@ -2901,11 +3100,14 @@ func (ec *executionContext) _MediaItem_user(ctx context.Context, field graphql.C return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } res := resTmp.(*model.User) fc.Result = res - return ec.marshalOUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) + return ec.marshalNUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) } func (ec *executionContext) _MediaItemResponse_data(ctx context.Context, field graphql.CollectedField, obj *model.MediaItemResponse) (ret graphql.Marshaler) { @@ -3435,7 +3637,7 @@ func (ec *executionContext) _Query_login(ctx context.Context, field graphql.Coll fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Login(rctx, args["user"].(string), args["password"].(string)) + return ec.resolvers.Query().Login(rctx, args["user"].(string), args["password"].(string), args["deviceID"].(*string)) }) if err != nil { ec.Error(ctx, err) @@ -3447,9 +3649,9 @@ func (ec *executionContext) _Query_login(ctx context.Context, field graphql.Coll } return graphql.Null } - res := resTmp.(model.AuthResult) + res := resTmp.(*model.AuthResponse) fc.Result = res - return ec.marshalNAuthResult2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResult(ctx, field.Selections, res) + return ec.marshalNAuthResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResponse(ctx, field.Selections, res) } func (ec *executionContext) _Query_logout(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { @@ -3491,10 +3693,10 @@ func (ec *executionContext) _Query_logout(ctx context.Context, field graphql.Col if tmp == nil { return nil, nil } - if data, ok := tmp.(model.AuthResult); ok { + if data, ok := tmp.(*model.AuthResponse); ok { return data, nil } - return nil, fmt.Errorf(`unexpected type %T from directive, should be reichard.io/imagini/graph/model.AuthResult`, tmp) + return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.AuthResponse`, tmp) }) if err != nil { ec.Error(ctx, err) @@ -3506,9 +3708,9 @@ func (ec *executionContext) _Query_logout(ctx context.Context, field graphql.Col } return graphql.Null } - res := resTmp.(model.AuthResult) + res := resTmp.(*model.AuthResponse) fc.Result = res - return ec.marshalNAuthResult2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResult(ctx, field.Selections, res) + return ec.marshalNAuthResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResponse(ctx, field.Selections, res) } func (ec *executionContext) _Query_mediaItem(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { @@ -4323,7 +4525,7 @@ func (ec *executionContext) _Tag_id(ctx context.Context, field graphql.Collected return obj.ID, nil } directive1 := func(ctx context.Context) (interface{}, error) { - gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primarykey;not null") + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primaryKey;not null") if err != nil { return nil, err } @@ -4340,21 +4542,24 @@ func (ec *executionContext) _Tag_id(ctx context.Context, field graphql.Collected if tmp == nil { return nil, nil } - if data, ok := tmp.(*string); ok { + if data, ok := tmp.(string); ok { return data, nil } - return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*string) + res := resTmp.(string) fc.Result = res - return ec.marshalOID2ᚖstring(ctx, field.Selections, res) + return ec.marshalNID2string(ctx, field.Selections, res) } func (ec *executionContext) _Tag_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.Tag) (ret graphql.Marshaler) { @@ -4569,7 +4774,7 @@ func (ec *executionContext) _User_id(ctx context.Context, field graphql.Collecte return obj.ID, nil } directive1 := func(ctx context.Context) (interface{}, error) { - gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primarykey;not null") + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "primaryKey;not null") if err != nil { return nil, err } @@ -4586,21 +4791,24 @@ func (ec *executionContext) _User_id(ctx context.Context, field graphql.Collecte if tmp == nil { return nil, nil } - if data, ok := tmp.(*string); ok { + if data, ok := tmp.(string); ok { return data, nil } - return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*string) + res := resTmp.(string) fc.Result = res - return ec.marshalOID2ᚖstring(ctx, field.Selections, res) + return ec.marshalNID2string(ctx, field.Selections, res) } func (ec *executionContext) _User_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { @@ -7282,6 +7490,9 @@ func (ec *executionContext) _Album(ctx context.Context, sel ast.SelectionSet, ob out.Values[i] = graphql.MarshalString("Album") case "id": out.Values[i] = ec._Album_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "createdAt": out.Values[i] = ec._Album_createdAt(ctx, field, obj) case "updatedAt": @@ -7347,6 +7558,8 @@ func (ec *executionContext) _AuthResponse(ctx context.Context, sel ast.Selection if out.Values[i] == graphql.Null { invalids++ } + case "Device": + out.Values[i] = ec._AuthResponse_Device(ctx, field, obj) case "Error": out.Values[i] = ec._AuthResponse_Error(ctx, field, obj) default: @@ -7373,6 +7586,9 @@ func (ec *executionContext) _Device(ctx context.Context, sel ast.SelectionSet, o out.Values[i] = graphql.MarshalString("Device") case "id": out.Values[i] = ec._Device_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "createdAt": out.Values[i] = ec._Device_createdAt(ctx, field, obj) case "updatedAt": @@ -7387,8 +7603,16 @@ func (ec *executionContext) _Device(ctx context.Context, sel ast.SelectionSet, o if out.Values[i] == graphql.Null { invalids++ } + case "userID": + out.Values[i] = ec._Device_userID(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "user": out.Values[i] = ec._Device_user(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "refreshKey": out.Values[i] = ec._Device_refreshKey(ctx, field, obj) default: @@ -7444,6 +7668,9 @@ func (ec *executionContext) _MediaItem(ctx context.Context, sel ast.SelectionSet out.Values[i] = graphql.MarshalString("MediaItem") case "id": out.Values[i] = ec._MediaItem_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "createdAt": out.Values[i] = ec._MediaItem_createdAt(ctx, field, obj) case "updatedAt": @@ -7473,8 +7700,16 @@ func (ec *executionContext) _MediaItem(ctx context.Context, sel ast.SelectionSet out.Values[i] = ec._MediaItem_tags(ctx, field, obj) case "albums": out.Values[i] = ec._MediaItem_albums(ctx, field, obj) + case "userID": + out.Values[i] = ec._MediaItem_userID(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "user": out.Values[i] = ec._MediaItem_user(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -7828,6 +8063,9 @@ func (ec *executionContext) _Tag(ctx context.Context, sel ast.SelectionSet, obj out.Values[i] = graphql.MarshalString("Tag") case "id": out.Values[i] = ec._Tag_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "createdAt": out.Values[i] = ec._Tag_createdAt(ctx, field, obj) case "updatedAt": @@ -7890,6 +8128,9 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj out.Values[i] = graphql.MarshalString("User") case "id": out.Values[i] = ec._User_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "createdAt": out.Values[i] = ec._User_createdAt(ctx, field, obj) case "updatedAt": @@ -8233,6 +8474,20 @@ func (ec *executionContext) marshalNAlbumResponse2ᚖreichardᚗioᚋimaginiᚋg return ec._AlbumResponse(ctx, sel, v) } +func (ec *executionContext) marshalNAuthResponse2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResponse(ctx context.Context, sel ast.SelectionSet, v model.AuthResponse) graphql.Marshaler { + return ec._AuthResponse(ctx, sel, &v) +} + +func (ec *executionContext) marshalNAuthResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResponse(ctx context.Context, sel ast.SelectionSet, v *model.AuthResponse) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._AuthResponse(ctx, sel, v) +} + func (ec *executionContext) unmarshalNAuthResult2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResult(ctx context.Context, v interface{}) (model.AuthResult, error) { var res model.AuthResult err := res.UnmarshalGQL(v) diff --git a/graph/model/models_auth.go b/graph/model/models_auth.go index 5c77bd9..3a40b57 100644 --- a/graph/model/models_auth.go +++ b/graph/model/models_auth.go @@ -1,12 +1,13 @@ package model import ( - "net/http" + "net/http" + + "github.com/lestrrat-go/jwx/jwt" ) type AuthContext struct { - AccessToken string - RefreshToken string - AuthResponse *http.ResponseWriter - AuthRequest *http.Request + AccessToken *jwt.Token + AuthResponse *http.ResponseWriter + AuthRequest *http.Request } diff --git a/graph/model/models_db.go b/graph/model/models_db.go index cd46621..4835610 100644 --- a/graph/model/models_db.go +++ b/graph/model/models_db.go @@ -1,36 +1,36 @@ package model import ( - "gorm.io/gorm" - "github.com/google/uuid" + "github.com/google/uuid" + "gorm.io/gorm" ) func (u *User) BeforeCreate(tx *gorm.DB) (err error) { - newID := uuid.New().String() - u.ID = &newID - return + newID := uuid.New().String() + u.ID = newID + return } func (a *Album) BeforeCreate(tx *gorm.DB) (err error) { - newID := uuid.New().String() - a.ID = &newID - return + newID := uuid.New().String() + a.ID = newID + return } func (m *MediaItem) BeforeCreate(tx *gorm.DB) (err error) { - newID := uuid.New().String() - m.ID = &newID - return + newID := uuid.New().String() + m.ID = newID + return } func (t *Tag) BeforeCreate(tx *gorm.DB) (err error) { - newID := uuid.New().String() - t.ID = &newID - return + newID := uuid.New().String() + t.ID = newID + return } func (d *Device) BeforeCreate(tx *gorm.DB) (err error) { - newID := uuid.New().String() - d.ID = &newID - return + newID := uuid.New().String() + d.ID = newID + return } diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index ed064a7..50787f3 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -12,7 +12,7 @@ import ( ) type Album struct { - ID *string `json:"id" gorm:"primarykey;not null"` + ID string `json:"id" gorm:"primaryKey;not null"` CreatedAt *time.Time `json:"createdAt" ` UpdatedAt *time.Time `json:"updatedAt" ` Name string `json:"name" gorm:"unique;not null"` @@ -34,6 +34,7 @@ type AlbumResponse struct { type AuthResponse struct { Result AuthResult `json:"Result" ` + Device *Device `json:"Device" ` Error *string `json:"Error" ` } @@ -50,12 +51,13 @@ type BooleanFilter struct { } type Device struct { - ID *string `json:"id" gorm:"primarykey;not null"` + ID string `json:"id" gorm:"primaryKey;not null"` CreatedAt *time.Time `json:"createdAt" ` UpdatedAt *time.Time `json:"updatedAt" ` Name string `json:"name" gorm:"not null"` Type DeviceType `json:"type" gorm:"default:Unknown;not null"` - User *User `json:"user" gorm:"ForeignKey:ID;not null"` + UserID string `json:"userID" gorm:"not null"` + User *User `json:"user" gorm:"foreignKey:ID;references:UserID;not null"` RefreshKey *string `json:"refreshKey" ` } @@ -111,7 +113,7 @@ type IntFilter struct { } type MediaItem struct { - ID *string `json:"id" gorm:"primarykey;not null"` + ID string `json:"id" gorm:"primaryKey;not null"` CreatedAt *time.Time `json:"createdAt" ` UpdatedAt *time.Time `json:"updatedAt" ` ExifDate *time.Time `json:"exifDate" ` @@ -122,7 +124,8 @@ type MediaItem struct { OrigName string `json:"origName" gorm:"not null"` Tags []*Tag `json:"tags" gorm:"many2many:media_tags"` Albums []*Album `json:"albums" gorm:"many2many:media_albums"` - User *User `json:"user" gorm:"ForeignKey:ID;not null"` + UserID string `json:"userID" gorm:"not null"` + User *User `json:"user" gorm:"foreignKey:ID;references:UserID;not null"` } type MediaItemFilter struct { @@ -206,7 +209,7 @@ type StringFilter struct { } type Tag struct { - ID *string `json:"id" gorm:"primarykey;not null"` + ID string `json:"id" gorm:"primaryKey;not null"` CreatedAt *time.Time `json:"createdAt" ` UpdatedAt *time.Time `json:"updatedAt" ` Name string `json:"name" gorm:"unique;not null"` @@ -236,7 +239,7 @@ type TimeFilter struct { } type User struct { - ID *string `json:"id" gorm:"primarykey;not null"` + ID string `json:"id" gorm:"primaryKey;not null"` CreatedAt *time.Time `json:"createdAt" ` UpdatedAt *time.Time `json:"updatedAt" ` Email string `json:"email" gorm:"not null;unique"` diff --git a/graph/resolver.go b/graph/resolver.go index e7fdab5..4249b75 100644 --- a/graph/resolver.go +++ b/graph/resolver.go @@ -1,13 +1,15 @@ package graph import ( - "reichard.io/imagini/internal/db" + "reichard.io/imagini/internal/auth" + "reichard.io/imagini/internal/db" ) // This file will not be regenerated automatically. // // It serves as dependency injection for your app, add any dependencies you require here. -type Resolver struct{ - DB *db.DBManager +type Resolver struct { + Auth *auth.AuthManager + DB *db.DBManager } diff --git a/graph/schema.graphqls b/graph/schema.graphqls index 3d90eb0..92e8493 100644 --- a/graph/schema.graphqls +++ b/graph/schema.graphqls @@ -42,6 +42,7 @@ enum AuthResult { type AuthResponse { Result: AuthResult! + Device: Device Error: String } @@ -138,17 +139,18 @@ input AuthTypeFilter { # ------------------------------------------------------------ type Device { - id: ID @meta(gorm: "primarykey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time name: String! @meta(gorm: "not null") type: DeviceType! @meta(gorm: "default:Unknown;not null") - user: User @meta(gorm: "ForeignKey:ID;not null") + userID: ID! @meta(gorm: "not null") + user: User! @meta(gorm: "foreignKey:ID;references:UserID;not null") refreshKey: String } type User { - id: ID @meta(gorm: "primarykey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time email: String! @meta(gorm: "not null;unique") @@ -161,7 +163,7 @@ type User { } type MediaItem { - id: ID @meta(gorm: "primarykey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time exifDate: Time @@ -172,18 +174,19 @@ type MediaItem { origName: String! @meta(gorm: "not null") tags: [Tag] @meta(gorm: "many2many:media_tags") albums: [Album] @meta(gorm: "many2many:media_albums") - user: User @meta(gorm: "ForeignKey:ID;not null") + userID: ID! @meta(gorm: "not null") + user: User! @meta(gorm: "foreignKey:ID;references:UserID;not null") } type Tag { - id: ID @meta(gorm: "primarykey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time name: String! @meta(gorm: "unique;not null") } type Album { - id: ID @meta(gorm: "primarykey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time name: String! @meta(gorm: "unique;not null") @@ -331,8 +334,9 @@ type Query { login( user: String! password: String! - ): AuthResult! - logout: AuthResult! @hasMinRole(role: User) + deviceID: ID + ): AuthResponse! + logout: AuthResponse! @hasMinRole(role: User) # Single Item mediaItem(id: ID!): MediaItem! @hasMinRole(role: User) diff --git a/graph/schema.resolvers.go b/graph/schema.resolvers.go index 3f72070..50f185e 100644 --- a/graph/schema.resolvers.go +++ b/graph/schema.resolvers.go @@ -4,10 +4,12 @@ package graph // will be copied through when generating and any unknown code will be moved to the end. import ( - "net/http" "context" "fmt" + "net/http" + "strings" + "github.com/google/uuid" "reichard.io/imagini/graph/generated" "reichard.io/imagini/graph/model" ) @@ -41,26 +43,66 @@ func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser) err := r.DB.CreateUser(user) if err != nil { - panic(fmt.Errorf("DB Error")) + return nil, err } return user, nil } -func (r *queryResolver) Login(ctx context.Context, user string, password string) (model.AuthResult, error) { - - // Set Cookie From Context +func (r *queryResolver) Login(ctx context.Context, user string, password string, deviceID *string) (*model.AuthResponse, error) { + // Set Cookie From Context authContext := ctx.Value("auth").(*model.AuthContext) - resp := *authContext.AuthResponse - testCookie := http.Cookie{Name: "TestCookie", Value: "Test123", Path: "/", HttpOnly: true} - http.SetCookie(resp, &testCookie) + resp := authContext.AuthResponse + req := authContext.AuthRequest - return model.AuthResultSuccess, nil + // Do Login + foundUser, success := r.Auth.AuthenticateUser(user, password) + if !success { + return &model.AuthResponse{Result: model.AuthResultFailure}, nil + } + + // Upsert Device + foundDevice := model.Device{} + if deviceID != nil { + parsedDeviceID, err := uuid.Parse(*deviceID) + if err != nil { + return &model.AuthResponse{Result: model.AuthResultFailure}, nil + } + foundDevice.ID = parsedDeviceID.String() + count, err := r.DB.Device(&foundDevice) + if count != 1 || err != nil { + return &model.AuthResponse{Result: model.AuthResultFailure}, nil + } + } else { + foundDevice.Type = deriveDeviceType(req) + err := r.DB.CreateDevice(&foundDevice) + if err != nil { + return &model.AuthResponse{Result: model.AuthResultFailure}, nil + } + } + + // Create Tokens + accessToken, err := r.Auth.CreateJWTAccessToken(foundUser, foundDevice) + if err != nil { + return &model.AuthResponse{Result: model.AuthResultFailure}, nil + } + refreshToken, err := r.Auth.CreateJWTRefreshToken(foundUser, foundDevice) + if err != nil { + return &model.AuthResponse{Result: model.AuthResultFailure}, nil + } + + // Set appropriate cookies + accessCookie := http.Cookie{Name: "AccessToken", Value: accessToken, Path: "/", HttpOnly: true} + refreshCookie := http.Cookie{Name: "RefreshToken", Value: refreshToken, Path: "/", HttpOnly: true} + http.SetCookie(*resp, &accessCookie) + http.SetCookie(*resp, &refreshCookie) + + return &model.AuthResponse{Result: model.AuthResultSuccess, Device: &foundDevice}, nil } -func (r *queryResolver) Logout(ctx context.Context) (model.AuthResult, error) { +func (r *queryResolver) Logout(ctx context.Context) (*model.AuthResponse, error) { // panic(fmt.Errorf("not implemented")) - return model.AuthResultSuccess, nil + return &model.AuthResponse{Result: model.AuthResultSuccess}, nil } func (r *queryResolver) MediaItem(ctx context.Context, id string) (*model.MediaItem, error) { @@ -126,3 +168,29 @@ func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } 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 deriveDeviceType(r *http.Request) model.DeviceType { + userAgent := strings.ToLower(r.Header.Get("User-Agent")) + if strings.Contains(userAgent, "ios-imagini") { + return model.DeviceTypeIOs + } else if strings.Contains(userAgent, "android-imagini") { + return model.DeviceTypeAndroid + } else if strings.Contains(userAgent, "chrome") { + return model.DeviceTypeChrome + } else if strings.Contains(userAgent, "firefox") { + return model.DeviceTypeFirefox + } else if strings.Contains(userAgent, "msie") { + return model.DeviceTypeInternetExplorer + } else if strings.Contains(userAgent, "edge") { + return model.DeviceTypeEdge + } else if strings.Contains(userAgent, "safari") { + return model.DeviceTypeSafari + } + return model.DeviceTypeUnknown +} diff --git a/internal/api/auth.go b/internal/api/auth.go index 81ef498..197bd17 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -1,248 +1,124 @@ package api import ( - "fmt" - "time" - "strings" - "context" - "net/http" - "encoding/json" + "context" + "errors" + "fmt" + "net/http" - "github.com/google/uuid" - log "github.com/sirupsen/logrus" - "github.com/lestrrat-go/jwx/jwt" "github.com/99designs/gqlgen/graphql" + "github.com/google/uuid" + "github.com/lestrrat-go/jwx/jwt" "reichard.io/imagini/graph/model" ) -func (api *API) loginHandler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Access-Control-Allow-Origin", "*") - if r.Method != http.MethodPost { - errorJSON(w, "Method is not supported.", http.StatusMethodNotAllowed) - return - } +func (api *API) refreshTokens(refreshToken jwt.Token) (string, string, error) { + // Acquire User & Device + did, ok := refreshToken.Get("did") + if !ok { + return "", "", errors.New("Missing DID") + } + uid, ok := refreshToken.Get(jwt.SubjectKey) + if !ok { + return "", "", errors.New("Missing UID") + } + deviceUUID, err := uuid.Parse(fmt.Sprintf("%v", did)) + if err != nil { + return "", "", errors.New("Invalid DID") + } + userUUID, err := uuid.Parse(fmt.Sprintf("%v", uid)) + if err != nil { + return "", "", errors.New("Invalid UID") + } - // Decode into Struct - var creds APICredentials - err := json.NewDecoder(r.Body).Decode(&creds) - if err != nil { - errorJSON(w, "Invalid parameters.", http.StatusBadRequest) - return - } + // Device & User Skeleton + user := model.User{ID: userUUID.String()} + device := model.Device{ID: deviceUUID.String()} - // Validate - if creds.User == "" || creds.Password == "" { - errorJSON(w, "Invalid parameters.", http.StatusBadRequest) - return - } + // Find User + _, err = api.DB.User(&user) + if err != nil { + return "", "", err + } - // Do login - resp, user := api.Auth.AuthenticateUser(creds.User, creds.Password) - if !resp { - errorJSON(w, "Invalid credentials.", http.StatusUnauthorized) - return - } + // Update Access Token + accessTokenCookie, err := api.Auth.CreateJWTAccessToken(user, device) + if err != nil { + return "", "", err + } - // Upsert device - device, err := api.upsertRequestedDevice(user, r) - if err != nil { - log.Error("[api] loginHandler - Failed to upsert device: ", err) - errorJSON(w, "DB error. Unable to proceed.", http.StatusUnauthorized) - return - } - - // Create Tokens - accessToken, err := api.Auth.CreateJWTAccessToken(user, device) - refreshToken, err := api.Auth.CreateJWTRefreshToken(user, device) - - // Set appropriate cookies - accessCookie := http.Cookie{Name: "AccessToken", Value: accessToken, Path: "/", HttpOnly: true} - refreshCookie := http.Cookie{Name: "RefreshToken", Value: refreshToken, Path: "/", HttpOnly: true} - http.SetCookie(w, &accessCookie) - http.SetCookie(w, &refreshCookie) - - // Response success - successJSON(w, "Login success.", http.StatusOK) + return accessTokenCookie, "", err } -func (api *API) logoutHandler(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - http.Error(w, "Method is not supported.", http.StatusMethodNotAllowed) - return - } +func (api *API) validateTokens(w *http.ResponseWriter, r *http.Request) (jwt.Token, error) { + // Validate Access Token + accessCookie, _ := r.Cookie("AccessToken") + if accessCookie != nil { + accessToken, err := api.Auth.ValidateJWTAccessToken(accessCookie.Value) + if err == nil { + return accessToken, nil + } + } - // TODO: Reset Refresh Key + // Validate Refresh Cookie Exists + refreshCookie, _ := r.Cookie("RefreshToken") + if refreshCookie == nil { + return nil, errors.New("Tokens Invalid") + } - // Clear Cookies - http.SetCookie(w, &http.Cookie{Name: "AccessToken", Expires: time.Unix(0, 0)}) - http.SetCookie(w, &http.Cookie{Name: "RefreshToken", Expires: time.Unix(0, 0)}) + // Validate Refresh Token + refreshToken, err := api.Auth.ValidateJWTRefreshToken(refreshCookie.Value) + if err != nil { + return nil, errors.New("Tokens Invalid") + } - successJSON(w, "Logout success.", http.StatusOK) + // Refresh Access Token & Generate New Refresh Token + newAccessCookie, newRefreshCookie, err := api.refreshTokens(refreshToken) + if err != nil { + return nil, err + } + + // TODO: Actually Refresh Refresh Token + newRefreshCookie = refreshCookie.Value + + // Update Access & Refresh Cookies + http.SetCookie(*w, &http.Cookie{ + Name: "AccessToken", + Value: newAccessCookie, + }) + http.SetCookie(*w, &http.Cookie{ + Name: "RefreshToken", + Value: newRefreshCookie, + }) + + return jwt.ParseBytes([]byte(newAccessCookie)) } -/** - * This will find or create the requested device based on ID and User. - **/ -func (api *API) upsertRequestedDevice(user model.User, r *http.Request) (model.Device, error) { - requestedDevice := deriveRequestedDevice(r) - requestedDevice.Type = deriveDeviceType(r) - requestedDevice.User.ID = user.ID +func (api *API) hasMinRoleDirective(ctx context.Context, obj interface{}, next graphql.Resolver, role model.Role) (res interface{}, err error) { + authContext := ctx.Value("auth").(*model.AuthContext) + accessToken, err := api.validateTokens(authContext.AuthResponse, authContext.AuthRequest) + if err != nil { + return nil, errors.New("Access Denied") + } + authContext.AccessToken = &accessToken - if *requestedDevice.ID == "" { - err := api.DB.CreateDevice(&requestedDevice) - createdDevice, err := api.DB.Device(&requestedDevice) - return createdDevice, err - } + userRole, ok := accessToken.Get("role") + if !ok { + return nil, errors.New("Access Denied") + } - foundDevice, err := api.DB.Device(&model.Device{ - ID: requestedDevice.ID, - User: &user, - }) + if userRole == model.RoleAdmin.String() { + return next(ctx) + } - return foundDevice, err + if userRole == role.String() { + return next(ctx) + } + + return nil, errors.New("Role Not Authenticated") } -func deriveDeviceType(r *http.Request) model.DeviceType { - userAgent := strings.ToLower(r.Header.Get("User-Agent")) - if strings.HasPrefix(userAgent, "ios-imagini"){ - return model.DeviceTypeIOs - } else if strings.HasPrefix(userAgent, "android-imagini"){ - return model.DeviceTypeAndroid - } else if strings.HasPrefix(userAgent, "chrome"){ - return model.DeviceTypeChrome - } else if strings.HasPrefix(userAgent, "firefox"){ - return model.DeviceTypeFirefox - } else if strings.HasPrefix(userAgent, "msie"){ - return model.DeviceTypeInternetExplorer - } else if strings.HasPrefix(userAgent, "edge"){ - return model.DeviceTypeEdge - } else if strings.HasPrefix(userAgent, "safari"){ - return model.DeviceTypeSafari - } - return model.DeviceTypeUnknown -} - -func deriveRequestedDevice(r *http.Request) model.Device { - deviceSkeleton := model.Device{} - authHeader := r.Header.Get("X-Imagini-Authorization") - splitAuthInfo := strings.Split(authHeader, ",") - - // For each Key - Value pair - for i := range splitAuthInfo { - - // Split Key - Value - item := strings.TrimSpace(splitAuthInfo[i]) - splitItem := strings.SplitN(item, "=", 2) - if len(splitItem) != 2 { - continue - } - - // Derive Key - key := strings.ToLower(strings.TrimSpace(splitItem[0])) - if key != "deviceid" && key != "devicename" { - continue - } - - // Derive Value - val := trimQuotes(strings.TrimSpace(splitItem[1])) - if key == "deviceid" { - parsedDeviceUUID, err := uuid.Parse(val) - if err != nil { - log.Warn("[auth] deriveRequestedDevice - Unable to parse requested DeviceUUID: ", val) - continue - } - stringDeviceUUID := parsedDeviceUUID.String() - deviceSkeleton.ID = &stringDeviceUUID - } else if key == "devicename" { - deviceSkeleton.Name = val - } - } - - // If name not set, set to type - if deviceSkeleton.Name == "" { - deviceSkeleton.Name = deviceSkeleton.Type.String() - } - - return deviceSkeleton -} - -func (api *API) refreshAccessToken(w http.ResponseWriter, r *http.Request) (jwt.Token, error) { - refreshCookie, err := r.Cookie("RefreshToken") - if err != nil { - log.Warn("[middleware] RefreshToken not found") - return nil, err - } - - // Validate Refresh Token - refreshToken, err := api.Auth.ValidateJWTRefreshToken(refreshCookie.Value) - if err != nil { - http.SetCookie(w, &http.Cookie{Name: "AccessToken", Expires: time.Unix(0, 0)}) - http.SetCookie(w, &http.Cookie{Name: "RefreshToken", Expires: time.Unix(0, 0)}) - return nil, err - } - - // Acquire User & Device (Trusted) - did, ok := refreshToken.Get("did") - if !ok { - return nil, err - } - uid, ok := refreshToken.Get(jwt.SubjectKey) - if !ok { - return nil, err - } - deviceUUID, err := uuid.Parse(fmt.Sprintf("%v", did)) - if err != nil { - return nil, err - } - userUUID, err := uuid.Parse(fmt.Sprintf("%v", uid)) - if err != nil { - return nil, err - } - - stringUserUUID := userUUID.String() - stringDeviceUUID := deviceUUID.String() - - // Device & User Skeleton - user := model.User{ID: &stringUserUUID} - device := model.Device{ID: &stringDeviceUUID} - - // Update token - accessTokenString, err := api.Auth.CreateJWTAccessToken(user, device) - if err != nil { - return nil, err - } - accessCookie := http.Cookie{Name: "AccessToken", Value: accessTokenString} - http.SetCookie(w, &accessCookie) - - // TODO: Update Refresh Key & Token - - // Convert to jwt.Token - accessTokenBytes := []byte(accessTokenString) - accessToken, err := jwt.ParseBytes(accessTokenBytes) - - return accessToken, err -} - -func trimQuotes(s string) string { - if len(s) >= 2 { - if s[0] == '"' && s[len(s)-1] == '"' { - return s[1 : len(s)-1] - } - } - return s -} - -func hasMinRoleDirective(ctx context.Context, obj interface{}, next graphql.Resolver, role model.Role) (res interface{}, err error) { - // if !getCurrentUser(ctx).HasRole(role) { - // // block calling the next resolver - // return nil, fmt.Errorf("Access denied") - // } - - // or let it pass through - return next(ctx) -} - -func metaDirective(ctx context.Context, obj interface{}, next graphql.Resolver, gorm *string) (res interface{}, err error){ - return next(ctx) +func (api *API) metaDirective(ctx context.Context, obj interface{}, next graphql.Resolver, gorm *string) (res interface{}, err error) { + return next(ctx) } diff --git a/internal/api/media.go b/internal/api/media.go index ed714e2..d648e25 100644 --- a/internal/api/media.go +++ b/internal/api/media.go @@ -1,50 +1,53 @@ package api import ( - "os" - "path" "net/http" + "os" + "path" + + "reichard.io/imagini/graph/model" ) // Responsible for serving up static images / videos func (api *API) mediaHandler(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodGet { - w.WriteHeader(http.StatusMethodNotAllowed) - return - } + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } - if path.Dir(r.URL.Path) != "/media" { - w.WriteHeader(http.StatusMethodNotAllowed) - return - } + if path.Dir(r.URL.Path) != "/media" { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } - // Acquire Width & Height Parameters - query := r.URL.Query() - width := query["width"] - height := query["height"] - _ = width - _ = height + // Acquire Width & Height Parameters + query := r.URL.Query() + width := query["width"] + height := query["height"] + _ = width + _ = height - // TODO: Caching & Resizing - // - If both, force resize with new scale - // - If one, scale resize proportionally + // TODO: Caching & Resizing + // - If both, force resize with new scale + // - If one, scale resize proportionally - // Pull out UUIDs - reqInfo := r.Context().Value("uuids").(map[string]string) - uid := reqInfo["uid"] + // Pull out userID + authContext := r.Context().Value("auth").(*model.AuthContext) + rawUserID, _ := (*authContext.AccessToken).Get("sub") + userID := rawUserID.(string) - // Derive Path - fileName := path.Base(r.URL.Path) - folderPath := path.Join("/" + api.Config.DataPath + "/media/" + uid) - mediaPath := path.Join(folderPath + "/" + fileName) + // Derive Path + fileName := path.Base(r.URL.Path) + folderPath := path.Join("/" + api.Config.DataPath + "/media/" + userID) + mediaPath := path.Join(folderPath + "/" + fileName) - // Check if File Exists - _, err := os.Stat(mediaPath) - if os.IsNotExist(err) { - // TODO: Different HTTP Response Code? - w.WriteHeader(http.StatusMethodNotAllowed) - return - } + // Check if File Exists + _, err := os.Stat(mediaPath) + if os.IsNotExist(err) { + // TODO: Different HTTP Response Code? + w.WriteHeader(http.StatusMethodNotAllowed) + return + } - http.ServeFile(w, r, mediaPath) + http.ServeFile(w, r, mediaPath) } diff --git a/internal/api/middlewares.go b/internal/api/middlewares.go index 6edb91b..3510133 100644 --- a/internal/api/middlewares.go +++ b/internal/api/middlewares.go @@ -1,104 +1,79 @@ package api import ( - log "github.com/sirupsen/logrus" - "net/http" - "context" - "os" + "context" + "net/http" + "os" - "reichard.io/imagini/graph/model" + log "github.com/sirupsen/logrus" + + "reichard.io/imagini/graph/model" ) type Middleware func(http.Handler) http.HandlerFunc func multipleMiddleware(h http.HandlerFunc, m ...Middleware) http.HandlerFunc { - if len(m) < 1 { - return h - } - wrapped := h - for i := len(m) - 1; i >= 0; i-- { - wrapped = m[i](wrapped) - } - return wrapped + if len(m) < 1 { + return h + } + wrapped := h + for i := len(m) - 1; i >= 0; i-- { + wrapped = m[i](wrapped) + } + return wrapped } +/** + * This is used for the graphQL endpoints that may require access to the + * Request and ResponseWriter variables. These are used to get / set cookies. + **/ func (api *API) injectContextMiddleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - log.Info("[middleware] Entering testMiddleware...") - authContext := &model.AuthContext{ - AuthResponse: &w, - AuthRequest: r, - } - accessCookie, err := r.Cookie("AccessToken") - if err != nil { - log.Warn("[middleware] AccessToken not found") - } else { - authContext.AccessToken = accessCookie.Value - } - refreshCookie, err := r.Cookie("RefreshToken") - if err != nil { - log.Warn("[middleware] RefreshToken not found") - } else { - authContext.RefreshToken = refreshCookie.Value - } + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Add context - ctx := context.WithValue(r.Context(), "auth", authContext) - r = r.WithContext(ctx) + authContext := &model.AuthContext{ + AuthResponse: &w, + AuthRequest: r, + } - log.Info("[middleware] Exiting testMiddleware...") - next.ServeHTTP(w, r) - }) + // Add context + ctx := context.WithValue(r.Context(), "auth", authContext) + r = r.WithContext(ctx) + + next.ServeHTTP(w, r) + + }) } +/** + * This is used for non graphQL endpoints that require authentication. + **/ func (api *API) authMiddleware(next http.Handler) http.HandlerFunc { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Acquire Token - accessCookie, err := r.Cookie("AccessToken") - if err != nil { - log.Warn("[middleware] AccessToken not found") - errorJSON(w, "Invalid token.", http.StatusUnauthorized) - return - } + accessToken, err := api.validateTokens(&w, r) + if err != nil { + errorJSON(w, "Invalid token.", http.StatusUnauthorized) + return + } - // Validate JWT Tokens - accessToken, err := api.Auth.ValidateJWTAccessToken(accessCookie.Value) + // Create Context + authContext := &model.AuthContext{ + AccessToken: &accessToken, + } + ctx := context.WithValue(r.Context(), "auth", authContext) + r = r.WithContext(ctx) - if err != nil && err.Error() == "exp not satisfied" { - log.Info("[middleware] Refreshing AccessToken") - accessToken, err = api.refreshAccessToken(w, r) - if err != nil { - log.Warn("[middleware] Refreshing AccessToken failed: ", err) - errorJSON(w, "Invalid token.", http.StatusUnauthorized) - return - } - log.Info("[middleware] AccessToken Refreshed") - } else if err != nil { - log.Warn("[middleware] AccessToken failed to validate") - errorJSON(w, "Invalid token.", http.StatusUnauthorized) - return - } + next.ServeHTTP(w, r) - // Acquire UserID and DeviceID - reqInfo := make(map[string]string) - uid, _ := accessToken.Get("sub") - did, _ := accessToken.Get("did") - reqInfo["uid"] = uid.(string) - reqInfo["did"] = did.(string) - - // Add context - ctx := context.WithValue(r.Context(), "uuids", reqInfo) - sr := r.WithContext(ctx) - - next.ServeHTTP(w, sr) - }) + }) } func (api *API) logMiddleware(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - log.SetOutput(os.Stdout) - log.Println(r.Method, r.URL) - h.ServeHTTP(w, r) - }) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + + log.SetOutput(os.Stdout) + log.Println(r.Method, r.URL) + h.ServeHTTP(w, r) + + }) } diff --git a/internal/api/routes.go b/internal/api/routes.go index 41bb097..7343c48 100644 --- a/internal/api/routes.go +++ b/internal/api/routes.go @@ -1,8 +1,8 @@ package api import ( - "net/http" - "encoding/json" + "encoding/json" + "net/http" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/playground" @@ -13,39 +13,46 @@ import ( func (api *API) registerRoutes() { - // Set up Directives - c := generated.Config{ Resolvers: &graph.Resolver{ DB: api.DB } } - c.Directives.HasMinRole = hasMinRoleDirective - c.Directives.Meta = metaDirective - srv := handler.NewDefaultServer(generated.NewExecutableSchema(c)) + // Set up Directives + graphConfig := generated.Config{ + Resolvers: &graph.Resolver{ + DB: api.DB, + Auth: api.Auth, + }, + Directives: generated.DirectiveRoot{ + Meta: api.metaDirective, + HasMinRole: api.hasMinRoleDirective, + }, + } + srv := handler.NewDefaultServer(generated.NewExecutableSchema(graphConfig)) - // Handle GraphQL + // Handle GraphQL api.Router.Handle("/playground", playground.Handler("GraphQL playground", "/query")) api.Router.Handle("/query", api.injectContextMiddleware(srv)) - // Handle Resource Route - api.Router.HandleFunc("/media/", multipleMiddleware( - api.mediaHandler, - api.authMiddleware, - )) + // Handle Resource Route + api.Router.HandleFunc("/media/", multipleMiddleware( + api.mediaHandler, + api.authMiddleware, + )) } func errorJSON(w http.ResponseWriter, err string, code int) { - errStruct := &APIResponse{Error: &APIError{Message: err, Code: int64(code)}} - responseJSON(w, errStruct, code) + errStruct := &APIResponse{Error: &APIError{Message: err, Code: int64(code)}} + responseJSON(w, errStruct, code) } func responseJSON(w http.ResponseWriter, msg interface{}, code int) { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - w.Header().Set("X-Content-Type-Options", "nosniff") - w.WriteHeader(code) - json.NewEncoder(w).Encode(msg) + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.Header().Set("X-Content-Type-Options", "nosniff") + w.WriteHeader(code) + json.NewEncoder(w).Encode(msg) } func successJSON(w http.ResponseWriter, msg string, code int) { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - w.Header().Set("X-Content-Type-Options", "nosniff") - w.WriteHeader(code) - json.NewEncoder(w).Encode(map[string]interface{}{"success": msg}) + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.Header().Set("X-Content-Type-Options", "nosniff") + w.WriteHeader(code) + json.NewEncoder(w).Encode(map[string]interface{}{"success": msg}) } diff --git a/internal/auth/auth.go b/internal/auth/auth.go index a4dfd8c..062a02f 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -1,185 +1,175 @@ package auth import ( - "fmt" - "time" - "errors" - "encoding/json" + "encoding/json" + "errors" + "fmt" + "time" - "gorm.io/gorm" - "github.com/google/uuid" - log "github.com/sirupsen/logrus" - "github.com/lestrrat-go/jwx/jwa" - "github.com/lestrrat-go/jwx/jwt" + "github.com/google/uuid" + "github.com/lestrrat-go/jwx/jwa" + "github.com/lestrrat-go/jwx/jwt" + log "github.com/sirupsen/logrus" + "gorm.io/gorm" - "reichard.io/imagini/graph/model" - "reichard.io/imagini/internal/db" - "reichard.io/imagini/internal/config" - "reichard.io/imagini/internal/session" + "reichard.io/imagini/graph/model" + "reichard.io/imagini/internal/config" + "reichard.io/imagini/internal/db" ) type AuthManager struct { - DB *db.DBManager - Config *config.Config - Session *session.SessionManager + DB *db.DBManager + Config *config.Config } func NewMgr(db *db.DBManager, c *config.Config) *AuthManager { - session := session.NewMgr() - return &AuthManager{ - DB: db, - Config: c, - Session: session, - } + return &AuthManager{ + DB: db, + Config: c, + } } -func (auth *AuthManager) AuthenticateUser(user, password string) (bool, model.User) { - // Search Objects - userByName := &model.User{} - userByName.Username = user +func (auth *AuthManager) AuthenticateUser(user, password string) (model.User, bool) { + // Find User by Username / Email + foundUser := &model.User{Username: user} + _, err := auth.DB.User(foundUser) - foundUser, err := auth.DB.User(userByName) - if errors.Is(err, gorm.ErrRecordNotFound) { - userByEmail := &model.User{} - userByEmail.Email = user - foundUser, err = auth.DB.User(userByEmail) - } + // By Username + if errors.Is(err, gorm.ErrRecordNotFound) { + foundUser = &model.User{Email: user} + _, err = auth.DB.User(foundUser) + } - // Error Checking - if errors.Is(err, gorm.ErrRecordNotFound) { - log.Warn("[auth] User not found: ", user) - return false, foundUser - } else if err != nil { - log.Error(err) - return false, foundUser - } + // By Email + if errors.Is(err, gorm.ErrRecordNotFound) { + log.Warn("[auth] User not found: ", user) + return *foundUser, false + } else if err != nil { + log.Error(err) + return *foundUser, false + } - log.Info("[auth] Authenticating user: ", foundUser.Username) + log.Info("[auth] Authenticating user: ", foundUser.Username) - // Determine Type - switch foundUser.AuthType { - case "Local": - return authenticateLocalUser(foundUser, password), foundUser - case "LDAP": - return authenticateLDAPUser(foundUser, password), foundUser - default: - return false, foundUser - } -} - -func (auth *AuthManager) getRole(user model.User) string { - // TODO: Lookup role of user - return "User" + // Determine Type + switch foundUser.AuthType { + case "Local": + return *foundUser, authenticateLocalUser(*foundUser, password) + case "LDAP": + return *foundUser, authenticateLDAPUser(*foundUser, password) + default: + return *foundUser, false + } } func (auth *AuthManager) ValidateJWTRefreshToken(refreshJWT string) (jwt.Token, error) { - byteRefreshJWT := []byte(refreshJWT) + byteRefreshJWT := []byte(refreshJWT) - // Acquire Relevant Device - unverifiedToken, err := jwt.ParseBytes(byteRefreshJWT) - did, ok := unverifiedToken.Get("did") - if !ok { - return nil, errors.New("did does not exist") - } - deviceID, err := uuid.Parse(fmt.Sprintf("%v", did)) - if err != nil { - return nil, errors.New("did does not parse") - } - stringDeviceID := deviceID.String() - device, err := auth.DB.Device(&model.Device{ID: &stringDeviceID}) - if err != nil { - return nil, err - } + // Acquire Relevant Device + unverifiedToken, err := jwt.ParseBytes(byteRefreshJWT) + did, ok := unverifiedToken.Get("did") + if !ok { + return nil, errors.New("did does not exist") + } + deviceID, err := uuid.Parse(fmt.Sprintf("%v", did)) + if err != nil { + return nil, errors.New("did does not parse") + } + device := &model.Device{ID: deviceID.String()} + _, err = auth.DB.Device(device) + if err != nil { + return nil, err + } - // Verify & Validate Token - verifiedToken, err := jwt.ParseBytes(byteRefreshJWT, - jwt.WithValidate(true), - jwt.WithVerify(jwa.HS256, []byte(*device.RefreshKey)), - ) - if err != nil { - fmt.Println("failed to parse payload: ", err) - return nil, err - } - return verifiedToken, nil + // Verify & Validate Token + verifiedToken, err := jwt.ParseBytes(byteRefreshJWT, + jwt.WithValidate(true), + jwt.WithVerify(jwa.HS256, []byte(*device.RefreshKey)), + ) + if err != nil { + fmt.Println("failed to parse payload: ", err) + return nil, err + } + return verifiedToken, nil } func (auth *AuthManager) ValidateJWTAccessToken(accessJWT string) (jwt.Token, error) { - byteAccessJWT := []byte(accessJWT) - verifiedToken, err := jwt.ParseBytes(byteAccessJWT, - jwt.WithValidate(true), - jwt.WithVerify(jwa.HS256, []byte(auth.Config.JWTSecret)), - ) + byteAccessJWT := []byte(accessJWT) + verifiedToken, err := jwt.ParseBytes(byteAccessJWT, + jwt.WithValidate(true), + jwt.WithVerify(jwa.HS256, []byte(auth.Config.JWTSecret)), + ) - if err != nil { - return nil, err - } + if err != nil { + return nil, err + } - return verifiedToken, nil + return verifiedToken, nil } func (auth *AuthManager) CreateJWTRefreshToken(user model.User, device model.Device) (string, error) { - // Acquire Refresh Key - byteKey := []byte(*device.RefreshKey) + // Acquire Refresh Key + byteKey := []byte(*device.RefreshKey) - // Create New Token - tm := time.Now() - t := jwt.New() - t.Set(`did`, device.ID) // Device ID - t.Set(jwt.SubjectKey, user.ID) // User ID - t.Set(jwt.AudienceKey, `imagini`) // App ID - t.Set(jwt.IssuedAtKey, tm) // Issued At + // Create New Token + tm := time.Now() + t := jwt.New() + t.Set(`did`, device.ID) // Device ID + t.Set(jwt.SubjectKey, user.ID) // User ID + t.Set(jwt.AudienceKey, `imagini`) // App ID + t.Set(jwt.IssuedAtKey, tm) // Issued At - // iOS & Android = Never Expiring Refresh Token - if device.Type != "iOS" && device.Type != "Android" { - t.Set(jwt.ExpirationKey, tm.Add(time.Hour * 24)) // 1 Day Access Key - } + // iOS & Android = Never Expiring Refresh Token + if device.Type != "iOS" && device.Type != "Android" { + t.Set(jwt.ExpirationKey, tm.Add(time.Hour*24)) // 1 Day Access Key + } - // Validate Token Creation - _, err := json.MarshalIndent(t, "", " ") - if err != nil { - fmt.Printf("failed to generate JSON: %s\n", err) - return "", err - } + // Validate Token Creation + _, err := json.MarshalIndent(t, "", " ") + if err != nil { + fmt.Printf("failed to generate JSON: %s\n", err) + return "", err + } - // Sign Token - signed, err := jwt.Sign(t, jwa.HS256, byteKey) - if err != nil { - log.Printf("failed to sign token: %s", err) - return "", err - } + // Sign Token + signed, err := jwt.Sign(t, jwa.HS256, byteKey) + if err != nil { + log.Printf("failed to sign token: %s", err) + return "", err + } - // Return Token - return string(signed), nil + // Return Token + return string(signed), nil } func (auth *AuthManager) CreateJWTAccessToken(user model.User, device model.Device) (string, error) { - // Create New Token - tm := time.Now() - t := jwt.New() - t.Set(`did`, device.ID) // Device ID - t.Set(`role`, auth.getRole(user)) // User Role (Admin / User) - t.Set(jwt.SubjectKey, user.ID) // User ID - t.Set(jwt.AudienceKey, `imagini`) // App ID - t.Set(jwt.IssuedAtKey, tm) // Issued At - t.Set(jwt.ExpirationKey, tm.Add(time.Hour * 2)) // 2 Hour Access Key + // Create New Token + tm := time.Now() + t := jwt.New() + t.Set(`did`, device.ID) // Device ID + t.Set(`role`, user.Role.String()) // User Role (Admin / User) + t.Set(jwt.SubjectKey, user.ID) // User ID + t.Set(jwt.AudienceKey, `imagini`) // App ID + t.Set(jwt.IssuedAtKey, tm) // Issued At + t.Set(jwt.ExpirationKey, tm.Add(time.Hour*2)) // 2 Hour Access Key - // Validate Token Creation - _, err := json.MarshalIndent(t, "", " ") - if err != nil { - fmt.Printf("failed to generate JSON: %s\n", err) - return "", err - } + // Validate Token Creation + _, err := json.MarshalIndent(t, "", " ") + if err != nil { + fmt.Printf("failed to generate JSON: %s\n", err) + return "", err + } - // Use Server Key - byteKey := []byte(auth.Config.JWTSecret) + // Use Server Key + byteKey := []byte(auth.Config.JWTSecret) - // Sign Token - signed, err := jwt.Sign(t, jwa.HS256, byteKey) - if err != nil { - log.Printf("failed to sign token: %s", err) - return "", err - } + // Sign Token + signed, err := jwt.Sign(t, jwa.HS256, byteKey) + if err != nil { + log.Printf("failed to sign token: %s", err) + return "", err + } - // Return Token - return string(signed), nil + // Return Token + return string(signed), nil } diff --git a/internal/db/db.go b/internal/db/db.go index 1873598..3f3de1a 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -1,113 +1,113 @@ package db import ( - "errors" - "path" - "fmt" + "errors" + "fmt" + "path" - log "github.com/sirupsen/logrus" - // "gorm.io/gorm/logger" - "gorm.io/driver/sqlite" - "gorm.io/gorm" + log "github.com/sirupsen/logrus" + // "gorm.io/gorm/logger" + "gorm.io/driver/sqlite" + "gorm.io/gorm" - "reichard.io/imagini/internal/config" - "reichard.io/imagini/graph/model" + "reichard.io/imagini/graph/model" + "reichard.io/imagini/internal/config" ) type DBManager struct { - db *gorm.DB + db *gorm.DB } func NewMgr(c *config.Config) *DBManager { - gormConfig := &gorm.Config{ - PrepareStmt: true, - // Logger: logger.Default.LogMode(logger.Silent), - } + gormConfig := &gorm.Config{ + PrepareStmt: true, + // Logger: logger.Default.LogMode(logger.Silent), + } - // Create manager - dbm := &DBManager{} + // Create manager + dbm := &DBManager{} - if c.DBType == "SQLite" { - dbLocation := path.Join(c.ConfigPath, "imagini.db") - dbm.db, _ = gorm.Open(sqlite.Open(dbLocation), gormConfig) - } else { - log.Fatal("Unsupported Database") - } + if c.DBType == "SQLite" { + dbLocation := path.Join(c.ConfigPath, "imagini.db") + dbm.db, _ = gorm.Open(sqlite.Open(dbLocation), gormConfig) + } else { + log.Fatal("Unsupported Database") + } - // Initialize database - dbm.db.AutoMigrate(&model.Device{}) - dbm.db.AutoMigrate(&model.User{}) - dbm.db.AutoMigrate(&model.MediaItem{}) - dbm.db.AutoMigrate(&model.Tag{}) - dbm.db.AutoMigrate(&model.Album{}) + // Initialize database + dbm.db.AutoMigrate(&model.Device{}) + dbm.db.AutoMigrate(&model.User{}) + dbm.db.AutoMigrate(&model.MediaItem{}) + dbm.db.AutoMigrate(&model.Tag{}) + dbm.db.AutoMigrate(&model.Album{}) - // Determine whether to bootstrap - var count int64 - dbm.db.Model(&model.User{}).Count(&count) - if count == 0 { - dbm.bootstrapDatabase() - } + // Determine whether to bootstrap + var count int64 + dbm.db.Model(&model.User{}).Count(&count) + if count == 0 { + dbm.bootstrapDatabase() + } - return dbm + return dbm } func (dbm *DBManager) bootstrapDatabase() { - log.Info("[query] Bootstrapping database.") + log.Info("[query] Bootstrapping database.") - password := "admin" - user := &model.User{ - Username: "admin", - AuthType: "Local", - Password: &password, - Role: model.RoleAdmin, - } + password := "admin" + user := &model.User{ + Username: "admin", + AuthType: "Local", + Password: &password, + Role: model.RoleAdmin, + } - err := dbm.CreateUser(user) + err := dbm.CreateUser(user) - if err != nil { - log.Fatal("[query] Unable to bootstrap database.") - } + if err != nil { + log.Fatal("[query] Unable to bootstrap database.") + } } func (dbm *DBManager) QueryBuilder(dest interface{}, params []byte) (int64, error) { - // TODO: - // - Where Filters - // - Sort Filters - // - Paging Filters + // TODO: + // - Where Filters + // - Sort Filters + // - Paging Filters - objType := fmt.Sprintf("%T", dest) - if objType == "*[]model.MediaItem" { - // TODO: Validate MediaItem Type - } else { - // Return Error - return 0, errors.New("Invalid type") - } + objType := fmt.Sprintf("%T", dest) + if objType == "*[]model.MediaItem" { + // TODO: Validate MediaItem Type + } else { + // Return Error + return 0, errors.New("Invalid type") + } - var count int64 - err := dbm.db.Find(dest).Count(&count).Error; - return count, err + var count int64 + err := dbm.db.Find(dest).Count(&count).Error + return count, err - // Paging: - // - Regular Pagination: - // - /api/v1/MediaItems?page[limit]=50&page=2 - // - Meta Count Only - // - /api/v1/MediaItems?page[limit]=0 + // Paging: + // - Regular Pagination: + // - /api/v1/MediaItems?page[limit]=50&page=2 + // - Meta Count Only + // - /api/v1/MediaItems?page[limit]=0 - // Sorting: - // - Ascending Sort: - // - /api/v1/MediaItems?sort=created_at - // - Descending Sort: - // - /api/v1/MediaItems?sort=-created_at + // Sorting: + // - Ascending Sort: + // - /api/v1/MediaItems?sort=created_at + // - Descending Sort: + // - /api/v1/MediaItems?sort=-created_at - // Filters: - // - Greater Than / Less Than (created_at, updated_at, exif_date) - // - /api/v1/MediaItems?filter[created_at]>=2020-01-01&filter[created_at]<=2021-01-01 - // - Long / Lat Range (latitude, longitude) - // - /api/v1/MediaItems?filter[latitude]>=71.1827&filter[latitude]<=72.0000&filter[longitude]>=100.000&filter[longitude]<=101.0000 - // - Image / Video (media_type) - // - /api/v1/MediaItems?filter[media_type]=Image - // - Tags (tags) - // - /api/v1/MediaItems?filter[tags]=id1,id2,id3 - // - Albums (albums) - // - /api/v1/MediaItems?filter[albums]=id1 + // Filters: + // - Greater Than / Less Than (created_at, updated_at, exif_date) + // - /api/v1/MediaItems?filter[created_at]>=2020-01-01&filter[created_at]<=2021-01-01 + // - Long / Lat Range (latitude, longitude) + // - /api/v1/MediaItems?filter[latitude]>=71.1827&filter[latitude]<=72.0000&filter[longitude]>=100.000&filter[longitude]<=101.0000 + // - Image / Video (media_type) + // - /api/v1/MediaItems?filter[media_type]=Image + // - Tags (tags) + // - /api/v1/MediaItems?filter[tags]=id1,id2,id3 + // - Albums (albums) + // - /api/v1/MediaItems?filter[albums]=id1 } diff --git a/internal/db/devices.go b/internal/db/devices.go index 9bb6d35..990cb18 100644 --- a/internal/db/devices.go +++ b/internal/db/devices.go @@ -1,31 +1,30 @@ package db import ( - "github.com/google/uuid" - log "github.com/sirupsen/logrus" + "github.com/google/uuid" + log "github.com/sirupsen/logrus" - "reichard.io/imagini/graph/model" + "reichard.io/imagini/graph/model" ) -func (dbm *DBManager) CreateDevice (device *model.Device) error { - log.Info("[db] Creating device: ", device.Name) - refreshKey := uuid.New().String() - device.RefreshKey = &refreshKey - err := dbm.db.Create(&device).Error - return err +func (dbm *DBManager) CreateDevice(device *model.Device) error { + log.Debug("[db] Creating device: ", device.Name) + refreshKey := uuid.New().String() + device.RefreshKey = &refreshKey + err := dbm.db.Create(device).Error + return err } -func (dbm *DBManager) Device (device *model.Device) (model.Device, error) { - var foundDevice model.Device - var count int64 - err := dbm.db.Where(&device).First(&foundDevice).Count(&count).Error - return foundDevice, err +func (dbm *DBManager) Device(device *model.Device) (int64, error) { + var count int64 + err := dbm.db.Where(device).First(device).Count(&count).Error + return count, err } -func (dbm *DBManager) DeleteDevice (user *model.Device) error { - return nil +func (dbm *DBManager) DeleteDevice(user *model.Device) error { + return nil } -func (dbm *DBManager) UpdateRefreshToken (device *model.Device, refreshToken string) error { - return nil +func (dbm *DBManager) UpdateRefreshToken(device *model.Device, refreshToken string) error { + return nil } diff --git a/internal/db/errors.go b/internal/db/errors.go index 035b3c1..787ae41 100644 --- a/internal/db/errors.go +++ b/internal/db/errors.go @@ -3,5 +3,5 @@ package db import "errors" var ( - ErrUserAlreadyExists = errors.New("user already exists") + ErrUserAlreadyExists = errors.New("user already exists") ) diff --git a/internal/db/media_items.go b/internal/db/media_items.go index 6e65c27..f7f3b80 100644 --- a/internal/db/media_items.go +++ b/internal/db/media_items.go @@ -1,21 +1,21 @@ package db import ( - log "github.com/sirupsen/logrus" + log "github.com/sirupsen/logrus" - "reichard.io/imagini/graph/model" + "reichard.io/imagini/graph/model" ) -func (dbm *DBManager) CreateMediaItem (mediaItem *model.MediaItem) error { - log.Info("[db] Creating media item: ", mediaItem.FileName) - err := dbm.db.Create(&mediaItem).Error - return err +func (dbm *DBManager) CreateMediaItem(mediaItem *model.MediaItem) error { + log.Debug("[db] Creating media item: ", mediaItem.FileName) + err := dbm.db.Create(mediaItem).Error + return err } func (dbm *DBManager) MediaItems(mediaItemFilter *model.MediaItem) ([]model.MediaItem, int64, error) { - var mediaItems []model.MediaItem - var count int64 + var mediaItems []model.MediaItem + var count int64 - err := dbm.db.Where(&mediaItemFilter).Find(&mediaItems).Count(&count).Error; - return mediaItems, count, err + err := dbm.db.Where(mediaItemFilter).Find(&mediaItems).Count(&count).Error + return mediaItems, count, err } diff --git a/internal/db/users.go b/internal/db/users.go index 8853789..e69fa6b 100644 --- a/internal/db/users.go +++ b/internal/db/users.go @@ -1,43 +1,41 @@ package db import ( - "golang.org/x/crypto/bcrypt" - log "github.com/sirupsen/logrus" + log "github.com/sirupsen/logrus" + "golang.org/x/crypto/bcrypt" - "reichard.io/imagini/graph/model" + "reichard.io/imagini/graph/model" ) -func (dbm *DBManager) CreateUser (user *model.User) error { - log.Info("[db] Creating user: ", user.Username) - hashedPassword, err := bcrypt.GenerateFromPassword([]byte(*user.Password), bcrypt.DefaultCost) - if err != nil { - log.Error(err) - return err - } - stringHashedPassword := string(hashedPassword) - user.Password = &stringHashedPassword - err = dbm.db.Create(&user).Error - return err +func (dbm *DBManager) CreateUser(user *model.User) error { + log.Info("[db] Creating user: ", user.Username) + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(*user.Password), bcrypt.DefaultCost) + if err != nil { + log.Error(err) + return err + } + stringHashedPassword := string(hashedPassword) + user.Password = &stringHashedPassword + return dbm.db.Create(user).Error } -func (dbm *DBManager) User (user *model.User) (model.User, error) { - var foundUser model.User - var count int64 - err := dbm.db.Where(&user).First(&foundUser).Count(&count).Error - return foundUser, err +func (dbm *DBManager) User(user *model.User) (int64, error) { + var count int64 + err := dbm.db.Where(user).First(user).Count(&count).Error + return count, err } -func (dbm *DBManager) Users () ([]*model.User, int64, error) { - var foundUsers []*model.User - var count int64 - err := dbm.db.Find(&foundUsers).Count(&count).Error - return foundUsers, count, err +func (dbm *DBManager) Users() ([]*model.User, int64, error) { + var foundUsers []*model.User + var count int64 + err := dbm.db.Find(&foundUsers).Count(&count).Error + return foundUsers, count, err } -func (dbm *DBManager) DeleteUser (user model.User) error { - return nil +func (dbm *DBManager) DeleteUser(user model.User) error { + return nil } -func (dbm *DBManager) UpdatePassword (user model.User, pw string) { +func (dbm *DBManager) UpdatePassword(user model.User, pw string) { } From a5692babb809d4bd31d5f515e35d70b36609dd41 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Thu, 4 Feb 2021 15:31:07 -0500 Subject: [PATCH 4/8] Clean Up --- cmd/server/server.go | 77 ++++++++++----------- graph/generated/generated.go | 36 +++++----- graph/model/models_gen.go | 6 +- graph/schema.graphqls | 11 +-- graph/schema.resolvers.go | 4 ++ internal/api/auth.go | 30 --------- internal/api/directives.go | 50 ++++++++++++++ internal/api/media.go | 4 +- internal/api/middlewares.go | 22 +----- internal/api/models.go | 24 ------- internal/api/routes.go | 27 +------- internal/auth/auth.go | 118 -------------------------------- internal/auth/jwt.go | 126 +++++++++++++++++++++++++++++++++++ internal/auth/ldap.go | 4 +- internal/auth/local.go | 22 +++--- internal/config/config.go | 42 ++++++------ internal/db/db.go | 1 + internal/db/errors.go | 7 -- internal/session/session.go | 36 +++++----- plugin/models.go | 20 +++--- 20 files changed, 319 insertions(+), 348 deletions(-) create mode 100644 internal/api/directives.go delete mode 100644 internal/api/models.go create mode 100644 internal/auth/jwt.go delete mode 100644 internal/db/errors.go diff --git a/cmd/server/server.go b/cmd/server/server.go index 4229c1e..95d3b65 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -1,58 +1,59 @@ package server import ( - "time" - "context" - "net/http" - log "github.com/sirupsen/logrus" + "context" + "net/http" + "time" - "reichard.io/imagini/internal/db" - "reichard.io/imagini/internal/api" - "reichard.io/imagini/internal/auth" - "reichard.io/imagini/internal/config" + log "github.com/sirupsen/logrus" + + "reichard.io/imagini/internal/api" + "reichard.io/imagini/internal/auth" + "reichard.io/imagini/internal/config" + "reichard.io/imagini/internal/db" ) type Server struct { - API *api.API - Auth *auth.AuthManager - Config *config.Config - Database *db.DBManager - httpServer *http.Server + API *api.API + Auth *auth.AuthManager + Config *config.Config + Database *db.DBManager + httpServer *http.Server } func NewServer() *Server { - c := config.Load() - db := db.NewMgr(c) - auth := auth.NewMgr(db, c) - api := api.NewApi(db, c, auth) + c := config.Load() + db := db.NewMgr(c) + auth := auth.NewMgr(db, c) + api := api.NewApi(db, c, auth) - return &Server{ - API: api, - Auth: auth, - Config: c, - Database: db, - } + return &Server{ + API: api, + Auth: auth, + Config: c, + Database: db, + } } func (s *Server) StartServer() { - listenAddr := (":" + s.Config.ListenPort) + listenAddr := (":" + s.Config.ListenPort) - s.httpServer = &http.Server{ - Handler: s.API.Router, - Addr: listenAddr, - } + s.httpServer = &http.Server{ + Handler: s.API.Router, + Addr: listenAddr, + } - go func() { - err := s.httpServer.ListenAndServe() - if err != nil { - log.Error("Error starting server ", err) - return - } - }() + go func() { + err := s.httpServer.ListenAndServe() + if err != nil { + log.Error("Error starting server ", err) + return + } + }() } func (s *Server) StopServer() { - ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second) - defer cancel() - s.httpServer.Shutdown(ctx) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + s.httpServer.Shutdown(ctx) } diff --git a/graph/generated/generated.go b/graph/generated/generated.go index dee8a1b..8aa1d49 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -43,6 +43,7 @@ type ResolverRoot interface { type DirectiveRoot struct { HasMinRole func(ctx context.Context, obj interface{}, next graphql.Resolver, role model.Role) (res interface{}, err error) + IsPrivate func(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) Meta func(ctx context.Context, obj interface{}, next graphql.Resolver, gorm *string) (res interface{}, err error) } @@ -243,21 +244,21 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.AlbumResponse.PageInfo(childComplexity), true - case "AuthResponse.Device": + case "AuthResponse.device": if e.complexity.AuthResponse.Device == nil { break } return e.complexity.AuthResponse.Device(childComplexity), true - case "AuthResponse.Error": + case "AuthResponse.error": if e.complexity.AuthResponse.Error == nil { break } return e.complexity.AuthResponse.Error(childComplexity), true - case "AuthResponse.Result": + case "AuthResponse.result": if e.complexity.AuthResponse.Result == nil { break } @@ -863,6 +864,7 @@ scalar Upload # https://gqlgen.com/reference/directives/ directive @hasMinRole(role: Role!) on FIELD_DEFINITION +directive @isPrivate on FIELD_DEFINITION | INPUT_FIELD_DEFINITION directive @meta( gorm: String, @@ -899,9 +901,9 @@ enum AuthResult { } type AuthResponse { - Result: AuthResult! - Device: Device - Error: String + result: AuthResult! + device: Device + error: String } # ------------------------------------------------------------ @@ -1004,7 +1006,7 @@ type Device { type: DeviceType! @meta(gorm: "default:Unknown;not null") userID: ID! @meta(gorm: "not null") user: User! @meta(gorm: "foreignKey:ID;references:UserID;not null") - refreshKey: String + refreshKey: String @deprecated(reason: "Private Field") # @isPrivate } type User { @@ -1017,7 +1019,7 @@ type User { lastName: String role: Role! @meta(gorm: "default:User;not null") authType: AuthType! @meta(gorm: "default:Local;not null") - password: String + password: String @deprecated(reason: "Private Field") #@isPrivate } type MediaItem { @@ -1927,7 +1929,7 @@ func (ec *executionContext) _AlbumResponse_pageInfo(ctx context.Context, field g return ec.marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) _AuthResponse_Result(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) { +func (ec *executionContext) _AuthResponse_result(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1962,7 +1964,7 @@ func (ec *executionContext) _AuthResponse_Result(ctx context.Context, field grap return ec.marshalNAuthResult2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthResult(ctx, field.Selections, res) } -func (ec *executionContext) _AuthResponse_Device(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) { +func (ec *executionContext) _AuthResponse_device(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1994,7 +1996,7 @@ func (ec *executionContext) _AuthResponse_Device(ctx context.Context, field grap return ec.marshalODevice2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx, field.Selections, res) } -func (ec *executionContext) _AuthResponse_Error(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) { +func (ec *executionContext) _AuthResponse_error(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -7553,15 +7555,15 @@ func (ec *executionContext) _AuthResponse(ctx context.Context, sel ast.Selection switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("AuthResponse") - case "Result": - out.Values[i] = ec._AuthResponse_Result(ctx, field, obj) + case "result": + out.Values[i] = ec._AuthResponse_result(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } - case "Device": - out.Values[i] = ec._AuthResponse_Device(ctx, field, obj) - case "Error": - out.Values[i] = ec._AuthResponse_Error(ctx, field, obj) + case "device": + out.Values[i] = ec._AuthResponse_device(ctx, field, obj) + case "error": + out.Values[i] = ec._AuthResponse_error(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 50787f3..d54d2f4 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -33,9 +33,9 @@ type AlbumResponse struct { } type AuthResponse struct { - Result AuthResult `json:"Result" ` - Device *Device `json:"Device" ` - Error *string `json:"Error" ` + Result AuthResult `json:"result" ` + Device *Device `json:"device" ` + Error *string `json:"error" ` } type AuthTypeFilter struct { diff --git a/graph/schema.graphqls b/graph/schema.graphqls index 92e8493..4d67510 100644 --- a/graph/schema.graphqls +++ b/graph/schema.graphqls @@ -5,6 +5,7 @@ scalar Upload # https://gqlgen.com/reference/directives/ directive @hasMinRole(role: Role!) on FIELD_DEFINITION +directive @isPrivate on FIELD_DEFINITION | INPUT_FIELD_DEFINITION directive @meta( gorm: String, @@ -41,9 +42,9 @@ enum AuthResult { } type AuthResponse { - Result: AuthResult! - Device: Device - Error: String + result: AuthResult! + device: Device + error: String } # ------------------------------------------------------------ @@ -146,7 +147,7 @@ type Device { type: DeviceType! @meta(gorm: "default:Unknown;not null") userID: ID! @meta(gorm: "not null") user: User! @meta(gorm: "foreignKey:ID;references:UserID;not null") - refreshKey: String + refreshKey: String @isPrivate } type User { @@ -159,7 +160,7 @@ type User { lastName: String role: Role! @meta(gorm: "default:User;not null") authType: AuthType! @meta(gorm: "default:Local;not null") - password: String + password: String @isPrivate } type MediaItem { diff --git a/graph/schema.resolvers.go b/graph/schema.resolvers.go index 50f185e..6f54faa 100644 --- a/graph/schema.resolvers.go +++ b/graph/schema.resolvers.go @@ -75,6 +75,8 @@ func (r *queryResolver) Login(ctx context.Context, user string, password string, } } else { foundDevice.Type = deriveDeviceType(req) + foundDevice.UserID = foundUser.ID + // TODO: foundDevice.User = &foundUser err := r.DB.CreateDevice(&foundDevice) if err != nil { return &model.AuthResponse{Result: model.AuthResultFailure}, nil @@ -97,6 +99,8 @@ func (r *queryResolver) Login(ctx context.Context, user string, password string, http.SetCookie(*resp, &accessCookie) http.SetCookie(*resp, &refreshCookie) + // TODO: Prob bandaid + foundDevice.User = &foundUser return &model.AuthResponse{Result: model.AuthResultSuccess, Device: &foundDevice}, nil } diff --git a/internal/api/auth.go b/internal/api/auth.go index 197bd17..66f4b66 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -1,12 +1,10 @@ package api import ( - "context" "errors" "fmt" "net/http" - "github.com/99designs/gqlgen/graphql" "github.com/google/uuid" "github.com/lestrrat-go/jwx/jwt" @@ -94,31 +92,3 @@ func (api *API) validateTokens(w *http.ResponseWriter, r *http.Request) (jwt.Tok return jwt.ParseBytes([]byte(newAccessCookie)) } - -func (api *API) hasMinRoleDirective(ctx context.Context, obj interface{}, next graphql.Resolver, role model.Role) (res interface{}, err error) { - authContext := ctx.Value("auth").(*model.AuthContext) - accessToken, err := api.validateTokens(authContext.AuthResponse, authContext.AuthRequest) - if err != nil { - return nil, errors.New("Access Denied") - } - authContext.AccessToken = &accessToken - - userRole, ok := accessToken.Get("role") - if !ok { - return nil, errors.New("Access Denied") - } - - if userRole == model.RoleAdmin.String() { - return next(ctx) - } - - if userRole == role.String() { - return next(ctx) - } - - return nil, errors.New("Role Not Authenticated") -} - -func (api *API) metaDirective(ctx context.Context, obj interface{}, next graphql.Resolver, gorm *string) (res interface{}, err error) { - return next(ctx) -} diff --git a/internal/api/directives.go b/internal/api/directives.go new file mode 100644 index 0000000..0c07f9a --- /dev/null +++ b/internal/api/directives.go @@ -0,0 +1,50 @@ +package api + +import ( + "context" + "errors" + + "github.com/99designs/gqlgen/graphql" + "reichard.io/imagini/graph/model" +) + +/** + * This is used to validate whether the users role is adequate for the requested resource. + **/ +func (api *API) hasMinRoleDirective(ctx context.Context, obj interface{}, next graphql.Resolver, role model.Role) (res interface{}, err error) { + authContext := ctx.Value("auth").(*model.AuthContext) + accessToken, err := api.validateTokens(authContext.AuthResponse, authContext.AuthRequest) + if err != nil { + return nil, errors.New("Access Denied") + } + authContext.AccessToken = &accessToken + + userRole, ok := accessToken.Get("role") + if !ok { + return nil, errors.New("Access Denied") + } + + if userRole == model.RoleAdmin.String() { + return next(ctx) + } + + if userRole == role.String() { + return next(ctx) + } + + return nil, errors.New("Role Not Authenticated") +} + +/** + * This is needed but not used. Meta is used for Gorm. + **/ +func (api *API) metaDirective(ctx context.Context, obj interface{}, next graphql.Resolver, gorm *string) (res interface{}, err error) { + return next(ctx) +} + +/** + * This overrides the response so fields with an @isPrivate directive are always nil. + **/ +func (api *API) isPrivateDirective(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) { + return nil, errors.New("Private Field") +} diff --git a/internal/api/media.go b/internal/api/media.go index d648e25..873b924 100644 --- a/internal/api/media.go +++ b/internal/api/media.go @@ -8,7 +8,9 @@ import ( "reichard.io/imagini/graph/model" ) -// Responsible for serving up static images / videos +/** + * Responsible for serving up static images / videos + **/ func (api *API) mediaHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { w.WriteHeader(http.StatusMethodNotAllowed) diff --git a/internal/api/middlewares.go b/internal/api/middlewares.go index 3510133..a845e24 100644 --- a/internal/api/middlewares.go +++ b/internal/api/middlewares.go @@ -3,9 +3,6 @@ package api import ( "context" "net/http" - "os" - - log "github.com/sirupsen/logrus" "reichard.io/imagini/graph/model" ) @@ -27,9 +24,8 @@ func multipleMiddleware(h http.HandlerFunc, m ...Middleware) http.HandlerFunc { * This is used for the graphQL endpoints that may require access to the * Request and ResponseWriter variables. These are used to get / set cookies. **/ -func (api *API) injectContextMiddleware(next http.Handler) http.Handler { +func (api *API) contextMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - authContext := &model.AuthContext{ AuthResponse: &w, AuthRequest: r, @@ -40,7 +36,6 @@ func (api *API) injectContextMiddleware(next http.Handler) http.Handler { r = r.WithContext(ctx) next.ServeHTTP(w, r) - }) } @@ -49,10 +44,10 @@ func (api *API) injectContextMiddleware(next http.Handler) http.Handler { **/ func (api *API) authMiddleware(next http.Handler) http.HandlerFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - + // Validate Tokens accessToken, err := api.validateTokens(&w, r) if err != nil { - errorJSON(w, "Invalid token.", http.StatusUnauthorized) + w.WriteHeader(http.StatusUnauthorized) return } @@ -64,16 +59,5 @@ func (api *API) authMiddleware(next http.Handler) http.HandlerFunc { r = r.WithContext(ctx) next.ServeHTTP(w, r) - - }) -} - -func (api *API) logMiddleware(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - - log.SetOutput(os.Stdout) - log.Println(r.Method, r.URL) - h.ServeHTTP(w, r) - }) } diff --git a/internal/api/models.go b/internal/api/models.go deleted file mode 100644 index 8a2345b..0000000 --- a/internal/api/models.go +++ /dev/null @@ -1,24 +0,0 @@ -package api - -type APICredentials struct { - User string `json:"user"` - Password string `json:"password"` -} - -type APIData interface{} - -type APIMeta struct { - Count int64 `json:"count"` - Page int64 `json:"page"` -} - -type APIError struct { - Message string `json:"message"` - Code int64 `json:"code"` -} - -type APIResponse struct { - Data APIData `json:"data,omitempty"` - Meta *APIMeta `json:"meta,omitempty"` - Error *APIError `json:"error,omitempty"` -} diff --git a/internal/api/routes.go b/internal/api/routes.go index 7343c48..2e342f2 100644 --- a/internal/api/routes.go +++ b/internal/api/routes.go @@ -1,9 +1,6 @@ package api import ( - "encoding/json" - "net/http" - "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/playground" @@ -12,7 +9,6 @@ import ( ) func (api *API) registerRoutes() { - // Set up Directives graphConfig := generated.Config{ Resolvers: &graph.Resolver{ @@ -21,6 +17,7 @@ func (api *API) registerRoutes() { }, Directives: generated.DirectiveRoot{ Meta: api.metaDirective, + IsPrivate: api.isPrivateDirective, HasMinRole: api.hasMinRoleDirective, }, } @@ -28,31 +25,11 @@ func (api *API) registerRoutes() { // Handle GraphQL api.Router.Handle("/playground", playground.Handler("GraphQL playground", "/query")) - api.Router.Handle("/query", api.injectContextMiddleware(srv)) + api.Router.Handle("/query", api.contextMiddleware(srv)) // Handle Resource Route api.Router.HandleFunc("/media/", multipleMiddleware( api.mediaHandler, api.authMiddleware, )) - -} - -func errorJSON(w http.ResponseWriter, err string, code int) { - errStruct := &APIResponse{Error: &APIError{Message: err, Code: int64(code)}} - responseJSON(w, errStruct, code) -} - -func responseJSON(w http.ResponseWriter, msg interface{}, code int) { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - w.Header().Set("X-Content-Type-Options", "nosniff") - w.WriteHeader(code) - json.NewEncoder(w).Encode(msg) -} - -func successJSON(w http.ResponseWriter, msg string, code int) { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - w.Header().Set("X-Content-Type-Options", "nosniff") - w.WriteHeader(code) - json.NewEncoder(w).Encode(map[string]interface{}{"success": msg}) } diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 062a02f..f444995 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -1,14 +1,8 @@ package auth import ( - "encoding/json" "errors" - "fmt" - "time" - "github.com/google/uuid" - "github.com/lestrrat-go/jwx/jwa" - "github.com/lestrrat-go/jwx/jwt" log "github.com/sirupsen/logrus" "gorm.io/gorm" @@ -61,115 +55,3 @@ func (auth *AuthManager) AuthenticateUser(user, password string) (model.User, bo return *foundUser, false } } - -func (auth *AuthManager) ValidateJWTRefreshToken(refreshJWT string) (jwt.Token, error) { - byteRefreshJWT := []byte(refreshJWT) - - // Acquire Relevant Device - unverifiedToken, err := jwt.ParseBytes(byteRefreshJWT) - did, ok := unverifiedToken.Get("did") - if !ok { - return nil, errors.New("did does not exist") - } - deviceID, err := uuid.Parse(fmt.Sprintf("%v", did)) - if err != nil { - return nil, errors.New("did does not parse") - } - device := &model.Device{ID: deviceID.String()} - _, err = auth.DB.Device(device) - if err != nil { - return nil, err - } - - // Verify & Validate Token - verifiedToken, err := jwt.ParseBytes(byteRefreshJWT, - jwt.WithValidate(true), - jwt.WithVerify(jwa.HS256, []byte(*device.RefreshKey)), - ) - if err != nil { - fmt.Println("failed to parse payload: ", err) - return nil, err - } - return verifiedToken, nil -} - -func (auth *AuthManager) ValidateJWTAccessToken(accessJWT string) (jwt.Token, error) { - byteAccessJWT := []byte(accessJWT) - verifiedToken, err := jwt.ParseBytes(byteAccessJWT, - jwt.WithValidate(true), - jwt.WithVerify(jwa.HS256, []byte(auth.Config.JWTSecret)), - ) - - if err != nil { - return nil, err - } - - return verifiedToken, nil -} - -func (auth *AuthManager) CreateJWTRefreshToken(user model.User, device model.Device) (string, error) { - // Acquire Refresh Key - byteKey := []byte(*device.RefreshKey) - - // Create New Token - tm := time.Now() - t := jwt.New() - t.Set(`did`, device.ID) // Device ID - t.Set(jwt.SubjectKey, user.ID) // User ID - t.Set(jwt.AudienceKey, `imagini`) // App ID - t.Set(jwt.IssuedAtKey, tm) // Issued At - - // iOS & Android = Never Expiring Refresh Token - if device.Type != "iOS" && device.Type != "Android" { - t.Set(jwt.ExpirationKey, tm.Add(time.Hour*24)) // 1 Day Access Key - } - - // Validate Token Creation - _, err := json.MarshalIndent(t, "", " ") - if err != nil { - fmt.Printf("failed to generate JSON: %s\n", err) - return "", err - } - - // Sign Token - signed, err := jwt.Sign(t, jwa.HS256, byteKey) - if err != nil { - log.Printf("failed to sign token: %s", err) - return "", err - } - - // Return Token - return string(signed), nil -} - -func (auth *AuthManager) CreateJWTAccessToken(user model.User, device model.Device) (string, error) { - // Create New Token - tm := time.Now() - t := jwt.New() - t.Set(`did`, device.ID) // Device ID - t.Set(`role`, user.Role.String()) // User Role (Admin / User) - t.Set(jwt.SubjectKey, user.ID) // User ID - t.Set(jwt.AudienceKey, `imagini`) // App ID - t.Set(jwt.IssuedAtKey, tm) // Issued At - t.Set(jwt.ExpirationKey, tm.Add(time.Hour*2)) // 2 Hour Access Key - - // Validate Token Creation - _, err := json.MarshalIndent(t, "", " ") - if err != nil { - fmt.Printf("failed to generate JSON: %s\n", err) - return "", err - } - - // Use Server Key - byteKey := []byte(auth.Config.JWTSecret) - - // Sign Token - signed, err := jwt.Sign(t, jwa.HS256, byteKey) - if err != nil { - log.Printf("failed to sign token: %s", err) - return "", err - } - - // Return Token - return string(signed), nil -} diff --git a/internal/auth/jwt.go b/internal/auth/jwt.go new file mode 100644 index 0000000..cd04c13 --- /dev/null +++ b/internal/auth/jwt.go @@ -0,0 +1,126 @@ +package auth + +import ( + "encoding/json" + "errors" + "fmt" + "time" + + "github.com/google/uuid" + "github.com/lestrrat-go/jwx/jwa" + "github.com/lestrrat-go/jwx/jwt" + log "github.com/sirupsen/logrus" + "reichard.io/imagini/graph/model" +) + +func (auth *AuthManager) ValidateJWTRefreshToken(refreshJWT string) (jwt.Token, error) { + byteRefreshJWT := []byte(refreshJWT) + + // Acquire Relevant Device + unverifiedToken, err := jwt.ParseBytes(byteRefreshJWT) + did, ok := unverifiedToken.Get("did") + if !ok { + return nil, errors.New("did does not exist") + } + deviceID, err := uuid.Parse(fmt.Sprintf("%v", did)) + if err != nil { + return nil, errors.New("did does not parse") + } + device := &model.Device{ID: deviceID.String()} + _, err = auth.DB.Device(device) + if err != nil { + return nil, err + } + + // Verify & Validate Token + verifiedToken, err := jwt.ParseBytes(byteRefreshJWT, + jwt.WithValidate(true), + jwt.WithVerify(jwa.HS256, []byte(*device.RefreshKey)), + ) + if err != nil { + fmt.Println("failed to parse payload: ", err) + return nil, err + } + return verifiedToken, nil +} + +func (auth *AuthManager) ValidateJWTAccessToken(accessJWT string) (jwt.Token, error) { + byteAccessJWT := []byte(accessJWT) + verifiedToken, err := jwt.ParseBytes(byteAccessJWT, + jwt.WithValidate(true), + jwt.WithVerify(jwa.HS256, []byte(auth.Config.JWTSecret)), + ) + + if err != nil { + return nil, err + } + + return verifiedToken, nil +} + +func (auth *AuthManager) CreateJWTRefreshToken(user model.User, device model.Device) (string, error) { + // Acquire Refresh Key + byteKey := []byte(*device.RefreshKey) + + // Create New Token + tm := time.Now() + t := jwt.New() + t.Set(`did`, device.ID) // Device ID + t.Set(jwt.SubjectKey, user.ID) // User ID + t.Set(jwt.AudienceKey, `imagini`) // App ID + t.Set(jwt.IssuedAtKey, tm) // Issued At + + // iOS & Android = Never Expiring Refresh Token + if device.Type != "iOS" && device.Type != "Android" { + t.Set(jwt.ExpirationKey, tm.Add(time.Hour*24)) // 1 Day Access Key + } + + // Validate Token Creation + _, err := json.MarshalIndent(t, "", " ") + if err != nil { + fmt.Printf("failed to generate JSON: %s\n", err) + return "", err + } + + // Sign Token + signed, err := jwt.Sign(t, jwa.HS256, byteKey) + if err != nil { + log.Printf("failed to sign token: %s", err) + return "", err + } + + // Return Token + return string(signed), nil +} + +func (auth *AuthManager) CreateJWTAccessToken(user model.User, device model.Device) (string, error) { + // Create New Token + tm := time.Now() + t := jwt.New() + t.Set(`did`, device.ID) // Device ID + t.Set(`role`, user.Role.String()) // User Role (Admin / User) + t.Set(jwt.SubjectKey, user.ID) // User ID + t.Set(jwt.AudienceKey, `imagini`) // App ID + t.Set(jwt.IssuedAtKey, tm) // Issued At + t.Set(jwt.ExpirationKey, tm.Add(time.Hour*2)) // 2 Hour Access Key + + // Validate Token Creation + _, err := json.MarshalIndent(t, "", " ") + if err != nil { + fmt.Printf("failed to generate JSON: %s\n", err) + return "", err + } + + // Use Server Key + byteKey := []byte(auth.Config.JWTSecret) + + // Sign Token + signed, err := jwt.Sign(t, jwa.HS256, byteKey) + if err != nil { + log.Printf("failed to sign token: %s", err) + return "", err + } + + // Return Token + return string(signed), nil +} diff --git a/internal/auth/ldap.go b/internal/auth/ldap.go index 0de965b..c3927e6 100644 --- a/internal/auth/ldap.go +++ b/internal/auth/ldap.go @@ -1,9 +1,9 @@ package auth import ( - "reichard.io/imagini/graph/model" + "reichard.io/imagini/graph/model" ) func authenticateLDAPUser(user model.User, pw string) bool { - return false + return false } diff --git a/internal/auth/local.go b/internal/auth/local.go index b5f06c9..644c2dc 100644 --- a/internal/auth/local.go +++ b/internal/auth/local.go @@ -1,18 +1,18 @@ package auth import ( - "golang.org/x/crypto/bcrypt" - log "github.com/sirupsen/logrus" - "reichard.io/imagini/graph/model" + log "github.com/sirupsen/logrus" + "golang.org/x/crypto/bcrypt" + "reichard.io/imagini/graph/model" ) func authenticateLocalUser(user model.User, pw string) bool { - bPassword :=[]byte(pw) - err := bcrypt.CompareHashAndPassword([]byte(*user.Password), bPassword) - if err == nil { - log.Info("[auth] Authentication successfull: ", user.Username) - return true - } - log.Warn("[auth] Authentication failed: ", user.Username) - return false + bPassword := []byte(pw) + err := bcrypt.CompareHashAndPassword([]byte(*user.Password), bPassword) + if err == nil { + log.Info("[auth] Authentication successfull: ", user.Username) + return true + } + log.Warn("[auth] Authentication failed: ", user.Username) + return false } diff --git a/internal/config/config.go b/internal/config/config.go index 4243563..416af51 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,34 +1,34 @@ package config import ( - "os" + "os" ) type Config struct { - DBType string - DBName string - DBPassword string - DataPath string - ConfigPath string - JWTSecret string - ListenPort string + DBType string + DBName string + DBPassword string + DataPath string + ConfigPath string + JWTSecret string + ListenPort string } func Load() *Config { - return &Config{ - DBType: getEnv("DATABASE_TYPE", "SQLite"), - DBName: getEnv("DATABASE_NAME", "imagini"), - DBPassword: getEnv("DATABASE_PASSWORD", ""), - ConfigPath: getEnv("CONFIG_PATH", "/config"), - DataPath: getEnv("DATA_PATH", "/data"), - JWTSecret: getEnv("JWT_SECRET", "58b9340c0472cf045db226bc445966524e780cd38bc3dd707afce80c95d4de6f"), - ListenPort: getEnv("LISTEN_PORT", "8484"), - } + return &Config{ + DBType: getEnv("DATABASE_TYPE", "SQLite"), + DBName: getEnv("DATABASE_NAME", "imagini"), + DBPassword: getEnv("DATABASE_PASSWORD", ""), + ConfigPath: getEnv("CONFIG_PATH", "/config"), + DataPath: getEnv("DATA_PATH", "/data"), + JWTSecret: getEnv("JWT_SECRET", "58b9340c0472cf045db226bc445966524e780cd38bc3dd707afce80c95d4de6f"), + ListenPort: getEnv("LISTEN_PORT", "8484"), + } } func getEnv(key, fallback string) string { - if value, ok := os.LookupEnv(key); ok { - return value - } - return fallback + if value, ok := os.LookupEnv(key); ok { + return value + } + return fallback } diff --git a/internal/db/db.go b/internal/db/db.go index 3f3de1a..cda921c 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -69,6 +69,7 @@ func (dbm *DBManager) bootstrapDatabase() { } } +// TODO func (dbm *DBManager) QueryBuilder(dest interface{}, params []byte) (int64, error) { // TODO: // - Where Filters diff --git a/internal/db/errors.go b/internal/db/errors.go deleted file mode 100644 index 787ae41..0000000 --- a/internal/db/errors.go +++ /dev/null @@ -1,7 +0,0 @@ -package db - -import "errors" - -var ( - ErrUserAlreadyExists = errors.New("user already exists") -) diff --git a/internal/session/session.go b/internal/session/session.go index 477a22c..e9aa8af 100644 --- a/internal/session/session.go +++ b/internal/session/session.go @@ -1,38 +1,40 @@ package session import ( - "sync" + "sync" ) // Used to maintain a cache of user specific jwt secrets // This will prevent DB lookups on every request +// May not actually be needed. Refresh Token is the only +// token that will require proactive DB lookups. type SessionManager struct { - mutex sync.Mutex - values map[string]string + mutex sync.Mutex + values map[string]string } func NewMgr() *SessionManager { - return &SessionManager{} + return &SessionManager{} } func (sm *SessionManager) Set(key, value string) { - sm.mutex.Lock() - sm.values[key] = value - sm.mutex.Unlock() + sm.mutex.Lock() + sm.values[key] = value + sm.mutex.Unlock() } func (sm *SessionManager) Get(key string) string { - sm.mutex.Lock() - defer sm.mutex.Unlock() - return sm.values[key] + sm.mutex.Lock() + defer sm.mutex.Unlock() + return sm.values[key] } func (sm *SessionManager) Delete(key string) { - sm.mutex.Lock() - defer sm.mutex.Unlock() - _, exists := sm.values[key] - if !exists { - return - } - delete(sm.values, key) + sm.mutex.Lock() + defer sm.mutex.Unlock() + _, exists := sm.values[key] + if !exists { + return + } + delete(sm.values, key) } diff --git a/plugin/models.go b/plugin/models.go index 3682a2d..30cd6f8 100644 --- a/plugin/models.go +++ b/plugin/models.go @@ -42,7 +42,7 @@ type Field struct { Name string Type types.Type Tag string - Gorm string + Gorm string } type Enum struct { @@ -163,21 +163,21 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { typ = types.NewPointer(typ) } - gormType := "" - directive := field.Directives.ForName("meta") - if directive != nil { - arg := directive.Arguments.ForName("gorm") - if arg != nil { - gormType = fmt.Sprintf("gorm:\"%s\"", arg.Value.Raw) - } - } + gormType := "" + directive := field.Directives.ForName("meta") + if directive != nil { + arg := directive.Arguments.ForName("gorm") + if arg != nil { + gormType = fmt.Sprintf("gorm:\"%s\"", arg.Value.Raw) + } + } it.Fields = append(it.Fields, &Field{ Name: name, Type: typ, Description: field.Description, Tag: `json:"` + field.Name + `"`, - Gorm: gormType, + Gorm: gormType, }) } From 548a50278a9787eb25a7eb8952f68e0555277573 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Fri, 5 Feb 2021 22:01:51 -0500 Subject: [PATCH 5/8] MediaItem Upload Support --- graph/generated/generated.go | 564 +++++++++++++++++------------------ graph/helpers.go | 74 +++++ graph/model/models_gen.go | 28 +- graph/resolver.go | 6 +- graph/schema.graphqls | 43 ++- graph/schema.resolvers.go | 141 ++++++--- internal/api/media_item.go | 1 + internal/api/routes.go | 5 +- internal/db/db.go | 19 ++ 9 files changed, 505 insertions(+), 376 deletions(-) create mode 100644 graph/helpers.go create mode 100644 internal/api/media_item.go diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 8aa1d49..18f3311 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -73,7 +73,6 @@ type ComplexityRoot struct { RefreshKey func(childComplexity int) int Type func(childComplexity int) int UpdatedAt func(childComplexity int) int - User func(childComplexity int) int UserID func(childComplexity int) int } @@ -94,7 +93,6 @@ type ComplexityRoot struct { OrigName func(childComplexity int) int Tags func(childComplexity int) int UpdatedAt func(childComplexity int) int - User func(childComplexity int) int UserID func(childComplexity int) int } @@ -105,7 +103,6 @@ type ComplexityRoot struct { Mutation struct { CreateAlbum func(childComplexity int, input model.NewAlbum) int - CreateDevice func(childComplexity int, input model.NewDevice) int CreateMediaItem func(childComplexity int, input model.NewMediaItem) int CreateTag func(childComplexity int, input model.NewTag) int CreateUser func(childComplexity int, input model.NewUser) int @@ -146,16 +143,18 @@ type ComplexityRoot struct { } User struct { - AuthType func(childComplexity int) int - CreatedAt func(childComplexity int) int - Email func(childComplexity int) int - FirstName func(childComplexity int) int - ID func(childComplexity int) int - LastName func(childComplexity int) int - Password func(childComplexity int) int - Role func(childComplexity int) int - UpdatedAt func(childComplexity int) int - Username func(childComplexity int) int + AuthType func(childComplexity int) int + CreatedAt func(childComplexity int) int + Devices func(childComplexity int) int + Email func(childComplexity int) int + FirstName func(childComplexity int) int + ID func(childComplexity int) int + LastName func(childComplexity int) int + MediaItems func(childComplexity int) int + Password func(childComplexity int) int + Role func(childComplexity int) int + UpdatedAt func(childComplexity int) int + Username func(childComplexity int) int } UserResponse struct { @@ -166,7 +165,6 @@ type ComplexityRoot struct { type MutationResolver interface { CreateMediaItem(ctx context.Context, input model.NewMediaItem) (*model.MediaItem, error) - CreateDevice(ctx context.Context, input model.NewDevice) (*model.Device, error) CreateAlbum(ctx context.Context, input model.NewAlbum) (*model.Album, error) CreateTag(ctx context.Context, input model.NewTag) (*model.Tag, error) CreateUser(ctx context.Context, input model.NewUser) (*model.User, error) @@ -307,13 +305,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Device.UpdatedAt(childComplexity), true - case "Device.user": - if e.complexity.Device.User == nil { - break - } - - return e.complexity.Device.User(childComplexity), true - case "Device.userID": if e.complexity.Device.UserID == nil { break @@ -412,13 +403,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.MediaItem.UpdatedAt(childComplexity), true - case "MediaItem.user": - if e.complexity.MediaItem.User == nil { - break - } - - return e.complexity.MediaItem.User(childComplexity), true - case "MediaItem.userID": if e.complexity.MediaItem.UserID == nil { break @@ -452,18 +436,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.CreateAlbum(childComplexity, args["input"].(model.NewAlbum)), true - case "Mutation.createDevice": - if e.complexity.Mutation.CreateDevice == nil { - break - } - - args, err := ec.field_Mutation_createDevice_args(context.TODO(), rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Mutation.CreateDevice(childComplexity, args["input"].(model.NewDevice)), true - case "Mutation.createMediaItem": if e.complexity.Mutation.CreateMediaItem == nil { break @@ -723,6 +695,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.User.CreatedAt(childComplexity), true + case "User.devices": + if e.complexity.User.Devices == nil { + break + } + + return e.complexity.User.Devices(childComplexity), true + case "User.email": if e.complexity.User.Email == nil { break @@ -751,6 +730,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.User.LastName(childComplexity), true + case "User.mediaItems": + if e.complexity.User.MediaItems == nil { + break + } + + return e.complexity.User.MediaItems(childComplexity), true + case "User.password": if e.complexity.User.Password == nil { break @@ -998,6 +984,21 @@ input AuthTypeFilter { # -------------------- Object Definitions -------------------- # ------------------------------------------------------------ +type User { + id: ID! @meta(gorm: "primaryKey;not null") + createdAt: Time + updatedAt: Time + email: String! @meta(gorm: "not null;unique") + username: String! @meta(gorm: "not null;unique") + firstName: String + lastName: String + role: Role! @meta(gorm: "default:User;not null") + authType: AuthType! @meta(gorm: "default:Local;not null") + password: String @isPrivate + devices: [Device!] @meta(gorm: "foreignKey:UserID") + mediaItems: [MediaItem!] @meta(gorm: "foreignKey:UserID") +} + type Device { id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time @@ -1005,21 +1006,7 @@ type Device { name: String! @meta(gorm: "not null") type: DeviceType! @meta(gorm: "default:Unknown;not null") userID: ID! @meta(gorm: "not null") - user: User! @meta(gorm: "foreignKey:ID;references:UserID;not null") - refreshKey: String @deprecated(reason: "Private Field") # @isPrivate -} - -type User { - id: ID! @meta(gorm: "primaryKey;not null") - createdAt: Time - updatedAt: Time - email: String! @meta(gorm: "not null;unique") - username: String! @meta(gorm: "not null;unique") - firstName: String - lastName: String - role: Role! @meta(gorm: "default:User;not null") - authType: AuthType! @meta(gorm: "default:Local;not null") - password: String @deprecated(reason: "Private Field") #@isPrivate + refreshKey: String @isPrivate } type MediaItem { @@ -1035,21 +1022,20 @@ type MediaItem { tags: [Tag] @meta(gorm: "many2many:media_tags") albums: [Album] @meta(gorm: "many2many:media_albums") userID: ID! @meta(gorm: "not null") - user: User! @meta(gorm: "foreignKey:ID;references:UserID;not null") } type Tag { - id: ID! @meta(gorm: "primaryKey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time - name: String! @meta(gorm: "unique;not null") + name: String! @meta(gorm: "unique;not null") } type Album { - id: ID! @meta(gorm: "primaryKey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time - name: String! @meta(gorm: "unique;not null") + name: String! @meta(gorm: "unique;not null") } # ------------------------------------------------------------ @@ -1131,10 +1117,6 @@ input NewUser { password: String } -input NewDevice { - name: String! -} - input NewMediaItem { file: Upload! tags: [ID!] @@ -1236,7 +1218,6 @@ type Query { type Mutation { createMediaItem(input: NewMediaItem!): MediaItem! @hasMinRole(role: User) - createDevice(input: NewDevice!): Device! @hasMinRole(role: User) createAlbum(input: NewAlbum!): Album! @hasMinRole(role: User) createTag(input: NewTag!): Tag! @hasMinRole(role: User) createUser(input: NewUser!): User! @hasMinRole(role: Admin) @@ -1294,21 +1275,6 @@ func (ec *executionContext) field_Mutation_createAlbum_args(ctx context.Context, return args, nil } -func (ec *executionContext) field_Mutation_createDevice_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { - var err error - args := map[string]interface{}{} - var arg0 model.NewDevice - if tmp, ok := rawArgs["input"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - arg0, err = ec.unmarshalNNewDevice2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewDevice(ctx, tmp) - if err != nil { - return nil, err - } - } - args["input"] = arg0 - return args, nil -} - func (ec *executionContext) field_Mutation_createMediaItem_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -2328,7 +2294,7 @@ func (ec *executionContext) _Device_userID(ctx context.Context, field graphql.Co return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _Device_user(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { +func (ec *executionContext) _Device_refreshKey(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2347,17 +2313,13 @@ func (ec *executionContext) _Device_user(ctx context.Context, field graphql.Coll resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.User, nil + return obj.RefreshKey, nil } directive1 := func(ctx context.Context) (interface{}, error) { - gorm, err := ec.unmarshalOString2ᚖstring(ctx, "foreignKey:ID;references:UserID;not null") - if err != nil { - return nil, err + if ec.directives.IsPrivate == nil { + return nil, errors.New("directive isPrivate is not implemented") } - if ec.directives.Meta == nil { - return nil, errors.New("directive meta is not implemented") - } - return ec.directives.Meta(ctx, obj, directive0, gorm) + return ec.directives.IsPrivate(ctx, obj, directive0) } tmp, err := directive1(rctx) @@ -2367,45 +2329,10 @@ func (ec *executionContext) _Device_user(ctx context.Context, field graphql.Coll if tmp == nil { return nil, nil } - if data, ok := tmp.(*model.User); ok { + if data, ok := tmp.(*string); ok { return data, nil } - return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.User`, tmp) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(*model.User) - fc.Result = res - return ec.marshalNUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) -} - -func (ec *executionContext) _Device_refreshKey(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - fc := &graphql.FieldContext{ - Object: "Device", - Field: field, - Args: nil, - IsMethod: false, - IsResolver: false, - } - - ctx = graphql.WithFieldContext(ctx, fc) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.RefreshKey, nil + return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) }) if err != nil { ec.Error(ctx, err) @@ -3053,65 +2980,6 @@ func (ec *executionContext) _MediaItem_userID(ctx context.Context, field graphql return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _MediaItem_user(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - fc := &graphql.FieldContext{ - Object: "MediaItem", - Field: field, - Args: nil, - IsMethod: false, - IsResolver: false, - } - - ctx = graphql.WithFieldContext(ctx, fc) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - directive0 := func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.User, nil - } - directive1 := func(ctx context.Context) (interface{}, error) { - gorm, err := ec.unmarshalOString2ᚖstring(ctx, "foreignKey:ID;references:UserID;not null") - if err != nil { - return nil, err - } - if ec.directives.Meta == nil { - return nil, errors.New("directive meta is not implemented") - } - return ec.directives.Meta(ctx, obj, directive0, gorm) - } - - tmp, err := directive1(rctx) - if err != nil { - return nil, graphql.ErrorOnPath(ctx, err) - } - if tmp == nil { - return nil, nil - } - if data, ok := tmp.(*model.User); ok { - return data, nil - } - return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.User`, tmp) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(*model.User) - fc.Result = res - return ec.marshalNUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) -} - func (ec *executionContext) _MediaItemResponse_data(ctx context.Context, field graphql.CollectedField, obj *model.MediaItemResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -3245,72 +3113,6 @@ func (ec *executionContext) _Mutation_createMediaItem(ctx context.Context, field return ec.marshalNMediaItem2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItem(ctx, field.Selections, res) } -func (ec *executionContext) _Mutation_createDevice(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - fc := &graphql.FieldContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, - IsResolver: true, - } - - ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Mutation_createDevice_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - directive0 := func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().CreateDevice(rctx, args["input"].(model.NewDevice)) - } - directive1 := func(ctx context.Context) (interface{}, error) { - role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") - if err != nil { - return nil, err - } - if ec.directives.HasMinRole == nil { - return nil, errors.New("directive hasMinRole is not implemented") - } - return ec.directives.HasMinRole(ctx, nil, directive0, role) - } - - tmp, err := directive1(rctx) - if err != nil { - return nil, graphql.ErrorOnPath(ctx, err) - } - if tmp == nil { - return nil, nil - } - if data, ok := tmp.(*model.Device); ok { - return data, nil - } - return nil, fmt.Errorf(`unexpected type %T from directive, should be *reichard.io/imagini/graph/model.Device`, tmp) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(*model.Device) - fc.Result = res - return ec.marshalNDevice2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx, field.Selections, res) -} - func (ec *executionContext) _Mutation_createAlbum(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -5194,8 +4996,28 @@ func (ec *executionContext) _User_password(ctx context.Context, field graphql.Co ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Password, nil + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Password, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + if ec.directives.IsPrivate == nil { + return nil, errors.New("directive isPrivate is not implemented") + } + return ec.directives.IsPrivate(ctx, obj, directive0) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) }) if err != nil { ec.Error(ctx, err) @@ -5209,6 +5031,118 @@ func (ec *executionContext) _User_password(ctx context.Context, field graphql.Co return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } +func (ec *executionContext) _User_devices(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Devices, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "foreignKey:UserID") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.([]*model.Device); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be []*reichard.io/imagini/graph/model.Device`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.Device) + fc.Result = res + return ec.marshalODevice2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_mediaItems(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MediaItems, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "foreignKey:UserID") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.([]*model.MediaItem); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be []*reichard.io/imagini/graph/model.MediaItem`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.MediaItem) + fc.Result = res + return ec.marshalOMediaItem2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemᚄ(ctx, field.Selections, res) +} + func (ec *executionContext) _UserResponse_data(ctx context.Context, field graphql.CollectedField, obj *model.UserResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -6931,26 +6865,6 @@ func (ec *executionContext) unmarshalInputNewAlbum(ctx context.Context, obj inte return it, nil } -func (ec *executionContext) unmarshalInputNewDevice(ctx context.Context, obj interface{}) (model.NewDevice, error) { - var it model.NewDevice - var asMap = obj.(map[string]interface{}) - - for k, v := range asMap { - switch k { - case "name": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) - it.Name, err = ec.unmarshalNString2string(ctx, v) - if err != nil { - return it, err - } - } - } - - return it, nil -} - func (ec *executionContext) unmarshalInputNewMediaItem(ctx context.Context, obj interface{}) (model.NewMediaItem, error) { var it model.NewMediaItem var asMap = obj.(map[string]interface{}) @@ -7610,11 +7524,6 @@ func (ec *executionContext) _Device(ctx context.Context, sel ast.SelectionSet, o if out.Values[i] == graphql.Null { invalids++ } - case "user": - out.Values[i] = ec._Device_user(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } case "refreshKey": out.Values[i] = ec._Device_refreshKey(ctx, field, obj) default: @@ -7707,11 +7616,6 @@ func (ec *executionContext) _MediaItem(ctx context.Context, sel ast.SelectionSet if out.Values[i] == graphql.Null { invalids++ } - case "user": - out.Values[i] = ec._MediaItem_user(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -7772,11 +7676,6 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { invalids++ } - case "createDevice": - out.Values[i] = ec._Mutation_createDevice(ctx, field) - if out.Values[i] == graphql.Null { - invalids++ - } case "createAlbum": out.Values[i] = ec._Mutation_createAlbum(ctx, field) if out.Values[i] == graphql.Null { @@ -8163,6 +8062,10 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj } case "password": out.Values[i] = ec._User_password(ctx, field, obj) + case "devices": + out.Values[i] = ec._User_devices(ctx, field, obj) + case "mediaItems": + out.Values[i] = ec._User_mediaItems(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -8641,11 +8544,6 @@ func (ec *executionContext) unmarshalNNewAlbum2reichardᚗioᚋimaginiᚋgraph return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalNNewDevice2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewDevice(ctx context.Context, v interface{}) (model.NewDevice, error) { - res, err := ec.unmarshalInputNewDevice(ctx, v) - return res, graphql.ErrorOnPath(ctx, err) -} - func (ec *executionContext) unmarshalNNewMediaItem2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐNewMediaItem(ctx context.Context, v interface{}) (model.NewMediaItem, error) { res, err := ec.unmarshalInputNewMediaItem(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -9211,6 +9109,46 @@ func (ec *executionContext) marshalODevice2ᚕᚖreichardᚗioᚋimaginiᚋgraph return ret } +func (ec *executionContext) marshalODevice2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Device) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNDevice2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + func (ec *executionContext) marshalODevice2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx context.Context, sel ast.SelectionSet, v *model.Device) graphql.Marshaler { if v == nil { return graphql.Null @@ -9523,6 +9461,46 @@ func (ec *executionContext) marshalOMediaItem2ᚕᚖreichardᚗioᚋimaginiᚋgr return ret } +func (ec *executionContext) marshalOMediaItem2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.MediaItem) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNMediaItem2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItem(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + func (ec *executionContext) marshalOMediaItem2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItem(ctx context.Context, sel ast.SelectionSet, v *model.MediaItem) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/helpers.go b/graph/helpers.go new file mode 100644 index 0000000..e2b2c07 --- /dev/null +++ b/graph/helpers.go @@ -0,0 +1,74 @@ +package graph + +import ( + "net/http" + "strings" + "time" + + "github.com/dsoprea/go-exif/v3" + exifcommon "github.com/dsoprea/go-exif/v3/common" + "reichard.io/imagini/graph/model" +) + +func deriveDeviceType(r *http.Request) model.DeviceType { + userAgent := strings.ToLower(r.Header.Get("User-Agent")) + if strings.Contains(userAgent, "ios-imagini") { + return model.DeviceTypeIOs + } else if strings.Contains(userAgent, "android-imagini") { + return model.DeviceTypeAndroid + } else if strings.Contains(userAgent, "chrome") { + return model.DeviceTypeChrome + } else if strings.Contains(userAgent, "firefox") { + return model.DeviceTypeFirefox + } else if strings.Contains(userAgent, "msie") { + return model.DeviceTypeInternetExplorer + } else if strings.Contains(userAgent, "edge") { + return model.DeviceTypeEdge + } else if strings.Contains(userAgent, "safari") { + return model.DeviceTypeSafari + } + return model.DeviceTypeUnknown +} + +func mediaItemFromEXIFData(filePath string) (*model.MediaItem, error) { + rawExif, err := exif.SearchFileAndExtractExif(filePath) + entries, _, err := exif.GetFlatExifData(rawExif, nil) + + decLong := float64(1) + decLat := float64(1) + + mediaItem := &model.MediaItem{} + for _, v := range entries { + if v.TagName == "DateTimeOriginal" { + formattedTime, _ := time.Parse("2006:01:02 15:04:05", v.Formatted) + mediaItem.ExifDate = &formattedTime + } else if v.TagName == "GPSLatitude" { + latStruct := v.Value.([]exifcommon.Rational) + decLat *= deriveDecimalCoordinate( + latStruct[0].Numerator/latStruct[0].Denominator, + latStruct[1].Numerator/latStruct[1].Denominator, + float64(latStruct[2].Numerator)/float64(latStruct[2].Denominator), + ) + } else if v.TagName == "GPSLongitude" { + longStruct := v.Value.([]exifcommon.Rational) + decLong *= deriveDecimalCoordinate( + longStruct[0].Numerator/longStruct[0].Denominator, + longStruct[1].Numerator/longStruct[1].Denominator, + float64(longStruct[2].Numerator)/float64(longStruct[2].Denominator), + ) + } else if v.TagName == "GPSLatitudeRef" && v.Formatted == "S" { + decLat *= -1 + } else if v.TagName == "GPSLongitudeRef" && v.Formatted == "W" { + decLong *= -1 + } + } + + mediaItem.Latitude = &decLat + mediaItem.Longitude = &decLong + + return mediaItem, err +} + +func deriveDecimalCoordinate(degrees, minutes uint32, seconds float64) float64 { + return float64(degrees) + (float64(minutes) / 60) + (seconds / 3600) +} diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index d54d2f4..6b3fa1e 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -57,7 +57,6 @@ type Device struct { Name string `json:"name" gorm:"not null"` Type DeviceType `json:"type" gorm:"default:Unknown;not null"` UserID string `json:"userID" gorm:"not null"` - User *User `json:"user" gorm:"foreignKey:ID;references:UserID;not null"` RefreshKey *string `json:"refreshKey" ` } @@ -125,7 +124,6 @@ type MediaItem struct { Tags []*Tag `json:"tags" gorm:"many2many:media_tags"` Albums []*Album `json:"albums" gorm:"many2many:media_albums"` UserID string `json:"userID" gorm:"not null"` - User *User `json:"user" gorm:"foreignKey:ID;references:UserID;not null"` } type MediaItemFilter struct { @@ -152,10 +150,6 @@ type NewAlbum struct { Name string `json:"name" ` } -type NewDevice struct { - Name string `json:"name" ` -} - type NewMediaItem struct { File graphql.Upload `json:"file" ` Tags []string `json:"tags" ` @@ -239,16 +233,18 @@ type TimeFilter struct { } type User struct { - ID string `json:"id" gorm:"primaryKey;not null"` - CreatedAt *time.Time `json:"createdAt" ` - UpdatedAt *time.Time `json:"updatedAt" ` - Email string `json:"email" gorm:"not null;unique"` - Username string `json:"username" gorm:"not null;unique"` - FirstName *string `json:"firstName" ` - LastName *string `json:"lastName" ` - Role Role `json:"role" gorm:"default:User;not null"` - AuthType AuthType `json:"authType" gorm:"default:Local;not null"` - Password *string `json:"password" ` + ID string `json:"id" gorm:"primaryKey;not null"` + CreatedAt *time.Time `json:"createdAt" ` + UpdatedAt *time.Time `json:"updatedAt" ` + Email string `json:"email" gorm:"not null;unique"` + Username string `json:"username" gorm:"not null;unique"` + FirstName *string `json:"firstName" ` + LastName *string `json:"lastName" ` + Role Role `json:"role" gorm:"default:User;not null"` + AuthType AuthType `json:"authType" gorm:"default:Local;not null"` + Password *string `json:"password" ` + Devices []*Device `json:"devices" gorm:"foreignKey:UserID"` + MediaItems []*MediaItem `json:"mediaItems" gorm:"foreignKey:UserID"` } type UserFilter struct { diff --git a/graph/resolver.go b/graph/resolver.go index 4249b75..59a1c97 100644 --- a/graph/resolver.go +++ b/graph/resolver.go @@ -2,6 +2,7 @@ package graph import ( "reichard.io/imagini/internal/auth" + "reichard.io/imagini/internal/config" "reichard.io/imagini/internal/db" ) @@ -10,6 +11,7 @@ import ( // It serves as dependency injection for your app, add any dependencies you require here. type Resolver struct { - Auth *auth.AuthManager - DB *db.DBManager + Config *config.Config + Auth *auth.AuthManager + DB *db.DBManager } diff --git a/graph/schema.graphqls b/graph/schema.graphqls index 4d67510..2dc90a9 100644 --- a/graph/schema.graphqls +++ b/graph/schema.graphqls @@ -139,6 +139,21 @@ input AuthTypeFilter { # -------------------- Object Definitions -------------------- # ------------------------------------------------------------ +type User { + id: ID! @meta(gorm: "primaryKey;not null") + createdAt: Time + updatedAt: Time + email: String! @meta(gorm: "not null;unique") + username: String! @meta(gorm: "not null;unique") + firstName: String + lastName: String + role: Role! @meta(gorm: "default:User;not null") + authType: AuthType! @meta(gorm: "default:Local;not null") + password: String @isPrivate + devices: [Device!] @meta(gorm: "foreignKey:UserID") + mediaItems: [MediaItem!] @meta(gorm: "foreignKey:UserID") +} + type Device { id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time @@ -146,23 +161,9 @@ type Device { name: String! @meta(gorm: "not null") type: DeviceType! @meta(gorm: "default:Unknown;not null") userID: ID! @meta(gorm: "not null") - user: User! @meta(gorm: "foreignKey:ID;references:UserID;not null") refreshKey: String @isPrivate } -type User { - id: ID! @meta(gorm: "primaryKey;not null") - createdAt: Time - updatedAt: Time - email: String! @meta(gorm: "not null;unique") - username: String! @meta(gorm: "not null;unique") - firstName: String - lastName: String - role: Role! @meta(gorm: "default:User;not null") - authType: AuthType! @meta(gorm: "default:Local;not null") - password: String @isPrivate -} - type MediaItem { id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time @@ -176,21 +177,20 @@ type MediaItem { tags: [Tag] @meta(gorm: "many2many:media_tags") albums: [Album] @meta(gorm: "many2many:media_albums") userID: ID! @meta(gorm: "not null") - user: User! @meta(gorm: "foreignKey:ID;references:UserID;not null") } type Tag { - id: ID! @meta(gorm: "primaryKey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time - name: String! @meta(gorm: "unique;not null") + name: String! @meta(gorm: "unique;not null") } type Album { - id: ID! @meta(gorm: "primaryKey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time - name: String! @meta(gorm: "unique;not null") + name: String! @meta(gorm: "unique;not null") } # ------------------------------------------------------------ @@ -272,10 +272,6 @@ input NewUser { password: String } -input NewDevice { - name: String! -} - input NewMediaItem { file: Upload! tags: [ID!] @@ -377,7 +373,6 @@ type Query { type Mutation { createMediaItem(input: NewMediaItem!): MediaItem! @hasMinRole(role: User) - createDevice(input: NewDevice!): Device! @hasMinRole(role: User) createAlbum(input: NewAlbum!): Album! @hasMinRole(role: User) createTag(input: NewTag!): Tag! @hasMinRole(role: User) createUser(input: NewUser!): User! @hasMinRole(role: Admin) diff --git a/graph/schema.resolvers.go b/graph/schema.resolvers.go index 6f54faa..8d66e4e 100644 --- a/graph/schema.resolvers.go +++ b/graph/schema.resolvers.go @@ -4,22 +4,100 @@ package graph // will be copied through when generating and any unknown code will be moved to the end. import ( + "bytes" "context" + "errors" "fmt" + "io" "net/http" + "os" + "path" "strings" + "time" + "github.com/gabriel-vasile/mimetype" "github.com/google/uuid" "reichard.io/imagini/graph/generated" "reichard.io/imagini/graph/model" ) +// Done func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewMediaItem) (*model.MediaItem, error) { - panic(fmt.Errorf("not implemented")) -} + // Get Context + authContext := ctx.Value("auth").(*model.AuthContext) + accessToken := *authContext.AccessToken + userID, ok := accessToken.Get("sub") + if !ok { + return nil, errors.New("Upload Failed") + } -func (r *mutationResolver) CreateDevice(ctx context.Context, input model.NewDevice) (*model.Device, error) { - panic(fmt.Errorf("not implemented")) + // File header placeholder + fileHeader := make([]byte, 64) + + // Copy headers into the buffer + if _, err := input.File.File.Read(fileHeader); err != nil { + return nil, errors.New("Upload Failed") + } + + // Determine media type + fileMime := mimetype.Detect(fileHeader) + contentType := fileMime.String() + var isVideo bool + if strings.HasPrefix(contentType, "image/") { + isVideo = false + } else if strings.HasPrefix(contentType, "video/") { + isVideo = true + } else { + return nil, errors.New("Upload Failed") + } + + // Derive Folder & File Path + mediaItemID := uuid.New().String() + fileName := mediaItemID + fileMime.Extension() + folderPath := path.Join("/" + r.Config.DataPath + "/media/" + userID.(string)) + os.MkdirAll(folderPath, 0700) + filePath := path.Join(folderPath + "/" + fileName) + + // Create File + f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + return nil, errors.New("Upload Failed") + } + defer f.Close() + + // Copy header to file + _, err = io.Copy(f, bytes.NewReader(fileHeader)) + if err != nil { + return nil, errors.New("Upload Failed") + } + + // Copy remaining file + _, err = io.Copy(f, input.File.File) + if err != nil { + return nil, errors.New("Upload Failed") + } + + // Create MediaItem From EXIF Data + mediaItem, err := mediaItemFromEXIFData(filePath) + if err != nil { + return nil, errors.New("Upload Failed") + } + + // Add Additional MediaItem Fields + mediaItem.ID = mediaItemID + mediaItem.UserID = userID.(string) + mediaItem.IsVideo = isVideo + mediaItem.FileName = fileName + mediaItem.OrigName = input.File.Filename + + // Create MediaItem in DB + err = r.DB.CreateMediaItem(mediaItem) + if err != nil { + return nil, errors.New("Upload Failed") + } + + // Success + return mediaItem, nil } func (r *mutationResolver) CreateAlbum(ctx context.Context, input model.NewAlbum) (*model.Album, error) { @@ -50,11 +128,17 @@ func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser) } func (r *queryResolver) Login(ctx context.Context, user string, password string, deviceID *string) (*model.AuthResponse, error) { - // Set Cookie From Context + // Get Context authContext := ctx.Value("auth").(*model.AuthContext) resp := authContext.AuthResponse req := authContext.AuthRequest + // Clear All Cookies By Default + accessCookie := http.Cookie{Name: "AccessToken", Path: "/", HttpOnly: true, MaxAge: -1, Expires: time.Now().Add(-100 * time.Hour)} + refreshCookie := http.Cookie{Name: "RefreshToken", Path: "/", HttpOnly: true, MaxAge: -1, Expires: time.Now().Add(-100 * time.Hour)} + http.SetCookie(*resp, &accessCookie) + http.SetCookie(*resp, &refreshCookie) + // Do Login foundUser, success := r.Auth.AuthenticateUser(user, password) if !success { @@ -62,7 +146,7 @@ func (r *queryResolver) Login(ctx context.Context, user string, password string, } // Upsert Device - foundDevice := model.Device{} + foundDevice := model.Device{UserID: foundUser.ID} if deviceID != nil { parsedDeviceID, err := uuid.Parse(*deviceID) if err != nil { @@ -75,8 +159,6 @@ func (r *queryResolver) Login(ctx context.Context, user string, password string, } } else { foundDevice.Type = deriveDeviceType(req) - foundDevice.UserID = foundUser.ID - // TODO: foundDevice.User = &foundUser err := r.DB.CreateDevice(&foundDevice) if err != nil { return &model.AuthResponse{Result: model.AuthResultFailure}, nil @@ -94,18 +176,25 @@ func (r *queryResolver) Login(ctx context.Context, user string, password string, } // Set appropriate cookies - accessCookie := http.Cookie{Name: "AccessToken", Value: accessToken, Path: "/", HttpOnly: true} - refreshCookie := http.Cookie{Name: "RefreshToken", Value: refreshToken, Path: "/", HttpOnly: true} + accessCookie = http.Cookie{Name: "AccessToken", Value: accessToken, Path: "/", HttpOnly: true} + refreshCookie = http.Cookie{Name: "RefreshToken", Value: refreshToken, Path: "/", HttpOnly: true} http.SetCookie(*resp, &accessCookie) http.SetCookie(*resp, &refreshCookie) - // TODO: Prob bandaid - foundDevice.User = &foundUser return &model.AuthResponse{Result: model.AuthResultSuccess, Device: &foundDevice}, nil } func (r *queryResolver) Logout(ctx context.Context) (*model.AuthResponse, error) { - // panic(fmt.Errorf("not implemented")) + // Set Cookie From Context + authContext := ctx.Value("auth").(*model.AuthContext) + resp := authContext.AuthResponse + + // Clear All Cookies + accessCookie := http.Cookie{Name: "AccessToken", Path: "/", HttpOnly: true, MaxAge: -1, Expires: time.Now().Add(-100 * time.Hour)} + refreshCookie := http.Cookie{Name: "RefreshToken", Path: "/", HttpOnly: true, MaxAge: -1, Expires: time.Now().Add(-100 * time.Hour)} + http.SetCookie(*resp, &accessCookie) + http.SetCookie(*resp, &refreshCookie) + return &model.AuthResponse{Result: model.AuthResultSuccess}, nil } @@ -172,29 +261,3 @@ func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } 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 deriveDeviceType(r *http.Request) model.DeviceType { - userAgent := strings.ToLower(r.Header.Get("User-Agent")) - if strings.Contains(userAgent, "ios-imagini") { - return model.DeviceTypeIOs - } else if strings.Contains(userAgent, "android-imagini") { - return model.DeviceTypeAndroid - } else if strings.Contains(userAgent, "chrome") { - return model.DeviceTypeChrome - } else if strings.Contains(userAgent, "firefox") { - return model.DeviceTypeFirefox - } else if strings.Contains(userAgent, "msie") { - return model.DeviceTypeInternetExplorer - } else if strings.Contains(userAgent, "edge") { - return model.DeviceTypeEdge - } else if strings.Contains(userAgent, "safari") { - return model.DeviceTypeSafari - } - return model.DeviceTypeUnknown -} diff --git a/internal/api/media_item.go b/internal/api/media_item.go new file mode 100644 index 0000000..778f64e --- /dev/null +++ b/internal/api/media_item.go @@ -0,0 +1 @@ +package api diff --git a/internal/api/routes.go b/internal/api/routes.go index 2e342f2..265c9fc 100644 --- a/internal/api/routes.go +++ b/internal/api/routes.go @@ -12,8 +12,9 @@ func (api *API) registerRoutes() { // Set up Directives graphConfig := generated.Config{ Resolvers: &graph.Resolver{ - DB: api.DB, - Auth: api.Auth, + DB: api.DB, + Auth: api.Auth, + Config: api.Config, }, Directives: generated.DirectiveRoot{ Meta: api.metaDirective, diff --git a/internal/db/db.go b/internal/db/db.go index cda921c..4121c42 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -48,9 +48,28 @@ func NewMgr(c *config.Config) *DBManager { dbm.bootstrapDatabase() } + dbm.testFeatures() + return dbm } +func (dbm *DBManager) testFeatures() { + + // Get Devices By UserID + // var myDevices []model.Device + // dbm.db.Debug().Where(&model.Device{UserID: "97589354-cd42-40e2-bc5e-7ba6badf89fa"}).Find(&myDevices) + // fmt.Printf("Devices: %+v\n", myDevices) + + // Get User by DeviceID + // var myUser []model.User + // dbm.db.Debug().Model(&model.User{}). + // Select("users.*"). + // Joins("left join devices on users.id = devices.user_id"). + // Where("devices.id = ?", "4e9aa851-f25b-4330-91dc-c0f975e56fa1"). + // Find(&myUser) + // fmt.Printf("User: %+v\n", myUser) +} + func (dbm *DBManager) bootstrapDatabase() { log.Info("[query] Bootstrapping database.") From 5fede6d6dac25b251116e48aa96c886af51126f9 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Sat, 6 Feb 2021 21:11:44 -0500 Subject: [PATCH 6/8] Moregit add internal/* --- graph/generated/generated.go | 387 ++++++++++++++++++++++++----------- graph/schema.graphqls | 42 +++- graph/schema.resolvers.go | 198 +++++++++++++++--- internal/db/albums.go | 29 +++ internal/db/devices.go | 7 + internal/db/media_items.go | 11 +- internal/db/tags.go | 29 +++ 7 files changed, 538 insertions(+), 165 deletions(-) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 18f3311..3c9fec9 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -115,19 +115,19 @@ type ComplexityRoot struct { } Query struct { - Album func(childComplexity int, id string) int - Albums func(childComplexity int, filter *model.AlbumFilter, count *int, page *int) int - Device func(childComplexity int, id string) int - Devices func(childComplexity int, filter *model.DeviceFilter, count *int, page *int) int + Album func(childComplexity int, id string, delete *bool) int + Albums func(childComplexity int, delete *bool, filter *model.AlbumFilter, count *int, page *int) int + Device func(childComplexity int, id string, delete *bool) int + Devices func(childComplexity int, delete *bool, filter *model.DeviceFilter, count *int, page *int) int Login func(childComplexity int, user string, password string, deviceID *string) int Logout func(childComplexity int) int - Me func(childComplexity int) int - MediaItem func(childComplexity int, id string) int - MediaItems func(childComplexity int, filter *model.MediaItemFilter, count *int, page *int) int - Tag func(childComplexity int, id string) int - Tags func(childComplexity int, filter *model.TagFilter, count *int, page *int) int - User func(childComplexity int, id string) int - Users func(childComplexity int, filter *model.UserFilter, count *int, page *int) int + Me func(childComplexity int, delete *bool) int + MediaItem func(childComplexity int, id string, delete *bool) int + MediaItems func(childComplexity int, delete *bool, filter *model.MediaItemFilter, count *int, page *int) int + Tag func(childComplexity int, id string, delete *bool) int + Tags func(childComplexity int, delete *bool, filter *model.TagFilter, count *int, page *int) int + User func(childComplexity int, id string, delete *bool) int + Users func(childComplexity int, delete *bool, filter *model.UserFilter, count *int, page *int) int } Tag struct { @@ -172,17 +172,17 @@ type MutationResolver interface { type QueryResolver interface { Login(ctx context.Context, user string, password string, deviceID *string) (*model.AuthResponse, error) Logout(ctx context.Context) (*model.AuthResponse, error) - MediaItem(ctx context.Context, id string) (*model.MediaItem, error) - Device(ctx context.Context, id string) (*model.Device, error) - Album(ctx context.Context, id string) (*model.Album, error) - User(ctx context.Context, id string) (*model.User, error) - Tag(ctx context.Context, id string) (*model.Tag, error) - Me(ctx context.Context) (*model.User, error) - MediaItems(ctx context.Context, filter *model.MediaItemFilter, count *int, page *int) (*model.MediaItemResponse, error) - Devices(ctx context.Context, filter *model.DeviceFilter, count *int, page *int) (*model.DeviceResponse, error) - Albums(ctx context.Context, filter *model.AlbumFilter, count *int, page *int) (*model.AlbumResponse, error) - Tags(ctx context.Context, filter *model.TagFilter, count *int, page *int) (*model.TagResponse, error) - Users(ctx context.Context, filter *model.UserFilter, count *int, page *int) (*model.UserResponse, error) + MediaItem(ctx context.Context, id string, delete *bool) (*model.MediaItem, error) + Device(ctx context.Context, id string, delete *bool) (*model.Device, error) + Album(ctx context.Context, id string, delete *bool) (*model.Album, error) + User(ctx context.Context, id string, delete *bool) (*model.User, error) + Tag(ctx context.Context, id string, delete *bool) (*model.Tag, error) + Me(ctx context.Context, delete *bool) (*model.User, error) + MediaItems(ctx context.Context, delete *bool, filter *model.MediaItemFilter, count *int, page *int) (*model.MediaItemResponse, error) + Devices(ctx context.Context, delete *bool, filter *model.DeviceFilter, count *int, page *int) (*model.DeviceResponse, error) + Albums(ctx context.Context, delete *bool, filter *model.AlbumFilter, count *int, page *int) (*model.AlbumResponse, error) + Tags(ctx context.Context, delete *bool, filter *model.TagFilter, count *int, page *int) (*model.TagResponse, error) + Users(ctx context.Context, delete *bool, filter *model.UserFilter, count *int, page *int) (*model.UserResponse, error) } type executableSchema struct { @@ -503,7 +503,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Album(childComplexity, args["id"].(string)), true + return e.complexity.Query.Album(childComplexity, args["id"].(string), args["delete"].(*bool)), true case "Query.albums": if e.complexity.Query.Albums == nil { @@ -515,7 +515,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Albums(childComplexity, args["filter"].(*model.AlbumFilter), args["count"].(*int), args["page"].(*int)), true + return e.complexity.Query.Albums(childComplexity, args["delete"].(*bool), args["filter"].(*model.AlbumFilter), args["count"].(*int), args["page"].(*int)), true case "Query.device": if e.complexity.Query.Device == nil { @@ -527,7 +527,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Device(childComplexity, args["id"].(string)), true + return e.complexity.Query.Device(childComplexity, args["id"].(string), args["delete"].(*bool)), true case "Query.devices": if e.complexity.Query.Devices == nil { @@ -539,7 +539,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Devices(childComplexity, args["filter"].(*model.DeviceFilter), args["count"].(*int), args["page"].(*int)), true + return e.complexity.Query.Devices(childComplexity, args["delete"].(*bool), args["filter"].(*model.DeviceFilter), args["count"].(*int), args["page"].(*int)), true case "Query.login": if e.complexity.Query.Login == nil { @@ -565,7 +565,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in break } - return e.complexity.Query.Me(childComplexity), true + args, err := ec.field_Query_me_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Me(childComplexity, args["delete"].(*bool)), true case "Query.mediaItem": if e.complexity.Query.MediaItem == nil { @@ -577,7 +582,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.MediaItem(childComplexity, args["id"].(string)), true + return e.complexity.Query.MediaItem(childComplexity, args["id"].(string), args["delete"].(*bool)), true case "Query.mediaItems": if e.complexity.Query.MediaItems == nil { @@ -589,7 +594,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.MediaItems(childComplexity, args["filter"].(*model.MediaItemFilter), args["count"].(*int), args["page"].(*int)), true + return e.complexity.Query.MediaItems(childComplexity, args["delete"].(*bool), args["filter"].(*model.MediaItemFilter), args["count"].(*int), args["page"].(*int)), true case "Query.tag": if e.complexity.Query.Tag == nil { @@ -601,7 +606,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Tag(childComplexity, args["id"].(string)), true + return e.complexity.Query.Tag(childComplexity, args["id"].(string), args["delete"].(*bool)), true case "Query.tags": if e.complexity.Query.Tags == nil { @@ -613,7 +618,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Tags(childComplexity, args["filter"].(*model.TagFilter), args["count"].(*int), args["page"].(*int)), true + return e.complexity.Query.Tags(childComplexity, args["delete"].(*bool), args["filter"].(*model.TagFilter), args["count"].(*int), args["page"].(*int)), true case "Query.user": if e.complexity.Query.User == nil { @@ -625,7 +630,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.User(childComplexity, args["id"].(string)), true + return e.complexity.Query.User(childComplexity, args["id"].(string), args["delete"].(*bool)), true case "Query.users": if e.complexity.Query.Users == nil { @@ -637,7 +642,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Users(childComplexity, args["filter"].(*model.UserFilter), args["count"].(*int), args["page"].(*int)), true + return e.complexity.Query.Users(childComplexity, args["delete"].(*bool), args["filter"].(*model.UserFilter), args["count"].(*int), args["page"].(*int)), true case "Tag.createdAt": if e.complexity.Tag.CreatedAt == nil { @@ -1032,10 +1037,11 @@ type Tag { } type Album { - id: ID! @meta(gorm: "primaryKey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time - name: String! @meta(gorm: "unique;not null") + name: String! @meta(gorm: "unique;not null") + # userID: ID! @meta(gorm: "not null") } # ------------------------------------------------------------ @@ -1171,49 +1177,68 @@ type AlbumResponse { # ------------------------------------------------------------ type Query { - # Authentication login( user: String! password: String! deviceID: ID ): AuthResponse! - logout: AuthResponse! @hasMinRole(role: User) + logout: AuthResponse! @hasMinRole(role: User) # Single Item - mediaItem(id: ID!): MediaItem! @hasMinRole(role: User) - device(id: ID!): Device! @hasMinRole(role: User) - album(id: ID!): Album! @hasMinRole(role: User) - user(id: ID!): User! @hasMinRole(role: Admin) - tag(id: ID!): Tag! @hasMinRole(role: User) - me: User! @hasMinRole(role: User) + mediaItem( + id: ID! + delete: Boolean + ): MediaItem! @hasMinRole(role: User) + device( + id: ID! + delete: Boolean + ): Device! @hasMinRole(role: User) + album( + id: ID! + delete: Boolean + ): Album! @hasMinRole(role: User) + user( + id: ID! + delete: Boolean + ): User! @hasMinRole(role: Admin) # TODO: Delete All User Content + tag( + id: ID! + delete: Boolean + ): Tag! @hasMinRole(role: User) + me(delete: Boolean): User! @hasMinRole(role: User) # All mediaItems( + delete: Boolean filter: MediaItemFilter count: Int page: Int ): MediaItemResponse! @hasMinRole(role: User) devices( + delete: Boolean filter: DeviceFilter count: Int page: Int ): DeviceResponse! @hasMinRole(role: User) albums( + delete: Boolean filter: AlbumFilter count: Int page: Int ): AlbumResponse! @hasMinRole(role: User) tags( + delete: Boolean filter: TagFilter count: Int page: Int ): TagResponse! @hasMinRole(role: User) users( + delete: Boolean filter: UserFilter count: Int page: Int - ): UserResponse! @hasMinRole(role: Admin) + ): UserResponse! @hasMinRole(role: Admin) # TODO: Delete All User Content } type Mutation { @@ -1347,39 +1372,57 @@ func (ec *executionContext) field_Query_album_args(ctx context.Context, rawArgs } } args["id"] = arg0 + var arg1 *bool + if tmp, ok := rawArgs["delete"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) + arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["delete"] = arg1 return args, nil } func (ec *executionContext) field_Query_albums_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *model.AlbumFilter + var arg0 *bool + if tmp, ok := rawArgs["delete"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) + arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["delete"] = arg0 + var arg1 *model.AlbumFilter if tmp, ok := rawArgs["filter"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg0, err = ec.unmarshalOAlbumFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbumFilter(ctx, tmp) + arg1, err = ec.unmarshalOAlbumFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbumFilter(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg0 - var arg1 *int + args["filter"] = arg1 + var arg2 *int if tmp, ok := rawArgs["count"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) - arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) - if err != nil { - return nil, err - } - } - args["count"] = arg1 - var arg2 *int - if tmp, ok := rawArgs["page"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err } } - args["page"] = arg2 + args["count"] = arg2 + var arg3 *int + if tmp, ok := rawArgs["page"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) + arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["page"] = arg3 return args, nil } @@ -1395,39 +1438,57 @@ func (ec *executionContext) field_Query_device_args(ctx context.Context, rawArgs } } args["id"] = arg0 + var arg1 *bool + if tmp, ok := rawArgs["delete"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) + arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["delete"] = arg1 return args, nil } func (ec *executionContext) field_Query_devices_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *model.DeviceFilter + var arg0 *bool + if tmp, ok := rawArgs["delete"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) + arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["delete"] = arg0 + var arg1 *model.DeviceFilter if tmp, ok := rawArgs["filter"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg0, err = ec.unmarshalODeviceFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceFilter(ctx, tmp) + arg1, err = ec.unmarshalODeviceFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceFilter(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg0 - var arg1 *int + args["filter"] = arg1 + var arg2 *int if tmp, ok := rawArgs["count"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) - arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) - if err != nil { - return nil, err - } - } - args["count"] = arg1 - var arg2 *int - if tmp, ok := rawArgs["page"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err } } - args["page"] = arg2 + args["count"] = arg2 + var arg3 *int + if tmp, ok := rawArgs["page"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) + arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["page"] = arg3 return args, nil } @@ -1464,6 +1525,21 @@ func (ec *executionContext) field_Query_login_args(ctx context.Context, rawArgs return args, nil } +func (ec *executionContext) field_Query_me_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *bool + if tmp, ok := rawArgs["delete"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) + arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["delete"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_mediaItem_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -1476,39 +1552,57 @@ func (ec *executionContext) field_Query_mediaItem_args(ctx context.Context, rawA } } args["id"] = arg0 + var arg1 *bool + if tmp, ok := rawArgs["delete"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) + arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["delete"] = arg1 return args, nil } func (ec *executionContext) field_Query_mediaItems_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *model.MediaItemFilter + var arg0 *bool + if tmp, ok := rawArgs["delete"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) + arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["delete"] = arg0 + var arg1 *model.MediaItemFilter if tmp, ok := rawArgs["filter"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg0, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, tmp) + arg1, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg0 - var arg1 *int + args["filter"] = arg1 + var arg2 *int if tmp, ok := rawArgs["count"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) - arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) - if err != nil { - return nil, err - } - } - args["count"] = arg1 - var arg2 *int - if tmp, ok := rawArgs["page"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err } } - args["page"] = arg2 + args["count"] = arg2 + var arg3 *int + if tmp, ok := rawArgs["page"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) + arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["page"] = arg3 return args, nil } @@ -1524,39 +1618,57 @@ func (ec *executionContext) field_Query_tag_args(ctx context.Context, rawArgs ma } } args["id"] = arg0 + var arg1 *bool + if tmp, ok := rawArgs["delete"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) + arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["delete"] = arg1 return args, nil } func (ec *executionContext) field_Query_tags_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *model.TagFilter + var arg0 *bool + if tmp, ok := rawArgs["delete"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) + arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["delete"] = arg0 + var arg1 *model.TagFilter if tmp, ok := rawArgs["filter"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg0, err = ec.unmarshalOTagFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTagFilter(ctx, tmp) + arg1, err = ec.unmarshalOTagFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTagFilter(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg0 - var arg1 *int + args["filter"] = arg1 + var arg2 *int if tmp, ok := rawArgs["count"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) - arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) - if err != nil { - return nil, err - } - } - args["count"] = arg1 - var arg2 *int - if tmp, ok := rawArgs["page"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err } } - args["page"] = arg2 + args["count"] = arg2 + var arg3 *int + if tmp, ok := rawArgs["page"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) + arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["page"] = arg3 return args, nil } @@ -1572,39 +1684,57 @@ func (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs m } } args["id"] = arg0 + var arg1 *bool + if tmp, ok := rawArgs["delete"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) + arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["delete"] = arg1 return args, nil } func (ec *executionContext) field_Query_users_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *model.UserFilter + var arg0 *bool + if tmp, ok := rawArgs["delete"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) + arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["delete"] = arg0 + var arg1 *model.UserFilter if tmp, ok := rawArgs["filter"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg0, err = ec.unmarshalOUserFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserFilter(ctx, tmp) + arg1, err = ec.unmarshalOUserFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserFilter(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg0 - var arg1 *int + args["filter"] = arg1 + var arg2 *int if tmp, ok := rawArgs["count"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) - arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) - if err != nil { - return nil, err - } - } - args["count"] = arg1 - var arg2 *int - if tmp, ok := rawArgs["page"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err } } - args["page"] = arg2 + args["count"] = arg2 + var arg3 *int + if tmp, ok := rawArgs["page"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) + arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["page"] = arg3 return args, nil } @@ -3543,7 +3673,7 @@ func (ec *executionContext) _Query_mediaItem(ctx context.Context, field graphql. resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().MediaItem(rctx, args["id"].(string)) + return ec.resolvers.Query().MediaItem(rctx, args["id"].(string), args["delete"].(*bool)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -3609,7 +3739,7 @@ func (ec *executionContext) _Query_device(ctx context.Context, field graphql.Col resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Device(rctx, args["id"].(string)) + return ec.resolvers.Query().Device(rctx, args["id"].(string), args["delete"].(*bool)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -3675,7 +3805,7 @@ func (ec *executionContext) _Query_album(ctx context.Context, field graphql.Coll resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Album(rctx, args["id"].(string)) + return ec.resolvers.Query().Album(rctx, args["id"].(string), args["delete"].(*bool)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -3741,7 +3871,7 @@ func (ec *executionContext) _Query_user(ctx context.Context, field graphql.Colle resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().User(rctx, args["id"].(string)) + return ec.resolvers.Query().User(rctx, args["id"].(string), args["delete"].(*bool)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "Admin") @@ -3807,7 +3937,7 @@ func (ec *executionContext) _Query_tag(ctx context.Context, field graphql.Collec resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Tag(rctx, args["id"].(string)) + return ec.resolvers.Query().Tag(rctx, args["id"].(string), args["delete"].(*bool)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -3863,10 +3993,17 @@ func (ec *executionContext) _Query_me(ctx context.Context, field graphql.Collect } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_me_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Me(rctx) + return ec.resolvers.Query().Me(rctx, args["delete"].(*bool)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -3932,7 +4069,7 @@ func (ec *executionContext) _Query_mediaItems(ctx context.Context, field graphql resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().MediaItems(rctx, args["filter"].(*model.MediaItemFilter), args["count"].(*int), args["page"].(*int)) + return ec.resolvers.Query().MediaItems(rctx, args["delete"].(*bool), args["filter"].(*model.MediaItemFilter), args["count"].(*int), args["page"].(*int)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -3998,7 +4135,7 @@ func (ec *executionContext) _Query_devices(ctx context.Context, field graphql.Co resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Devices(rctx, args["filter"].(*model.DeviceFilter), args["count"].(*int), args["page"].(*int)) + return ec.resolvers.Query().Devices(rctx, args["delete"].(*bool), args["filter"].(*model.DeviceFilter), args["count"].(*int), args["page"].(*int)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -4064,7 +4201,7 @@ func (ec *executionContext) _Query_albums(ctx context.Context, field graphql.Col resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Albums(rctx, args["filter"].(*model.AlbumFilter), args["count"].(*int), args["page"].(*int)) + return ec.resolvers.Query().Albums(rctx, args["delete"].(*bool), args["filter"].(*model.AlbumFilter), args["count"].(*int), args["page"].(*int)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -4130,7 +4267,7 @@ func (ec *executionContext) _Query_tags(ctx context.Context, field graphql.Colle resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Tags(rctx, args["filter"].(*model.TagFilter), args["count"].(*int), args["page"].(*int)) + return ec.resolvers.Query().Tags(rctx, args["delete"].(*bool), args["filter"].(*model.TagFilter), args["count"].(*int), args["page"].(*int)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -4196,7 +4333,7 @@ func (ec *executionContext) _Query_users(ctx context.Context, field graphql.Coll resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Users(rctx, args["filter"].(*model.UserFilter), args["count"].(*int), args["page"].(*int)) + return ec.resolvers.Query().Users(rctx, args["delete"].(*bool), args["filter"].(*model.UserFilter), args["count"].(*int), args["page"].(*int)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "Admin") diff --git a/graph/schema.graphqls b/graph/schema.graphqls index 2dc90a9..7501878 100644 --- a/graph/schema.graphqls +++ b/graph/schema.graphqls @@ -187,10 +187,11 @@ type Tag { } type Album { - id: ID! @meta(gorm: "primaryKey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time - name: String! @meta(gorm: "unique;not null") + name: String! @meta(gorm: "unique;not null") + # userID: ID! @meta(gorm: "not null") } # ------------------------------------------------------------ @@ -326,49 +327,68 @@ type AlbumResponse { # ------------------------------------------------------------ type Query { - # Authentication login( user: String! password: String! deviceID: ID ): AuthResponse! - logout: AuthResponse! @hasMinRole(role: User) + logout: AuthResponse! @hasMinRole(role: User) # Single Item - mediaItem(id: ID!): MediaItem! @hasMinRole(role: User) - device(id: ID!): Device! @hasMinRole(role: User) - album(id: ID!): Album! @hasMinRole(role: User) - user(id: ID!): User! @hasMinRole(role: Admin) - tag(id: ID!): Tag! @hasMinRole(role: User) - me: User! @hasMinRole(role: User) + mediaItem( + id: ID! + delete: Boolean + ): MediaItem! @hasMinRole(role: User) + device( + id: ID! + delete: Boolean + ): Device! @hasMinRole(role: User) + album( + id: ID! + delete: Boolean + ): Album! @hasMinRole(role: User) + user( + id: ID! + delete: Boolean + ): User! @hasMinRole(role: Admin) # TODO: Delete All User Content + tag( + id: ID! + delete: Boolean + ): Tag! @hasMinRole(role: User) + me(delete: Boolean): User! @hasMinRole(role: User) # All mediaItems( + delete: Boolean filter: MediaItemFilter count: Int page: Int ): MediaItemResponse! @hasMinRole(role: User) devices( + delete: Boolean filter: DeviceFilter count: Int page: Int ): DeviceResponse! @hasMinRole(role: User) albums( + delete: Boolean filter: AlbumFilter count: Int page: Int ): AlbumResponse! @hasMinRole(role: User) tags( + delete: Boolean filter: TagFilter count: Int page: Int ): TagResponse! @hasMinRole(role: User) users( + delete: Boolean filter: UserFilter count: Int page: Int - ): UserResponse! @hasMinRole(role: Admin) + ): UserResponse! @hasMinRole(role: Admin) # TODO: Delete All User Content } type Mutation { diff --git a/graph/schema.resolvers.go b/graph/schema.resolvers.go index 8d66e4e..1616c71 100644 --- a/graph/schema.resolvers.go +++ b/graph/schema.resolvers.go @@ -7,7 +7,6 @@ import ( "bytes" "context" "errors" - "fmt" "io" "net/http" "os" @@ -21,7 +20,6 @@ import ( "reichard.io/imagini/graph/model" ) -// Done func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewMediaItem) (*model.MediaItem, error) { // Get Context authContext := ctx.Value("auth").(*model.AuthContext) @@ -101,11 +99,37 @@ func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewM } func (r *mutationResolver) CreateAlbum(ctx context.Context, input model.NewAlbum) (*model.Album, error) { - panic(fmt.Errorf("not implemented")) + // Get Context + authContext := ctx.Value("auth").(*model.AuthContext) + accessToken := *authContext.AccessToken + _, ok := accessToken.Get("sub") + if !ok { + return nil, errors.New("Upload Failed") + } + + album := &model.Album{ + Name: input.Name, + } + + err := r.DB.CreateAlbum(album) + if err != nil { + return nil, err + } + + return album, nil } func (r *mutationResolver) CreateTag(ctx context.Context, input model.NewTag) (*model.Tag, error) { - panic(fmt.Errorf("not implemented")) + tag := &model.Tag{ + Name: input.Name, + } + + err := r.DB.CreateTag(tag) + if err != nil { + return nil, err + } + + return tag, nil } func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser) (*model.User, error) { @@ -198,50 +222,172 @@ func (r *queryResolver) Logout(ctx context.Context) (*model.AuthResponse, error) return &model.AuthResponse{Result: model.AuthResultSuccess}, nil } -func (r *queryResolver) MediaItem(ctx context.Context, id string) (*model.MediaItem, error) { - panic(fmt.Errorf("not implemented")) +func (r *queryResolver) MediaItem(ctx context.Context, id string, delete *bool) (*model.MediaItem, error) { + // TODO: User Specific + deviceID, err := uuid.Parse(id) + if err != nil { + return nil, errors.New("Invalid ID Format") + } + + foundMediaItem := &model.MediaItem{ID: deviceID.String()} + count, err := r.DB.MediaItem(foundMediaItem) + if err != nil { + return nil, errors.New("DB Error") + } else if count != 1 { + return nil, errors.New("MediaItem Not Found") + } + return foundMediaItem, nil } -func (r *queryResolver) Device(ctx context.Context, id string) (*model.Device, error) { - panic(fmt.Errorf("not implemented")) +func (r *queryResolver) Device(ctx context.Context, id string, delete *bool) (*model.Device, error) { + // TODO: User Specific + deviceID, err := uuid.Parse(id) + if err != nil { + return nil, errors.New("Invalid ID Format") + } + + foundDevice := &model.Device{ID: deviceID.String()} + count, err := r.DB.Device(foundDevice) + if err != nil { + return nil, errors.New("DB Error") + } else if count != 1 { + return nil, errors.New("Device Not Found") + } + return foundDevice, nil } -func (r *queryResolver) Album(ctx context.Context, id string) (*model.Album, error) { - panic(fmt.Errorf("not implemented")) +func (r *queryResolver) Album(ctx context.Context, id string, delete *bool) (*model.Album, error) { + // TODO: User Specific + albumID, err := uuid.Parse(id) + if err != nil { + return nil, errors.New("Invalid ID Format") + } + + foundAlbum := &model.Album{ID: albumID.String()} + count, err := r.DB.Album(foundAlbum) + if err != nil { + return nil, errors.New("DB Error") + } else if count != 1 { + return nil, errors.New("Album Not Found") + } + return foundAlbum, nil } -func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) { - panic(fmt.Errorf("not implemented")) +func (r *queryResolver) User(ctx context.Context, id string, delete *bool) (*model.User, error) { + userID, err := uuid.Parse(id) + if err != nil { + return nil, errors.New("Invalid ID Format") + } + + foundUser := &model.User{ID: userID.String()} + count, err := r.DB.User(foundUser) + if err != nil { + return nil, errors.New("DB Error") + } else if count != 1 { + return nil, errors.New("User Not Found") + } + return foundUser, nil } -func (r *queryResolver) Tag(ctx context.Context, id string) (*model.Tag, error) { - panic(fmt.Errorf("not implemented")) +func (r *queryResolver) Tag(ctx context.Context, id string, delete *bool) (*model.Tag, error) { + tagID, err := uuid.Parse(id) + if err != nil { + return nil, errors.New("Invalid ID Format") + } + + foundTag := &model.Tag{ID: tagID.String()} + count, err := r.DB.Tag(foundTag) + if err != nil { + return nil, errors.New("DB Error") + } else if count != 1 { + return nil, errors.New("Tag Not Found") + } + return foundTag, nil } -func (r *queryResolver) Me(ctx context.Context) (*model.User, error) { - panic(fmt.Errorf("not implemented")) +func (r *queryResolver) Me(ctx context.Context, delete *bool) (*model.User, error) { + // Get Context + authContext := ctx.Value("auth").(*model.AuthContext) + accessToken := *authContext.AccessToken + userID, ok := accessToken.Get("sub") + if !ok { + return nil, errors.New("Context Error") + } + + foundUser := &model.User{ID: userID.(string)} + count, err := r.DB.User(foundUser) + if err != nil || count != 1 { + return nil, errors.New("DB Error") + } + return foundUser, nil } -func (r *queryResolver) MediaItems(ctx context.Context, filter *model.MediaItemFilter, count *int, page *int) (*model.MediaItemResponse, error) { - panic(fmt.Errorf("not implemented")) +func (r *queryResolver) MediaItems(ctx context.Context, delete *bool, filter *model.MediaItemFilter, count *int, page *int) (*model.MediaItemResponse, error) { + resp, totalCount, err := r.DB.MediaItems() + if err != nil { + return nil, errors.New("Context Error") + } + return &model.MediaItemResponse{ + Data: resp, + PageInfo: &model.PageInfo{ + Count: int(totalCount), + Page: 0, + Total: int(totalCount), + }, + }, nil } -func (r *queryResolver) Devices(ctx context.Context, filter *model.DeviceFilter, count *int, page *int) (*model.DeviceResponse, error) { - panic(fmt.Errorf("not implemented")) +func (r *queryResolver) Devices(ctx context.Context, delete *bool, filter *model.DeviceFilter, count *int, page *int) (*model.DeviceResponse, error) { + // TODO: User Specific + resp, totalCount, err := r.DB.Devices() + if err != nil { + return nil, errors.New("Context Error") + } + return &model.DeviceResponse{ + Data: resp, + PageInfo: &model.PageInfo{ + Count: int(totalCount), + Page: 0, + Total: int(totalCount), + }, + }, nil } -func (r *queryResolver) Albums(ctx context.Context, filter *model.AlbumFilter, count *int, page *int) (*model.AlbumResponse, error) { - panic(fmt.Errorf("not implemented")) +func (r *queryResolver) Albums(ctx context.Context, delete *bool, filter *model.AlbumFilter, count *int, page *int) (*model.AlbumResponse, error) { + // TODO: User Specific + resp, totalCount, err := r.DB.Albums() + if err != nil { + return nil, errors.New("Context Error") + } + return &model.AlbumResponse{ + Data: resp, + PageInfo: &model.PageInfo{ + Count: int(totalCount), + Page: 0, + Total: int(totalCount), + }, + }, nil } -func (r *queryResolver) Tags(ctx context.Context, filter *model.TagFilter, count *int, page *int) (*model.TagResponse, error) { - panic(fmt.Errorf("not implemented")) +func (r *queryResolver) Tags(ctx context.Context, delete *bool, filter *model.TagFilter, count *int, page *int) (*model.TagResponse, error) { + resp, totalCount, err := r.DB.Tags() + if err != nil { + return nil, errors.New("Context Error") + } + return &model.TagResponse{ + Data: resp, + PageInfo: &model.PageInfo{ + Count: int(totalCount), + Page: 0, + Total: int(totalCount), + }, + }, nil } -func (r *queryResolver) Users(ctx context.Context, filter *model.UserFilter, count *int, page *int) (*model.UserResponse, error) { +func (r *queryResolver) Users(ctx context.Context, delete *bool, filter *model.UserFilter, count *int, page *int) (*model.UserResponse, error) { resp, totalCount, err := r.DB.Users() if err != nil { - panic(fmt.Errorf("DB Error")) + return nil, errors.New("Context Error") } return &model.UserResponse{ Data: resp, diff --git a/internal/db/albums.go b/internal/db/albums.go index 3a49c63..c2def31 100644 --- a/internal/db/albums.go +++ b/internal/db/albums.go @@ -1 +1,30 @@ package db + +import ( + log "github.com/sirupsen/logrus" + + "reichard.io/imagini/graph/model" +) + +func (dbm *DBManager) CreateAlbum(album *model.Album) error { + log.Debug("[db] Creating album: ", album.Name) + err := dbm.db.Create(album).Error + return err +} + +func (dbm *DBManager) Album(album *model.Album) (int64, error) { + var count int64 + err := dbm.db.Where(album).First(album).Count(&count).Error + return count, err +} + +func (dbm *DBManager) Albums() ([]*model.Album, int64, error) { + var foundAlbums []*model.Album + var count int64 + err := dbm.db.Find(&foundAlbums).Count(&count).Error + return foundAlbums, count, err +} + +func (dbm *DBManager) DeleteAlbum(album *model.Album) error { + return nil +} diff --git a/internal/db/devices.go b/internal/db/devices.go index 990cb18..27bce06 100644 --- a/internal/db/devices.go +++ b/internal/db/devices.go @@ -21,6 +21,13 @@ func (dbm *DBManager) Device(device *model.Device) (int64, error) { return count, err } +func (dbm *DBManager) Devices() ([]*model.Device, int64, error) { + var foundDevices []*model.Device + var count int64 + err := dbm.db.Find(&foundDevices).Count(&count).Error + return foundDevices, count, err +} + func (dbm *DBManager) DeleteDevice(user *model.Device) error { return nil } diff --git a/internal/db/media_items.go b/internal/db/media_items.go index f7f3b80..3dab426 100644 --- a/internal/db/media_items.go +++ b/internal/db/media_items.go @@ -12,10 +12,15 @@ func (dbm *DBManager) CreateMediaItem(mediaItem *model.MediaItem) error { return err } -func (dbm *DBManager) MediaItems(mediaItemFilter *model.MediaItem) ([]model.MediaItem, int64, error) { - var mediaItems []model.MediaItem +func (dbm *DBManager) MediaItem(mediaItem *model.MediaItem) (int64, error) { var count int64 + err := dbm.db.Where(mediaItem).First(mediaItem).Count(&count).Error + return count, err +} - err := dbm.db.Where(mediaItemFilter).Find(&mediaItems).Count(&count).Error +func (dbm *DBManager) MediaItems() ([]*model.MediaItem, int64, error) { + var mediaItems []*model.MediaItem + var count int64 + err := dbm.db.Find(&mediaItems).Count(&count).Error return mediaItems, count, err } diff --git a/internal/db/tags.go b/internal/db/tags.go index 3a49c63..8a017ca 100644 --- a/internal/db/tags.go +++ b/internal/db/tags.go @@ -1 +1,30 @@ package db + +import ( + log "github.com/sirupsen/logrus" + + "reichard.io/imagini/graph/model" +) + +func (dbm *DBManager) CreateTag(tag *model.Tag) error { + log.Debug("[db] Creating tag: ", tag.Name) + err := dbm.db.Create(tag).Error + return err +} + +func (dbm *DBManager) Tag(tag *model.Tag) (int64, error) { + var count int64 + err := dbm.db.Where(tag).First(tag).Count(&count).Error + return count, err +} + +func (dbm *DBManager) Tags() ([]*model.Tag, int64, error) { + var foundTags []*model.Tag + var count int64 + err := dbm.db.Find(&foundTags).Count(&count).Error + return foundTags, count, err +} + +func (dbm *DBManager) DeleteTag(tag *model.Tag) error { + return nil +} From 66973589605f902eb5c392b89ee431f54cfa600c Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Mon, 8 Feb 2021 12:41:58 -0500 Subject: [PATCH 7/8] Add Filters! --- go.mod | 1 + go.sum | 2 + graph/generated/generated.go | 1021 +++++++++++----------------------- graph/model/models_gen.go | 146 ++--- graph/schema.graphqls | 82 ++- graph/schema.resolvers.go | 65 ++- internal/db/filters.go | 193 +++++++ internal/db/media_items.go | 9 +- 8 files changed, 664 insertions(+), 855 deletions(-) create mode 100644 internal/db/filters.go diff --git a/go.mod b/go.mod index 810144d..34eab88 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/dsoprea/go-exif/v3 v3.0.0-20201216222538-db167117f483 github.com/gabriel-vasile/mimetype v1.1.2 github.com/google/uuid v1.1.5 + github.com/iancoleman/strcase v0.1.3 github.com/lestrrat-go/jwx v1.0.8 github.com/mattn/go-sqlite3 v1.14.6 github.com/sirupsen/logrus v1.7.0 diff --git a/go.sum b/go.sum index fee82df..e6f8078 100644 --- a/go.sum +++ b/go.sum @@ -96,6 +96,8 @@ github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplb github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/iancoleman/strcase v0.1.3 h1:dJBk1m2/qjL1twPLf68JND55vvivMupZ4wIzE8CTdBw= +github.com/iancoleman/strcase v0.1.3/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 3c9fec9..2b29157 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -53,6 +53,7 @@ type ComplexityRoot struct { ID func(childComplexity int) int Name func(childComplexity int) int UpdatedAt func(childComplexity int) int + UserID func(childComplexity int) int } AlbumResponse struct { @@ -135,6 +136,7 @@ type ComplexityRoot struct { ID func(childComplexity int) int Name func(childComplexity int) int UpdatedAt func(childComplexity int) int + UserID func(childComplexity int) int } TagResponse struct { @@ -228,6 +230,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Album.UpdatedAt(childComplexity), true + case "Album.userID": + if e.complexity.Album.UserID == nil { + break + } + + return e.complexity.Album.UserID(childComplexity), true + case "AlbumResponse.data": if e.complexity.AlbumResponse.Data == nil { break @@ -672,6 +681,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Tag.UpdatedAt(childComplexity), true + case "Tag.userID": + if e.complexity.Tag.UserID == nil { + break + } + + return e.complexity.Tag.UserID(childComplexity), true + case "TagResponse.data": if e.complexity.TagResponse.Data == nil { break @@ -906,8 +922,8 @@ input TimeFilter { notEqualTo: Time lessThan: Time lessThanOrEqualTo: Time - moreThan: Time - moreThanOrEqualTo: Time + greaterThan: Time + greaterThanOrEqualTo: Time } input IntFilter { @@ -915,10 +931,8 @@ input IntFilter { notEqualTo: Int lessThan: Int lessThanOrEqualTo: Int - moreThan: Int - moreThanOrEqualTo: Int - in: [Int!] - notIn: [Int!] + greaterThan: Int + greaterThanOrEqualTo: Int } input FloatFilter { @@ -926,10 +940,8 @@ input FloatFilter { notEqualTo: Float lessThan: Float lessThanOrEqualTo: Float - moreThan: Float - moreThanOrEqualTo: Float - in: [Float!] - notIn: [Float!] + greaterThan: Float + greaterThanOrEqualTo: Float } input BooleanFilter { @@ -940,49 +952,32 @@ input BooleanFilter { input IDFilter { equalTo: ID notEqualTo: ID - in: [ID!] - notIn: [ID!] } input StringFilter { equalTo: String notEqualTo: String - startWith: String - notStartWith: String - endWith: String - notEndWith: String - contain: String - notContain: String - in: [String!] - notIn: [String!] - - startWithStrict: String - notStartWithStrict: String - endWithStrict: String - notEndWithStrict: String - containStrict: String - notContainStrict: String + startsWith: String + notStartsWith: String + endsWith: String + notEndsWith: String + contains: String + notContains: String } input RoleFilter { equalTo: Role notEqualTo: Role - in: [Role!] - notIn: [Role!] } input DeviceTypeFilter { equalTo: DeviceType notEqualTo: DeviceType - in: [DeviceType!] - notIn: [DeviceType!] } input AuthTypeFilter { equalTo: AuthType notEqualTo: AuthType - in: [AuthType!] - notIn: [AuthType!] } # ------------------------------------------------------------ @@ -1010,8 +1005,8 @@ type Device { updatedAt: Time name: String! @meta(gorm: "not null") type: DeviceType! @meta(gorm: "default:Unknown;not null") - userID: ID! @meta(gorm: "not null") refreshKey: String @isPrivate + userID: ID! @meta(gorm: "not null") } type MediaItem { @@ -1019,21 +1014,22 @@ type MediaItem { createdAt: Time updatedAt: Time exifDate: Time - latitude: Float - longitude: Float + latitude: Float @meta(gorm: "precision:5") + longitude: Float @meta(gorm: "precision:5") isVideo: Boolean! @meta(gorm: "default:false;not null") fileName: String! @meta(gorm: "not null") origName: String! @meta(gorm: "not null") - tags: [Tag] @meta(gorm: "many2many:media_tags") - albums: [Album] @meta(gorm: "many2many:media_albums") + tags: [Tag] @meta(gorm: "many2many:media_tags;foreignKey:ID,UserID;References:ID") + albums: [Album] @meta(gorm: "many2many:media_albums;foreignKey:ID,UserID;Refrences:ID") userID: ID! @meta(gorm: "not null") } type Tag { - id: ID! @meta(gorm: "primaryKey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time - name: String! @meta(gorm: "unique;not null") + name: String! @meta(gorm: "unique;not null") + userID: ID! @meta(gorm: "not null") } type Album { @@ -1041,7 +1037,7 @@ type Album { createdAt: Time updatedAt: Time name: String! @meta(gorm: "unique;not null") - # userID: ID! @meta(gorm: "not null") + userID: ID! @meta(gorm: "not null") } # ------------------------------------------------------------ @@ -1058,8 +1054,8 @@ input UserFilter { role: RoleFilter authType: AuthTypeFilter - and: UserFilter - or: UserFilter + # and: UserFilter + # or: UserFilter } input MediaItemFilter { @@ -1074,8 +1070,8 @@ input MediaItemFilter { tags: TagFilter albums: AlbumFilter - and: MediaItemFilter - or: MediaItemFilter + # and: MediaItemFilter + # or: MediaItemFilter } input DeviceFilter { @@ -1085,8 +1081,8 @@ input DeviceFilter { name: StringFilter type: DeviceTypeFilter - and: MediaItemFilter - or: MediaItemFilter + # and: MediaItemFilter + # or: MediaItemFilter } input TagFilter { @@ -1095,8 +1091,8 @@ input TagFilter { updatedAt: TimeFilter name: StringFilter - and: MediaItemFilter - or: MediaItemFilter + # and: MediaItemFilter + # or: MediaItemFilter } input AlbumFilter { @@ -1105,8 +1101,8 @@ input AlbumFilter { updatedAt: TimeFilter name: StringFilter - and: MediaItemFilter - or: MediaItemFilter + # and: MediaItemFilter + # or: MediaItemFilter } # ------------------------------------------------------------ @@ -1958,6 +1954,65 @@ func (ec *executionContext) _Album_name(ctx context.Context, field graphql.Colle return ec.marshalNString2string(ctx, field.Selections, res) } +func (ec *executionContext) _Album_userID(ctx context.Context, field graphql.CollectedField, obj *model.Album) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Album", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UserID, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + func (ec *executionContext) _AlbumResponse_data(ctx context.Context, field graphql.CollectedField, obj *model.AlbumResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -2365,6 +2420,58 @@ func (ec *executionContext) _Device_type(ctx context.Context, field graphql.Coll return ec.marshalNDeviceType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx, field.Selections, res) } +func (ec *executionContext) _Device_refreshKey(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Device", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.RefreshKey, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + if ec.directives.IsPrivate == nil { + return nil, errors.New("directive isPrivate is not implemented") + } + return ec.directives.IsPrivate(ctx, obj, directive0) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + func (ec *executionContext) _Device_userID(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -2424,58 +2531,6 @@ func (ec *executionContext) _Device_userID(ctx context.Context, field graphql.Co return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _Device_refreshKey(ctx context.Context, field graphql.CollectedField, obj *model.Device) (ret graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - fc := &graphql.FieldContext{ - Object: "Device", - Field: field, - Args: nil, - IsMethod: false, - IsResolver: false, - } - - ctx = graphql.WithFieldContext(ctx, fc) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - directive0 := func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.RefreshKey, nil - } - directive1 := func(ctx context.Context) (interface{}, error) { - if ec.directives.IsPrivate == nil { - return nil, errors.New("directive isPrivate is not implemented") - } - return ec.directives.IsPrivate(ctx, obj, directive0) - } - - tmp, err := directive1(rctx) - if err != nil { - return nil, graphql.ErrorOnPath(ctx, err) - } - if tmp == nil { - return nil, nil - } - if data, ok := tmp.(*string); ok { - return data, nil - } - return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(*string) - fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) -} - func (ec *executionContext) _DeviceResponse_data(ctx context.Context, field graphql.CollectedField, obj *model.DeviceResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -2715,8 +2770,32 @@ func (ec *executionContext) _MediaItem_latitude(ctx context.Context, field graph ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Latitude, nil + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Latitude, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "precision:5") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*float64); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *float64`, tmp) }) if err != nil { ec.Error(ctx, err) @@ -2747,8 +2826,32 @@ func (ec *executionContext) _MediaItem_longitude(ctx context.Context, field grap ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Longitude, nil + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Longitude, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "precision:5") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(*float64); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be *float64`, tmp) }) if err != nil { ec.Error(ctx, err) @@ -2961,7 +3064,7 @@ func (ec *executionContext) _MediaItem_tags(ctx context.Context, field graphql.C return obj.Tags, nil } directive1 := func(ctx context.Context) (interface{}, error) { - gorm, err := ec.unmarshalOString2ᚖstring(ctx, "many2many:media_tags") + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "many2many:media_tags;foreignKey:ID,UserID;References:ID") if err != nil { return nil, err } @@ -3017,7 +3120,7 @@ func (ec *executionContext) _MediaItem_albums(ctx context.Context, field graphql return obj.Albums, nil } directive1 := func(ctx context.Context) (interface{}, error) { - gorm, err := ec.unmarshalOString2ᚖstring(ctx, "many2many:media_albums") + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "many2many:media_albums;foreignKey:ID,UserID;Refrences:ID") if err != nil { return nil, err } @@ -4626,6 +4729,65 @@ func (ec *executionContext) _Tag_name(ctx context.Context, field graphql.Collect return ec.marshalNString2string(ctx, field.Selections, res) } +func (ec *executionContext) _Tag_userID(ctx context.Context, field graphql.CollectedField, obj *model.Tag) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Tag", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UserID, nil + } + directive1 := func(ctx context.Context) (interface{}, error) { + gorm, err := ec.unmarshalOString2ᚖstring(ctx, "not null") + if err != nil { + return nil, err + } + if ec.directives.Meta == nil { + return nil, errors.New("directive meta is not implemented") + } + return ec.directives.Meta(ctx, obj, directive0, gorm) + } + + tmp, err := directive1(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(string); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be string`, tmp) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + func (ec *executionContext) _TagResponse_data(ctx context.Context, field graphql.CollectedField, obj *model.TagResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -6472,22 +6634,6 @@ func (ec *executionContext) unmarshalInputAlbumFilter(ctx context.Context, obj i if err != nil { return it, err } - case "and": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) - it.And, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) - if err != nil { - return it, err - } - case "or": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) - it.Or, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) - if err != nil { - return it, err - } } } @@ -6516,22 +6662,6 @@ func (ec *executionContext) unmarshalInputAuthTypeFilter(ctx context.Context, ob if err != nil { return it, err } - case "in": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) - it.In, err = ec.unmarshalOAuthType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthTypeᚄ(ctx, v) - if err != nil { - return it, err - } - case "notIn": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) - it.NotIn, err = ec.unmarshalOAuthType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthTypeᚄ(ctx, v) - if err != nil { - return it, err - } } } @@ -6612,22 +6742,6 @@ func (ec *executionContext) unmarshalInputDeviceFilter(ctx context.Context, obj if err != nil { return it, err } - case "and": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) - it.And, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) - if err != nil { - return it, err - } - case "or": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) - it.Or, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) - if err != nil { - return it, err - } } } @@ -6656,22 +6770,6 @@ func (ec *executionContext) unmarshalInputDeviceTypeFilter(ctx context.Context, if err != nil { return it, err } - case "in": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) - it.In, err = ec.unmarshalODeviceType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceTypeᚄ(ctx, v) - if err != nil { - return it, err - } - case "notIn": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) - it.NotIn, err = ec.unmarshalODeviceType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceTypeᚄ(ctx, v) - if err != nil { - return it, err - } } } @@ -6716,35 +6814,19 @@ func (ec *executionContext) unmarshalInputFloatFilter(ctx context.Context, obj i if err != nil { return it, err } - case "moreThan": + case "greaterThan": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("moreThan")) - it.MoreThan, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("greaterThan")) + it.GreaterThan, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) if err != nil { return it, err } - case "moreThanOrEqualTo": + case "greaterThanOrEqualTo": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("moreThanOrEqualTo")) - it.MoreThanOrEqualTo, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) - if err != nil { - return it, err - } - case "in": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) - it.In, err = ec.unmarshalOFloat2ᚕfloat64ᚄ(ctx, v) - if err != nil { - return it, err - } - case "notIn": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) - it.NotIn, err = ec.unmarshalOFloat2ᚕfloat64ᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("greaterThanOrEqualTo")) + it.GreaterThanOrEqualTo, err = ec.unmarshalOFloat2ᚖfloat64(ctx, v) if err != nil { return it, err } @@ -6776,22 +6858,6 @@ func (ec *executionContext) unmarshalInputIDFilter(ctx context.Context, obj inte if err != nil { return it, err } - case "in": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) - it.In, err = ec.unmarshalOID2ᚕstringᚄ(ctx, v) - if err != nil { - return it, err - } - case "notIn": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) - it.NotIn, err = ec.unmarshalOID2ᚕstringᚄ(ctx, v) - if err != nil { - return it, err - } } } @@ -6836,35 +6902,19 @@ func (ec *executionContext) unmarshalInputIntFilter(ctx context.Context, obj int if err != nil { return it, err } - case "moreThan": + case "greaterThan": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("moreThan")) - it.MoreThan, err = ec.unmarshalOInt2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("greaterThan")) + it.GreaterThan, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "moreThanOrEqualTo": + case "greaterThanOrEqualTo": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("moreThanOrEqualTo")) - it.MoreThanOrEqualTo, err = ec.unmarshalOInt2ᚖint(ctx, v) - if err != nil { - return it, err - } - case "in": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) - it.In, err = ec.unmarshalOInt2ᚕintᚄ(ctx, v) - if err != nil { - return it, err - } - case "notIn": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) - it.NotIn, err = ec.unmarshalOInt2ᚕintᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("greaterThanOrEqualTo")) + it.GreaterThanOrEqualTo, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } @@ -6960,22 +7010,6 @@ func (ec *executionContext) unmarshalInputMediaItemFilter(ctx context.Context, o if err != nil { return it, err } - case "and": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) - it.And, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) - if err != nil { - return it, err - } - case "or": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) - it.Or, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) - if err != nil { - return it, err - } } } @@ -7148,22 +7182,6 @@ func (ec *executionContext) unmarshalInputRoleFilter(ctx context.Context, obj in if err != nil { return it, err } - case "in": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) - it.In, err = ec.unmarshalORole2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRoleᚄ(ctx, v) - if err != nil { - return it, err - } - case "notIn": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) - it.NotIn, err = ec.unmarshalORole2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRoleᚄ(ctx, v) - if err != nil { - return it, err - } } } @@ -7192,115 +7210,51 @@ func (ec *executionContext) unmarshalInputStringFilter(ctx context.Context, obj if err != nil { return it, err } - case "startWith": + case "startsWith": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("startWith")) - it.StartWith, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("startsWith")) + it.StartsWith, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "notStartWith": + case "notStartsWith": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notStartWith")) - it.NotStartWith, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notStartsWith")) + it.NotStartsWith, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "endWith": + case "endsWith": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("endWith")) - it.EndWith, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("endsWith")) + it.EndsWith, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "notEndWith": + case "notEndsWith": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEndWith")) - it.NotEndWith, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEndsWith")) + it.NotEndsWith, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "contain": + case "contains": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("contain")) - it.Contain, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("contains")) + it.Contains, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "notContain": + case "notContains": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notContain")) - it.NotContain, err = ec.unmarshalOString2ᚖstring(ctx, v) - if err != nil { - return it, err - } - case "in": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("in")) - it.In, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) - if err != nil { - return it, err - } - case "notIn": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notIn")) - it.NotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) - if err != nil { - return it, err - } - case "startWithStrict": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("startWithStrict")) - it.StartWithStrict, err = ec.unmarshalOString2ᚖstring(ctx, v) - if err != nil { - return it, err - } - case "notStartWithStrict": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notStartWithStrict")) - it.NotStartWithStrict, err = ec.unmarshalOString2ᚖstring(ctx, v) - if err != nil { - return it, err - } - case "endWithStrict": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("endWithStrict")) - it.EndWithStrict, err = ec.unmarshalOString2ᚖstring(ctx, v) - if err != nil { - return it, err - } - case "notEndWithStrict": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notEndWithStrict")) - it.NotEndWithStrict, err = ec.unmarshalOString2ᚖstring(ctx, v) - if err != nil { - return it, err - } - case "containStrict": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("containStrict")) - it.ContainStrict, err = ec.unmarshalOString2ᚖstring(ctx, v) - if err != nil { - return it, err - } - case "notContainStrict": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notContainStrict")) - it.NotContainStrict, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notContains")) + it.NotContains, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } @@ -7348,22 +7302,6 @@ func (ec *executionContext) unmarshalInputTagFilter(ctx context.Context, obj int if err != nil { return it, err } - case "and": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) - it.And, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) - if err != nil { - return it, err - } - case "or": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) - it.Or, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, v) - if err != nil { - return it, err - } } } @@ -7408,19 +7346,19 @@ func (ec *executionContext) unmarshalInputTimeFilter(ctx context.Context, obj in if err != nil { return it, err } - case "moreThan": + case "greaterThan": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("moreThan")) - it.MoreThan, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("greaterThan")) + it.GreaterThan, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) if err != nil { return it, err } - case "moreThanOrEqualTo": + case "greaterThanOrEqualTo": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("moreThanOrEqualTo")) - it.MoreThanOrEqualTo, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("greaterThanOrEqualTo")) + it.GreaterThanOrEqualTo, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) if err != nil { return it, err } @@ -7500,22 +7438,6 @@ func (ec *executionContext) unmarshalInputUserFilter(ctx context.Context, obj in if err != nil { return it, err } - case "and": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) - it.And, err = ec.unmarshalOUserFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserFilter(ctx, v) - if err != nil { - return it, err - } - case "or": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) - it.Or, err = ec.unmarshalOUserFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserFilter(ctx, v) - if err != nil { - return it, err - } } } @@ -7555,6 +7477,11 @@ func (ec *executionContext) _Album(ctx context.Context, sel ast.SelectionSet, ob if out.Values[i] == graphql.Null { invalids++ } + case "userID": + out.Values[i] = ec._Album_userID(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -7656,13 +7583,13 @@ func (ec *executionContext) _Device(ctx context.Context, sel ast.SelectionSet, o if out.Values[i] == graphql.Null { invalids++ } + case "refreshKey": + out.Values[i] = ec._Device_refreshKey(ctx, field, obj) case "userID": out.Values[i] = ec._Device_userID(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } - case "refreshKey": - out.Values[i] = ec._Device_refreshKey(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -8113,6 +8040,11 @@ func (ec *executionContext) _Tag(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { invalids++ } + case "userID": + out.Values[i] = ec._Tag_userID(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -8603,21 +8535,6 @@ func (ec *executionContext) marshalNDeviceType2reichardᚗioᚋimaginiᚋgraph return v } -func (ec *executionContext) unmarshalNFloat2float64(ctx context.Context, v interface{}) (float64, error) { - res, err := graphql.UnmarshalFloat(v) - return res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.SelectionSet, v float64) graphql.Marshaler { - res := graphql.MarshalFloat(v) - if res == graphql.Null { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "must not be null") - } - } - return res -} - func (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) { res, err := graphql.UnmarshalID(v) return res, graphql.ErrorOnPath(ctx, err) @@ -9086,70 +9003,6 @@ func (ec *executionContext) unmarshalOAlbumFilter2ᚖreichardᚗioᚋimaginiᚋg return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalOAuthType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthTypeᚄ(ctx context.Context, v interface{}) ([]model.AuthType, error) { - if v == nil { - return nil, nil - } - var vSlice []interface{} - if v != nil { - if tmp1, ok := v.([]interface{}); ok { - vSlice = tmp1 - } else { - vSlice = []interface{}{v} - } - } - var err error - res := make([]model.AuthType, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNAuthType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - -func (ec *executionContext) marshalOAuthType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []model.AuthType) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNAuthType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - return ret -} - func (ec *executionContext) unmarshalOAuthType2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAuthType(ctx context.Context, v interface{}) (*model.AuthType, error) { if v == nil { return nil, nil @@ -9301,70 +9154,6 @@ func (ec *executionContext) unmarshalODeviceFilter2ᚖreichardᚗioᚋimaginiᚋ return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalODeviceType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceTypeᚄ(ctx context.Context, v interface{}) ([]model.DeviceType, error) { - if v == nil { - return nil, nil - } - var vSlice []interface{} - if v != nil { - if tmp1, ok := v.([]interface{}); ok { - vSlice = tmp1 - } else { - vSlice = []interface{}{v} - } - } - var err error - res := make([]model.DeviceType, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNDeviceType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - -func (ec *executionContext) marshalODeviceType2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []model.DeviceType) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNDeviceType2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - return ret -} - func (ec *executionContext) unmarshalODeviceType2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceType(ctx context.Context, v interface{}) (*model.DeviceType, error) { if v == nil { return nil, nil @@ -9389,42 +9178,6 @@ func (ec *executionContext) unmarshalODeviceTypeFilter2ᚖreichardᚗioᚋimagin return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalOFloat2ᚕfloat64ᚄ(ctx context.Context, v interface{}) ([]float64, error) { - if v == nil { - return nil, nil - } - var vSlice []interface{} - if v != nil { - if tmp1, ok := v.([]interface{}); ok { - vSlice = tmp1 - } else { - vSlice = []interface{}{v} - } - } - var err error - res := make([]float64, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNFloat2float64(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - -func (ec *executionContext) marshalOFloat2ᚕfloat64ᚄ(ctx context.Context, sel ast.SelectionSet, v []float64) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - for i := range v { - ret[i] = ec.marshalNFloat2float64(ctx, sel, v[i]) - } - - return ret -} - func (ec *executionContext) unmarshalOFloat2ᚖfloat64(ctx context.Context, v interface{}) (*float64, error) { if v == nil { return nil, nil @@ -9507,42 +9260,6 @@ func (ec *executionContext) unmarshalOIDFilter2ᚖreichardᚗioᚋimaginiᚋgrap return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalOInt2ᚕintᚄ(ctx context.Context, v interface{}) ([]int, error) { - if v == nil { - return nil, nil - } - var vSlice []interface{} - if v != nil { - if tmp1, ok := v.([]interface{}); ok { - vSlice = tmp1 - } else { - vSlice = []interface{}{v} - } - } - var err error - res := make([]int, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNInt2int(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - -func (ec *executionContext) marshalOInt2ᚕintᚄ(ctx context.Context, sel ast.SelectionSet, v []int) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - for i := range v { - ret[i] = ec.marshalNInt2int(ctx, sel, v[i]) - } - - return ret -} - func (ec *executionContext) unmarshalOInt2ᚖint(ctx context.Context, v interface{}) (*int, error) { if v == nil { return nil, nil @@ -9653,70 +9370,6 @@ func (ec *executionContext) unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimagini return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalORole2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRoleᚄ(ctx context.Context, v interface{}) ([]model.Role, error) { - if v == nil { - return nil, nil - } - var vSlice []interface{} - if v != nil { - if tmp1, ok := v.([]interface{}); ok { - vSlice = tmp1 - } else { - vSlice = []interface{}{v} - } - } - var err error - res := make([]model.Role, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - -func (ec *executionContext) marshalORole2ᚕreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRoleᚄ(ctx context.Context, sel ast.SelectionSet, v []model.Role) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - return ret -} - func (ec *executionContext) unmarshalORole2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx context.Context, v interface{}) (*model.Role, error) { if v == nil { return nil, nil @@ -9750,42 +9403,6 @@ func (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.S return graphql.MarshalString(v) } -func (ec *executionContext) unmarshalOString2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { - if v == nil { - return nil, nil - } - var vSlice []interface{} - if v != nil { - if tmp1, ok := v.([]interface{}); ok { - vSlice = tmp1 - } else { - vSlice = []interface{}{v} - } - } - var err error - res := make([]string, len(vSlice)) - for i := range vSlice { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNString2string(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - -func (ec *executionContext) marshalOString2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - for i := range v { - ret[i] = ec.marshalNString2string(ctx, sel, v[i]) - } - - return ret -} - func (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) { if v == nil { return nil, nil diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index 6b3fa1e..a2cdbbc 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -16,15 +16,14 @@ type Album struct { CreatedAt *time.Time `json:"createdAt" ` UpdatedAt *time.Time `json:"updatedAt" ` Name string `json:"name" gorm:"unique;not null"` + UserID string `json:"userID" gorm:"not null"` } type AlbumFilter struct { - ID *IDFilter `json:"id" ` - CreatedAt *TimeFilter `json:"createdAt" ` - UpdatedAt *TimeFilter `json:"updatedAt" ` - Name *StringFilter `json:"name" ` - And *MediaItemFilter `json:"and" ` - Or *MediaItemFilter `json:"or" ` + ID *IDFilter `json:"id" ` + CreatedAt *TimeFilter `json:"createdAt" ` + UpdatedAt *TimeFilter `json:"updatedAt" ` + Name *StringFilter `json:"name" ` } type AlbumResponse struct { @@ -39,10 +38,8 @@ type AuthResponse struct { } type AuthTypeFilter struct { - EqualTo *AuthType `json:"equalTo" ` - NotEqualTo *AuthType `json:"notEqualTo" ` - In []AuthType `json:"in" ` - NotIn []AuthType `json:"notIn" ` + EqualTo *AuthType `json:"equalTo" ` + NotEqualTo *AuthType `json:"notEqualTo" ` } type BooleanFilter struct { @@ -56,8 +53,8 @@ type Device struct { UpdatedAt *time.Time `json:"updatedAt" ` Name string `json:"name" gorm:"not null"` Type DeviceType `json:"type" gorm:"default:Unknown;not null"` - UserID string `json:"userID" gorm:"not null"` RefreshKey *string `json:"refreshKey" ` + UserID string `json:"userID" gorm:"not null"` } type DeviceFilter struct { @@ -66,8 +63,6 @@ type DeviceFilter struct { UpdatedAt *TimeFilter `json:"updatedAt" ` Name *StringFilter `json:"name" ` Type *DeviceTypeFilter `json:"type" ` - And *MediaItemFilter `json:"and" ` - Or *MediaItemFilter `json:"or" ` } type DeviceResponse struct { @@ -76,39 +71,31 @@ type DeviceResponse struct { } type DeviceTypeFilter struct { - EqualTo *DeviceType `json:"equalTo" ` - NotEqualTo *DeviceType `json:"notEqualTo" ` - In []DeviceType `json:"in" ` - NotIn []DeviceType `json:"notIn" ` + EqualTo *DeviceType `json:"equalTo" ` + NotEqualTo *DeviceType `json:"notEqualTo" ` } type FloatFilter struct { - EqualTo *float64 `json:"equalTo" ` - NotEqualTo *float64 `json:"notEqualTo" ` - LessThan *float64 `json:"lessThan" ` - LessThanOrEqualTo *float64 `json:"lessThanOrEqualTo" ` - MoreThan *float64 `json:"moreThan" ` - MoreThanOrEqualTo *float64 `json:"moreThanOrEqualTo" ` - In []float64 `json:"in" ` - NotIn []float64 `json:"notIn" ` + EqualTo *float64 `json:"equalTo" ` + NotEqualTo *float64 `json:"notEqualTo" ` + LessThan *float64 `json:"lessThan" ` + LessThanOrEqualTo *float64 `json:"lessThanOrEqualTo" ` + GreaterThan *float64 `json:"greaterThan" ` + GreaterThanOrEqualTo *float64 `json:"greaterThanOrEqualTo" ` } type IDFilter struct { - EqualTo *string `json:"equalTo" ` - NotEqualTo *string `json:"notEqualTo" ` - In []string `json:"in" ` - NotIn []string `json:"notIn" ` + EqualTo *string `json:"equalTo" ` + NotEqualTo *string `json:"notEqualTo" ` } type IntFilter struct { - EqualTo *int `json:"equalTo" ` - NotEqualTo *int `json:"notEqualTo" ` - LessThan *int `json:"lessThan" ` - LessThanOrEqualTo *int `json:"lessThanOrEqualTo" ` - MoreThan *int `json:"moreThan" ` - MoreThanOrEqualTo *int `json:"moreThanOrEqualTo" ` - In []int `json:"in" ` - NotIn []int `json:"notIn" ` + EqualTo *int `json:"equalTo" ` + NotEqualTo *int `json:"notEqualTo" ` + LessThan *int `json:"lessThan" ` + LessThanOrEqualTo *int `json:"lessThanOrEqualTo" ` + GreaterThan *int `json:"greaterThan" ` + GreaterThanOrEqualTo *int `json:"greaterThanOrEqualTo" ` } type MediaItem struct { @@ -116,29 +103,27 @@ type MediaItem struct { CreatedAt *time.Time `json:"createdAt" ` UpdatedAt *time.Time `json:"updatedAt" ` ExifDate *time.Time `json:"exifDate" ` - Latitude *float64 `json:"latitude" ` - Longitude *float64 `json:"longitude" ` + Latitude *float64 `json:"latitude" gorm:"precision:5"` + Longitude *float64 `json:"longitude" gorm:"precision:5"` IsVideo bool `json:"isVideo" gorm:"default:false;not null"` FileName string `json:"fileName" gorm:"not null"` OrigName string `json:"origName" gorm:"not null"` - Tags []*Tag `json:"tags" gorm:"many2many:media_tags"` - Albums []*Album `json:"albums" gorm:"many2many:media_albums"` + Tags []*Tag `json:"tags" gorm:"many2many:media_tags;foreignKey:ID,UserID;References:ID"` + Albums []*Album `json:"albums" gorm:"many2many:media_albums;foreignKey:ID,UserID;Refrences:ID"` UserID string `json:"userID" gorm:"not null"` } type MediaItemFilter struct { - ID *IDFilter `json:"id" ` - CreatedAt *TimeFilter `json:"createdAt" ` - UpdatedAt *TimeFilter `json:"updatedAt" ` - ExifDate *TimeFilter `json:"exifDate" ` - Latitude *FloatFilter `json:"latitude" ` - Longitude *FloatFilter `json:"longitude" ` - IsVideo *BooleanFilter `json:"isVideo" ` - OrigName *StringFilter `json:"origName" ` - Tags *TagFilter `json:"tags" ` - Albums *AlbumFilter `json:"albums" ` - And *MediaItemFilter `json:"and" ` - Or *MediaItemFilter `json:"or" ` + ID *IDFilter `json:"id" ` + CreatedAt *TimeFilter `json:"createdAt" ` + UpdatedAt *TimeFilter `json:"updatedAt" ` + ExifDate *TimeFilter `json:"exifDate" ` + Latitude *FloatFilter `json:"latitude" ` + Longitude *FloatFilter `json:"longitude" ` + IsVideo *BooleanFilter `json:"isVideo" ` + OrigName *StringFilter `json:"origName" ` + Tags *TagFilter `json:"tags" ` + Albums *AlbumFilter `json:"albums" ` } type MediaItemResponse struct { @@ -177,29 +162,19 @@ type PageInfo struct { } type RoleFilter struct { - EqualTo *Role `json:"equalTo" ` - NotEqualTo *Role `json:"notEqualTo" ` - In []Role `json:"in" ` - NotIn []Role `json:"notIn" ` + EqualTo *Role `json:"equalTo" ` + NotEqualTo *Role `json:"notEqualTo" ` } type StringFilter struct { - EqualTo *string `json:"equalTo" ` - NotEqualTo *string `json:"notEqualTo" ` - StartWith *string `json:"startWith" ` - NotStartWith *string `json:"notStartWith" ` - EndWith *string `json:"endWith" ` - NotEndWith *string `json:"notEndWith" ` - Contain *string `json:"contain" ` - NotContain *string `json:"notContain" ` - In []string `json:"in" ` - NotIn []string `json:"notIn" ` - StartWithStrict *string `json:"startWithStrict" ` - NotStartWithStrict *string `json:"notStartWithStrict" ` - EndWithStrict *string `json:"endWithStrict" ` - NotEndWithStrict *string `json:"notEndWithStrict" ` - ContainStrict *string `json:"containStrict" ` - NotContainStrict *string `json:"notContainStrict" ` + EqualTo *string `json:"equalTo" ` + NotEqualTo *string `json:"notEqualTo" ` + StartsWith *string `json:"startsWith" ` + NotStartsWith *string `json:"notStartsWith" ` + EndsWith *string `json:"endsWith" ` + NotEndsWith *string `json:"notEndsWith" ` + Contains *string `json:"contains" ` + NotContains *string `json:"notContains" ` } type Tag struct { @@ -207,15 +182,14 @@ type Tag struct { CreatedAt *time.Time `json:"createdAt" ` UpdatedAt *time.Time `json:"updatedAt" ` Name string `json:"name" gorm:"unique;not null"` + UserID string `json:"userID" gorm:"not null"` } type TagFilter struct { - ID *IDFilter `json:"id" ` - CreatedAt *TimeFilter `json:"createdAt" ` - UpdatedAt *TimeFilter `json:"updatedAt" ` - Name *StringFilter `json:"name" ` - And *MediaItemFilter `json:"and" ` - Or *MediaItemFilter `json:"or" ` + ID *IDFilter `json:"id" ` + CreatedAt *TimeFilter `json:"createdAt" ` + UpdatedAt *TimeFilter `json:"updatedAt" ` + Name *StringFilter `json:"name" ` } type TagResponse struct { @@ -224,12 +198,12 @@ type TagResponse struct { } type TimeFilter struct { - EqualTo *time.Time `json:"equalTo" ` - NotEqualTo *time.Time `json:"notEqualTo" ` - LessThan *time.Time `json:"lessThan" ` - LessThanOrEqualTo *time.Time `json:"lessThanOrEqualTo" ` - MoreThan *time.Time `json:"moreThan" ` - MoreThanOrEqualTo *time.Time `json:"moreThanOrEqualTo" ` + EqualTo *time.Time `json:"equalTo" ` + NotEqualTo *time.Time `json:"notEqualTo" ` + LessThan *time.Time `json:"lessThan" ` + LessThanOrEqualTo *time.Time `json:"lessThanOrEqualTo" ` + GreaterThan *time.Time `json:"greaterThan" ` + GreaterThanOrEqualTo *time.Time `json:"greaterThanOrEqualTo" ` } type User struct { @@ -256,8 +230,6 @@ type UserFilter struct { LastName *StringFilter `json:"lastName" ` Role *RoleFilter `json:"role" ` AuthType *AuthTypeFilter `json:"authType" ` - And *UserFilter `json:"and" ` - Or *UserFilter `json:"or" ` } type UserResponse struct { diff --git a/graph/schema.graphqls b/graph/schema.graphqls index 7501878..c3448f0 100644 --- a/graph/schema.graphqls +++ b/graph/schema.graphqls @@ -56,8 +56,8 @@ input TimeFilter { notEqualTo: Time lessThan: Time lessThanOrEqualTo: Time - moreThan: Time - moreThanOrEqualTo: Time + greaterThan: Time + greaterThanOrEqualTo: Time } input IntFilter { @@ -65,10 +65,8 @@ input IntFilter { notEqualTo: Int lessThan: Int lessThanOrEqualTo: Int - moreThan: Int - moreThanOrEqualTo: Int - in: [Int!] - notIn: [Int!] + greaterThan: Int + greaterThanOrEqualTo: Int } input FloatFilter { @@ -76,10 +74,8 @@ input FloatFilter { notEqualTo: Float lessThan: Float lessThanOrEqualTo: Float - moreThan: Float - moreThanOrEqualTo: Float - in: [Float!] - notIn: [Float!] + greaterThan: Float + greaterThanOrEqualTo: Float } input BooleanFilter { @@ -90,49 +86,32 @@ input BooleanFilter { input IDFilter { equalTo: ID notEqualTo: ID - in: [ID!] - notIn: [ID!] } input StringFilter { equalTo: String notEqualTo: String - startWith: String - notStartWith: String - endWith: String - notEndWith: String - contain: String - notContain: String - in: [String!] - notIn: [String!] - - startWithStrict: String - notStartWithStrict: String - endWithStrict: String - notEndWithStrict: String - containStrict: String - notContainStrict: String + startsWith: String + notStartsWith: String + endsWith: String + notEndsWith: String + contains: String + notContains: String } input RoleFilter { equalTo: Role notEqualTo: Role - in: [Role!] - notIn: [Role!] } input DeviceTypeFilter { equalTo: DeviceType notEqualTo: DeviceType - in: [DeviceType!] - notIn: [DeviceType!] } input AuthTypeFilter { equalTo: AuthType notEqualTo: AuthType - in: [AuthType!] - notIn: [AuthType!] } # ------------------------------------------------------------ @@ -160,8 +139,8 @@ type Device { updatedAt: Time name: String! @meta(gorm: "not null") type: DeviceType! @meta(gorm: "default:Unknown;not null") - userID: ID! @meta(gorm: "not null") refreshKey: String @isPrivate + userID: ID! @meta(gorm: "not null") } type MediaItem { @@ -169,21 +148,22 @@ type MediaItem { createdAt: Time updatedAt: Time exifDate: Time - latitude: Float - longitude: Float + latitude: Float @meta(gorm: "precision:5") + longitude: Float @meta(gorm: "precision:5") isVideo: Boolean! @meta(gorm: "default:false;not null") fileName: String! @meta(gorm: "not null") origName: String! @meta(gorm: "not null") - tags: [Tag] @meta(gorm: "many2many:media_tags") - albums: [Album] @meta(gorm: "many2many:media_albums") + tags: [Tag] @meta(gorm: "many2many:media_tags;foreignKey:ID,UserID;References:ID") + albums: [Album] @meta(gorm: "many2many:media_albums;foreignKey:ID,UserID;Refrences:ID") userID: ID! @meta(gorm: "not null") } type Tag { - id: ID! @meta(gorm: "primaryKey;not null") + id: ID! @meta(gorm: "primaryKey;not null") createdAt: Time updatedAt: Time - name: String! @meta(gorm: "unique;not null") + name: String! @meta(gorm: "unique;not null") + userID: ID! @meta(gorm: "not null") } type Album { @@ -191,7 +171,7 @@ type Album { createdAt: Time updatedAt: Time name: String! @meta(gorm: "unique;not null") - # userID: ID! @meta(gorm: "not null") + userID: ID! @meta(gorm: "not null") } # ------------------------------------------------------------ @@ -208,8 +188,8 @@ input UserFilter { role: RoleFilter authType: AuthTypeFilter - and: UserFilter - or: UserFilter + # and: UserFilter + # or: UserFilter } input MediaItemFilter { @@ -224,8 +204,8 @@ input MediaItemFilter { tags: TagFilter albums: AlbumFilter - and: MediaItemFilter - or: MediaItemFilter + # and: MediaItemFilter + # or: MediaItemFilter } input DeviceFilter { @@ -235,8 +215,8 @@ input DeviceFilter { name: StringFilter type: DeviceTypeFilter - and: MediaItemFilter - or: MediaItemFilter + # and: MediaItemFilter + # or: MediaItemFilter } input TagFilter { @@ -245,8 +225,8 @@ input TagFilter { updatedAt: TimeFilter name: StringFilter - and: MediaItemFilter - or: MediaItemFilter + # and: MediaItemFilter + # or: MediaItemFilter } input AlbumFilter { @@ -255,8 +235,8 @@ input AlbumFilter { updatedAt: TimeFilter name: StringFilter - and: MediaItemFilter - or: MediaItemFilter + # and: MediaItemFilter + # or: MediaItemFilter } # ------------------------------------------------------------ diff --git a/graph/schema.resolvers.go b/graph/schema.resolvers.go index 1616c71..bdb69d9 100644 --- a/graph/schema.resolvers.go +++ b/graph/schema.resolvers.go @@ -102,13 +102,14 @@ func (r *mutationResolver) CreateAlbum(ctx context.Context, input model.NewAlbum // Get Context authContext := ctx.Value("auth").(*model.AuthContext) accessToken := *authContext.AccessToken - _, ok := accessToken.Get("sub") + userID, ok := accessToken.Get("sub") if !ok { return nil, errors.New("Upload Failed") } album := &model.Album{ - Name: input.Name, + Name: input.Name, + UserID: userID.(string), } err := r.DB.CreateAlbum(album) @@ -120,8 +121,17 @@ func (r *mutationResolver) CreateAlbum(ctx context.Context, input model.NewAlbum } func (r *mutationResolver) CreateTag(ctx context.Context, input model.NewTag) (*model.Tag, error) { + // Get Context + authContext := ctx.Value("auth").(*model.AuthContext) + accessToken := *authContext.AccessToken + userID, ok := accessToken.Get("sub") + if !ok { + return nil, errors.New("Upload Failed") + } + tag := &model.Tag{ - Name: input.Name, + Name: input.Name, + UserID: userID.(string), } err := r.DB.CreateTag(tag) @@ -223,13 +233,20 @@ func (r *queryResolver) Logout(ctx context.Context) (*model.AuthResponse, error) } func (r *queryResolver) MediaItem(ctx context.Context, id string, delete *bool) (*model.MediaItem, error) { - // TODO: User Specific - deviceID, err := uuid.Parse(id) + // Get Context + authContext := ctx.Value("auth").(*model.AuthContext) + accessToken := *authContext.AccessToken + userID, ok := accessToken.Get("sub") + if !ok { + return nil, errors.New("Context Error") + } + + mediaItemID, err := uuid.Parse(id) if err != nil { return nil, errors.New("Invalid ID Format") } - foundMediaItem := &model.MediaItem{ID: deviceID.String()} + foundMediaItem := &model.MediaItem{ID: mediaItemID.String(), UserID: userID.(string)} count, err := r.DB.MediaItem(foundMediaItem) if err != nil { return nil, errors.New("DB Error") @@ -240,13 +257,20 @@ func (r *queryResolver) MediaItem(ctx context.Context, id string, delete *bool) } func (r *queryResolver) Device(ctx context.Context, id string, delete *bool) (*model.Device, error) { - // TODO: User Specific + // Get Context + authContext := ctx.Value("auth").(*model.AuthContext) + accessToken := *authContext.AccessToken + userID, ok := accessToken.Get("sub") + if !ok { + return nil, errors.New("Context Error") + } + deviceID, err := uuid.Parse(id) if err != nil { return nil, errors.New("Invalid ID Format") } - foundDevice := &model.Device{ID: deviceID.String()} + foundDevice := &model.Device{ID: deviceID.String(), UserID: userID.(string)} count, err := r.DB.Device(foundDevice) if err != nil { return nil, errors.New("DB Error") @@ -257,13 +281,20 @@ func (r *queryResolver) Device(ctx context.Context, id string, delete *bool) (*m } func (r *queryResolver) Album(ctx context.Context, id string, delete *bool) (*model.Album, error) { - // TODO: User Specific + // Get Context + authContext := ctx.Value("auth").(*model.AuthContext) + accessToken := *authContext.AccessToken + userID, ok := accessToken.Get("sub") + if !ok { + return nil, errors.New("Context Error") + } + albumID, err := uuid.Parse(id) if err != nil { return nil, errors.New("Invalid ID Format") } - foundAlbum := &model.Album{ID: albumID.String()} + foundAlbum := &model.Album{ID: albumID.String(), UserID: userID.(string)} count, err := r.DB.Album(foundAlbum) if err != nil { return nil, errors.New("DB Error") @@ -323,7 +354,7 @@ func (r *queryResolver) Me(ctx context.Context, delete *bool) (*model.User, erro } func (r *queryResolver) MediaItems(ctx context.Context, delete *bool, filter *model.MediaItemFilter, count *int, page *int) (*model.MediaItemResponse, error) { - resp, totalCount, err := r.DB.MediaItems() + resp, totalCount, err := r.DB.MediaItems(filter) if err != nil { return nil, errors.New("Context Error") } @@ -338,10 +369,18 @@ func (r *queryResolver) MediaItems(ctx context.Context, delete *bool, filter *mo } func (r *queryResolver) Devices(ctx context.Context, delete *bool, filter *model.DeviceFilter, count *int, page *int) (*model.DeviceResponse, error) { - // TODO: User Specific + // Get Context + authContext := ctx.Value("auth").(*model.AuthContext) + accessToken := *authContext.AccessToken + userID, ok := accessToken.Get("sub") + if !ok { + return nil, errors.New("Context Error") + } + _ = userID + resp, totalCount, err := r.DB.Devices() if err != nil { - return nil, errors.New("Context Error") + return nil, errors.New("DB Error") } return &model.DeviceResponse{ Data: resp, diff --git a/internal/db/filters.go b/internal/db/filters.go new file mode 100644 index 0000000..a13731b --- /dev/null +++ b/internal/db/filters.go @@ -0,0 +1,193 @@ +package db + +import ( + "fmt" + "reflect" + + "github.com/iancoleman/strcase" + "gorm.io/gorm" + "reichard.io/imagini/graph/model" +) + +// Generic function used to generate filters for the DB +func (dbm *DBManager) generateFilters(filter interface{}) (*gorm.DB, error) { + tx := dbm.db.Session(&gorm.Session{}).Debug() + + v := reflect.ValueOf(filter) + + for i := 0; i < v.NumField(); i++ { + fieldName := strcase.ToSnake(v.Type().Field(i).Name) + fieldVal := v.Field(i) + + if fieldVal.IsNil() { + continue + } + + switch valType := fieldVal.Type(); valType { + case reflect.TypeOf(&model.StringFilter{}): + tx = generateStringFilter(tx, fieldName, fieldVal.Interface().(*model.StringFilter)) + case reflect.TypeOf(&model.BooleanFilter{}): + tx = generateBooleanFilter(tx, fieldName, fieldVal.Interface().(*model.BooleanFilter)) + case reflect.TypeOf(&model.FloatFilter{}): + tx = generateFloatFilter(tx, fieldName, fieldVal.Interface().(*model.FloatFilter)) + case reflect.TypeOf(&model.IntFilter{}): + tx = generateIntFilter(tx, fieldName, fieldVal.Interface().(*model.IntFilter)) + case reflect.TypeOf(&model.IDFilter{}): + tx = generateIDFilter(tx, fieldName, fieldVal.Interface().(*model.IDFilter)) + case reflect.TypeOf(&model.TimeFilter{}): + tx = generateTimeFilter(tx, fieldName, fieldVal.Interface().(*model.TimeFilter)) + case reflect.TypeOf(&model.RoleFilter{}): + tx = generateRoleFilter(tx, fieldName, fieldVal.Interface().(*model.RoleFilter)) + case reflect.TypeOf(&model.DeviceTypeFilter{}): + tx = generateDeviceTypeFilter(tx, fieldName, fieldVal.Interface().(*model.DeviceTypeFilter)) + case reflect.TypeOf(&model.AuthTypeFilter{}): + tx = generateAuthTypeFilter(tx, fieldName, fieldVal.Interface().(*model.AuthTypeFilter)) + } + } + + return tx, nil +} + +func generateStringFilter(tx *gorm.DB, fieldName string, filter *model.StringFilter) *gorm.DB { + if filter.EqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s == ?", fieldName), *filter.EqualTo) + } + if filter.NotEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s != ?", fieldName), *filter.NotEqualTo) + } + if filter.StartsWith != nil { + tx = tx.Where(fmt.Sprintf("%s LIKE ?", fieldName), fmt.Sprintf("%s%%", *filter.StartsWith)) + } + if filter.NotStartsWith != nil { + tx = tx.Where(fmt.Sprintf("%s NOT LIKE ?", fieldName), fmt.Sprintf("%s%%", *filter.NotStartsWith)) + } + if filter.EndsWith != nil { + tx = tx.Where(fmt.Sprintf("%s LIKE ?", fieldName), fmt.Sprintf("%%%s", *filter.EndsWith)) + } + if filter.NotEndsWith != nil { + tx = tx.Where(fmt.Sprintf("%s NOT LIKE ?", fieldName), fmt.Sprintf("%%%s", *filter.NotEndsWith)) + } + if filter.Contains != nil { + tx = tx.Where(fmt.Sprintf("%s LIKE ?", fieldName), fmt.Sprintf("%%%s%%", *filter.Contains)) + } + if filter.NotContains != nil { + tx = tx.Where(fmt.Sprintf("%s NOT LIKE ?", fieldName), fmt.Sprintf("%%%s%%", *filter.NotContains)) + } + return tx +} + +func generateBooleanFilter(tx *gorm.DB, fieldName string, filter *model.BooleanFilter) *gorm.DB { + if filter.EqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s == ?", fieldName), *filter.EqualTo) + } + if filter.NotEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s != ?", fieldName), *filter.NotEqualTo) + } + return tx +} + +func generateFloatFilter(tx *gorm.DB, fieldName string, filter *model.FloatFilter) *gorm.DB { + if filter.EqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s == ?", fieldName), *filter.EqualTo) + } + if filter.NotEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s != ?", fieldName), *filter.NotEqualTo) + } + if filter.GreaterThan != nil { + tx = tx.Where(fmt.Sprintf("%s > ?", fieldName), *filter.GreaterThan) + } + if filter.GreaterThanOrEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s >= ?", fieldName), *filter.GreaterThanOrEqualTo) + } + if filter.LessThan != nil { + tx = tx.Where(fmt.Sprintf("%s < ?", fieldName), *filter.LessThan) + } + if filter.LessThanOrEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s <= ?", fieldName), *filter.LessThanOrEqualTo) + } + return tx +} + +func generateIntFilter(tx *gorm.DB, fieldName string, filter *model.IntFilter) *gorm.DB { + if filter.EqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s == ?", fieldName), *filter.EqualTo) + } + if filter.NotEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s != ?", fieldName), *filter.NotEqualTo) + } + if filter.GreaterThan != nil { + tx = tx.Where(fmt.Sprintf("%s > ?", fieldName), *filter.GreaterThan) + } + if filter.GreaterThanOrEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s >= ?", fieldName), *filter.GreaterThanOrEqualTo) + } + if filter.LessThan != nil { + tx = tx.Where(fmt.Sprintf("%s < ?", fieldName), *filter.LessThan) + } + if filter.LessThanOrEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s <= ?", fieldName), *filter.LessThanOrEqualTo) + } + return tx +} + +func generateIDFilter(tx *gorm.DB, fieldName string, filter *model.IDFilter) *gorm.DB { + if filter.EqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s == ?", fieldName), *filter.EqualTo) + } + if filter.NotEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s != ?", fieldName), *filter.NotEqualTo) + } + return tx +} + +func generateTimeFilter(tx *gorm.DB, fieldName string, filter *model.TimeFilter) *gorm.DB { + if filter.EqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s == ?", fieldName), *filter.EqualTo) + } + if filter.NotEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s != ?", fieldName), *filter.NotEqualTo) + } + if filter.GreaterThan != nil { + tx = tx.Where(fmt.Sprintf("%s > ?", fieldName), *filter.GreaterThan) + } + if filter.GreaterThanOrEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s >= ?", fieldName), *filter.GreaterThanOrEqualTo) + } + if filter.LessThan != nil { + tx = tx.Where(fmt.Sprintf("%s < ?", fieldName), *filter.LessThan) + } + if filter.LessThanOrEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s <= ?", fieldName), *filter.LessThanOrEqualTo) + } + return tx +} + +func generateRoleFilter(tx *gorm.DB, fieldName string, filter *model.RoleFilter) *gorm.DB { + if filter.EqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s == ?", fieldName), *filter.EqualTo) + } + if filter.NotEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s != ?", fieldName), *filter.NotEqualTo) + } + return tx +} + +func generateDeviceTypeFilter(tx *gorm.DB, fieldName string, filter *model.DeviceTypeFilter) *gorm.DB { + if filter.EqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s == ?", fieldName), *filter.EqualTo) + } + if filter.NotEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s != ?", fieldName), *filter.NotEqualTo) + } + return tx +} + +func generateAuthTypeFilter(tx *gorm.DB, fieldName string, filter *model.AuthTypeFilter) *gorm.DB { + if filter.EqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s == ?", fieldName), *filter.EqualTo) + } + if filter.NotEqualTo != nil { + tx = tx.Where(fmt.Sprintf("%s != ?", fieldName), *filter.NotEqualTo) + } + return tx +} diff --git a/internal/db/media_items.go b/internal/db/media_items.go index 3dab426..11656c9 100644 --- a/internal/db/media_items.go +++ b/internal/db/media_items.go @@ -18,9 +18,14 @@ func (dbm *DBManager) MediaItem(mediaItem *model.MediaItem) (int64, error) { return count, err } -func (dbm *DBManager) MediaItems() ([]*model.MediaItem, int64, error) { +func (dbm *DBManager) MediaItems(filters *model.MediaItemFilter) ([]*model.MediaItem, int64, error) { + // Perform Filters + tx, err := dbm.generateFilters(*filters) + if err != nil { + return nil, 0, err + } var mediaItems []*model.MediaItem var count int64 - err := dbm.db.Find(&mediaItems).Count(&count).Error + err = tx.Find(&mediaItems).Count(&count).Error return mediaItems, count, err } From af237110f941832925cfe5ad56504cdcb2c03539 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Mon, 8 Feb 2021 19:42:20 -0500 Subject: [PATCH 8/8] Order & Sorting --- graph/generated/generated.go | 692 +++++++++++++++++------------------ graph/helpers.go | 46 +++ graph/model/models_gen.go | 75 +++- graph/schema.graphqls | 83 +++-- graph/schema.resolvers.go | 209 +++++------ internal/db/albums.go | 15 +- internal/db/db.go | 134 ++++--- internal/db/devices.go | 15 +- internal/db/filters.go | 11 +- internal/db/media_items.go | 21 +- internal/db/tags.go | 15 +- internal/db/users.go | 15 +- 12 files changed, 727 insertions(+), 604 deletions(-) diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 2b29157..19bb14d 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -57,8 +57,8 @@ type ComplexityRoot struct { } AlbumResponse struct { - Data func(childComplexity int) int - PageInfo func(childComplexity int) int + Data func(childComplexity int) int + Page func(childComplexity int) int } AuthResponse struct { @@ -78,8 +78,8 @@ type ComplexityRoot struct { } DeviceResponse struct { - Data func(childComplexity int) int - PageInfo func(childComplexity int) int + Data func(childComplexity int) int + Page func(childComplexity int) int } MediaItem struct { @@ -98,8 +98,8 @@ type ComplexityRoot struct { } MediaItemResponse struct { - Data func(childComplexity int) int - PageInfo func(childComplexity int) int + Data func(childComplexity int) int + Page func(childComplexity int) int } Mutation struct { @@ -109,26 +109,26 @@ type ComplexityRoot struct { CreateUser func(childComplexity int, input model.NewUser) int } - PageInfo struct { - Count func(childComplexity int) int + PageResponse struct { Page func(childComplexity int) int + Size func(childComplexity int) int Total func(childComplexity int) int } Query struct { - Album func(childComplexity int, id string, delete *bool) int - Albums func(childComplexity int, delete *bool, filter *model.AlbumFilter, count *int, page *int) int - Device func(childComplexity int, id string, delete *bool) int - Devices func(childComplexity int, delete *bool, filter *model.DeviceFilter, count *int, page *int) int + Album func(childComplexity int, id string) int + Albums func(childComplexity int, filter *model.AlbumFilter, page *model.Page, order *model.Order) int + Device func(childComplexity int, id string) int + Devices func(childComplexity int, filter *model.DeviceFilter, page *model.Page, order *model.Order) int Login func(childComplexity int, user string, password string, deviceID *string) int Logout func(childComplexity int) int - Me func(childComplexity int, delete *bool) int - MediaItem func(childComplexity int, id string, delete *bool) int - MediaItems func(childComplexity int, delete *bool, filter *model.MediaItemFilter, count *int, page *int) int - Tag func(childComplexity int, id string, delete *bool) int - Tags func(childComplexity int, delete *bool, filter *model.TagFilter, count *int, page *int) int - User func(childComplexity int, id string, delete *bool) int - Users func(childComplexity int, delete *bool, filter *model.UserFilter, count *int, page *int) int + Me func(childComplexity int) int + MediaItem func(childComplexity int, id string) int + MediaItems func(childComplexity int, filter *model.MediaItemFilter, page *model.Page, order *model.Order) int + Tag func(childComplexity int, id string) int + Tags func(childComplexity int, filter *model.TagFilter, page *model.Page, order *model.Order) int + User func(childComplexity int, id string) int + Users func(childComplexity int, filter *model.UserFilter, page *model.Page, order *model.Order) int } Tag struct { @@ -140,8 +140,8 @@ type ComplexityRoot struct { } TagResponse struct { - Data func(childComplexity int) int - PageInfo func(childComplexity int) int + Data func(childComplexity int) int + Page func(childComplexity int) int } User struct { @@ -160,8 +160,8 @@ type ComplexityRoot struct { } UserResponse struct { - Data func(childComplexity int) int - PageInfo func(childComplexity int) int + Data func(childComplexity int) int + Page func(childComplexity int) int } } @@ -174,17 +174,17 @@ type MutationResolver interface { type QueryResolver interface { Login(ctx context.Context, user string, password string, deviceID *string) (*model.AuthResponse, error) Logout(ctx context.Context) (*model.AuthResponse, error) - MediaItem(ctx context.Context, id string, delete *bool) (*model.MediaItem, error) - Device(ctx context.Context, id string, delete *bool) (*model.Device, error) - Album(ctx context.Context, id string, delete *bool) (*model.Album, error) - User(ctx context.Context, id string, delete *bool) (*model.User, error) - Tag(ctx context.Context, id string, delete *bool) (*model.Tag, error) - Me(ctx context.Context, delete *bool) (*model.User, error) - MediaItems(ctx context.Context, delete *bool, filter *model.MediaItemFilter, count *int, page *int) (*model.MediaItemResponse, error) - Devices(ctx context.Context, delete *bool, filter *model.DeviceFilter, count *int, page *int) (*model.DeviceResponse, error) - Albums(ctx context.Context, delete *bool, filter *model.AlbumFilter, count *int, page *int) (*model.AlbumResponse, error) - Tags(ctx context.Context, delete *bool, filter *model.TagFilter, count *int, page *int) (*model.TagResponse, error) - Users(ctx context.Context, delete *bool, filter *model.UserFilter, count *int, page *int) (*model.UserResponse, error) + MediaItem(ctx context.Context, id string) (*model.MediaItem, error) + Device(ctx context.Context, id string) (*model.Device, error) + Album(ctx context.Context, id string) (*model.Album, error) + User(ctx context.Context, id string) (*model.User, error) + Tag(ctx context.Context, id string) (*model.Tag, error) + Me(ctx context.Context) (*model.User, error) + MediaItems(ctx context.Context, filter *model.MediaItemFilter, page *model.Page, order *model.Order) (*model.MediaItemResponse, error) + Devices(ctx context.Context, filter *model.DeviceFilter, page *model.Page, order *model.Order) (*model.DeviceResponse, error) + Albums(ctx context.Context, filter *model.AlbumFilter, page *model.Page, order *model.Order) (*model.AlbumResponse, error) + Tags(ctx context.Context, filter *model.TagFilter, page *model.Page, order *model.Order) (*model.TagResponse, error) + Users(ctx context.Context, filter *model.UserFilter, page *model.Page, order *model.Order) (*model.UserResponse, error) } type executableSchema struct { @@ -244,12 +244,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.AlbumResponse.Data(childComplexity), true - case "AlbumResponse.pageInfo": - if e.complexity.AlbumResponse.PageInfo == nil { + case "AlbumResponse.page": + if e.complexity.AlbumResponse.Page == nil { break } - return e.complexity.AlbumResponse.PageInfo(childComplexity), true + return e.complexity.AlbumResponse.Page(childComplexity), true case "AuthResponse.device": if e.complexity.AuthResponse.Device == nil { @@ -328,12 +328,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DeviceResponse.Data(childComplexity), true - case "DeviceResponse.pageInfo": - if e.complexity.DeviceResponse.PageInfo == nil { + case "DeviceResponse.page": + if e.complexity.DeviceResponse.Page == nil { break } - return e.complexity.DeviceResponse.PageInfo(childComplexity), true + return e.complexity.DeviceResponse.Page(childComplexity), true case "MediaItem.albums": if e.complexity.MediaItem.Albums == nil { @@ -426,12 +426,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.MediaItemResponse.Data(childComplexity), true - case "MediaItemResponse.pageInfo": - if e.complexity.MediaItemResponse.PageInfo == nil { + case "MediaItemResponse.page": + if e.complexity.MediaItemResponse.Page == nil { break } - return e.complexity.MediaItemResponse.PageInfo(childComplexity), true + return e.complexity.MediaItemResponse.Page(childComplexity), true case "Mutation.createAlbum": if e.complexity.Mutation.CreateAlbum == nil { @@ -481,26 +481,26 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.CreateUser(childComplexity, args["input"].(model.NewUser)), true - case "PageInfo.count": - if e.complexity.PageInfo.Count == nil { + case "PageResponse.page": + if e.complexity.PageResponse.Page == nil { break } - return e.complexity.PageInfo.Count(childComplexity), true + return e.complexity.PageResponse.Page(childComplexity), true - case "PageInfo.page": - if e.complexity.PageInfo.Page == nil { + case "PageResponse.size": + if e.complexity.PageResponse.Size == nil { break } - return e.complexity.PageInfo.Page(childComplexity), true + return e.complexity.PageResponse.Size(childComplexity), true - case "PageInfo.total": - if e.complexity.PageInfo.Total == nil { + case "PageResponse.total": + if e.complexity.PageResponse.Total == nil { break } - return e.complexity.PageInfo.Total(childComplexity), true + return e.complexity.PageResponse.Total(childComplexity), true case "Query.album": if e.complexity.Query.Album == nil { @@ -512,7 +512,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Album(childComplexity, args["id"].(string), args["delete"].(*bool)), true + return e.complexity.Query.Album(childComplexity, args["id"].(string)), true case "Query.albums": if e.complexity.Query.Albums == nil { @@ -524,7 +524,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Albums(childComplexity, args["delete"].(*bool), args["filter"].(*model.AlbumFilter), args["count"].(*int), args["page"].(*int)), true + return e.complexity.Query.Albums(childComplexity, args["filter"].(*model.AlbumFilter), args["page"].(*model.Page), args["order"].(*model.Order)), true case "Query.device": if e.complexity.Query.Device == nil { @@ -536,7 +536,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Device(childComplexity, args["id"].(string), args["delete"].(*bool)), true + return e.complexity.Query.Device(childComplexity, args["id"].(string)), true case "Query.devices": if e.complexity.Query.Devices == nil { @@ -548,7 +548,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Devices(childComplexity, args["delete"].(*bool), args["filter"].(*model.DeviceFilter), args["count"].(*int), args["page"].(*int)), true + return e.complexity.Query.Devices(childComplexity, args["filter"].(*model.DeviceFilter), args["page"].(*model.Page), args["order"].(*model.Order)), true case "Query.login": if e.complexity.Query.Login == nil { @@ -574,12 +574,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in break } - args, err := ec.field_Query_me_args(context.TODO(), rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Query.Me(childComplexity, args["delete"].(*bool)), true + return e.complexity.Query.Me(childComplexity), true case "Query.mediaItem": if e.complexity.Query.MediaItem == nil { @@ -591,7 +586,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.MediaItem(childComplexity, args["id"].(string), args["delete"].(*bool)), true + return e.complexity.Query.MediaItem(childComplexity, args["id"].(string)), true case "Query.mediaItems": if e.complexity.Query.MediaItems == nil { @@ -603,7 +598,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.MediaItems(childComplexity, args["delete"].(*bool), args["filter"].(*model.MediaItemFilter), args["count"].(*int), args["page"].(*int)), true + return e.complexity.Query.MediaItems(childComplexity, args["filter"].(*model.MediaItemFilter), args["page"].(*model.Page), args["order"].(*model.Order)), true case "Query.tag": if e.complexity.Query.Tag == nil { @@ -615,7 +610,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Tag(childComplexity, args["id"].(string), args["delete"].(*bool)), true + return e.complexity.Query.Tag(childComplexity, args["id"].(string)), true case "Query.tags": if e.complexity.Query.Tags == nil { @@ -627,7 +622,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Tags(childComplexity, args["delete"].(*bool), args["filter"].(*model.TagFilter), args["count"].(*int), args["page"].(*int)), true + return e.complexity.Query.Tags(childComplexity, args["filter"].(*model.TagFilter), args["page"].(*model.Page), args["order"].(*model.Order)), true case "Query.user": if e.complexity.Query.User == nil { @@ -639,7 +634,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.User(childComplexity, args["id"].(string), args["delete"].(*bool)), true + return e.complexity.Query.User(childComplexity, args["id"].(string)), true case "Query.users": if e.complexity.Query.Users == nil { @@ -651,7 +646,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Users(childComplexity, args["delete"].(*bool), args["filter"].(*model.UserFilter), args["count"].(*int), args["page"].(*int)), true + return e.complexity.Query.Users(childComplexity, args["filter"].(*model.UserFilter), args["page"].(*model.Page), args["order"].(*model.Order)), true case "Tag.createdAt": if e.complexity.Tag.CreatedAt == nil { @@ -695,12 +690,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.TagResponse.Data(childComplexity), true - case "TagResponse.pageInfo": - if e.complexity.TagResponse.PageInfo == nil { + case "TagResponse.page": + if e.complexity.TagResponse.Page == nil { break } - return e.complexity.TagResponse.PageInfo(childComplexity), true + return e.complexity.TagResponse.Page(childComplexity), true case "User.authType": if e.complexity.User.AuthType == nil { @@ -793,12 +788,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.UserResponse.Data(childComplexity), true - case "UserResponse.pageInfo": - if e.complexity.UserResponse.PageInfo == nil { + case "UserResponse.page": + if e.complexity.UserResponse.Page == nil { break } - return e.complexity.UserResponse.PageInfo(childComplexity), true + return e.complexity.UserResponse.Page(childComplexity), true } return 0, false @@ -898,6 +893,11 @@ enum AuthType { LDAP } +enum OrderDirection { + ASC + DESC +} + # ------------------------------------------------------------ # ---------------------- Authentication ---------------------- # ------------------------------------------------------------ @@ -1133,39 +1133,49 @@ input NewAlbum { name: String! } +input Page { + size: Int + page: Int +} + +input Order { + by: String + direction: OrderDirection +} + # ------------------------------------------------------------ # ------------------------ Responses ------------------------- # ------------------------------------------------------------ -type PageInfo { - count: Int! +type PageResponse { + size: Int! page: Int! total: Int! } type MediaItemResponse { data: [MediaItem] - pageInfo: PageInfo! + page: PageResponse! } type UserResponse { data: [User] - pageInfo: PageInfo! + page: PageResponse! } type DeviceResponse { data: [Device] - pageInfo: PageInfo! + page: PageResponse! } type TagResponse { data: [Tag] - pageInfo: PageInfo! + page: PageResponse! } type AlbumResponse { data: [Album] - pageInfo: PageInfo! + page: PageResponse! } # ------------------------------------------------------------ @@ -1179,62 +1189,52 @@ type Query { password: String! deviceID: ID ): AuthResponse! - logout: AuthResponse! @hasMinRole(role: User) + logout: AuthResponse! @hasMinRole(role: User) # Single Item mediaItem( id: ID! - delete: Boolean - ): MediaItem! @hasMinRole(role: User) + ): MediaItem! @hasMinRole(role: User) device( id: ID! - delete: Boolean - ): Device! @hasMinRole(role: User) + ): Device! @hasMinRole(role: User) album( id: ID! - delete: Boolean - ): Album! @hasMinRole(role: User) + ): Album! @hasMinRole(role: User) user( id: ID! - delete: Boolean - ): User! @hasMinRole(role: Admin) # TODO: Delete All User Content + ): User! @hasMinRole(role: Admin) tag( id: ID! - delete: Boolean - ): Tag! @hasMinRole(role: User) - me(delete: Boolean): User! @hasMinRole(role: User) + ): Tag! @hasMinRole(role: User) + me: User! @hasMinRole(role: User) # All mediaItems( - delete: Boolean filter: MediaItemFilter - count: Int - page: Int - ): MediaItemResponse! @hasMinRole(role: User) + page: Page + order: Order + ): MediaItemResponse! @hasMinRole(role: User) devices( - delete: Boolean filter: DeviceFilter - count: Int - page: Int - ): DeviceResponse! @hasMinRole(role: User) + page: Page + order: Order + ): DeviceResponse! @hasMinRole(role: User) albums( - delete: Boolean filter: AlbumFilter - count: Int - page: Int - ): AlbumResponse! @hasMinRole(role: User) + page: Page + order: Order + ): AlbumResponse! @hasMinRole(role: User) tags( - delete: Boolean filter: TagFilter - count: Int - page: Int - ): TagResponse! @hasMinRole(role: User) + page: Page + order: Order + ): TagResponse! @hasMinRole(role: User) users( - delete: Boolean filter: UserFilter - count: Int - page: Int - ): UserResponse! @hasMinRole(role: Admin) # TODO: Delete All User Content + page: Page + order: Order + ): UserResponse! @hasMinRole(role: Admin) } type Mutation { @@ -1368,57 +1368,39 @@ func (ec *executionContext) field_Query_album_args(ctx context.Context, rawArgs } } args["id"] = arg0 - var arg1 *bool - if tmp, ok := rawArgs["delete"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) - arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["delete"] = arg1 return args, nil } func (ec *executionContext) field_Query_albums_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *bool - if tmp, ok := rawArgs["delete"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) - arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["delete"] = arg0 - var arg1 *model.AlbumFilter + var arg0 *model.AlbumFilter if tmp, ok := rawArgs["filter"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg1, err = ec.unmarshalOAlbumFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbumFilter(ctx, tmp) + arg0, err = ec.unmarshalOAlbumFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbumFilter(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg1 - var arg2 *int - if tmp, ok := rawArgs["count"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) - arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) - if err != nil { - return nil, err - } - } - args["count"] = arg2 - var arg3 *int + args["filter"] = arg0 + var arg1 *model.Page if tmp, ok := rawArgs["page"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) - arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + arg1, err = ec.unmarshalOPage2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPage(ctx, tmp) if err != nil { return nil, err } } - args["page"] = arg3 + args["page"] = arg1 + var arg2 *model.Order + if tmp, ok := rawArgs["order"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("order")) + arg2, err = ec.unmarshalOOrder2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐOrder(ctx, tmp) + if err != nil { + return nil, err + } + } + args["order"] = arg2 return args, nil } @@ -1434,57 +1416,39 @@ func (ec *executionContext) field_Query_device_args(ctx context.Context, rawArgs } } args["id"] = arg0 - var arg1 *bool - if tmp, ok := rawArgs["delete"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) - arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["delete"] = arg1 return args, nil } func (ec *executionContext) field_Query_devices_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *bool - if tmp, ok := rawArgs["delete"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) - arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["delete"] = arg0 - var arg1 *model.DeviceFilter + var arg0 *model.DeviceFilter if tmp, ok := rawArgs["filter"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg1, err = ec.unmarshalODeviceFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceFilter(ctx, tmp) + arg0, err = ec.unmarshalODeviceFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDeviceFilter(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg1 - var arg2 *int - if tmp, ok := rawArgs["count"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) - arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) - if err != nil { - return nil, err - } - } - args["count"] = arg2 - var arg3 *int + args["filter"] = arg0 + var arg1 *model.Page if tmp, ok := rawArgs["page"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) - arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + arg1, err = ec.unmarshalOPage2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPage(ctx, tmp) if err != nil { return nil, err } } - args["page"] = arg3 + args["page"] = arg1 + var arg2 *model.Order + if tmp, ok := rawArgs["order"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("order")) + arg2, err = ec.unmarshalOOrder2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐOrder(ctx, tmp) + if err != nil { + return nil, err + } + } + args["order"] = arg2 return args, nil } @@ -1521,21 +1485,6 @@ func (ec *executionContext) field_Query_login_args(ctx context.Context, rawArgs return args, nil } -func (ec *executionContext) field_Query_me_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { - var err error - args := map[string]interface{}{} - var arg0 *bool - if tmp, ok := rawArgs["delete"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) - arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["delete"] = arg0 - return args, nil -} - func (ec *executionContext) field_Query_mediaItem_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -1548,57 +1497,39 @@ func (ec *executionContext) field_Query_mediaItem_args(ctx context.Context, rawA } } args["id"] = arg0 - var arg1 *bool - if tmp, ok := rawArgs["delete"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) - arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["delete"] = arg1 return args, nil } func (ec *executionContext) field_Query_mediaItems_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *bool - if tmp, ok := rawArgs["delete"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) - arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["delete"] = arg0 - var arg1 *model.MediaItemFilter + var arg0 *model.MediaItemFilter if tmp, ok := rawArgs["filter"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg1, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, tmp) + arg0, err = ec.unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItemFilter(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg1 - var arg2 *int - if tmp, ok := rawArgs["count"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) - arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) - if err != nil { - return nil, err - } - } - args["count"] = arg2 - var arg3 *int + args["filter"] = arg0 + var arg1 *model.Page if tmp, ok := rawArgs["page"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) - arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + arg1, err = ec.unmarshalOPage2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPage(ctx, tmp) if err != nil { return nil, err } } - args["page"] = arg3 + args["page"] = arg1 + var arg2 *model.Order + if tmp, ok := rawArgs["order"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("order")) + arg2, err = ec.unmarshalOOrder2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐOrder(ctx, tmp) + if err != nil { + return nil, err + } + } + args["order"] = arg2 return args, nil } @@ -1614,57 +1545,39 @@ func (ec *executionContext) field_Query_tag_args(ctx context.Context, rawArgs ma } } args["id"] = arg0 - var arg1 *bool - if tmp, ok := rawArgs["delete"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) - arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["delete"] = arg1 return args, nil } func (ec *executionContext) field_Query_tags_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *bool - if tmp, ok := rawArgs["delete"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) - arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["delete"] = arg0 - var arg1 *model.TagFilter + var arg0 *model.TagFilter if tmp, ok := rawArgs["filter"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg1, err = ec.unmarshalOTagFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTagFilter(ctx, tmp) + arg0, err = ec.unmarshalOTagFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTagFilter(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg1 - var arg2 *int - if tmp, ok := rawArgs["count"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) - arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) - if err != nil { - return nil, err - } - } - args["count"] = arg2 - var arg3 *int + args["filter"] = arg0 + var arg1 *model.Page if tmp, ok := rawArgs["page"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) - arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + arg1, err = ec.unmarshalOPage2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPage(ctx, tmp) if err != nil { return nil, err } } - args["page"] = arg3 + args["page"] = arg1 + var arg2 *model.Order + if tmp, ok := rawArgs["order"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("order")) + arg2, err = ec.unmarshalOOrder2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐOrder(ctx, tmp) + if err != nil { + return nil, err + } + } + args["order"] = arg2 return args, nil } @@ -1680,57 +1593,39 @@ func (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs m } } args["id"] = arg0 - var arg1 *bool - if tmp, ok := rawArgs["delete"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) - arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["delete"] = arg1 return args, nil } func (ec *executionContext) field_Query_users_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *bool - if tmp, ok := rawArgs["delete"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("delete")) - arg0, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["delete"] = arg0 - var arg1 *model.UserFilter + var arg0 *model.UserFilter if tmp, ok := rawArgs["filter"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) - arg1, err = ec.unmarshalOUserFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserFilter(ctx, tmp) + arg0, err = ec.unmarshalOUserFilter2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUserFilter(ctx, tmp) if err != nil { return nil, err } } - args["filter"] = arg1 - var arg2 *int - if tmp, ok := rawArgs["count"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("count")) - arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) - if err != nil { - return nil, err - } - } - args["count"] = arg2 - var arg3 *int + args["filter"] = arg0 + var arg1 *model.Page if tmp, ok := rawArgs["page"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) - arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + arg1, err = ec.unmarshalOPage2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPage(ctx, tmp) if err != nil { return nil, err } } - args["page"] = arg3 + args["page"] = arg1 + var arg2 *model.Order + if tmp, ok := rawArgs["order"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("order")) + arg2, err = ec.unmarshalOOrder2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐOrder(ctx, tmp) + if err != nil { + return nil, err + } + } + args["order"] = arg2 return args, nil } @@ -2045,7 +1940,7 @@ func (ec *executionContext) _AlbumResponse_data(ctx context.Context, field graph return ec.marshalOAlbum2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐAlbum(ctx, field.Selections, res) } -func (ec *executionContext) _AlbumResponse_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.AlbumResponse) (ret graphql.Marshaler) { +func (ec *executionContext) _AlbumResponse_page(ctx context.Context, field graphql.CollectedField, obj *model.AlbumResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2063,7 +1958,7 @@ func (ec *executionContext) _AlbumResponse_pageInfo(ctx context.Context, field g ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PageInfo, nil + return obj.Page, nil }) if err != nil { ec.Error(ctx, err) @@ -2075,9 +1970,9 @@ func (ec *executionContext) _AlbumResponse_pageInfo(ctx context.Context, field g } return graphql.Null } - res := resTmp.(*model.PageInfo) + res := resTmp.(*model.PageResponse) fc.Result = res - return ec.marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) + return ec.marshalNPageResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageResponse(ctx, field.Selections, res) } func (ec *executionContext) _AuthResponse_result(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) { @@ -2563,7 +2458,7 @@ func (ec *executionContext) _DeviceResponse_data(ctx context.Context, field grap return ec.marshalODevice2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐDevice(ctx, field.Selections, res) } -func (ec *executionContext) _DeviceResponse_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.DeviceResponse) (ret graphql.Marshaler) { +func (ec *executionContext) _DeviceResponse_page(ctx context.Context, field graphql.CollectedField, obj *model.DeviceResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2581,7 +2476,7 @@ func (ec *executionContext) _DeviceResponse_pageInfo(ctx context.Context, field ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PageInfo, nil + return obj.Page, nil }) if err != nil { ec.Error(ctx, err) @@ -2593,9 +2488,9 @@ func (ec *executionContext) _DeviceResponse_pageInfo(ctx context.Context, field } return graphql.Null } - res := resTmp.(*model.PageInfo) + res := resTmp.(*model.PageResponse) fc.Result = res - return ec.marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) + return ec.marshalNPageResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageResponse(ctx, field.Selections, res) } func (ec *executionContext) _MediaItem_id(ctx context.Context, field graphql.CollectedField, obj *model.MediaItem) (ret graphql.Marshaler) { @@ -3245,7 +3140,7 @@ func (ec *executionContext) _MediaItemResponse_data(ctx context.Context, field g return ec.marshalOMediaItem2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐMediaItem(ctx, field.Selections, res) } -func (ec *executionContext) _MediaItemResponse_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.MediaItemResponse) (ret graphql.Marshaler) { +func (ec *executionContext) _MediaItemResponse_page(ctx context.Context, field graphql.CollectedField, obj *model.MediaItemResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3263,7 +3158,7 @@ func (ec *executionContext) _MediaItemResponse_pageInfo(ctx context.Context, fie ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PageInfo, nil + return obj.Page, nil }) if err != nil { ec.Error(ctx, err) @@ -3275,9 +3170,9 @@ func (ec *executionContext) _MediaItemResponse_pageInfo(ctx context.Context, fie } return graphql.Null } - res := resTmp.(*model.PageInfo) + res := resTmp.(*model.PageResponse) fc.Result = res - return ec.marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) + return ec.marshalNPageResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageResponse(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_createMediaItem(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { @@ -3544,7 +3439,7 @@ func (ec *executionContext) _Mutation_createUser(ctx context.Context, field grap return ec.marshalNUser2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) } -func (ec *executionContext) _PageInfo_count(ctx context.Context, field graphql.CollectedField, obj *model.PageInfo) (ret graphql.Marshaler) { +func (ec *executionContext) _PageResponse_size(ctx context.Context, field graphql.CollectedField, obj *model.PageResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3552,7 +3447,7 @@ func (ec *executionContext) _PageInfo_count(ctx context.Context, field graphql.C } }() fc := &graphql.FieldContext{ - Object: "PageInfo", + Object: "PageResponse", Field: field, Args: nil, IsMethod: false, @@ -3562,7 +3457,7 @@ func (ec *executionContext) _PageInfo_count(ctx context.Context, field graphql.C ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Count, nil + return obj.Size, nil }) if err != nil { ec.Error(ctx, err) @@ -3579,7 +3474,7 @@ func (ec *executionContext) _PageInfo_count(ctx context.Context, field graphql.C return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _PageInfo_page(ctx context.Context, field graphql.CollectedField, obj *model.PageInfo) (ret graphql.Marshaler) { +func (ec *executionContext) _PageResponse_page(ctx context.Context, field graphql.CollectedField, obj *model.PageResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3587,7 +3482,7 @@ func (ec *executionContext) _PageInfo_page(ctx context.Context, field graphql.Co } }() fc := &graphql.FieldContext{ - Object: "PageInfo", + Object: "PageResponse", Field: field, Args: nil, IsMethod: false, @@ -3614,7 +3509,7 @@ func (ec *executionContext) _PageInfo_page(ctx context.Context, field graphql.Co return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _PageInfo_total(ctx context.Context, field graphql.CollectedField, obj *model.PageInfo) (ret graphql.Marshaler) { +func (ec *executionContext) _PageResponse_total(ctx context.Context, field graphql.CollectedField, obj *model.PageResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3622,7 +3517,7 @@ func (ec *executionContext) _PageInfo_total(ctx context.Context, field graphql.C } }() fc := &graphql.FieldContext{ - Object: "PageInfo", + Object: "PageResponse", Field: field, Args: nil, IsMethod: false, @@ -3776,7 +3671,7 @@ func (ec *executionContext) _Query_mediaItem(ctx context.Context, field graphql. resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().MediaItem(rctx, args["id"].(string), args["delete"].(*bool)) + return ec.resolvers.Query().MediaItem(rctx, args["id"].(string)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -3842,7 +3737,7 @@ func (ec *executionContext) _Query_device(ctx context.Context, field graphql.Col resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Device(rctx, args["id"].(string), args["delete"].(*bool)) + return ec.resolvers.Query().Device(rctx, args["id"].(string)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -3908,7 +3803,7 @@ func (ec *executionContext) _Query_album(ctx context.Context, field graphql.Coll resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Album(rctx, args["id"].(string), args["delete"].(*bool)) + return ec.resolvers.Query().Album(rctx, args["id"].(string)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -3974,7 +3869,7 @@ func (ec *executionContext) _Query_user(ctx context.Context, field graphql.Colle resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().User(rctx, args["id"].(string), args["delete"].(*bool)) + return ec.resolvers.Query().User(rctx, args["id"].(string)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "Admin") @@ -4040,7 +3935,7 @@ func (ec *executionContext) _Query_tag(ctx context.Context, field graphql.Collec resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Tag(rctx, args["id"].(string), args["delete"].(*bool)) + return ec.resolvers.Query().Tag(rctx, args["id"].(string)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -4096,17 +3991,10 @@ func (ec *executionContext) _Query_me(ctx context.Context, field graphql.Collect } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_me_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Me(rctx, args["delete"].(*bool)) + return ec.resolvers.Query().Me(rctx) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -4172,7 +4060,7 @@ func (ec *executionContext) _Query_mediaItems(ctx context.Context, field graphql resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().MediaItems(rctx, args["delete"].(*bool), args["filter"].(*model.MediaItemFilter), args["count"].(*int), args["page"].(*int)) + return ec.resolvers.Query().MediaItems(rctx, args["filter"].(*model.MediaItemFilter), args["page"].(*model.Page), args["order"].(*model.Order)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -4238,7 +4126,7 @@ func (ec *executionContext) _Query_devices(ctx context.Context, field graphql.Co resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Devices(rctx, args["delete"].(*bool), args["filter"].(*model.DeviceFilter), args["count"].(*int), args["page"].(*int)) + return ec.resolvers.Query().Devices(rctx, args["filter"].(*model.DeviceFilter), args["page"].(*model.Page), args["order"].(*model.Order)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -4304,7 +4192,7 @@ func (ec *executionContext) _Query_albums(ctx context.Context, field graphql.Col resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Albums(rctx, args["delete"].(*bool), args["filter"].(*model.AlbumFilter), args["count"].(*int), args["page"].(*int)) + return ec.resolvers.Query().Albums(rctx, args["filter"].(*model.AlbumFilter), args["page"].(*model.Page), args["order"].(*model.Order)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -4370,7 +4258,7 @@ func (ec *executionContext) _Query_tags(ctx context.Context, field graphql.Colle resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Tags(rctx, args["delete"].(*bool), args["filter"].(*model.TagFilter), args["count"].(*int), args["page"].(*int)) + return ec.resolvers.Query().Tags(rctx, args["filter"].(*model.TagFilter), args["page"].(*model.Page), args["order"].(*model.Order)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "User") @@ -4436,7 +4324,7 @@ func (ec *executionContext) _Query_users(ctx context.Context, field graphql.Coll resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Users(rctx, args["delete"].(*bool), args["filter"].(*model.UserFilter), args["count"].(*int), args["page"].(*int)) + return ec.resolvers.Query().Users(rctx, args["filter"].(*model.UserFilter), args["page"].(*model.Page), args["order"].(*model.Order)) } directive1 := func(ctx context.Context) (interface{}, error) { role, err := ec.unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx, "Admin") @@ -4820,7 +4708,7 @@ func (ec *executionContext) _TagResponse_data(ctx context.Context, field graphql return ec.marshalOTag2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐTag(ctx, field.Selections, res) } -func (ec *executionContext) _TagResponse_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.TagResponse) (ret graphql.Marshaler) { +func (ec *executionContext) _TagResponse_page(ctx context.Context, field graphql.CollectedField, obj *model.TagResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4838,7 +4726,7 @@ func (ec *executionContext) _TagResponse_pageInfo(ctx context.Context, field gra ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PageInfo, nil + return obj.Page, nil }) if err != nil { ec.Error(ctx, err) @@ -4850,9 +4738,9 @@ func (ec *executionContext) _TagResponse_pageInfo(ctx context.Context, field gra } return graphql.Null } - res := resTmp.(*model.PageInfo) + res := resTmp.(*model.PageResponse) fc.Result = res - return ec.marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) + return ec.marshalNPageResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageResponse(ctx, field.Selections, res) } func (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { @@ -5474,7 +5362,7 @@ func (ec *executionContext) _UserResponse_data(ctx context.Context, field graphq return ec.marshalOUser2ᚕᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐUser(ctx, field.Selections, res) } -func (ec *executionContext) _UserResponse_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.UserResponse) (ret graphql.Marshaler) { +func (ec *executionContext) _UserResponse_page(ctx context.Context, field graphql.CollectedField, obj *model.UserResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5492,7 +5380,7 @@ func (ec *executionContext) _UserResponse_pageInfo(ctx context.Context, field gr ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PageInfo, nil + return obj.Page, nil }) if err != nil { ec.Error(ctx, err) @@ -5504,9 +5392,9 @@ func (ec *executionContext) _UserResponse_pageInfo(ctx context.Context, field gr } return graphql.Null } - res := resTmp.(*model.PageInfo) + res := resTmp.(*model.PageResponse) fc.Result = res - return ec.marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) + return ec.marshalNPageResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageResponse(ctx, field.Selections, res) } func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { @@ -7160,6 +7048,62 @@ func (ec *executionContext) unmarshalInputNewUser(ctx context.Context, obj inter return it, nil } +func (ec *executionContext) unmarshalInputOrder(ctx context.Context, obj interface{}) (model.Order, error) { + var it model.Order + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "by": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("by")) + it.By, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "direction": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("direction")) + it.Direction, err = ec.unmarshalOOrderDirection2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐOrderDirection(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputPage(ctx context.Context, obj interface{}) (model.Page, error) { + var it model.Page + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "size": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("size")) + it.Size, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "page": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) + it.Page, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputRoleFilter(ctx context.Context, obj interface{}) (model.RoleFilter, error) { var it model.RoleFilter var asMap = obj.(map[string]interface{}) @@ -7506,8 +7450,8 @@ func (ec *executionContext) _AlbumResponse(ctx context.Context, sel ast.Selectio out.Values[i] = graphql.MarshalString("AlbumResponse") case "data": out.Values[i] = ec._AlbumResponse_data(ctx, field, obj) - case "pageInfo": - out.Values[i] = ec._AlbumResponse_pageInfo(ctx, field, obj) + case "page": + out.Values[i] = ec._AlbumResponse_page(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } @@ -7614,8 +7558,8 @@ func (ec *executionContext) _DeviceResponse(ctx context.Context, sel ast.Selecti out.Values[i] = graphql.MarshalString("DeviceResponse") case "data": out.Values[i] = ec._DeviceResponse_data(ctx, field, obj) - case "pageInfo": - out.Values[i] = ec._DeviceResponse_pageInfo(ctx, field, obj) + case "page": + out.Values[i] = ec._DeviceResponse_page(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } @@ -7704,8 +7648,8 @@ func (ec *executionContext) _MediaItemResponse(ctx context.Context, sel ast.Sele out.Values[i] = graphql.MarshalString("MediaItemResponse") case "data": out.Values[i] = ec._MediaItemResponse_data(ctx, field, obj) - case "pageInfo": - out.Values[i] = ec._MediaItemResponse_pageInfo(ctx, field, obj) + case "page": + out.Values[i] = ec._MediaItemResponse_page(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } @@ -7766,29 +7710,29 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) return out } -var pageInfoImplementors = []string{"PageInfo"} +var pageResponseImplementors = []string{"PageResponse"} -func (ec *executionContext) _PageInfo(ctx context.Context, sel ast.SelectionSet, obj *model.PageInfo) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, pageInfoImplementors) +func (ec *executionContext) _PageResponse(ctx context.Context, sel ast.SelectionSet, obj *model.PageResponse) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, pageResponseImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("PageInfo") - case "count": - out.Values[i] = ec._PageInfo_count(ctx, field, obj) + out.Values[i] = graphql.MarshalString("PageResponse") + case "size": + out.Values[i] = ec._PageResponse_size(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "page": - out.Values[i] = ec._PageInfo_page(ctx, field, obj) + out.Values[i] = ec._PageResponse_page(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } case "total": - out.Values[i] = ec._PageInfo_total(ctx, field, obj) + out.Values[i] = ec._PageResponse_total(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } @@ -8069,8 +8013,8 @@ func (ec *executionContext) _TagResponse(ctx context.Context, sel ast.SelectionS out.Values[i] = graphql.MarshalString("TagResponse") case "data": out.Values[i] = ec._TagResponse_data(ctx, field, obj) - case "pageInfo": - out.Values[i] = ec._TagResponse_pageInfo(ctx, field, obj) + case "page": + out.Values[i] = ec._TagResponse_page(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } @@ -8159,8 +8103,8 @@ func (ec *executionContext) _UserResponse(ctx context.Context, sel ast.Selection out.Values[i] = graphql.MarshalString("UserResponse") case "data": out.Values[i] = ec._UserResponse_data(ctx, field, obj) - case "pageInfo": - out.Values[i] = ec._UserResponse_pageInfo(ctx, field, obj) + case "page": + out.Values[i] = ec._UserResponse_page(ctx, field, obj) if out.Values[i] == graphql.Null { invalids++ } @@ -8613,14 +8557,14 @@ func (ec *executionContext) unmarshalNNewUser2reichardᚗioᚋimaginiᚋgraphᚋ return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNPageInfo2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageInfo(ctx context.Context, sel ast.SelectionSet, v *model.PageInfo) graphql.Marshaler { +func (ec *executionContext) marshalNPageResponse2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPageResponse(ctx context.Context, sel ast.SelectionSet, v *model.PageResponse) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - return ec._PageInfo(ctx, sel, v) + return ec._PageResponse(ctx, sel, v) } func (ec *executionContext) unmarshalNRole2reichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx context.Context, v interface{}) (model.Role, error) { @@ -9370,6 +9314,38 @@ func (ec *executionContext) unmarshalOMediaItemFilter2ᚖreichardᚗioᚋimagini return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalOOrder2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐOrder(ctx context.Context, v interface{}) (*model.Order, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputOrder(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOOrderDirection2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐOrderDirection(ctx context.Context, v interface{}) (*model.OrderDirection, error) { + if v == nil { + return nil, nil + } + var res = new(model.OrderDirection) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOOrderDirection2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐOrderDirection(ctx context.Context, sel ast.SelectionSet, v *model.OrderDirection) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return v +} + +func (ec *executionContext) unmarshalOPage2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐPage(ctx context.Context, v interface{}) (*model.Page, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputPage(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalORole2ᚖreichardᚗioᚋimaginiᚋgraphᚋmodelᚐRole(ctx context.Context, v interface{}) (*model.Role, error) { if v == nil { return nil, nil diff --git a/graph/helpers.go b/graph/helpers.go index e2b2c07..409842c 100644 --- a/graph/helpers.go +++ b/graph/helpers.go @@ -1,15 +1,61 @@ package graph import ( + "context" + "errors" "net/http" "strings" "time" "github.com/dsoprea/go-exif/v3" exifcommon "github.com/dsoprea/go-exif/v3/common" + "github.com/google/uuid" "reichard.io/imagini/graph/model" ) +func getContextHTTP(ctx context.Context) (*http.ResponseWriter, *http.Request, error) { + authContext := ctx.Value("auth").(*model.AuthContext) + + resp := authContext.AuthResponse + if resp == nil { + return nil, nil, errors.New("Context Error") + } + + req := authContext.AuthRequest + if resp == nil { + return nil, nil, errors.New("Context Error") + } + + return resp, req, nil +} + +func getContextIDs(ctx context.Context) (string, string, error) { + authContext := ctx.Value("auth").(*model.AuthContext) + accessToken := *authContext.AccessToken + + uid, ok := accessToken.Get("sub") + if !ok { + return "", "", errors.New("Context Error") + } + + did, ok := accessToken.Get("sub") + if !ok { + return "", "", errors.New("Context Error") + } + + userID, err := uuid.Parse(uid.(string)) + if err != nil { + return "", "", errors.New("Context Error") + } + + deviceID, err := uuid.Parse(did.(string)) + if err != nil { + return "", "", errors.New("Context Error") + } + + return userID.String(), deviceID.String(), nil +} + func deriveDeviceType(r *http.Request) model.DeviceType { userAgent := strings.ToLower(r.Header.Get("User-Agent")) if strings.Contains(userAgent, "ios-imagini") { diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index a2cdbbc..66d036a 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -27,8 +27,8 @@ type AlbumFilter struct { } type AlbumResponse struct { - Data []*Album `json:"data" ` - PageInfo *PageInfo `json:"pageInfo" ` + Data []*Album `json:"data" ` + Page *PageResponse `json:"page" ` } type AuthResponse struct { @@ -66,8 +66,8 @@ type DeviceFilter struct { } type DeviceResponse struct { - Data []*Device `json:"data" ` - PageInfo *PageInfo `json:"pageInfo" ` + Data []*Device `json:"data" ` + Page *PageResponse `json:"page" ` } type DeviceTypeFilter struct { @@ -127,8 +127,8 @@ type MediaItemFilter struct { } type MediaItemResponse struct { - Data []*MediaItem `json:"data" ` - PageInfo *PageInfo `json:"pageInfo" ` + Data []*MediaItem `json:"data" ` + Page *PageResponse `json:"page" ` } type NewAlbum struct { @@ -155,8 +155,18 @@ type NewUser struct { Password *string `json:"password" ` } -type PageInfo struct { - Count int `json:"count" ` +type Order struct { + By *string `json:"by" ` + Direction *OrderDirection `json:"direction" ` +} + +type Page struct { + Size *int `json:"size" ` + Page *int `json:"page" ` +} + +type PageResponse struct { + Size int `json:"size" ` Page int `json:"page" ` Total int `json:"total" ` } @@ -193,8 +203,8 @@ type TagFilter struct { } type TagResponse struct { - Data []*Tag `json:"data" ` - PageInfo *PageInfo `json:"pageInfo" ` + Data []*Tag `json:"data" ` + Page *PageResponse `json:"page" ` } type TimeFilter struct { @@ -233,8 +243,8 @@ type UserFilter struct { } type UserResponse struct { - Data []*User `json:"data" ` - PageInfo *PageInfo `json:"pageInfo" ` + Data []*User `json:"data" ` + Page *PageResponse `json:"page" ` } type AuthResult string @@ -372,6 +382,47 @@ func (e DeviceType) MarshalGQL(w io.Writer) { fmt.Fprint(w, strconv.Quote(e.String())) } +type OrderDirection string + +const ( + OrderDirectionAsc OrderDirection = "ASC" + OrderDirectionDesc OrderDirection = "DESC" +) + +var AllOrderDirection = []OrderDirection{ + OrderDirectionAsc, + OrderDirectionDesc, +} + +func (e OrderDirection) IsValid() bool { + switch e { + case OrderDirectionAsc, OrderDirectionDesc: + return true + } + return false +} + +func (e OrderDirection) String() string { + return string(e) +} + +func (e *OrderDirection) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = OrderDirection(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid OrderDirection", str) + } + return nil +} + +func (e OrderDirection) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + type Role string const ( diff --git a/graph/schema.graphqls b/graph/schema.graphqls index c3448f0..8e7bfdb 100644 --- a/graph/schema.graphqls +++ b/graph/schema.graphqls @@ -32,6 +32,11 @@ enum AuthType { LDAP } +enum OrderDirection { + ASC + DESC +} + # ------------------------------------------------------------ # ---------------------- Authentication ---------------------- # ------------------------------------------------------------ @@ -267,39 +272,49 @@ input NewAlbum { name: String! } +input Page { + size: Int + page: Int +} + +input Order { + by: String + direction: OrderDirection +} + # ------------------------------------------------------------ # ------------------------ Responses ------------------------- # ------------------------------------------------------------ -type PageInfo { - count: Int! +type PageResponse { + size: Int! page: Int! total: Int! } type MediaItemResponse { data: [MediaItem] - pageInfo: PageInfo! + page: PageResponse! } type UserResponse { data: [User] - pageInfo: PageInfo! + page: PageResponse! } type DeviceResponse { data: [Device] - pageInfo: PageInfo! + page: PageResponse! } type TagResponse { data: [Tag] - pageInfo: PageInfo! + page: PageResponse! } type AlbumResponse { data: [Album] - pageInfo: PageInfo! + page: PageResponse! } # ------------------------------------------------------------ @@ -313,62 +328,52 @@ type Query { password: String! deviceID: ID ): AuthResponse! - logout: AuthResponse! @hasMinRole(role: User) + logout: AuthResponse! @hasMinRole(role: User) # Single Item mediaItem( id: ID! - delete: Boolean - ): MediaItem! @hasMinRole(role: User) + ): MediaItem! @hasMinRole(role: User) device( id: ID! - delete: Boolean - ): Device! @hasMinRole(role: User) + ): Device! @hasMinRole(role: User) album( id: ID! - delete: Boolean - ): Album! @hasMinRole(role: User) + ): Album! @hasMinRole(role: User) user( id: ID! - delete: Boolean - ): User! @hasMinRole(role: Admin) # TODO: Delete All User Content + ): User! @hasMinRole(role: Admin) tag( id: ID! - delete: Boolean - ): Tag! @hasMinRole(role: User) - me(delete: Boolean): User! @hasMinRole(role: User) + ): Tag! @hasMinRole(role: User) + me: User! @hasMinRole(role: User) # All mediaItems( - delete: Boolean filter: MediaItemFilter - count: Int - page: Int - ): MediaItemResponse! @hasMinRole(role: User) + page: Page + order: Order + ): MediaItemResponse! @hasMinRole(role: User) devices( - delete: Boolean filter: DeviceFilter - count: Int - page: Int - ): DeviceResponse! @hasMinRole(role: User) + page: Page + order: Order + ): DeviceResponse! @hasMinRole(role: User) albums( - delete: Boolean filter: AlbumFilter - count: Int - page: Int - ): AlbumResponse! @hasMinRole(role: User) + page: Page + order: Order + ): AlbumResponse! @hasMinRole(role: User) tags( - delete: Boolean filter: TagFilter - count: Int - page: Int - ): TagResponse! @hasMinRole(role: User) + page: Page + order: Order + ): TagResponse! @hasMinRole(role: User) users( - delete: Boolean filter: UserFilter - count: Int - page: Int - ): UserResponse! @hasMinRole(role: Admin) # TODO: Delete All User Content + page: Page + order: Order + ): UserResponse! @hasMinRole(role: Admin) } type Mutation { diff --git a/graph/schema.resolvers.go b/graph/schema.resolvers.go index bdb69d9..08ce5fa 100644 --- a/graph/schema.resolvers.go +++ b/graph/schema.resolvers.go @@ -21,12 +21,10 @@ import ( ) func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewMediaItem) (*model.MediaItem, error) { - // Get Context - authContext := ctx.Value("auth").(*model.AuthContext) - accessToken := *authContext.AccessToken - userID, ok := accessToken.Get("sub") - if !ok { - return nil, errors.New("Upload Failed") + // Acquire Context + userID, _, err := getContextIDs(ctx) + if err != nil { + return nil, err } // File header placeholder @@ -52,7 +50,7 @@ func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewM // Derive Folder & File Path mediaItemID := uuid.New().String() fileName := mediaItemID + fileMime.Extension() - folderPath := path.Join("/" + r.Config.DataPath + "/media/" + userID.(string)) + folderPath := path.Join("/" + r.Config.DataPath + "/media/" + userID) os.MkdirAll(folderPath, 0700) filePath := path.Join(folderPath + "/" + fileName) @@ -83,7 +81,7 @@ func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewM // Add Additional MediaItem Fields mediaItem.ID = mediaItemID - mediaItem.UserID = userID.(string) + mediaItem.UserID = userID mediaItem.IsVideo = isVideo mediaItem.FileName = fileName mediaItem.OrigName = input.File.Filename @@ -99,20 +97,18 @@ func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewM } func (r *mutationResolver) CreateAlbum(ctx context.Context, input model.NewAlbum) (*model.Album, error) { - // Get Context - authContext := ctx.Value("auth").(*model.AuthContext) - accessToken := *authContext.AccessToken - userID, ok := accessToken.Get("sub") - if !ok { - return nil, errors.New("Upload Failed") + // Acquire Context + userID, _, err := getContextIDs(ctx) + if err != nil { + return nil, err } album := &model.Album{ Name: input.Name, - UserID: userID.(string), + UserID: userID, } - err := r.DB.CreateAlbum(album) + err = r.DB.CreateAlbum(album) if err != nil { return nil, err } @@ -121,20 +117,18 @@ func (r *mutationResolver) CreateAlbum(ctx context.Context, input model.NewAlbum } func (r *mutationResolver) CreateTag(ctx context.Context, input model.NewTag) (*model.Tag, error) { - // Get Context - authContext := ctx.Value("auth").(*model.AuthContext) - accessToken := *authContext.AccessToken - userID, ok := accessToken.Get("sub") - if !ok { - return nil, errors.New("Upload Failed") + // Acquire Context + userID, _, err := getContextIDs(ctx) + if err != nil { + return nil, err } tag := &model.Tag{ Name: input.Name, - UserID: userID.(string), + UserID: userID, } - err := r.DB.CreateTag(tag) + err = r.DB.CreateTag(tag) if err != nil { return nil, err } @@ -162,10 +156,11 @@ func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser) } func (r *queryResolver) Login(ctx context.Context, user string, password string, deviceID *string) (*model.AuthResponse, error) { - // Get Context - authContext := ctx.Value("auth").(*model.AuthContext) - resp := authContext.AuthResponse - req := authContext.AuthRequest + // Acquire Context + resp, req, err := getContextHTTP(ctx) + if err != nil { + return nil, err + } // Clear All Cookies By Default accessCookie := http.Cookie{Name: "AccessToken", Path: "/", HttpOnly: true, MaxAge: -1, Expires: time.Now().Add(-100 * time.Hour)} @@ -219,9 +214,11 @@ func (r *queryResolver) Login(ctx context.Context, user string, password string, } func (r *queryResolver) Logout(ctx context.Context) (*model.AuthResponse, error) { - // Set Cookie From Context - authContext := ctx.Value("auth").(*model.AuthContext) - resp := authContext.AuthResponse + // Acquire Context + resp, _, err := getContextHTTP(ctx) + if err != nil { + return nil, err + } // Clear All Cookies accessCookie := http.Cookie{Name: "AccessToken", Path: "/", HttpOnly: true, MaxAge: -1, Expires: time.Now().Add(-100 * time.Hour)} @@ -232,13 +229,11 @@ func (r *queryResolver) Logout(ctx context.Context) (*model.AuthResponse, error) return &model.AuthResponse{Result: model.AuthResultSuccess}, nil } -func (r *queryResolver) MediaItem(ctx context.Context, id string, delete *bool) (*model.MediaItem, error) { - // Get Context - authContext := ctx.Value("auth").(*model.AuthContext) - accessToken := *authContext.AccessToken - userID, ok := accessToken.Get("sub") - if !ok { - return nil, errors.New("Context Error") +func (r *queryResolver) MediaItem(ctx context.Context, id string) (*model.MediaItem, error) { + // Acquire Context + userID, _, err := getContextIDs(ctx) + if err != nil { + return nil, err } mediaItemID, err := uuid.Parse(id) @@ -246,7 +241,7 @@ func (r *queryResolver) MediaItem(ctx context.Context, id string, delete *bool) return nil, errors.New("Invalid ID Format") } - foundMediaItem := &model.MediaItem{ID: mediaItemID.String(), UserID: userID.(string)} + foundMediaItem := &model.MediaItem{ID: mediaItemID.String(), UserID: userID} count, err := r.DB.MediaItem(foundMediaItem) if err != nil { return nil, errors.New("DB Error") @@ -256,13 +251,11 @@ func (r *queryResolver) MediaItem(ctx context.Context, id string, delete *bool) return foundMediaItem, nil } -func (r *queryResolver) Device(ctx context.Context, id string, delete *bool) (*model.Device, error) { - // Get Context - authContext := ctx.Value("auth").(*model.AuthContext) - accessToken := *authContext.AccessToken - userID, ok := accessToken.Get("sub") - if !ok { - return nil, errors.New("Context Error") +func (r *queryResolver) Device(ctx context.Context, id string) (*model.Device, error) { + // Acquire Context + userID, _, err := getContextIDs(ctx) + if err != nil { + return nil, err } deviceID, err := uuid.Parse(id) @@ -270,7 +263,7 @@ func (r *queryResolver) Device(ctx context.Context, id string, delete *bool) (*m return nil, errors.New("Invalid ID Format") } - foundDevice := &model.Device{ID: deviceID.String(), UserID: userID.(string)} + foundDevice := &model.Device{ID: deviceID.String(), UserID: userID} count, err := r.DB.Device(foundDevice) if err != nil { return nil, errors.New("DB Error") @@ -280,13 +273,11 @@ func (r *queryResolver) Device(ctx context.Context, id string, delete *bool) (*m return foundDevice, nil } -func (r *queryResolver) Album(ctx context.Context, id string, delete *bool) (*model.Album, error) { - // Get Context - authContext := ctx.Value("auth").(*model.AuthContext) - accessToken := *authContext.AccessToken - userID, ok := accessToken.Get("sub") - if !ok { - return nil, errors.New("Context Error") +func (r *queryResolver) Album(ctx context.Context, id string) (*model.Album, error) { + // Acquire Context + userID, _, err := getContextIDs(ctx) + if err != nil { + return nil, err } albumID, err := uuid.Parse(id) @@ -294,7 +285,7 @@ func (r *queryResolver) Album(ctx context.Context, id string, delete *bool) (*mo return nil, errors.New("Invalid ID Format") } - foundAlbum := &model.Album{ID: albumID.String(), UserID: userID.(string)} + foundAlbum := &model.Album{ID: albumID.String(), UserID: userID} count, err := r.DB.Album(foundAlbum) if err != nil { return nil, errors.New("DB Error") @@ -304,7 +295,7 @@ func (r *queryResolver) Album(ctx context.Context, id string, delete *bool) (*mo return foundAlbum, nil } -func (r *queryResolver) User(ctx context.Context, id string, delete *bool) (*model.User, error) { +func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) { userID, err := uuid.Parse(id) if err != nil { return nil, errors.New("Invalid ID Format") @@ -320,13 +311,19 @@ func (r *queryResolver) User(ctx context.Context, id string, delete *bool) (*mod return foundUser, nil } -func (r *queryResolver) Tag(ctx context.Context, id string, delete *bool) (*model.Tag, error) { +func (r *queryResolver) Tag(ctx context.Context, id string) (*model.Tag, error) { + // Acquire Context + userID, _, err := getContextIDs(ctx) + if err != nil { + return nil, err + } + tagID, err := uuid.Parse(id) if err != nil { return nil, errors.New("Invalid ID Format") } - foundTag := &model.Tag{ID: tagID.String()} + foundTag := &model.Tag{ID: tagID.String(), UserID: userID} count, err := r.DB.Tag(foundTag) if err != nil { return nil, errors.New("DB Error") @@ -336,16 +333,14 @@ func (r *queryResolver) Tag(ctx context.Context, id string, delete *bool) (*mode return foundTag, nil } -func (r *queryResolver) Me(ctx context.Context, delete *bool) (*model.User, error) { - // Get Context - authContext := ctx.Value("auth").(*model.AuthContext) - accessToken := *authContext.AccessToken - userID, ok := accessToken.Get("sub") - if !ok { - return nil, errors.New("Context Error") +func (r *queryResolver) Me(ctx context.Context) (*model.User, error) { + // Acquire Context + userID, _, err := getContextIDs(ctx) + if err != nil { + return nil, err } - foundUser := &model.User{ID: userID.(string)} + foundUser := &model.User{ID: userID} count, err := r.DB.User(foundUser) if err != nil || count != 1 { return nil, errors.New("DB Error") @@ -353,88 +348,82 @@ func (r *queryResolver) Me(ctx context.Context, delete *bool) (*model.User, erro return foundUser, nil } -func (r *queryResolver) MediaItems(ctx context.Context, delete *bool, filter *model.MediaItemFilter, count *int, page *int) (*model.MediaItemResponse, error) { - resp, totalCount, err := r.DB.MediaItems(filter) +func (r *queryResolver) MediaItems(ctx context.Context, filter *model.MediaItemFilter, page *model.Page, order *model.Order) (*model.MediaItemResponse, error) { + // Acquire Context + userID, _, err := getContextIDs(ctx) if err != nil { - return nil, errors.New("Context Error") + return nil, err + } + + resp, pageResponse, err := r.DB.MediaItems(userID, filter, page, order) + if err != nil { + return nil, errors.New("DB Error") } return &model.MediaItemResponse{ Data: resp, - PageInfo: &model.PageInfo{ - Count: int(totalCount), - Page: 0, - Total: int(totalCount), - }, + Page: &pageResponse, }, nil } -func (r *queryResolver) Devices(ctx context.Context, delete *bool, filter *model.DeviceFilter, count *int, page *int) (*model.DeviceResponse, error) { - // Get Context - authContext := ctx.Value("auth").(*model.AuthContext) - accessToken := *authContext.AccessToken - userID, ok := accessToken.Get("sub") - if !ok { - return nil, errors.New("Context Error") +func (r *queryResolver) Devices(ctx context.Context, filter *model.DeviceFilter, page *model.Page, order *model.Order) (*model.DeviceResponse, error) { + // Acquire Context + userID, _, err := getContextIDs(ctx) + if err != nil { + return nil, err } - _ = userID - resp, totalCount, err := r.DB.Devices() + resp, pageResponse, err := r.DB.Devices(userID, filter, page, order) if err != nil { return nil, errors.New("DB Error") } return &model.DeviceResponse{ Data: resp, - PageInfo: &model.PageInfo{ - Count: int(totalCount), - Page: 0, - Total: int(totalCount), - }, + Page: &pageResponse, }, nil } -func (r *queryResolver) Albums(ctx context.Context, delete *bool, filter *model.AlbumFilter, count *int, page *int) (*model.AlbumResponse, error) { - // TODO: User Specific - resp, totalCount, err := r.DB.Albums() +func (r *queryResolver) Albums(ctx context.Context, filter *model.AlbumFilter, page *model.Page, order *model.Order) (*model.AlbumResponse, error) { + // Acquire Context + userID, _, err := getContextIDs(ctx) + if err != nil { + return nil, err + } + + resp, pageResponse, err := r.DB.Albums(userID, filter, page, order) if err != nil { return nil, errors.New("Context Error") } return &model.AlbumResponse{ Data: resp, - PageInfo: &model.PageInfo{ - Count: int(totalCount), - Page: 0, - Total: int(totalCount), - }, + Page: &pageResponse, }, nil } -func (r *queryResolver) Tags(ctx context.Context, delete *bool, filter *model.TagFilter, count *int, page *int) (*model.TagResponse, error) { - resp, totalCount, err := r.DB.Tags() +func (r *queryResolver) Tags(ctx context.Context, filter *model.TagFilter, page *model.Page, order *model.Order) (*model.TagResponse, error) { + // Acquire Context + userID, _, err := getContextIDs(ctx) + if err != nil { + return nil, err + } + + resp, pageResponse, err := r.DB.Tags(userID, filter, page, order) if err != nil { return nil, errors.New("Context Error") } return &model.TagResponse{ Data: resp, - PageInfo: &model.PageInfo{ - Count: int(totalCount), - Page: 0, - Total: int(totalCount), - }, + Page: &pageResponse, }, nil } -func (r *queryResolver) Users(ctx context.Context, delete *bool, filter *model.UserFilter, count *int, page *int) (*model.UserResponse, error) { - resp, totalCount, err := r.DB.Users() +func (r *queryResolver) Users(ctx context.Context, filter *model.UserFilter, page *model.Page, order *model.Order) (*model.UserResponse, error) { + resp, pageResponse, err := r.DB.Users(filter, page, order) if err != nil { return nil, errors.New("Context Error") } return &model.UserResponse{ Data: resp, - PageInfo: &model.PageInfo{ - Count: int(totalCount), - Page: 0, - Total: int(totalCount), - }, + Page: &pageResponse, }, nil } diff --git a/internal/db/albums.go b/internal/db/albums.go index c2def31..2ffae04 100644 --- a/internal/db/albums.go +++ b/internal/db/albums.go @@ -2,6 +2,7 @@ package db import ( log "github.com/sirupsen/logrus" + "gorm.io/gorm" "reichard.io/imagini/graph/model" ) @@ -18,11 +19,17 @@ func (dbm *DBManager) Album(album *model.Album) (int64, error) { return count, err } -func (dbm *DBManager) Albums() ([]*model.Album, int64, error) { +func (dbm *DBManager) Albums(userID string, filters *model.AlbumFilter, page *model.Page, order *model.Order) ([]*model.Album, model.PageResponse, error) { + // Initial User Filter + tx := dbm.db.Session(&gorm.Session{}).Model(&model.Album{}).Where("user_id == ?", userID) + + // Dynamically Generate Base Query + tx, pageResponse := dbm.generateBaseQuery(tx, filters, page, order) + + // Acquire Results var foundAlbums []*model.Album - var count int64 - err := dbm.db.Find(&foundAlbums).Count(&count).Error - return foundAlbums, count, err + err := tx.Find(&foundAlbums).Error + return foundAlbums, pageResponse, err } func (dbm *DBManager) DeleteAlbum(album *model.Album) error { diff --git a/internal/db/db.go b/internal/db/db.go index 4121c42..a1f32a8 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -1,11 +1,13 @@ package db import ( - "errors" "fmt" "path" + "reflect" + "github.com/iancoleman/strcase" log "github.com/sirupsen/logrus" + // "gorm.io/gorm/logger" "gorm.io/driver/sqlite" "gorm.io/gorm" @@ -30,6 +32,7 @@ func NewMgr(c *config.Config) *DBManager { if c.DBType == "SQLite" { dbLocation := path.Join(c.ConfigPath, "imagini.db") dbm.db, _ = gorm.Open(sqlite.Open(dbLocation), gormConfig) + dbm.db = dbm.db.Debug() } else { log.Fatal("Unsupported Database") } @@ -48,28 +51,9 @@ func NewMgr(c *config.Config) *DBManager { dbm.bootstrapDatabase() } - dbm.testFeatures() - return dbm } -func (dbm *DBManager) testFeatures() { - - // Get Devices By UserID - // var myDevices []model.Device - // dbm.db.Debug().Where(&model.Device{UserID: "97589354-cd42-40e2-bc5e-7ba6badf89fa"}).Find(&myDevices) - // fmt.Printf("Devices: %+v\n", myDevices) - - // Get User by DeviceID - // var myUser []model.User - // dbm.db.Debug().Model(&model.User{}). - // Select("users.*"). - // Joins("left join devices on users.id = devices.user_id"). - // Where("devices.id = ?", "4e9aa851-f25b-4330-91dc-c0f975e56fa1"). - // Find(&myUser) - // fmt.Printf("User: %+v\n", myUser) -} - func (dbm *DBManager) bootstrapDatabase() { log.Info("[query] Bootstrapping database.") @@ -88,46 +72,84 @@ func (dbm *DBManager) bootstrapDatabase() { } } -// TODO -func (dbm *DBManager) QueryBuilder(dest interface{}, params []byte) (int64, error) { - // TODO: - // - Where Filters - // - Sort Filters - // - Paging Filters +func (dbm *DBManager) generateBaseQuery(tx *gorm.DB, filter interface{}, page *model.Page, order *model.Order) (*gorm.DB, model.PageResponse) { + tx = dbm.generateFilter(tx, filter) + tx = dbm.generateOrder(tx, order, filter) + tx, pageResponse := dbm.generatePage(tx, page) + return tx, pageResponse +} - objType := fmt.Sprintf("%T", dest) - if objType == "*[]model.MediaItem" { - // TODO: Validate MediaItem Type - } else { - // Return Error - return 0, errors.New("Invalid type") +func (dbm *DBManager) generateOrder(tx *gorm.DB, order *model.Order, filter interface{}) *gorm.DB { + // Set Defaults + orderBy := "created_at" + orderDirection := model.OrderDirectionDesc + + if order == nil { + order = &model.Order{ + By: &orderBy, + Direction: &orderDirection, + } } - var count int64 - err := dbm.db.Find(dest).Count(&count).Error - return count, err + if order.By == nil { + order.By = &orderBy + } - // Paging: - // - Regular Pagination: - // - /api/v1/MediaItems?page[limit]=50&page=2 - // - Meta Count Only - // - /api/v1/MediaItems?page[limit]=0 + if order.Direction == nil { + order.Direction = &orderDirection + } - // Sorting: - // - Ascending Sort: - // - /api/v1/MediaItems?sort=created_at - // - Descending Sort: - // - /api/v1/MediaItems?sort=-created_at + // Get Possible Values + ptr := reflect.New(reflect.TypeOf(filter).Elem()) + v := reflect.Indirect(ptr) - // Filters: - // - Greater Than / Less Than (created_at, updated_at, exif_date) - // - /api/v1/MediaItems?filter[created_at]>=2020-01-01&filter[created_at]<=2021-01-01 - // - Long / Lat Range (latitude, longitude) - // - /api/v1/MediaItems?filter[latitude]>=71.1827&filter[latitude]<=72.0000&filter[longitude]>=100.000&filter[longitude]<=101.0000 - // - Image / Video (media_type) - // - /api/v1/MediaItems?filter[media_type]=Image - // - Tags (tags) - // - /api/v1/MediaItems?filter[tags]=id1,id2,id3 - // - Albums (albums) - // - /api/v1/MediaItems?filter[albums]=id1 + isValid := false + for i := 0; i < v.NumField(); i++ { + fieldName := v.Type().Field(i).Name + if strcase.ToSnake(*order.By) == strcase.ToSnake(fieldName) { + isValid = true + break + } + } + + if isValid { + tx = tx.Order(fmt.Sprintf("%s %s", strcase.ToSnake(*order.By), order.Direction.String())) + } + + return tx +} + +func (dbm *DBManager) generatePage(tx *gorm.DB, page *model.Page) (*gorm.DB, model.PageResponse) { + // Set Defaults + var count int64 + pageSize := 50 + pageNum := 1 + + if page == nil { + page = &model.Page{ + Size: &pageSize, + Page: &pageNum, + } + } + + if page.Size == nil { + page.Size = &pageSize + } + + if page.Page == nil { + page.Page = &pageNum + } + + // Acquire Counts Before Pagination + tx.Count(&count) + + // Calculate Offset + calculatedOffset := (*page.Page - 1) * *page.Size + tx = tx.Limit(*page.Size).Offset(calculatedOffset) + + return tx, model.PageResponse{ + Page: *page.Page, + Size: *page.Size, + Total: int(count), + } } diff --git a/internal/db/devices.go b/internal/db/devices.go index 27bce06..393218b 100644 --- a/internal/db/devices.go +++ b/internal/db/devices.go @@ -3,6 +3,7 @@ package db import ( "github.com/google/uuid" log "github.com/sirupsen/logrus" + "gorm.io/gorm" "reichard.io/imagini/graph/model" ) @@ -21,11 +22,17 @@ func (dbm *DBManager) Device(device *model.Device) (int64, error) { return count, err } -func (dbm *DBManager) Devices() ([]*model.Device, int64, error) { +func (dbm *DBManager) Devices(userID string, filters *model.DeviceFilter, page *model.Page, order *model.Order) ([]*model.Device, model.PageResponse, error) { + // Initial User Filter + tx := dbm.db.Session(&gorm.Session{}).Model(&model.Device{}).Where("user_id == ?", userID) + + // Dynamically Generate Base Query + tx, pageResponse := dbm.generateBaseQuery(tx, filters, page, order) + + // Acquire Results var foundDevices []*model.Device - var count int64 - err := dbm.db.Find(&foundDevices).Count(&count).Error - return foundDevices, count, err + err := tx.Find(&foundDevices).Error + return foundDevices, pageResponse, err } func (dbm *DBManager) DeleteDevice(user *model.Device) error { diff --git a/internal/db/filters.go b/internal/db/filters.go index a13731b..7c0eaa7 100644 --- a/internal/db/filters.go +++ b/internal/db/filters.go @@ -10,10 +10,13 @@ import ( ) // Generic function used to generate filters for the DB -func (dbm *DBManager) generateFilters(filter interface{}) (*gorm.DB, error) { - tx := dbm.db.Session(&gorm.Session{}).Debug() +func (dbm *DBManager) generateFilter(tx *gorm.DB, filter interface{}) *gorm.DB { + ptr := reflect.ValueOf(filter) + v := reflect.Indirect(ptr) - v := reflect.ValueOf(filter) + if v == reflect.ValueOf(nil) { + return tx + } for i := 0; i < v.NumField(); i++ { fieldName := strcase.ToSnake(v.Type().Field(i).Name) @@ -45,7 +48,7 @@ func (dbm *DBManager) generateFilters(filter interface{}) (*gorm.DB, error) { } } - return tx, nil + return tx } func generateStringFilter(tx *gorm.DB, fieldName string, filter *model.StringFilter) *gorm.DB { diff --git a/internal/db/media_items.go b/internal/db/media_items.go index 11656c9..d914cd7 100644 --- a/internal/db/media_items.go +++ b/internal/db/media_items.go @@ -2,6 +2,7 @@ package db import ( log "github.com/sirupsen/logrus" + "gorm.io/gorm" "reichard.io/imagini/graph/model" ) @@ -18,14 +19,16 @@ func (dbm *DBManager) MediaItem(mediaItem *model.MediaItem) (int64, error) { return count, err } -func (dbm *DBManager) MediaItems(filters *model.MediaItemFilter) ([]*model.MediaItem, int64, error) { - // Perform Filters - tx, err := dbm.generateFilters(*filters) - if err != nil { - return nil, 0, err - } +// UserID, Filters, Sort, Page, Delete +func (dbm *DBManager) MediaItems(userID string, filters *model.MediaItemFilter, page *model.Page, order *model.Order) ([]*model.MediaItem, model.PageResponse, error) { + // Initial User Filter + tx := dbm.db.Session(&gorm.Session{}).Model(&model.MediaItem{}).Where("user_id == ?", userID) + + // Dynamically Generate Base Query + tx, pageResponse := dbm.generateBaseQuery(tx, filters, page, order) + + // Acquire Results var mediaItems []*model.MediaItem - var count int64 - err = tx.Find(&mediaItems).Count(&count).Error - return mediaItems, count, err + err := tx.Find(&mediaItems).Error + return mediaItems, pageResponse, err } diff --git a/internal/db/tags.go b/internal/db/tags.go index 8a017ca..0018469 100644 --- a/internal/db/tags.go +++ b/internal/db/tags.go @@ -2,6 +2,7 @@ package db import ( log "github.com/sirupsen/logrus" + "gorm.io/gorm" "reichard.io/imagini/graph/model" ) @@ -18,11 +19,17 @@ func (dbm *DBManager) Tag(tag *model.Tag) (int64, error) { return count, err } -func (dbm *DBManager) Tags() ([]*model.Tag, int64, error) { +func (dbm *DBManager) Tags(userID string, filters *model.TagFilter, page *model.Page, order *model.Order) ([]*model.Tag, model.PageResponse, error) { + // Initial User Filter + tx := dbm.db.Session(&gorm.Session{}).Model(&model.Tag{}).Where("user_id == ?", userID) + + // Dynamically Generate Base Query + tx, pageResponse := dbm.generateBaseQuery(tx, filters, page, order) + + // Acquire Results var foundTags []*model.Tag - var count int64 - err := dbm.db.Find(&foundTags).Count(&count).Error - return foundTags, count, err + err := tx.Find(&foundTags).Error + return foundTags, pageResponse, err } func (dbm *DBManager) DeleteTag(tag *model.Tag) error { diff --git a/internal/db/users.go b/internal/db/users.go index e69fa6b..31ffdbd 100644 --- a/internal/db/users.go +++ b/internal/db/users.go @@ -3,6 +3,7 @@ package db import ( log "github.com/sirupsen/logrus" "golang.org/x/crypto/bcrypt" + "gorm.io/gorm" "reichard.io/imagini/graph/model" ) @@ -25,11 +26,17 @@ func (dbm *DBManager) User(user *model.User) (int64, error) { return count, err } -func (dbm *DBManager) Users() ([]*model.User, int64, error) { +func (dbm *DBManager) Users(filters *model.UserFilter, page *model.Page, order *model.Order) ([]*model.User, model.PageResponse, error) { + // Initial User Filter + tx := dbm.db.Session(&gorm.Session{}).Model(&model.Tag{}) + + // Dynamically Generate Base Query + tx, pageResponse := dbm.generateBaseQuery(tx, filters, page, order) + + // Acquire Results var foundUsers []*model.User - var count int64 - err := dbm.db.Find(&foundUsers).Count(&count).Error - return foundUsers, count, err + err := tx.Find(&foundUsers).Error + return foundUsers, pageResponse, err } func (dbm *DBManager) DeleteUser(user model.User) error {