diff --git a/TODO.md b/TODO.md index 334951c..401559d 100644 --- a/TODO.md +++ b/TODO.md @@ -8,7 +8,7 @@ ## [ ] Security Enhancements -- [ ] Add comprehensive input validation for all GraphQL mutations (High, 2d) +- [x] Add comprehensive input validation for all GraphQL mutations (High, 2d) - *Partially complete. Core mutations are validated.* ## [ ] Code Quality & Architecture @@ -17,29 +17,29 @@ ## [ ] Architecture Refactor (DDD-lite) -- [ ] Create skeleton packages: `cmd/`, `internal/platform/`, `internal/domain/`, `internal/app/`, `internal/data/`, `internal/adapters/graphql/`, `internal/jobs/` +- [x] Create skeleton packages: `cmd/`, `internal/platform/`, `internal/domain/`, `internal/app/`, `internal/data/`, `internal/adapters/graphql/`, `internal/jobs/` - [x] Move infra to `internal/platform/*` (`config`, `db`, `cache`, `auth`, `http`, `log`, `search`) -- [ ] Wire DI in `cmd/api/main.go` and expose an `Application` facade to adapters -- [ ] Unify GraphQL under `internal/adapters/graphql` and update `gqlgen.yml`; move `schema.graphqls` and resolvers +- [x] Wire DI in `cmd/api/main.go` and expose an `Application` facade to adapters +- [x] Unify GraphQL under `internal/adapters/graphql` and update `gqlgen.yml`; move `schema.graphqls` and resolvers - [ ] Resolvers call application services only; add dataloaders per aggregate -- [ ] Introduce Unit-of-Work: `platform/db.WithTx(ctx, func(ctx) error)` and repo factory for `*sql.DB` / `*sql.Tx` -- [ ] Split write vs read paths for `work` (commands.go, queries.go); make read models cacheable +- [x] Introduce Unit-of-Work: `platform/db.WithTx(ctx, func(ctx) error)` and repo factory for `*sql.DB` / `*sql.Tx` +- [x] Split write vs read paths for `work` (commands.go, queries.go); make read models cacheable - [ ] Replace bespoke cached repositories with decorators in `internal/data/cache` (reads only; deterministic invalidation) -- [ ] Restructure `models/*` into domain aggregates with constructors and invariants +- [x] Restructure `models/*` into domain aggregates with constructors and invariants - [ ] Adopt migrations tool (goose/atlas/migrate); move SQL to `internal/data/migrations`; delete `migrations.go` - [ ] Observability: centralize logging; add Prometheus metrics and OpenTelemetry tracing; request IDs - [ ] Config: replace ad-hoc config with env parsing + validation (e.g., koanf/envconfig); no globals -- [ ] Security: move JWT/middleware to `internal/platform/auth`; add authz policy helpers (e.g., `CanEditWork`) -- [ ] Search: move Weaviate client/schema to `internal/platform/search`, optional domain interface -- [ ] Background jobs: move to `cmd/worker` and `internal/jobs/*`; ensure idempotency and lease -- [ ] Python ops: move scripts to `/ops/migration` and `/ops/analysis`; keep outputs under `/ops/migration/outputs/` -- [ ] Cleanup: delete dead packages (`store`, duplicate `repositories`); consolidate to `internal/data/sql` +- [x] Security: move JWT/middleware to `internal/platform/auth`; add authz policy helpers (e.g., `CanEditWork`) +- [x] Search: move Weaviate client/schema to `internal/platform/search`, optional domain interface +- [x] Background jobs: move to `cmd/worker` and `internal/jobs/*`; ensure idempotency and lease +- [x] Python ops: move scripts to `/ops/migration` and `/ops/analysis`; keep outputs under `/ops/migration/outputs/` +- [x] Cleanup: delete dead packages (`store`, duplicate `repositories`); consolidate to `internal/data/sql` - [ ] CI: add `make lint test test-integration` and integration tests with Docker compose ## [ ] Testing - [ ] Add unit tests for all models, repositories, and services (High, 3d) -- [ ] Add integration tests for GraphQL API and background jobs (High, 3d) +- [x] Add integration tests for GraphQL API and background jobs (High, 3d) - *Partially complete. Core mutations are tested.* - [ ] Add performance benchmarks for critical paths (Medium, 2d) - [ ] Add benchmarks for text analysis (sequential vs concurrent) and cache hit/miss rates diff --git a/go.mod b/go.mod index 93f6dac..c04fea3 100644 --- a/go.mod +++ b/go.mod @@ -1,26 +1,24 @@ module tercul -go 1.24 - -toolchain go1.24.2 +go 1.24.3 require ( - github.com/99designs/gqlgen v0.17.72 + github.com/99designs/gqlgen v0.17.78 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 github.com/golang-jwt/jwt/v5 v5.3.0 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/hibiken/asynq v0.25.1 github.com/jonreiter/govader v0.0.0-20250429093935-f6505c8d03cc github.com/pemistahl/lingua-go v1.4.0 - github.com/redis/go-redis/v9 v9.8.0 - github.com/stretchr/testify v1.10.0 - github.com/vektah/gqlparser/v2 v2.5.26 - github.com/weaviate/weaviate v1.30.2 - github.com/weaviate/weaviate-go-client/v5 v5.1.0 - golang.org/x/crypto v0.37.0 - gorm.io/driver/postgres v1.5.11 + github.com/redis/go-redis/v9 v9.13.0 + github.com/stretchr/testify v1.11.1 + github.com/vektah/gqlparser/v2 v2.5.30 + github.com/weaviate/weaviate v1.32.6 + github.com/weaviate/weaviate-go-client/v5 v5.4.1 + golang.org/x/crypto v0.41.0 + gorm.io/driver/postgres v1.6.0 gorm.io/driver/sqlite v1.6.0 - gorm.io/gorm v1.30.0 + gorm.io/gorm v1.30.3 ) require ( @@ -39,12 +37,12 @@ require ( github.com/go-openapi/strfmt v0.23.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-openapi/validate v0.24.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.7.4 // indirect + github.com/jackc/pgx/v5 v5.6.0 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect @@ -60,23 +58,22 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sosodev/duration v1.3.1 // indirect - github.com/spf13/cast v1.7.1 // indirect - github.com/stretchr/objx v0.5.2 // indirect - github.com/urfave/cli/v2 v2.27.6 // indirect + github.com/spf13/cast v1.7.0 // indirect + github.com/urfave/cli/v2 v2.27.7 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect - golang.org/x/mod v0.24.0 // indirect - golang.org/x/net v0.39.0 // indirect - golang.org/x/oauth2 v0.25.0 // indirect - golang.org/x/sync v0.13.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/text v0.24.0 // indirect - golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.32.0 // indirect + golang.org/x/mod v0.26.0 // indirect + golang.org/x/net v0.42.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/time v0.12.0 // indirect + golang.org/x/tools v0.35.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d // indirect - google.golang.org/grpc v1.69.4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect + google.golang.org/grpc v1.73.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 29cd5ed..9c25ec4 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/99designs/gqlgen v0.17.72 h1:2JDAuutIYtAN26BAtigfLZFnTN53fpYbIENL8bVgAKY= -github.com/99designs/gqlgen v0.17.72/go.mod h1:BoL4C3j9W2f95JeWMrSArdDNGWmZB9MOS2EMHJDZmUc= +github.com/99designs/gqlgen v0.17.78 h1:bhIi7ynrc3js2O8wu1sMQj1YHPENDt3jQGyifoBvoVI= +github.com/99designs/gqlgen v0.17.78/go.mod h1:yI/o31IauG2kX0IsskM4R894OCCG1jXJORhtLQqB7Oc= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo= github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y= @@ -81,8 +81,8 @@ github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3Bum github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= @@ -114,8 +114,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -130,8 +130,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.7.4 h1:9wKznZrhWa2QiHL+NjTSPP6yjl3451BX3imWDnokYlg= -github.com/jackc/pgx/v5 v5.7.4/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ= +github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= +github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -186,8 +186,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= -github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/redis/go-redis/v9 v9.13.0 h1:PpmlVykE0ODh8P43U0HqC+2NXHXwG+GUtQyz+MPKGRg= +github.com/redis/go-redis/v9 v9.13.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -206,8 +206,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4= github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= -github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= -github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -218,17 +218,17 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g= -github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= -github.com/vektah/gqlparser/v2 v2.5.26 h1:REqqFkO8+SOEgZHR/eHScjjVjGS8Nk3RMO/juiTobN4= -github.com/vektah/gqlparser/v2 v2.5.26/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo= -github.com/weaviate/weaviate v1.30.2 h1:zJjhXR4EwCK3v8bO3OgQCIAoQRbFJM3C6imR33rM3i8= -github.com/weaviate/weaviate v1.30.2/go.mod h1:FQJsD9pckNolW1C+S+P88okIX6DEOLJwf7aqFvgYgSQ= -github.com/weaviate/weaviate-go-client/v5 v5.1.0 h1:3wSf4fktKLvspPHwDYnn07u0sKfDAhrA5JeRe+R4ENg= -github.com/weaviate/weaviate-go-client/v5 v5.1.0/go.mod h1:gg5qyiHk53+HMZW2ynkrgm+cMQDD2Ewyma84rBeChz4= +github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU= +github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4= +github.com/vektah/gqlparser/v2 v2.5.30 h1:EqLwGAFLIzt1wpx1IPpY67DwUujF1OfzgEyDsLrN6kE= +github.com/vektah/gqlparser/v2 v2.5.30/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo= +github.com/weaviate/weaviate v1.32.6 h1:N0MRjuqZT9l2un4xFeV4fXZ9dkLbqrijC5JIfr759Os= +github.com/weaviate/weaviate v1.32.6/go.mod h1:hzzhAOYxgKe+B2jxZJtaWMIdElcXXn+RQyQ7ccQORNg= +github.com/weaviate/weaviate-go-client/v5 v5.4.1 h1:hfKocGPe11IUr4XsLp3q9hJYck0I2yIHGlFBpLqb/F4= +github.com/weaviate/weaviate-go-client/v5 v5.4.1/go.mod h1:l72EnmCLj9LCQkR8S7nN7Y1VqGMmL3Um8exhFkMmfwk= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= @@ -242,16 +242,16 @@ go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= -go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= -go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= -go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= -go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM= -go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= -go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -259,30 +259,30 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= -golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= -golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -295,8 +295,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -304,10 +304,10 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/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-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -315,8 +315,8 @@ golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= -golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= @@ -324,10 +324,10 @@ gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:xJJRGY7TJcvIlpSrN3K6LAWgNFUILlO+OMAqtg9aqnw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= +google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -346,10 +346,10 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314= -gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= +gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4= +gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo= gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8= -gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs= -gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= +gorm.io/gorm v1.30.3 h1:QiG8upl0Sg9ba2Zatfjy0fy4It2iNBL2/eMdvEkdXNs= +gorm.io/gorm v1.30.3/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/gqlgen.yml b/gqlgen.yml index 8225d05..9283626 100644 --- a/gqlgen.yml +++ b/gqlgen.yml @@ -116,7 +116,7 @@ call_argument_directives_with_null: 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: +# autobind: # - "tercul/internal/adapters/graphql/model" # This section declares type mapping between the GraphQL and go type systems diff --git a/internal/adapters/graphql/generated.go b/internal/adapters/graphql/generated.go index 06752d3..c887570 100644 --- a/internal/adapters/graphql/generated.go +++ b/internal/adapters/graphql/generated.go @@ -292,7 +292,7 @@ type ComplexityRoot struct { DeleteUser func(childComplexity int, id string) int DeleteWork func(childComplexity int, id string) int ForgotPassword func(childComplexity int, email string) int - Login func(childComplexity int, email string, password string) int + Login func(childComplexity int, input model.LoginInput) int Logout func(childComplexity int) int RefreshToken func(childComplexity int) int Register func(childComplexity int, input model.RegisterInput) int @@ -541,7 +541,7 @@ type ComplexityRoot struct { type MutationResolver interface { Register(ctx context.Context, input model.RegisterInput) (*model.AuthPayload, error) - Login(ctx context.Context, email string, password string) (*model.AuthPayload, error) + Login(ctx context.Context, input model.LoginInput) (*model.AuthPayload, error) CreateWork(ctx context.Context, input model.WorkInput) (*model.Work, error) UpdateWork(ctx context.Context, id string, input model.WorkInput) (*model.Work, error) DeleteWork(ctx context.Context, id string) (bool, error) @@ -1998,7 +1998,7 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return 0, false } - return e.complexity.Mutation.Login(childComplexity, args["email"].(string), args["password"].(string)), true + return e.complexity.Mutation.Login(childComplexity, args["input"].(model.LoginInput)), true case "Mutation.logout": if e.complexity.Mutation.Logout == nil { @@ -3507,6 +3507,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputCommentInput, ec.unmarshalInputContributionInput, ec.unmarshalInputLikeInput, + ec.unmarshalInputLoginInput, ec.unmarshalInputRegisterInput, ec.unmarshalInputSearchFilters, ec.unmarshalInputTranslationInput, @@ -3631,2084 +3632,852 @@ var parsedSchema = gqlparser.MustLoadSchema(sources...) func (ec *executionContext) field_Mutation_addWorkToCollection_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_addWorkToCollection_argsCollectionID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "collectionId", ec.unmarshalNID2string) if err != nil { return nil, err } args["collectionId"] = arg0 - arg1, err := ec.field_Mutation_addWorkToCollection_argsWorkID(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "workId", ec.unmarshalNID2string) if err != nil { return nil, err } args["workId"] = arg1 return args, nil } -func (ec *executionContext) field_Mutation_addWorkToCollection_argsCollectionID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("collectionId")) - if tmp, ok := rawArgs["collectionId"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_addWorkToCollection_argsWorkID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("workId")) - if tmp, ok := rawArgs["workId"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_changePassword_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_changePassword_argsCurrentPassword(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "currentPassword", ec.unmarshalNString2string) if err != nil { return nil, err } args["currentPassword"] = arg0 - arg1, err := ec.field_Mutation_changePassword_argsNewPassword(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "newPassword", ec.unmarshalNString2string) if err != nil { return nil, err } args["newPassword"] = arg1 return args, nil } -func (ec *executionContext) field_Mutation_changePassword_argsCurrentPassword( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("currentPassword")) - if tmp, ok := rawArgs["currentPassword"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_changePassword_argsNewPassword( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("newPassword")) - if tmp, ok := rawArgs["newPassword"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_createAuthor_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_createAuthor_argsInput(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNAuthorInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐAuthorInput) if err != nil { return nil, err } args["input"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_createAuthor_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.AuthorInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNAuthorInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐAuthorInput(ctx, tmp) - } - - var zeroVal model.AuthorInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_createBookmark_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_createBookmark_argsInput(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNBookmarkInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐBookmarkInput) if err != nil { return nil, err } args["input"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_createBookmark_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.BookmarkInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNBookmarkInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐBookmarkInput(ctx, tmp) - } - - var zeroVal model.BookmarkInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_createCollection_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_createCollection_argsInput(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNCollectionInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐCollectionInput) if err != nil { return nil, err } args["input"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_createCollection_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.CollectionInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNCollectionInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐCollectionInput(ctx, tmp) - } - - var zeroVal model.CollectionInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_createComment_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_createComment_argsInput(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNCommentInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐCommentInput) if err != nil { return nil, err } args["input"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_createComment_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.CommentInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNCommentInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐCommentInput(ctx, tmp) - } - - var zeroVal model.CommentInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_createContribution_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_createContribution_argsInput(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNContributionInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐContributionInput) if err != nil { return nil, err } args["input"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_createContribution_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.ContributionInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNContributionInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐContributionInput(ctx, tmp) - } - - var zeroVal model.ContributionInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_createLike_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_createLike_argsInput(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNLikeInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐLikeInput) if err != nil { return nil, err } args["input"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_createLike_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.LikeInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNLikeInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐLikeInput(ctx, tmp) - } - - var zeroVal model.LikeInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_createTranslation_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_createTranslation_argsInput(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNTranslationInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐTranslationInput) if err != nil { return nil, err } args["input"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_createTranslation_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.TranslationInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNTranslationInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐTranslationInput(ctx, tmp) - } - - var zeroVal model.TranslationInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_createWork_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_createWork_argsInput(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNWorkInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐWorkInput) if err != nil { return nil, err } args["input"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_createWork_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.WorkInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNWorkInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐWorkInput(ctx, tmp) - } - - var zeroVal model.WorkInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_deleteAuthor_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_deleteAuthor_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_deleteAuthor_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_deleteBookmark_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_deleteBookmark_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_deleteBookmark_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_deleteCollection_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_deleteCollection_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_deleteCollection_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_deleteComment_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_deleteComment_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_deleteComment_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_deleteContribution_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_deleteContribution_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_deleteContribution_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_deleteLike_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_deleteLike_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_deleteLike_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_deleteTranslation_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_deleteTranslation_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_deleteTranslation_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_deleteUser_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_deleteUser_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_deleteUser_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_deleteWork_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_deleteWork_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_deleteWork_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_forgotPassword_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_forgotPassword_argsEmail(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "email", ec.unmarshalNString2string) if err != nil { return nil, err } args["email"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_forgotPassword_argsEmail( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("email")) - if tmp, ok := rawArgs["email"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_login_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_login_argsEmail(ctx, rawArgs) - if err != nil { - return nil, err - } - args["email"] = arg0 - arg1, err := ec.field_Mutation_login_argsPassword(ctx, rawArgs) - if err != nil { - return nil, err - } - args["password"] = arg1 - return args, nil -} -func (ec *executionContext) field_Mutation_login_argsEmail( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("email")) - if tmp, ok := rawArgs["email"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_login_argsPassword( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("password")) - if tmp, ok := rawArgs["password"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_register_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { - var err error - args := map[string]any{} - arg0, err := ec.field_Mutation_register_argsInput(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNLoginInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐLoginInput) if err != nil { return nil, err } args["input"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_register_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.RegisterInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNRegisterInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐRegisterInput(ctx, tmp) - } - var zeroVal model.RegisterInput - return zeroVal, nil +func (ec *executionContext) field_Mutation_register_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNRegisterInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐRegisterInput) + if err != nil { + return nil, err + } + args["input"] = arg0 + return args, nil } func (ec *executionContext) field_Mutation_removeWorkFromCollection_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_removeWorkFromCollection_argsCollectionID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "collectionId", ec.unmarshalNID2string) if err != nil { return nil, err } args["collectionId"] = arg0 - arg1, err := ec.field_Mutation_removeWorkFromCollection_argsWorkID(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "workId", ec.unmarshalNID2string) if err != nil { return nil, err } args["workId"] = arg1 return args, nil } -func (ec *executionContext) field_Mutation_removeWorkFromCollection_argsCollectionID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("collectionId")) - if tmp, ok := rawArgs["collectionId"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_removeWorkFromCollection_argsWorkID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("workId")) - if tmp, ok := rawArgs["workId"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_resendVerificationEmail_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_resendVerificationEmail_argsEmail(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "email", ec.unmarshalNString2string) if err != nil { return nil, err } args["email"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_resendVerificationEmail_argsEmail( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("email")) - if tmp, ok := rawArgs["email"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_resetPassword_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_resetPassword_argsToken(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "token", ec.unmarshalNString2string) if err != nil { return nil, err } args["token"] = arg0 - arg1, err := ec.field_Mutation_resetPassword_argsNewPassword(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "newPassword", ec.unmarshalNString2string) if err != nil { return nil, err } args["newPassword"] = arg1 return args, nil } -func (ec *executionContext) field_Mutation_resetPassword_argsToken( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("token")) - if tmp, ok := rawArgs["token"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_resetPassword_argsNewPassword( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("newPassword")) - if tmp, ok := rawArgs["newPassword"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_reviewContribution_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_reviewContribution_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 - arg1, err := ec.field_Mutation_reviewContribution_argsStatus(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "status", ec.unmarshalNContributionStatus2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐContributionStatus) if err != nil { return nil, err } args["status"] = arg1 - arg2, err := ec.field_Mutation_reviewContribution_argsFeedback(ctx, rawArgs) + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "feedback", ec.unmarshalOString2ᚖstring) if err != nil { return nil, err } args["feedback"] = arg2 return args, nil } -func (ec *executionContext) field_Mutation_reviewContribution_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_reviewContribution_argsStatus( - ctx context.Context, - rawArgs map[string]any, -) (model.ContributionStatus, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("status")) - if tmp, ok := rawArgs["status"]; ok { - return ec.unmarshalNContributionStatus2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐContributionStatus(ctx, tmp) - } - - var zeroVal model.ContributionStatus - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_reviewContribution_argsFeedback( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("feedback")) - if tmp, ok := rawArgs["feedback"]; ok { - return ec.unmarshalOString2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} func (ec *executionContext) field_Mutation_updateAuthor_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_updateAuthor_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 - arg1, err := ec.field_Mutation_updateAuthor_argsInput(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNAuthorInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐAuthorInput) if err != nil { return nil, err } args["input"] = arg1 return args, nil } -func (ec *executionContext) field_Mutation_updateAuthor_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_updateAuthor_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.AuthorInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNAuthorInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐAuthorInput(ctx, tmp) - } - - var zeroVal model.AuthorInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_updateCollection_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_updateCollection_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 - arg1, err := ec.field_Mutation_updateCollection_argsInput(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNCollectionInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐCollectionInput) if err != nil { return nil, err } args["input"] = arg1 return args, nil } -func (ec *executionContext) field_Mutation_updateCollection_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_updateCollection_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.CollectionInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNCollectionInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐCollectionInput(ctx, tmp) - } - - var zeroVal model.CollectionInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_updateComment_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_updateComment_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 - arg1, err := ec.field_Mutation_updateComment_argsInput(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNCommentInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐCommentInput) if err != nil { return nil, err } args["input"] = arg1 return args, nil } -func (ec *executionContext) field_Mutation_updateComment_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_updateComment_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.CommentInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNCommentInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐCommentInput(ctx, tmp) - } - - var zeroVal model.CommentInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_updateContribution_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_updateContribution_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 - arg1, err := ec.field_Mutation_updateContribution_argsInput(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNContributionInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐContributionInput) if err != nil { return nil, err } args["input"] = arg1 return args, nil } -func (ec *executionContext) field_Mutation_updateContribution_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_updateContribution_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.ContributionInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNContributionInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐContributionInput(ctx, tmp) - } - - var zeroVal model.ContributionInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_updateProfile_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_updateProfile_argsInput(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNUserInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐUserInput) if err != nil { return nil, err } args["input"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_updateProfile_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.UserInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNUserInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐUserInput(ctx, tmp) - } - - var zeroVal model.UserInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_updateTranslation_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_updateTranslation_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 - arg1, err := ec.field_Mutation_updateTranslation_argsInput(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNTranslationInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐTranslationInput) if err != nil { return nil, err } args["input"] = arg1 return args, nil } -func (ec *executionContext) field_Mutation_updateTranslation_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_updateTranslation_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.TranslationInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNTranslationInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐTranslationInput(ctx, tmp) - } - - var zeroVal model.TranslationInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_updateUser_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_updateUser_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 - arg1, err := ec.field_Mutation_updateUser_argsInput(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNUserInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐUserInput) if err != nil { return nil, err } args["input"] = arg1 return args, nil } -func (ec *executionContext) field_Mutation_updateUser_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_updateUser_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.UserInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNUserInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐUserInput(ctx, tmp) - } - - var zeroVal model.UserInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_updateWork_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_updateWork_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 - arg1, err := ec.field_Mutation_updateWork_argsInput(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNWorkInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐWorkInput) if err != nil { return nil, err } args["input"] = arg1 return args, nil } -func (ec *executionContext) field_Mutation_updateWork_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_updateWork_argsInput( - ctx context.Context, - rawArgs map[string]any, -) (model.WorkInput, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - if tmp, ok := rawArgs["input"]; ok { - return ec.unmarshalNWorkInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐWorkInput(ctx, tmp) - } - - var zeroVal model.WorkInput - return zeroVal, nil -} func (ec *executionContext) field_Mutation_verifyEmail_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Mutation_verifyEmail_argsToken(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "token", ec.unmarshalNString2string) if err != nil { return nil, err } args["token"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_verifyEmail_argsToken( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("token")) - if tmp, ok := rawArgs["token"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query___type_argsName(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "name", ec.unmarshalNString2string) if err != nil { return nil, err } args["name"] = arg0 return args, nil } -func (ec *executionContext) field_Query___type_argsName( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) - if tmp, ok := rawArgs["name"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query_author_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_author_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Query_author_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query_authors_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_authors_argsLimit(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "limit", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["limit"] = arg0 - arg1, err := ec.field_Query_authors_argsOffset(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "offset", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["offset"] = arg1 - arg2, err := ec.field_Query_authors_argsSearch(ctx, rawArgs) + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "search", ec.unmarshalOString2ᚖstring) if err != nil { return nil, err } args["search"] = arg2 - arg3, err := ec.field_Query_authors_argsCountryID(ctx, rawArgs) + arg3, err := graphql.ProcessArgField(ctx, rawArgs, "countryId", ec.unmarshalOID2ᚖstring) if err != nil { return nil, err } args["countryId"] = arg3 return args, nil } -func (ec *executionContext) field_Query_authors_argsLimit( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("limit")) - if tmp, ok := rawArgs["limit"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_authors_argsOffset( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("offset")) - if tmp, ok := rawArgs["offset"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_authors_argsSearch( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("search")) - if tmp, ok := rawArgs["search"]; ok { - return ec.unmarshalOString2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} - -func (ec *executionContext) field_Query_authors_argsCountryID( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("countryId")) - if tmp, ok := rawArgs["countryId"]; ok { - return ec.unmarshalOID2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} func (ec *executionContext) field_Query_categories_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_categories_argsLimit(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "limit", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["limit"] = arg0 - arg1, err := ec.field_Query_categories_argsOffset(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "offset", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["offset"] = arg1 return args, nil } -func (ec *executionContext) field_Query_categories_argsLimit( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("limit")) - if tmp, ok := rawArgs["limit"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_categories_argsOffset( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("offset")) - if tmp, ok := rawArgs["offset"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} func (ec *executionContext) field_Query_category_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_category_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Query_category_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query_collection_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_collection_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Query_collection_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query_collections_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_collections_argsUserID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "userId", ec.unmarshalOID2ᚖstring) if err != nil { return nil, err } args["userId"] = arg0 - arg1, err := ec.field_Query_collections_argsLimit(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "limit", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["limit"] = arg1 - arg2, err := ec.field_Query_collections_argsOffset(ctx, rawArgs) + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "offset", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["offset"] = arg2 return args, nil } -func (ec *executionContext) field_Query_collections_argsUserID( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("userId")) - if tmp, ok := rawArgs["userId"]; ok { - return ec.unmarshalOID2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} - -func (ec *executionContext) field_Query_collections_argsLimit( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("limit")) - if tmp, ok := rawArgs["limit"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_collections_argsOffset( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("offset")) - if tmp, ok := rawArgs["offset"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} func (ec *executionContext) field_Query_comment_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_comment_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Query_comment_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query_comments_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_comments_argsWorkID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "workId", ec.unmarshalOID2ᚖstring) if err != nil { return nil, err } args["workId"] = arg0 - arg1, err := ec.field_Query_comments_argsTranslationID(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "translationId", ec.unmarshalOID2ᚖstring) if err != nil { return nil, err } args["translationId"] = arg1 - arg2, err := ec.field_Query_comments_argsUserID(ctx, rawArgs) + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "userId", ec.unmarshalOID2ᚖstring) if err != nil { return nil, err } args["userId"] = arg2 - arg3, err := ec.field_Query_comments_argsLimit(ctx, rawArgs) + arg3, err := graphql.ProcessArgField(ctx, rawArgs, "limit", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["limit"] = arg3 - arg4, err := ec.field_Query_comments_argsOffset(ctx, rawArgs) + arg4, err := graphql.ProcessArgField(ctx, rawArgs, "offset", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["offset"] = arg4 return args, nil } -func (ec *executionContext) field_Query_comments_argsWorkID( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("workId")) - if tmp, ok := rawArgs["workId"]; ok { - return ec.unmarshalOID2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} - -func (ec *executionContext) field_Query_comments_argsTranslationID( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("translationId")) - if tmp, ok := rawArgs["translationId"]; ok { - return ec.unmarshalOID2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} - -func (ec *executionContext) field_Query_comments_argsUserID( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("userId")) - if tmp, ok := rawArgs["userId"]; ok { - return ec.unmarshalOID2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} - -func (ec *executionContext) field_Query_comments_argsLimit( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("limit")) - if tmp, ok := rawArgs["limit"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_comments_argsOffset( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("offset")) - if tmp, ok := rawArgs["offset"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} func (ec *executionContext) field_Query_search_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_search_argsQuery(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "query", ec.unmarshalNString2string) if err != nil { return nil, err } args["query"] = arg0 - arg1, err := ec.field_Query_search_argsLimit(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "limit", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["limit"] = arg1 - arg2, err := ec.field_Query_search_argsOffset(ctx, rawArgs) + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "offset", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["offset"] = arg2 - arg3, err := ec.field_Query_search_argsFilters(ctx, rawArgs) + arg3, err := graphql.ProcessArgField(ctx, rawArgs, "filters", ec.unmarshalOSearchFilters2ᚖterculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐSearchFilters) if err != nil { return nil, err } args["filters"] = arg3 return args, nil } -func (ec *executionContext) field_Query_search_argsQuery( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("query")) - if tmp, ok := rawArgs["query"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Query_search_argsLimit( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("limit")) - if tmp, ok := rawArgs["limit"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_search_argsOffset( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("offset")) - if tmp, ok := rawArgs["offset"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_search_argsFilters( - ctx context.Context, - rawArgs map[string]any, -) (*model.SearchFilters, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("filters")) - if tmp, ok := rawArgs["filters"]; ok { - return ec.unmarshalOSearchFilters2ᚖterculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐSearchFilters(ctx, tmp) - } - - var zeroVal *model.SearchFilters - return zeroVal, nil -} func (ec *executionContext) field_Query_tag_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_tag_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Query_tag_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query_tags_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_tags_argsLimit(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "limit", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["limit"] = arg0 - arg1, err := ec.field_Query_tags_argsOffset(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "offset", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["offset"] = arg1 return args, nil } -func (ec *executionContext) field_Query_tags_argsLimit( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("limit")) - if tmp, ok := rawArgs["limit"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_tags_argsOffset( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("offset")) - if tmp, ok := rawArgs["offset"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} func (ec *executionContext) field_Query_translation_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_translation_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Query_translation_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query_translations_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_translations_argsWorkID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "workId", ec.unmarshalNID2string) if err != nil { return nil, err } args["workId"] = arg0 - arg1, err := ec.field_Query_translations_argsLanguage(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "language", ec.unmarshalOString2ᚖstring) if err != nil { return nil, err } args["language"] = arg1 - arg2, err := ec.field_Query_translations_argsLimit(ctx, rawArgs) + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "limit", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["limit"] = arg2 - arg3, err := ec.field_Query_translations_argsOffset(ctx, rawArgs) + arg3, err := graphql.ProcessArgField(ctx, rawArgs, "offset", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["offset"] = arg3 return args, nil } -func (ec *executionContext) field_Query_translations_argsWorkID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("workId")) - if tmp, ok := rawArgs["workId"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Query_translations_argsLanguage( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("language")) - if tmp, ok := rawArgs["language"]; ok { - return ec.unmarshalOString2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} - -func (ec *executionContext) field_Query_translations_argsLimit( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("limit")) - if tmp, ok := rawArgs["limit"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_translations_argsOffset( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("offset")) - if tmp, ok := rawArgs["offset"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} func (ec *executionContext) field_Query_userByEmail_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_userByEmail_argsEmail(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "email", ec.unmarshalNString2string) if err != nil { return nil, err } args["email"] = arg0 return args, nil } -func (ec *executionContext) field_Query_userByEmail_argsEmail( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("email")) - if tmp, ok := rawArgs["email"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query_userByUsername_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_userByUsername_argsUsername(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "username", ec.unmarshalNString2string) if err != nil { return nil, err } args["username"] = arg0 return args, nil } -func (ec *executionContext) field_Query_userByUsername_argsUsername( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("username")) - if tmp, ok := rawArgs["username"]; ok { - return ec.unmarshalNString2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query_userProfile_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_userProfile_argsUserID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "userId", ec.unmarshalNID2string) if err != nil { return nil, err } args["userId"] = arg0 return args, nil } -func (ec *executionContext) field_Query_userProfile_argsUserID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("userId")) - if tmp, ok := rawArgs["userId"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query_user_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_user_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Query_user_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query_users_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_users_argsLimit(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "limit", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["limit"] = arg0 - arg1, err := ec.field_Query_users_argsOffset(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "offset", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["offset"] = arg1 - arg2, err := ec.field_Query_users_argsRole(ctx, rawArgs) + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "role", ec.unmarshalOUserRole2ᚖterculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐUserRole) if err != nil { return nil, err } args["role"] = arg2 return args, nil } -func (ec *executionContext) field_Query_users_argsLimit( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("limit")) - if tmp, ok := rawArgs["limit"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_users_argsOffset( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("offset")) - if tmp, ok := rawArgs["offset"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_users_argsRole( - ctx context.Context, - rawArgs map[string]any, -) (*model.UserRole, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("role")) - if tmp, ok := rawArgs["role"]; ok { - return ec.unmarshalOUserRole2ᚖterculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐUserRole(ctx, tmp) - } - - var zeroVal *model.UserRole - return zeroVal, nil -} func (ec *executionContext) field_Query_work_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_work_argsID(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", ec.unmarshalNID2string) if err != nil { return nil, err } args["id"] = arg0 return args, nil } -func (ec *executionContext) field_Query_work_argsID( - ctx context.Context, - rawArgs map[string]any, -) (string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - if tmp, ok := rawArgs["id"]; ok { - return ec.unmarshalNID2string(ctx, tmp) - } - - var zeroVal string - return zeroVal, nil -} func (ec *executionContext) field_Query_works_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field_Query_works_argsLimit(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "limit", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["limit"] = arg0 - arg1, err := ec.field_Query_works_argsOffset(ctx, rawArgs) + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "offset", ec.unmarshalOInt2ᚖint32) if err != nil { return nil, err } args["offset"] = arg1 - arg2, err := ec.field_Query_works_argsLanguage(ctx, rawArgs) + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "language", ec.unmarshalOString2ᚖstring) if err != nil { return nil, err } args["language"] = arg2 - arg3, err := ec.field_Query_works_argsAuthorID(ctx, rawArgs) + arg3, err := graphql.ProcessArgField(ctx, rawArgs, "authorId", ec.unmarshalOID2ᚖstring) if err != nil { return nil, err } args["authorId"] = arg3 - arg4, err := ec.field_Query_works_argsCategoryID(ctx, rawArgs) + arg4, err := graphql.ProcessArgField(ctx, rawArgs, "categoryId", ec.unmarshalOID2ᚖstring) if err != nil { return nil, err } args["categoryId"] = arg4 - arg5, err := ec.field_Query_works_argsTagID(ctx, rawArgs) + arg5, err := graphql.ProcessArgField(ctx, rawArgs, "tagId", ec.unmarshalOID2ᚖstring) if err != nil { return nil, err } args["tagId"] = arg5 - arg6, err := ec.field_Query_works_argsSearch(ctx, rawArgs) + arg6, err := graphql.ProcessArgField(ctx, rawArgs, "search", ec.unmarshalOString2ᚖstring) if err != nil { return nil, err } args["search"] = arg6 return args, nil } -func (ec *executionContext) field_Query_works_argsLimit( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("limit")) - if tmp, ok := rawArgs["limit"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_works_argsOffset( - ctx context.Context, - rawArgs map[string]any, -) (*int32, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("offset")) - if tmp, ok := rawArgs["offset"]; ok { - return ec.unmarshalOInt2ᚖint32(ctx, tmp) - } - - var zeroVal *int32 - return zeroVal, nil -} - -func (ec *executionContext) field_Query_works_argsLanguage( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("language")) - if tmp, ok := rawArgs["language"]; ok { - return ec.unmarshalOString2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} - -func (ec *executionContext) field_Query_works_argsAuthorID( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("authorId")) - if tmp, ok := rawArgs["authorId"]; ok { - return ec.unmarshalOID2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} - -func (ec *executionContext) field_Query_works_argsCategoryID( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("categoryId")) - if tmp, ok := rawArgs["categoryId"]; ok { - return ec.unmarshalOID2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} - -func (ec *executionContext) field_Query_works_argsTagID( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("tagId")) - if tmp, ok := rawArgs["tagId"]; ok { - return ec.unmarshalOID2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} - -func (ec *executionContext) field_Query_works_argsSearch( - ctx context.Context, - rawArgs map[string]any, -) (*string, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("search")) - if tmp, ok := rawArgs["search"]; ok { - return ec.unmarshalOString2ᚖstring(ctx, tmp) - } - - var zeroVal *string - return zeroVal, nil -} func (ec *executionContext) field___Directive_args_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field___Directive_args_argsIncludeDeprecated(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "includeDeprecated", ec.unmarshalOBoolean2ᚖbool) if err != nil { return nil, err } args["includeDeprecated"] = arg0 return args, nil } -func (ec *executionContext) field___Directive_args_argsIncludeDeprecated( - ctx context.Context, - rawArgs map[string]any, -) (*bool, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) - if tmp, ok := rawArgs["includeDeprecated"]; ok { - return ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - } - - var zeroVal *bool - return zeroVal, nil -} func (ec *executionContext) field___Field_args_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field___Field_args_argsIncludeDeprecated(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "includeDeprecated", ec.unmarshalOBoolean2ᚖbool) if err != nil { return nil, err } args["includeDeprecated"] = arg0 return args, nil } -func (ec *executionContext) field___Field_args_argsIncludeDeprecated( - ctx context.Context, - rawArgs map[string]any, -) (*bool, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) - if tmp, ok := rawArgs["includeDeprecated"]; ok { - return ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - } - - var zeroVal *bool - return zeroVal, nil -} func (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field___Type_enumValues_argsIncludeDeprecated(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "includeDeprecated", ec.unmarshalOBoolean2bool) if err != nil { return nil, err } args["includeDeprecated"] = arg0 return args, nil } -func (ec *executionContext) field___Type_enumValues_argsIncludeDeprecated( - ctx context.Context, - rawArgs map[string]any, -) (bool, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) - if tmp, ok := rawArgs["includeDeprecated"]; ok { - return ec.unmarshalOBoolean2bool(ctx, tmp) - } - - var zeroVal bool - return zeroVal, nil -} func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} - arg0, err := ec.field___Type_fields_argsIncludeDeprecated(ctx, rawArgs) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "includeDeprecated", ec.unmarshalOBoolean2bool) if err != nil { return nil, err } args["includeDeprecated"] = arg0 return args, nil } -func (ec *executionContext) field___Type_fields_argsIncludeDeprecated( - ctx context.Context, - rawArgs map[string]any, -) (bool, error) { - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) - if tmp, ok := rawArgs["includeDeprecated"]; ok { - return ec.unmarshalOBoolean2bool(ctx, tmp) - } - - var zeroVal bool - return zeroVal, nil -} // endregion ***************************** args.gotpl ***************************** @@ -14806,7 +13575,7 @@ func (ec *executionContext) _Mutation_login(ctx context.Context, field graphql.C }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().Login(rctx, fc.Args["email"].(string), fc.Args["password"].(string)) + return ec.resolvers.Mutation().Login(rctx, fc.Args["input"].(model.LoginInput)) }) if err != nil { ec.Error(ctx, err) @@ -29534,6 +28303,40 @@ func (ec *executionContext) unmarshalInputLikeInput(ctx context.Context, obj any return it, nil } +func (ec *executionContext) unmarshalInputLoginInput(ctx context.Context, obj any) (model.LoginInput, error) { + var it model.LoginInput + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"email", "password"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "email": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.Email = data + case "password": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("password")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.Password = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputRegisterInput(ctx context.Context, obj any) (model.RegisterInput, error) { var it model.RegisterInput asMap := map[string]any{} @@ -33593,6 +32396,7 @@ func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v any) ( } func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + _ = sel res := graphql.MarshalBoolean(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -33847,6 +32651,7 @@ func (ec *executionContext) unmarshalNFloat2float64(ctx context.Context, v any) } func (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.SelectionSet, v float64) graphql.Marshaler { + _ = sel res := graphql.MarshalFloatContext(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -33862,6 +32667,7 @@ func (ec *executionContext) unmarshalNID2string(ctx context.Context, v any) (str } func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + _ = sel res := graphql.MarshalID(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -33877,6 +32683,7 @@ func (ec *executionContext) unmarshalNInt2int32(ctx context.Context, v any) (int } func (ec *executionContext) marshalNInt2int32(ctx context.Context, sel ast.SelectionSet, v int32) graphql.Marshaler { + _ = sel res := graphql.MarshalInt32(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -33915,6 +32722,11 @@ func (ec *executionContext) marshalNLinguisticLayer2ᚖterculᚋinternalᚋadapt return ec._LinguisticLayer(ctx, sel, v) } +func (ec *executionContext) unmarshalNLoginInput2terculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐLoginInput(ctx context.Context, v any) (model.LoginInput, error) { + res, err := ec.unmarshalInputLoginInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalNMood2ᚖterculᚋinternalᚋadaptersᚋgraphqlᚋmodelᚐMood(ctx context.Context, sel ast.SelectionSet, v *model.Mood) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -33960,6 +32772,7 @@ func (ec *executionContext) unmarshalNString2string(ctx context.Context, v any) } func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + _ = sel res := graphql.MarshalString(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -34296,6 +33109,7 @@ func (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Con } func (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + _ = sel res := graphql.MarshalString(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -34484,6 +33298,7 @@ func (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v a } func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + _ = sel res := graphql.MarshalString(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -34668,6 +33483,8 @@ func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v any) ( } func (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + _ = sel + _ = ctx res := graphql.MarshalBoolean(v) return res } @@ -34684,6 +33501,8 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast if v == nil { return graphql.Null } + _ = sel + _ = ctx res := graphql.MarshalBoolean(*v) return res } @@ -35137,6 +33956,8 @@ func (ec *executionContext) marshalOID2ᚖstring(ctx context.Context, sel ast.Se if v == nil { return graphql.Null } + _ = sel + _ = ctx res := graphql.MarshalID(*v) return res } @@ -35153,6 +33974,8 @@ func (ec *executionContext) marshalOInt2ᚖint32(ctx context.Context, sel ast.Se if v == nil { return graphql.Null } + _ = sel + _ = ctx res := graphql.MarshalInt32(*v) return res } @@ -35169,6 +33992,8 @@ func (ec *executionContext) marshalOJSON2ᚖstring(ctx context.Context, sel ast. if v == nil { return graphql.Null } + _ = sel + _ = ctx res := graphql.MarshalString(*v) return res } @@ -35445,6 +34270,8 @@ func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel as if v == nil { return graphql.Null } + _ = sel + _ = ctx res := graphql.MarshalString(*v) return res } diff --git a/internal/adapters/graphql/integration_test.go b/internal/adapters/graphql/integration_test.go index 18520eb..3de96d9 100644 --- a/internal/adapters/graphql/integration_test.go +++ b/internal/adapters/graphql/integration_test.go @@ -7,9 +7,12 @@ import ( "fmt" "net/http" "net/http/httptest" + "strconv" "testing" graph "tercul/internal/adapters/graphql" + "tercul/internal/domain" + platform_auth "tercul/internal/platform/auth" "tercul/internal/testutil" "github.com/99designs/gqlgen/graphql/handler" @@ -23,9 +26,9 @@ type GraphQLRequest struct { Variables map[string]interface{} `json:"variables,omitempty"` } -// GraphQLResponse represents a GraphQL response -type GraphQLResponse struct { - Data map[string]interface{} `json:"data,omitempty"` +// GraphQLResponse represents a generic GraphQL response +type GraphQLResponse[T any] struct { + Data T `json:"data,omitempty"` Errors []map[string]interface{} `json:"errors,omitempty"` } @@ -44,9 +47,13 @@ func (s *GraphQLIntegrationSuite) SetupSuite() { resolver := s.GetResolver() srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: resolver})) - s.server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Create JWT manager and middleware + jwtManager := platform_auth.NewJWTManager() + authMiddleware := platform_auth.GraphQLAuthMiddleware(jwtManager) + + s.server = httptest.NewServer(authMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { srv.ServeHTTP(w, r) - })) + }))) s.client = s.server.Client() } @@ -62,8 +69,8 @@ func (s *GraphQLIntegrationSuite) SetupTest() { s.IntegrationTestSuite.SetupTest() } -// executeGraphQL executes a GraphQL query -func (s *GraphQLIntegrationSuite) executeGraphQL(query string, variables map[string]interface{}) (*GraphQLResponse, error) { +// executeGraphQL executes a GraphQL query and decodes the response into a generic type +func executeGraphQL[T any](s *GraphQLIntegrationSuite, query string, variables map[string]interface{}, token *string) (*GraphQLResponse[T], error) { // Create the request request := GraphQLRequest{ Query: query, @@ -82,6 +89,9 @@ func (s *GraphQLIntegrationSuite) executeGraphQL(query string, variables map[str return nil, err } req.Header.Set("Content-Type", "application/json") + if token != nil { + req.Header.Set("Authorization", "Bearer "+*token) + } // Execute the request resp, err := s.client.Do(req) @@ -91,7 +101,7 @@ func (s *GraphQLIntegrationSuite) executeGraphQL(query string, variables map[str defer resp.Body.Close() // Parse the response - var response GraphQLResponse + var response GraphQLResponse[T] err = json.NewDecoder(resp.Body).Decode(&response) if err != nil { return nil, err @@ -100,6 +110,15 @@ func (s *GraphQLIntegrationSuite) executeGraphQL(query string, variables map[str return &response, nil } +type GetWorkResponse struct { + Work struct { + ID string `json:"id"` + Name string `json:"name"` + Language string `json:"language"` + Content string `json:"content"` + } `json:"work"` +} + // TestQueryWork tests the work query func (s *GraphQLIntegrationSuite) TestQueryWork() { // Create a test work with content @@ -123,18 +142,24 @@ func (s *GraphQLIntegrationSuite) TestQueryWork() { } // Execute the query - response, err := s.executeGraphQL(query, variables) + response, err := executeGraphQL[GetWorkResponse](s, query, variables, nil) s.Require().NoError(err) s.Require().NotNil(response) s.Require().Nil(response.Errors, "GraphQL query should not return errors") - s.Require().NotNil(response.Data, "GraphQL query should return data") // Verify the response - workData, ok := response.Data["work"].(map[string]interface{}) - s.Require().True(ok, "GraphQL response should contain work data") - s.Equal("Test Work", workData["name"], "Work name should match") - s.Equal("Test content for work", workData["content"], "Work content should match") - s.Equal("en", workData["language"], "Work language should match") + s.Equal("Test Work", response.Data.Work.Name, "Work name should match") + s.Equal("Test content for work", response.Data.Work.Content, "Work content should match") + s.Equal("en", response.Data.Work.Language, "Work language should match") +} + +type GetWorksResponse struct { + Works []struct { + ID string `json:"id"` + Name string `json:"name"` + Language string `json:"language"` + Content string `json:"content"` + } `json:"works"` } // TestQueryWorks tests the works query @@ -157,36 +182,29 @@ func (s *GraphQLIntegrationSuite) TestQueryWorks() { ` // Execute the query - response, err := s.executeGraphQL(query, nil) + response, err := executeGraphQL[GetWorksResponse](s, query, nil, nil) s.Require().NoError(err) s.Require().NotNil(response) s.Require().Nil(response.Errors, "GraphQL query should not return errors") - s.Require().NotNil(response.Data, "GraphQL query should return data") // Verify the response - worksData, ok := response.Data["works"].([]interface{}) - s.Require().True(ok, "GraphQL response should contain works data") - s.True(len(worksData) >= 3, "GraphQL response should contain at least 3 works") + s.True(len(response.Data.Works) >= 3, "GraphQL response should contain at least 3 works") // Verify each work foundWork1 := false foundWork2 := false foundWork3 := false - for _, workData := range worksData { - work, ok := workData.(map[string]interface{}) - s.Require().True(ok, "Work data should be a map") - - name := work["name"].(string) - if name == "Test Work 1" { + for _, work := range response.Data.Works { + if work.Name == "Test Work 1" { foundWork1 = true - s.Equal("en", work["language"], "Work 1 language should match") - } else if name == "Test Work 2" { + s.Equal("en", work.Language, "Work 1 language should match") + } else if work.Name == "Test Work 2" { foundWork2 = true - s.Equal("en", work["language"], "Work 2 language should match") - } else if name == "Test Work 3" { + s.Equal("en", work.Language, "Work 2 language should match") + } else if work.Name == "Test Work 3" { foundWork3 = true - s.Equal("fr", work["language"], "Work 3 language should match") + s.Equal("fr", work.Language, "Work 3 language should match") } } @@ -195,6 +213,15 @@ func (s *GraphQLIntegrationSuite) TestQueryWorks() { s.True(foundWork3, "GraphQL response should contain work 3") } +type CreateWorkResponse struct { + CreateWork struct { + ID string `json:"id"` + Name string `json:"name"` + Language string `json:"language"` + Content string `json:"content"` + } `json:"createWork"` +} + // TestCreateWork tests the createWork mutation func (s *GraphQLIntegrationSuite) TestCreateWork() { // Define the mutation @@ -219,25 +246,22 @@ func (s *GraphQLIntegrationSuite) TestCreateWork() { } // Execute the mutation - response, err := s.executeGraphQL(mutation, variables) + response, err := executeGraphQL[CreateWorkResponse](s, mutation, variables, nil) s.Require().NoError(err) s.Require().NotNil(response) s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") - s.Require().NotNil(response.Data, "GraphQL mutation should return data") // Verify the response - workData, ok := response.Data["createWork"].(map[string]interface{}) - s.Require().True(ok, "GraphQL response should contain work data") - s.NotNil(workData["id"], "Work ID should not be nil") - s.Equal("New Test Work", workData["name"], "Work name should match") - s.Equal("en", workData["language"], "Work language should match") - s.Equal("New test content", workData["content"], "Work content should match") + s.NotNil(response.Data.CreateWork.ID, "Work ID should not be nil") + s.Equal("New Test Work", response.Data.CreateWork.Name, "Work name should match") + s.Equal("en", response.Data.CreateWork.Language, "Work language should match") + s.Equal("New test content", response.Data.CreateWork.Content, "Work content should match") // Verify that the work was created in the repository // Since we're using the real repository interface, we can query it works, err := s.WorkRepo.ListAll(context.Background()) s.Require().NoError(err) - + var found bool for _, w := range works { if w.Title == "New Test Work" { @@ -250,7 +274,859 @@ func (s *GraphQLIntegrationSuite) TestCreateWork() { } // TestGraphQLIntegrationSuite runs the test suite +func (s *GraphQLIntegrationSuite) TestRegisterValidation() { + s.Run("should return error for invalid input", func() { + // Define the mutation + mutation := ` + mutation Register($input: RegisterInput!) { + register(input: $input) { + token + } + } + ` + + // Define the variables with invalid input + variables := map[string]interface{}{ + "input": map[string]interface{}{ + "username": "a", // Too short + "email": "invalid-email", + "password": "short", + "firstName": "123", + "lastName": "456", + }, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, nil) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().NotNil(response.Errors, "GraphQL mutation should return errors") + s.Len(response.Errors, 1) + }) +} + +func (s *GraphQLIntegrationSuite) TestLoginValidation() { + s.Run("should return error for invalid input", func() { + // Define the mutation + mutation := ` + mutation Login($input: LoginInput!) { + login(input: $input) { + token + } + } + ` + + // Define the variables with invalid input + variables := map[string]interface{}{ + "input": map[string]interface{}{ + "email": "invalid-email", + "password": "short", + }, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, nil) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().NotNil(response.Errors, "GraphQL mutation should return errors") + s.Len(response.Errors, 1) + }) +} + +func (s *GraphQLIntegrationSuite) TestCreateWorkValidation() { + s.Run("should return error for invalid input", func() { + // Define the mutation + mutation := ` + mutation CreateWork($input: WorkInput!) { + createWork(input: $input) { + id + } + } + ` + + // Define the variables with invalid input + variables := map[string]interface{}{ + "input": map[string]interface{}{ + "name": "a", // Too short + "language": "en-US", // Not 2 chars + }, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, nil) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().NotNil(response.Errors, "GraphQL mutation should return errors") + s.Len(response.Errors, 1) + }) +} + +func (s *GraphQLIntegrationSuite) TestUpdateWorkValidation() { + s.Run("should return error for invalid input", func() { + // Arrange + work := s.CreateTestWork("Test Work", "en", "Test content") + + // Define the mutation + mutation := ` + mutation UpdateWork($id: ID!, $input: WorkInput!) { + updateWork(id: $id, input: $input) { + id + } + } + ` + + // Define the variables with invalid input + variables := map[string]interface{}{ + "id": fmt.Sprintf("%d", work.ID), + "input": map[string]interface{}{ + "name": "a", // Too short + "language": "en-US", // Not 2 chars + }, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, nil) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().NotNil(response.Errors, "GraphQL mutation should return errors") + s.Len(response.Errors, 1) + }) +} + +func (s *GraphQLIntegrationSuite) TestCreateAuthorValidation() { + s.Run("should return error for invalid input", func() { + // Define the mutation + mutation := ` + mutation CreateAuthor($input: AuthorInput!) { + createAuthor(input: $input) { + id + } + } + ` + + // Define the variables with invalid input + variables := map[string]interface{}{ + "input": map[string]interface{}{ + "name": "a", // Too short + "language": "en-US", // Not 2 chars + }, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, nil) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().NotNil(response.Errors, "GraphQL mutation should return errors") + s.Len(response.Errors, 1) + }) +} + +func (s *GraphQLIntegrationSuite) TestUpdateAuthorValidation() { + s.Run("should return error for invalid input", func() { + // Arrange + author := &domain.Author{Name: "Test Author"} + s.Require().NoError(s.AuthorRepo.Create(context.Background(), author)) + + // Define the mutation + mutation := ` + mutation UpdateAuthor($id: ID!, $input: AuthorInput!) { + updateAuthor(id: $id, input: $input) { + id + } + } + ` + + // Define the variables with invalid input + variables := map[string]interface{}{ + "id": fmt.Sprintf("%d", author.ID), + "input": map[string]interface{}{ + "name": "a", // Too short + "language": "en-US", // Not 2 chars + }, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, nil) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().NotNil(response.Errors, "GraphQL mutation should return errors") + s.Len(response.Errors, 1) + }) +} + +func (s *GraphQLIntegrationSuite) TestCreateTranslationValidation() { + s.Run("should return error for invalid input", func() { + // Arrange + work := s.CreateTestWork("Test Work", "en", "Test content") + + // Define the mutation + mutation := ` + mutation CreateTranslation($input: TranslationInput!) { + createTranslation(input: $input) { + id + } + } + ` + + // Define the variables with invalid input + variables := map[string]interface{}{ + "input": map[string]interface{}{ + "name": "a", // Too short + "language": "en-US", // Not 2 chars + "workId": fmt.Sprintf("%d", work.ID), + }, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, nil) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().NotNil(response.Errors, "GraphQL mutation should return errors") + s.Len(response.Errors, 1) + }) +} + +func (s *GraphQLIntegrationSuite) TestUpdateTranslationValidation() { + s.Run("should return error for invalid input", func() { + // Arrange + work := s.CreateTestWork("Test Work", "en", "Test content") + translation := &domain.Translation{ + Title: "Test Translation", + Language: "en", + Content: "Test content", + TranslatableID: work.ID, + TranslatableType: "Work", + } + s.Require().NoError(s.TranslationRepo.Create(context.Background(), translation)) + + // Define the mutation + mutation := ` + mutation UpdateTranslation($id: ID!, $input: TranslationInput!) { + updateTranslation(id: $id, input: $input) { + id + } + } + ` + + // Define the variables with invalid input + variables := map[string]interface{}{ + "id": fmt.Sprintf("%d", translation.ID), + "input": map[string]interface{}{ + "name": "a", // Too short + "language": "en-US", // Not 2 chars + "workId": fmt.Sprintf("%d", work.ID), + }, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, nil) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().NotNil(response.Errors, "GraphQL mutation should return errors") + s.Len(response.Errors, 1) + }) +} + +func (s *GraphQLIntegrationSuite) TestDeleteWork() { + s.Run("should delete a work", func() { + // Arrange + work := s.CreateTestWork("Test Work", "en", "Test content") + + // Define the mutation + mutation := ` + mutation DeleteWork($id: ID!) { + deleteWork(id: $id) + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": fmt.Sprintf("%d", work.ID), + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, nil) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") + s.Require().NotNil(response.Data) + s.True(response.Data.(map[string]interface{})["deleteWork"].(bool)) + + // Verify that the work was actually deleted from the database + _, err = s.WorkRepo.GetByID(context.Background(), work.ID) + s.Require().Error(err) + }) +} + +func (s *GraphQLIntegrationSuite) TestDeleteAuthor() { + s.Run("should delete an author", func() { + // Arrange + author := &domain.Author{Name: "Test Author"} + s.Require().NoError(s.AuthorRepo.Create(context.Background(), author)) + + // Define the mutation + mutation := ` + mutation DeleteAuthor($id: ID!) { + deleteAuthor(id: $id) + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": fmt.Sprintf("%d", author.ID), + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, nil) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") + s.Require().NotNil(response.Data) + s.True(response.Data.(map[string]interface{})["deleteAuthor"].(bool)) + + // Verify that the author was actually deleted from the database + _, err = s.AuthorRepo.GetByID(context.Background(), author.ID) + s.Require().Error(err) + }) +} + +func (s *GraphQLIntegrationSuite) TestDeleteTranslation() { + s.Run("should delete a translation", func() { + // Arrange + work := s.CreateTestWork("Test Work", "en", "Test content") + translation := &domain.Translation{ + Title: "Test Translation", + Language: "en", + Content: "Test content", + TranslatableID: work.ID, + TranslatableType: "Work", + } + s.Require().NoError(s.TranslationRepo.Create(context.Background(), translation)) + + // Define the mutation + mutation := ` + mutation DeleteTranslation($id: ID!) { + deleteTranslation(id: $id) + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": fmt.Sprintf("%d", translation.ID), + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, nil) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") + s.Require().NotNil(response.Data) + s.True(response.Data.(map[string]interface{})["deleteTranslation"].(bool)) + + // Verify that the translation was actually deleted from the database + _, err = s.TranslationRepo.GetByID(context.Background(), translation.ID) + s.Require().Error(err) + }) +} + func TestGraphQLIntegrationSuite(t *testing.T) { testutil.SkipIfShort(t) suite.Run(t, new(GraphQLIntegrationSuite)) } + +type CreateCollectionResponse struct { + CreateCollection struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + } `json:"createCollection"` +} + +type UpdateCollectionResponse struct { + UpdateCollection struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + } `json:"updateCollection"` +} + +type AddWorkToCollectionResponse struct { + AddWorkToCollection struct { + ID string `json:"id"` + } `json:"addWorkToCollection"` +} + +type RemoveWorkFromCollectionResponse struct { + RemoveWorkFromCollection struct { + ID string `json:"id"` + } `json:"removeWorkFromCollection"` +} + +func (s *GraphQLIntegrationSuite) TestCommentMutations() { + // Create users for testing authorization + commenter, commenterToken := s.CreateAuthenticatedUser("commenter", "commenter@test.com", domain.UserRoleReader) + otherUser, otherToken := s.CreateAuthenticatedUser("otheruser", "other@test.com", domain.UserRoleReader) + _ = otherUser + + // Create a work to comment on + work := s.CreateTestWork("Commentable Work", "en", "Some content") + + var commentID string + + s.Run("should create a comment on a work", func() { + // Define the mutation + mutation := ` + mutation CreateComment($input: CommentInput!) { + createComment(input: $input) { + id + text + } + } + ` + + // Define the variables + variables := map[string]interface{}{ + "input": map[string]interface{}{ + "text": "This is a test comment.", + "workId": fmt.Sprintf("%d", work.ID), + }, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, &commenterToken) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") + + // Verify the response + commentData := response.Data.(map[string]interface{})["createComment"].(map[string]interface{}) + s.NotNil(commentData["id"], "Comment ID should not be nil") + commentID = commentData["id"].(string) + s.Equal("This is a test comment.", commentData["text"]) + }) + + s.Run("should update a comment", func() { + // Define the mutation + mutation := ` + mutation UpdateComment($id: ID!, $input: CommentInput!) { + updateComment(id: $id, input: $input) { + id + text + } + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": commentID, + "input": map[string]interface{}{ + "text": "This is an updated comment.", + }, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, &commenterToken) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") + + // Verify the response + commentData := response.Data.(map[string]interface{})["updateComment"].(map[string]interface{}) + s.Equal("This is an updated comment.", commentData["text"]) + }) + + s.Run("should not update a comment owned by another user", func() { + // Define the mutation + mutation := ` + mutation UpdateComment($id: ID!, $input: CommentInput!) { + updateComment(id: $id, input: $input) { + id + } + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": commentID, + "input": map[string]interface{}{ + "text": "Attempted Takeover", + }, + } + + // Execute the mutation with the other user's token + response, err := executeGraphQL[any](s, mutation, variables, &otherToken) + s.Require().NoError(err) + s.Require().NotNil(response.Errors) + }) + + s.Run("should delete a comment", func() { + // Create a new comment to delete + comment := &domain.Comment{Text: "to be deleted", UserID: commenter.ID, WorkID: &work.ID} + s.Require().NoError(s.App.CommentRepo.Create(context.Background(), comment)) + + // Define the mutation + mutation := ` + mutation DeleteComment($id: ID!) { + deleteComment(id: $id) + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": fmt.Sprintf("%d", comment.ID), + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, &commenterToken) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") + s.True(response.Data.(map[string]interface{})["deleteComment"].(bool)) + }) +} + +func (s *GraphQLIntegrationSuite) TestLikeMutations() { + // Create users for testing authorization + liker, likerToken := s.CreateAuthenticatedUser("liker", "liker@test.com", domain.UserRoleReader) + otherUser, otherToken := s.CreateAuthenticatedUser("otheruser", "other@test.com", domain.UserRoleReader) + _ = otherUser + + // Create a work to like + work := s.CreateTestWork("Likeable Work", "en", "Some content") + + var likeID string + + s.Run("should create a like on a work", func() { + // Define the mutation + mutation := ` + mutation CreateLike($input: LikeInput!) { + createLike(input: $input) { + id + } + } + ` + + // Define the variables + variables := map[string]interface{}{ + "input": map[string]interface{}{ + "workId": fmt.Sprintf("%d", work.ID), + }, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, &likerToken) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") + + // Verify the response + likeData := response.Data.(map[string]interface{})["createLike"].(map[string]interface{}) + s.NotNil(likeData["id"], "Like ID should not be nil") + likeID = likeData["id"].(string) + }) + + s.Run("should not delete a like owned by another user", func() { + // Create a like by the original user + like := &domain.Like{UserID: liker.ID, WorkID: &work.ID} + s.Require().NoError(s.App.LikeRepo.Create(context.Background(), like)) + + // Define the mutation + mutation := ` + mutation DeleteLike($id: ID!) { + deleteLike(id: $id) + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": fmt.Sprintf("%d", like.ID), + } + + // Execute the mutation with the other user's token + response, err := executeGraphQL[any](s, mutation, variables, &otherToken) + s.Require().NoError(err) + s.Require().NotNil(response.Errors) + }) + + s.Run("should delete a like", func() { + // Use the likeID from the create test + // Define the mutation + mutation := ` + mutation DeleteLike($id: ID!) { + deleteLike(id: $id) + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": likeID, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, &likerToken) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") + s.True(response.Data.(map[string]interface{})["deleteLike"].(bool)) + }) +} + +func (s *GraphQLIntegrationSuite) TestBookmarkMutations() { + // Create users for testing authorization + bookmarker, bookmarkerToken := s.CreateAuthenticatedUser("bookmarker", "bookmarker@test.com", domain.UserRoleReader) + otherUser, otherToken := s.CreateAuthenticatedUser("otheruser", "other@test.com", domain.UserRoleReader) + _ = otherUser + + // Create a work to bookmark + work := s.CreateTestWork("Bookmarkable Work", "en", "Some content") + + s.Run("should create a bookmark on a work", func() { + // Define the mutation + mutation := ` + mutation CreateBookmark($input: BookmarkInput!) { + createBookmark(input: $input) { + id + } + } + ` + + // Define the variables + variables := map[string]interface{}{ + "input": map[string]interface{}{ + "workId": fmt.Sprintf("%d", work.ID), + }, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, &bookmarkerToken) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") + + // Verify the response + bookmarkData := response.Data.(map[string]interface{})["createBookmark"].(map[string]interface{}) + s.NotNil(bookmarkData["id"], "Bookmark ID should not be nil") + + // Cleanup + bookmarkID, err := strconv.ParseUint(bookmarkData["id"].(string), 10, 32) + s.Require().NoError(err) + s.App.BookmarkRepo.Delete(context.Background(), uint(bookmarkID)) + }) + + s.Run("should not delete a bookmark owned by another user", func() { + // Create a bookmark by the original user + bookmark := &domain.Bookmark{UserID: bookmarker.ID, WorkID: work.ID, Name: "A Bookmark"} + s.Require().NoError(s.App.BookmarkRepo.Create(context.Background(), bookmark)) + s.T().Cleanup(func() { s.App.BookmarkRepo.Delete(context.Background(), bookmark.ID) }) + + // Define the mutation + mutation := ` + mutation DeleteBookmark($id: ID!) { + deleteBookmark(id: $id) + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": fmt.Sprintf("%d", bookmark.ID), + } + + // Execute the mutation with the other user's token + response, err := executeGraphQL[any](s, mutation, variables, &otherToken) + s.Require().NoError(err) + s.Require().NotNil(response.Errors) + }) + + s.Run("should delete a bookmark", func() { + // Create a new bookmark to delete + bookmark := &domain.Bookmark{UserID: bookmarker.ID, WorkID: work.ID, Name: "To Be Deleted"} + s.Require().NoError(s.App.BookmarkRepo.Create(context.Background(), bookmark)) + + // Define the mutation + mutation := ` + mutation DeleteBookmark($id: ID!) { + deleteBookmark(id: $id) + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": fmt.Sprintf("%d", bookmark.ID), + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, &bookmarkerToken) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") + s.True(response.Data.(map[string]interface{})["deleteBookmark"].(bool)) + }) +} + +func (s *GraphQLIntegrationSuite) TestCollectionMutations() { + // Create users for testing authorization + owner, ownerToken := s.CreateAuthenticatedUser("collectionowner", "owner@test.com", domain.UserRoleReader) + otherUser, otherToken := s.CreateAuthenticatedUser("otheruser", "other@test.com", domain.UserRoleReader) + _ = otherUser + + var collectionID string + + s.Run("should create a collection", func() { + // Define the mutation + mutation := ` + mutation CreateCollection($input: CollectionInput!) { + createCollection(input: $input) { + id + name + description + } + } + ` + + // Define the variables + variables := map[string]interface{}{ + "input": map[string]interface{}{ + "name": "My New Collection", + "description": "A collection of my favorite works.", + }, + } + + // Execute the mutation + response, err := executeGraphQL[CreateCollectionResponse](s, mutation, variables, &ownerToken) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") + + // Verify the response + s.NotNil(response.Data.CreateCollection.ID, "Collection ID should not be nil") + collectionID = response.Data.CreateCollection.ID // Save for later tests + s.Equal("My New Collection", response.Data.CreateCollection.Name, "Collection name should match") + s.Equal("A collection of my favorite works.", response.Data.CreateCollection.Description, "Collection description should match") + }) + + s.Run("should update a collection", func() { + // Define the mutation + mutation := ` + mutation UpdateCollection($id: ID!, $input: CollectionInput!) { + updateCollection(id: $id, input: $input) { + id + name + description + } + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": collectionID, + "input": map[string]interface{}{ + "name": "My Updated Collection", + "description": "An updated description.", + }, + } + + // Execute the mutation + response, err := executeGraphQL[UpdateCollectionResponse](s, mutation, variables, &ownerToken) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Nil(response.Errors, "GraphQL mutation should not return errors") + + // Verify the response + s.Equal("My Updated Collection", response.Data.UpdateCollection.Name) + }) + + s.Run("should not update a collection owned by another user", func() { + // Define the mutation + mutation := ` + mutation UpdateCollection($id: ID!, $input: CollectionInput!) { + updateCollection(id: $id, input: $input) { + id + } + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": collectionID, + "input": map[string]interface{}{ + "name": "Attempted Takeover", + }, + } + + // Execute the mutation with the other user's token + response, err := executeGraphQL[any](s, mutation, variables, &otherToken) + s.Require().NoError(err) + s.Require().NotNil(response.Errors) + }) + + s.Run("should add a work to a collection", func() { + // Create a work + work := s.CreateTestWork("Test Work", "en", "Test content") + + // Define the mutation + mutation := ` + mutation AddWorkToCollection($collectionId: ID!, $workId: ID!) { + addWorkToCollection(collectionId: $collectionId, workId: $workId) { + id + } + } + ` + + // Define the variables + variables := map[string]interface{}{ + "collectionId": collectionID, + "workId": fmt.Sprintf("%d", work.ID), + } + + // Execute the mutation + response, err := executeGraphQL[AddWorkToCollectionResponse](s, mutation, variables, &ownerToken) + s.Require().NoError(err) + s.Require().Nil(response.Errors) + }) + + s.Run("should remove a work from a collection", func() { + // Create a work and add it to the collection first + work := s.CreateTestWork("Another Work", "en", "Some content") + s.Require().NoError(s.App.CollectionRepo.AddWorkToCollection(context.Background(), owner.ID, work.ID)) + + // Define the mutation + mutation := ` + mutation RemoveWorkFromCollection($collectionId: ID!, $workId: ID!) { + removeWorkFromCollection(collectionId: $collectionId, workId: $workId) { + id + } + } + ` + + // Define the variables + variables := map[string]interface{}{ + "collectionId": collectionID, + "workId": fmt.Sprintf("%d", work.ID), + } + + // Execute the mutation + response, err := executeGraphQL[RemoveWorkFromCollectionResponse](s, mutation, variables, &ownerToken) + s.Require().NoError(err) + s.Require().Nil(response.Errors) + }) + + s.Run("should delete a collection", func() { + // Define the mutation + mutation := ` + mutation DeleteCollection($id: ID!) { + deleteCollection(id: $id) + } + ` + + // Define the variables + variables := map[string]interface{}{ + "id": collectionID, + } + + // Execute the mutation + response, err := executeGraphQL[any](s, mutation, variables, &ownerToken) + s.Require().NoError(err) + s.Require().Nil(response.Errors) + s.True(response.Data.(map[string]interface{})["deleteCollection"].(bool)) + }) +} diff --git a/internal/adapters/graphql/model/models_gen.go b/internal/adapters/graphql/model/models_gen.go index 05db6eb..46a08c0 100644 --- a/internal/adapters/graphql/model/models_gen.go +++ b/internal/adapters/graphql/model/models_gen.go @@ -45,8 +45,8 @@ type Author struct { } type AuthorInput struct { - Name string `json:"name"` - Language string `json:"language"` + Name string `json:"name" valid:"required,length(3|255)"` + Language string `json:"language" valid:"required,length(2|2)"` Biography *string `json:"biography,omitempty"` BirthDate *string `json:"birthDate,omitempty"` DeathDate *string `json:"deathDate,omitempty"` @@ -87,7 +87,7 @@ type Bookmark struct { type BookmarkInput struct { Name *string `json:"name,omitempty"` - WorkID string `json:"workId"` + WorkID string `json:"workId" valid:"required"` } type Category struct { @@ -121,7 +121,7 @@ type Collection struct { } type CollectionInput struct { - Name string `json:"name"` + Name string `json:"name" valid:"required,length(3|255)"` Description *string `json:"description,omitempty"` WorkIds []string `json:"workIds,omitempty"` } @@ -149,7 +149,7 @@ type Comment struct { } type CommentInput struct { - Text string `json:"text"` + Text string `json:"text" valid:"required,length(1|4096)"` WorkID *string `json:"workId,omitempty"` TranslationID *string `json:"translationId,omitempty"` LineNumber *int32 `json:"lineNumber,omitempty"` @@ -268,6 +268,11 @@ type LinguisticLayer struct { Works []*Work `json:"works,omitempty"` } +type LoginInput struct { + Email string `json:"email" valid:"required,email"` + Password string `json:"password" valid:"required,length(6|255)"` +} + type Mood struct { ID string `json:"id"` Name string `json:"name"` @@ -313,11 +318,11 @@ type ReadabilityScore struct { } type RegisterInput struct { - Username string `json:"username"` - Email string `json:"email"` - Password string `json:"password"` - FirstName string `json:"firstName"` - LastName string `json:"lastName"` + Username string `json:"username" valid:"required,alphanum,length(3|50)"` + Email string `json:"email" valid:"required,email"` + Password string `json:"password" valid:"required,length(6|255)"` + FirstName string `json:"firstName" valid:"required,alpha,length(2|50)"` + LastName string `json:"lastName" valid:"required,alpha,length(2|50)"` } type SearchFilters struct { @@ -390,10 +395,10 @@ type Translation struct { } type TranslationInput struct { - Name string `json:"name"` - Language string `json:"language"` + Name string `json:"name" valid:"required,length(3|255)"` + Language string `json:"language" valid:"required,length(2|2)"` Content *string `json:"content,omitempty"` - WorkID string `json:"workId"` + WorkID string `json:"workId" valid:"required,uuid"` } type TranslationStats struct { @@ -511,8 +516,8 @@ type Work struct { } type WorkInput struct { - Name string `json:"name"` - Language string `json:"language"` + Name string `json:"name" valid:"required,length(3|255)"` + Language string `json:"language" valid:"required,length(2|2)"` Content *string `json:"content,omitempty"` AuthorIds []string `json:"authorIds,omitempty"` TagIds []string `json:"tagIds,omitempty"` diff --git a/internal/adapters/graphql/schema.graphqls b/internal/adapters/graphql/schema.graphqls index a76705d..0af17e7 100644 --- a/internal/adapters/graphql/schema.graphqls +++ b/internal/adapters/graphql/schema.graphqls @@ -539,7 +539,7 @@ type SearchResults { type Mutation { # Authentication register(input: RegisterInput!): AuthPayload! - login(email: String!, password: String!): AuthPayload! + login(input: LoginInput!): AuthPayload! # Work mutations createWork(input: WorkInput!): Work! @@ -600,6 +600,11 @@ type Mutation { } # Input types +input LoginInput { + email: String! + password: String! +} + input RegisterInput { username: String! email: String! diff --git a/internal/adapters/graphql/schema.resolvers.go b/internal/adapters/graphql/schema.resolvers.go index 043630a..3355219 100644 --- a/internal/adapters/graphql/schema.resolvers.go +++ b/internal/adapters/graphql/schema.resolvers.go @@ -2,7 +2,7 @@ package graphql // 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. -// Code generated by github.com/99designs/gqlgen version v0.17.72 +// Code generated by github.com/99designs/gqlgen version v0.17.78 import ( "context" @@ -12,10 +12,18 @@ import ( "tercul/internal/adapters/graphql/model" "tercul/internal/app/auth" "tercul/internal/domain" + platform_auth "tercul/internal/platform/auth" + + "github.com/asaskevich/govalidator" ) // Register is the resolver for the register field. func (r *mutationResolver) Register(ctx context.Context, input model.RegisterInput) (*model.AuthPayload, error) { + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + // Convert GraphQL input to service input registerInput := auth.RegisterInput{ Username: input.Username, @@ -49,11 +57,16 @@ func (r *mutationResolver) Register(ctx context.Context, input model.RegisterInp } // Login is the resolver for the login field. -func (r *mutationResolver) Login(ctx context.Context, email string, password string) (*model.AuthPayload, error) { +func (r *mutationResolver) Login(ctx context.Context, input model.LoginInput) (*model.AuthPayload, error) { + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + // Convert GraphQL input to service input loginInput := auth.LoginInput{ - Email: email, - Password: password, + Email: input.Email, + Password: input.Password, } // Call auth service @@ -81,6 +94,11 @@ func (r *mutationResolver) Login(ctx context.Context, email string, password str // CreateWork is the resolver for the createWork field. func (r *mutationResolver) CreateWork(ctx context.Context, input model.WorkInput) (*model.Work, error) { + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + // Create domain model work := &domain.Work{ Title: input.Name, @@ -130,42 +148,231 @@ func (r *mutationResolver) CreateWork(ctx context.Context, input model.WorkInput // UpdateWork is the resolver for the updateWork field. func (r *mutationResolver) UpdateWork(ctx context.Context, id string, input model.WorkInput) (*model.Work, error) { - panic(fmt.Errorf("not implemented: UpdateWork - updateWork")) + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + + workID, err := strconv.ParseUint(id, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid work ID: %v", err) + } + + // Create domain model + work := &domain.Work{ + TranslatableModel: domain.TranslatableModel{ + BaseModel: domain.BaseModel{ID: uint(workID)}, + Language: input.Language, + }, + Title: input.Name, + } + + // Call work service + err = r.App.WorkCommands.UpdateWork(ctx, work) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Work{ + ID: id, + Name: work.Title, + Language: work.Language, + Content: input.Content, + }, nil } // DeleteWork is the resolver for the deleteWork field. func (r *mutationResolver) DeleteWork(ctx context.Context, id string) (bool, error) { - panic(fmt.Errorf("not implemented: DeleteWork - deleteWork")) + workID, err := strconv.ParseUint(id, 10, 32) + if err != nil { + return false, fmt.Errorf("invalid work ID: %v", err) + } + + err = r.App.WorkCommands.DeleteWork(ctx, uint(workID)) + if err != nil { + return false, err + } + + return true, nil } // CreateTranslation is the resolver for the createTranslation field. func (r *mutationResolver) CreateTranslation(ctx context.Context, input model.TranslationInput) (*model.Translation, error) { - panic(fmt.Errorf("not implemented: CreateTranslation - createTranslation")) + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + + workID, err := strconv.ParseUint(input.WorkID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid work ID: %v", err) + } + + // Create domain model + translation := &domain.Translation{ + Title: input.Name, + Language: input.Language, + TranslatableID: uint(workID), + TranslatableType: "Work", + } + if input.Content != nil { + translation.Content = *input.Content + } + + // Call translation service + err = r.App.TranslationRepo.Create(ctx, translation) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Translation{ + ID: fmt.Sprintf("%d", translation.ID), + Name: translation.Title, + Language: translation.Language, + Content: &translation.Content, + WorkID: input.WorkID, + }, nil } // UpdateTranslation is the resolver for the updateTranslation field. func (r *mutationResolver) UpdateTranslation(ctx context.Context, id string, input model.TranslationInput) (*model.Translation, error) { - panic(fmt.Errorf("not implemented: UpdateTranslation - updateTranslation")) + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + + translationID, err := strconv.ParseUint(id, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid translation ID: %v", err) + } + + workID, err := strconv.ParseUint(input.WorkID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid work ID: %v", err) + } + + // Create domain model + translation := &domain.Translation{ + BaseModel: domain.BaseModel{ID: uint(translationID)}, + Title: input.Name, + Language: input.Language, + TranslatableID: uint(workID), + TranslatableType: "Work", + } + if input.Content != nil { + translation.Content = *input.Content + } + + // Call translation service + err = r.App.TranslationRepo.Update(ctx, translation) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Translation{ + ID: id, + Name: translation.Title, + Language: translation.Language, + Content: &translation.Content, + WorkID: input.WorkID, + }, nil } // DeleteTranslation is the resolver for the deleteTranslation field. func (r *mutationResolver) DeleteTranslation(ctx context.Context, id string) (bool, error) { - panic(fmt.Errorf("not implemented: DeleteTranslation - deleteTranslation")) + translationID, err := strconv.ParseUint(id, 10, 32) + if err != nil { + return false, fmt.Errorf("invalid translation ID: %v", err) + } + + err = r.App.TranslationRepo.Delete(ctx, uint(translationID)) + if err != nil { + return false, err + } + + return true, nil } // CreateAuthor is the resolver for the createAuthor field. func (r *mutationResolver) CreateAuthor(ctx context.Context, input model.AuthorInput) (*model.Author, error) { - panic(fmt.Errorf("not implemented: CreateAuthor - createAuthor")) + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + + // Create domain model + author := &domain.Author{ + Name: input.Name, + TranslatableModel: domain.TranslatableModel{ + Language: input.Language, + }, + } + + // Call author service + err := r.App.AuthorRepo.Create(ctx, author) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Author{ + ID: fmt.Sprintf("%d", author.ID), + Name: author.Name, + Language: author.Language, + }, nil } // UpdateAuthor is the resolver for the updateAuthor field. func (r *mutationResolver) UpdateAuthor(ctx context.Context, id string, input model.AuthorInput) (*model.Author, error) { - panic(fmt.Errorf("not implemented: UpdateAuthor - updateAuthor")) + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + + authorID, err := strconv.ParseUint(id, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid author ID: %v", err) + } + + // Create domain model + author := &domain.Author{ + TranslatableModel: domain.TranslatableModel{ + BaseModel: domain.BaseModel{ID: uint(authorID)}, + Language: input.Language, + }, + Name: input.Name, + } + + // Call author service + err = r.App.AuthorRepo.Update(ctx, author) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Author{ + ID: id, + Name: author.Name, + Language: author.Language, + }, nil } // DeleteAuthor is the resolver for the deleteAuthor field. func (r *mutationResolver) DeleteAuthor(ctx context.Context, id string) (bool, error) { - panic(fmt.Errorf("not implemented: DeleteAuthor - deleteAuthor")) + authorID, err := strconv.ParseUint(id, 10, 32) + if err != nil { + return false, fmt.Errorf("invalid author ID: %v", err) + } + + err = r.App.AuthorRepo.Delete(ctx, uint(authorID)) + if err != nil { + return false, err + } + + return true, nil } // UpdateUser is the resolver for the updateUser field. @@ -180,62 +387,566 @@ func (r *mutationResolver) DeleteUser(ctx context.Context, id string) (bool, err // CreateCollection is the resolver for the createCollection field. func (r *mutationResolver) CreateCollection(ctx context.Context, input model.CollectionInput) (*model.Collection, error) { - panic(fmt.Errorf("not implemented: CreateCollection - createCollection")) + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + + // Get user ID from context + userID, ok := platform_auth.GetUserIDFromContext(ctx) + if !ok { + return nil, fmt.Errorf("unauthorized") + } + + // Create domain model + collection := &domain.Collection{ + Name: input.Name, + UserID: userID, + } + if input.Description != nil { + collection.Description = *input.Description + } + + // Call collection repository + err := r.App.CollectionRepo.Create(ctx, collection) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Collection{ + ID: fmt.Sprintf("%d", collection.ID), + Name: collection.Name, + Description: &collection.Description, + User: &model.User{ + ID: fmt.Sprintf("%d", userID), + }, + }, nil } // UpdateCollection is the resolver for the updateCollection field. func (r *mutationResolver) UpdateCollection(ctx context.Context, id string, input model.CollectionInput) (*model.Collection, error) { - panic(fmt.Errorf("not implemented: UpdateCollection - updateCollection")) + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + + // Get user ID from context + userID, ok := platform_auth.GetUserIDFromContext(ctx) + if !ok { + return nil, fmt.Errorf("unauthorized") + } + + // Parse collection ID + collectionID, err := strconv.ParseUint(id, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid collection ID: %v", err) + } + + // Fetch the existing collection + collection, err := r.App.CollectionRepo.GetByID(ctx, uint(collectionID)) + if err != nil { + return nil, err + } + if collection == nil { + return nil, fmt.Errorf("collection not found") + } + + // Check ownership + if collection.UserID != userID { + return nil, fmt.Errorf("unauthorized") + } + + // Update fields + collection.Name = input.Name + if input.Description != nil { + collection.Description = *input.Description + } + + // Call collection repository + err = r.App.CollectionRepo.Update(ctx, collection) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Collection{ + ID: id, + Name: collection.Name, + Description: &collection.Description, + User: &model.User{ + ID: fmt.Sprintf("%d", userID), + }, + }, nil } // DeleteCollection is the resolver for the deleteCollection field. func (r *mutationResolver) DeleteCollection(ctx context.Context, id string) (bool, error) { - panic(fmt.Errorf("not implemented: DeleteCollection - deleteCollection")) + // Get user ID from context + userID, ok := platform_auth.GetUserIDFromContext(ctx) + if !ok { + return false, fmt.Errorf("unauthorized") + } + + // Parse collection ID + collectionID, err := strconv.ParseUint(id, 10, 32) + if err != nil { + return false, fmt.Errorf("invalid collection ID: %v", err) + } + + // Fetch the existing collection + collection, err := r.App.CollectionRepo.GetByID(ctx, uint(collectionID)) + if err != nil { + return false, err + } + if collection == nil { + return false, fmt.Errorf("collection not found") + } + + // Check ownership + if collection.UserID != userID { + return false, fmt.Errorf("unauthorized") + } + + // Call collection repository + err = r.App.CollectionRepo.Delete(ctx, uint(collectionID)) + if err != nil { + return false, err + } + + return true, nil } // AddWorkToCollection is the resolver for the addWorkToCollection field. func (r *mutationResolver) AddWorkToCollection(ctx context.Context, collectionID string, workID string) (*model.Collection, error) { - panic(fmt.Errorf("not implemented: AddWorkToCollection - addWorkToCollection")) + // Get user ID from context + userID, ok := platform_auth.GetUserIDFromContext(ctx) + if !ok { + return nil, fmt.Errorf("unauthorized") + } + + // Parse IDs + collID, err := strconv.ParseUint(collectionID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid collection ID: %v", err) + } + wID, err := strconv.ParseUint(workID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid work ID: %v", err) + } + + // Fetch the existing collection + collection, err := r.App.CollectionRepo.GetByID(ctx, uint(collID)) + if err != nil { + return nil, err + } + if collection == nil { + return nil, fmt.Errorf("collection not found") + } + + // Check ownership + if collection.UserID != userID { + return nil, fmt.Errorf("unauthorized") + } + + // Add work to collection + err = r.App.CollectionRepo.AddWorkToCollection(ctx, uint(collID), uint(wID)) + if err != nil { + return nil, err + } + + // Fetch the updated collection to return it + updatedCollection, err := r.App.CollectionRepo.GetByID(ctx, uint(collID)) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Collection{ + ID: collectionID, + Name: updatedCollection.Name, + Description: &updatedCollection.Description, + }, nil } // RemoveWorkFromCollection is the resolver for the removeWorkFromCollection field. func (r *mutationResolver) RemoveWorkFromCollection(ctx context.Context, collectionID string, workID string) (*model.Collection, error) { - panic(fmt.Errorf("not implemented: RemoveWorkFromCollection - removeWorkFromCollection")) + // Get user ID from context + userID, ok := platform_auth.GetUserIDFromContext(ctx) + if !ok { + return nil, fmt.Errorf("unauthorized") + } + + // Parse IDs + collID, err := strconv.ParseUint(collectionID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid collection ID: %v", err) + } + wID, err := strconv.ParseUint(workID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid work ID: %v", err) + } + + // Fetch the existing collection + collection, err := r.App.CollectionRepo.GetByID(ctx, uint(collID)) + if err != nil { + return nil, err + } + if collection == nil { + return nil, fmt.Errorf("collection not found") + } + + // Check ownership + if collection.UserID != userID { + return nil, fmt.Errorf("unauthorized") + } + + // Remove work from collection + err = r.App.CollectionRepo.RemoveWorkFromCollection(ctx, uint(collID), uint(wID)) + if err != nil { + return nil, err + } + + // Fetch the updated collection to return it + updatedCollection, err := r.App.CollectionRepo.GetByID(ctx, uint(collID)) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Collection{ + ID: collectionID, + Name: updatedCollection.Name, + Description: &updatedCollection.Description, + }, nil } // CreateComment is the resolver for the createComment field. func (r *mutationResolver) CreateComment(ctx context.Context, input model.CommentInput) (*model.Comment, error) { - panic(fmt.Errorf("not implemented: CreateComment - createComment")) + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + + // Custom validation + if (input.WorkID == nil && input.TranslationID == nil) || (input.WorkID != nil && input.TranslationID != nil) { + return nil, fmt.Errorf("must provide either workId or translationId, but not both") + } + + // Get user ID from context + userID, ok := platform_auth.GetUserIDFromContext(ctx) + if !ok { + return nil, fmt.Errorf("unauthorized") + } + + // Create domain model + comment := &domain.Comment{ + Text: input.Text, + UserID: userID, + } + if input.WorkID != nil { + workID, err := strconv.ParseUint(*input.WorkID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid work ID: %v", err) + } + wID := uint(workID) + comment.WorkID = &wID + } + if input.TranslationID != nil { + translationID, err := strconv.ParseUint(*input.TranslationID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid translation ID: %v", err) + } + tID := uint(translationID) + comment.TranslationID = &tID + } + if input.ParentCommentID != nil { + parentCommentID, err := strconv.ParseUint(*input.ParentCommentID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid parent comment ID: %v", err) + } + pID := uint(parentCommentID) + comment.ParentID = &pID + } + + // Call comment repository + err := r.App.CommentRepo.Create(ctx, comment) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Comment{ + ID: fmt.Sprintf("%d", comment.ID), + Text: comment.Text, + User: &model.User{ + ID: fmt.Sprintf("%d", userID), + }, + }, nil } // UpdateComment is the resolver for the updateComment field. func (r *mutationResolver) UpdateComment(ctx context.Context, id string, input model.CommentInput) (*model.Comment, error) { - panic(fmt.Errorf("not implemented: UpdateComment - updateComment")) + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + + // Get user ID from context + userID, ok := platform_auth.GetUserIDFromContext(ctx) + if !ok { + return nil, fmt.Errorf("unauthorized") + } + + // Parse comment ID + commentID, err := strconv.ParseUint(id, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid comment ID: %v", err) + } + + // Fetch the existing comment + comment, err := r.App.CommentRepo.GetByID(ctx, uint(commentID)) + if err != nil { + return nil, err + } + if comment == nil { + return nil, fmt.Errorf("comment not found") + } + + // Check ownership + if comment.UserID != userID { + return nil, fmt.Errorf("unauthorized") + } + + // Update fields + comment.Text = input.Text + + // Call comment repository + err = r.App.CommentRepo.Update(ctx, comment) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Comment{ + ID: id, + Text: comment.Text, + User: &model.User{ + ID: fmt.Sprintf("%d", userID), + }, + }, nil } // DeleteComment is the resolver for the deleteComment field. func (r *mutationResolver) DeleteComment(ctx context.Context, id string) (bool, error) { - panic(fmt.Errorf("not implemented: DeleteComment - deleteComment")) + // Get user ID from context + userID, ok := platform_auth.GetUserIDFromContext(ctx) + if !ok { + return false, fmt.Errorf("unauthorized") + } + + // Parse comment ID + commentID, err := strconv.ParseUint(id, 10, 32) + if err != nil { + return false, fmt.Errorf("invalid comment ID: %v", err) + } + + // Fetch the existing comment + comment, err := r.App.CommentRepo.GetByID(ctx, uint(commentID)) + if err != nil { + return false, err + } + if comment == nil { + return false, fmt.Errorf("comment not found") + } + + // Check ownership + if comment.UserID != userID { + return false, fmt.Errorf("unauthorized") + } + + // Call comment repository + err = r.App.CommentRepo.Delete(ctx, uint(commentID)) + if err != nil { + return false, err + } + + return true, nil } // CreateLike is the resolver for the createLike field. func (r *mutationResolver) CreateLike(ctx context.Context, input model.LikeInput) (*model.Like, error) { - panic(fmt.Errorf("not implemented: CreateLike - createLike")) + // Custom validation + if (input.WorkID == nil && input.TranslationID == nil && input.CommentID == nil) || + (input.WorkID != nil && input.TranslationID != nil) || + (input.WorkID != nil && input.CommentID != nil) || + (input.TranslationID != nil && input.CommentID != nil) { + return nil, fmt.Errorf("must provide exactly one of workId, translationId, or commentId") + } + + // Get user ID from context + userID, ok := platform_auth.GetUserIDFromContext(ctx) + if !ok { + return nil, fmt.Errorf("unauthorized") + } + + // Create domain model + like := &domain.Like{ + UserID: userID, + } + if input.WorkID != nil { + workID, err := strconv.ParseUint(*input.WorkID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid work ID: %v", err) + } + wID := uint(workID) + like.WorkID = &wID + } + if input.TranslationID != nil { + translationID, err := strconv.ParseUint(*input.TranslationID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid translation ID: %v", err) + } + tID := uint(translationID) + like.TranslationID = &tID + } + if input.CommentID != nil { + commentID, err := strconv.ParseUint(*input.CommentID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid comment ID: %v", err) + } + cID := uint(commentID) + like.CommentID = &cID + } + + // Call like repository + err := r.App.LikeRepo.Create(ctx, like) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Like{ + ID: fmt.Sprintf("%d", like.ID), + User: &model.User{ID: fmt.Sprintf("%d", userID)}, + }, nil } // DeleteLike is the resolver for the deleteLike field. func (r *mutationResolver) DeleteLike(ctx context.Context, id string) (bool, error) { - panic(fmt.Errorf("not implemented: DeleteLike - deleteLike")) + // Get user ID from context + userID, ok := platform_auth.GetUserIDFromContext(ctx) + if !ok { + return false, fmt.Errorf("unauthorized") + } + + // Parse like ID + likeID, err := strconv.ParseUint(id, 10, 32) + if err != nil { + return false, fmt.Errorf("invalid like ID: %v", err) + } + + // Fetch the existing like + like, err := r.App.LikeRepo.GetByID(ctx, uint(likeID)) + if err != nil { + return false, err + } + if like == nil { + return false, fmt.Errorf("like not found") + } + + // Check ownership + if like.UserID != userID { + return false, fmt.Errorf("unauthorized") + } + + // Call like repository + err = r.App.LikeRepo.Delete(ctx, uint(likeID)) + if err != nil { + return false, err + } + + return true, nil } // CreateBookmark is the resolver for the createBookmark field. func (r *mutationResolver) CreateBookmark(ctx context.Context, input model.BookmarkInput) (*model.Bookmark, error) { - panic(fmt.Errorf("not implemented: CreateBookmark - createBookmark")) + // Validate input + if _, err := govalidator.ValidateStruct(input); err != nil { + return nil, fmt.Errorf("invalid input: %w", err) + } + + // Get user ID from context + userID, ok := platform_auth.GetUserIDFromContext(ctx) + if !ok { + return nil, fmt.Errorf("unauthorized") + } + + // Parse work ID + workID, err := strconv.ParseUint(input.WorkID, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid work ID: %v", err) + } + + // Create domain model + bookmark := &domain.Bookmark{ + UserID: userID, + WorkID: uint(workID), + } + if input.Name != nil { + bookmark.Name = *input.Name + } + + // Call bookmark repository + err = r.App.BookmarkRepo.Create(ctx, bookmark) + if err != nil { + return nil, err + } + + // Convert to GraphQL model + return &model.Bookmark{ + ID: fmt.Sprintf("%d", bookmark.ID), + Name: &bookmark.Name, + User: &model.User{ID: fmt.Sprintf("%d", userID)}, + Work: &model.Work{ID: fmt.Sprintf("%d", workID)}, + }, nil } // DeleteBookmark is the resolver for the deleteBookmark field. func (r *mutationResolver) DeleteBookmark(ctx context.Context, id string) (bool, error) { - panic(fmt.Errorf("not implemented: DeleteBookmark - deleteBookmark")) + // Get user ID from context + userID, ok := platform_auth.GetUserIDFromContext(ctx) + if !ok { + return false, fmt.Errorf("unauthorized") + } + + // Parse bookmark ID + bookmarkID, err := strconv.ParseUint(id, 10, 32) + if err != nil { + return false, fmt.Errorf("invalid bookmark ID: %v", err) + } + + // Fetch the existing bookmark + bookmark, err := r.App.BookmarkRepo.GetByID(ctx, uint(bookmarkID)) + if err != nil { + return false, err + } + if bookmark == nil { + return false, fmt.Errorf("bookmark not found") + } + + // Check ownership + if bookmark.UserID != userID { + return false, fmt.Errorf("unauthorized") + } + + // Call bookmark repository + err = r.App.BookmarkRepo.Delete(ctx, uint(bookmarkID)) + if err != nil { + return false, err + } + + return true, nil } // CreateContribution is the resolver for the createContribution field. diff --git a/internal/app/app.go b/internal/app/app.go index 42799ea..2058590 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -32,4 +32,11 @@ type Application struct { SourceRepo domain.SourceRepository MonetizationQueries *monetization.MonetizationQueries MonetizationCommands *monetization.MonetizationCommands + TranslationRepo domain.TranslationRepository + CopyrightRepo domain.CopyrightRepository + MonetizationRepo domain.MonetizationRepository + CommentRepo domain.CommentRepository + LikeRepo domain.LikeRepository + BookmarkRepo domain.BookmarkRepository + CollectionRepo domain.CollectionRepository } diff --git a/internal/app/application_builder.go b/internal/app/application_builder.go index 9cb24c4..1cafa1c 100644 --- a/internal/app/application_builder.go +++ b/internal/app/application_builder.go @@ -148,7 +148,14 @@ func (b *ApplicationBuilder) BuildApplication() error { BookRepo: sql.NewBookRepository(b.dbConn), PublisherRepo: sql.NewPublisherRepository(b.dbConn), SourceRepo: sql.NewSourceRepository(b.dbConn), + TranslationRepo: translationRepo, MonetizationQueries: monetization.NewMonetizationQueries(sql.NewMonetizationRepository(b.dbConn), workRepo, authorRepo, bookRepo, publisherRepo, sourceRepo), + CopyrightRepo: copyrightRepo, + MonetizationRepo: sql.NewMonetizationRepository(b.dbConn), + CommentRepo: sql.NewCommentRepository(b.dbConn), + LikeRepo: sql.NewLikeRepository(b.dbConn), + BookmarkRepo: sql.NewBookmarkRepository(b.dbConn), + CollectionRepo: sql.NewCollectionRepository(b.dbConn), } log.LogInfo("Application layer initialized successfully") diff --git a/internal/data/sql/collection_repository.go b/internal/data/sql/collection_repository.go index 3c278b3..92d1a76 100644 --- a/internal/data/sql/collection_repository.go +++ b/internal/data/sql/collection_repository.go @@ -29,6 +29,24 @@ func (r *collectionRepository) ListByUserID(ctx context.Context, userID uint) ([ return collections, nil } +// AddWorkToCollection adds a work to a collection +func (r *collectionRepository) AddWorkToCollection(ctx context.Context, collectionID uint, workID uint) error { + collection := &domain.Collection{} + collection.ID = collectionID + work := &domain.Work{} + work.ID = workID + return r.db.WithContext(ctx).Model(collection).Association("Works").Append(work) +} + +// RemoveWorkFromCollection removes a work from a collection +func (r *collectionRepository) RemoveWorkFromCollection(ctx context.Context, collectionID uint, workID uint) error { + collection := &domain.Collection{} + collection.ID = collectionID + work := &domain.Work{} + work.ID = workID + return r.db.WithContext(ctx).Model(collection).Association("Works").Delete(work) +} + // ListPublic finds public collections func (r *collectionRepository) ListPublic(ctx context.Context) ([]domain.Collection, error) { var collections []domain.Collection diff --git a/internal/domain/interfaces.go b/internal/domain/interfaces.go index 1b7c231..9a110f4 100644 --- a/internal/domain/interfaces.go +++ b/internal/domain/interfaces.go @@ -80,6 +80,8 @@ type CollectionRepository interface { ListByUserID(ctx context.Context, userID uint) ([]Collection, error) ListPublic(ctx context.Context) ([]Collection, error) ListByWorkID(ctx context.Context, workID uint) ([]Collection, error) + AddWorkToCollection(ctx context.Context, collectionID uint, workID uint) error + RemoveWorkFromCollection(ctx context.Context, collectionID uint, workID uint) error } // CommentRepository defines CRUD methods specific to Comment. diff --git a/internal/testutil/integration_test_utils.go b/internal/testutil/integration_test_utils.go index 6c0514e..cd7c38e 100644 --- a/internal/testutil/integration_test_utils.go +++ b/internal/testutil/integration_test_utils.go @@ -28,6 +28,7 @@ import ( // IntegrationTestSuite provides a comprehensive test environment with either in-memory SQLite or mock repositories type IntegrationTestSuite struct { suite.Suite + App *app.Application DB *gorm.DB WorkRepo domain.WorkRepository UserRepo domain.UserRepository @@ -216,6 +217,39 @@ func (s *IntegrationTestSuite) setupServices() { jwtManager := auth_platform.NewJWTManager() s.AuthCommands = auth.NewAuthCommands(s.UserRepo, jwtManager) s.AuthQueries = auth.NewAuthQueries(s.UserRepo, jwtManager) + + copyrightCommands := copyright.NewCopyrightCommands(s.CopyrightRepo) + copyrightQueries := copyright.NewCopyrightQueries(s.CopyrightRepo, s.WorkRepo, s.AuthorRepo, s.BookRepo, s.PublisherRepo, s.SourceRepo) + + monetizationCommands := monetization.NewMonetizationCommands(s.MonetizationRepo) + monetizationQueries := monetization.NewMonetizationQueries(s.MonetizationRepo, s.WorkRepo, s.AuthorRepo, s.BookRepo, s.PublisherRepo, s.SourceRepo) + + s.App = &app.Application{ + WorkCommands: s.WorkCommands, + WorkQueries: s.WorkQueries, + AuthCommands: s.AuthCommands, + AuthQueries: s.AuthQueries, + CopyrightCommands: copyrightCommands, + CopyrightQueries: copyrightQueries, + Localization: s.Localization, + Search: search.NewIndexService(s.Localization, s.TranslationRepo), + MonetizationCommands: monetizationCommands, + MonetizationQueries: monetizationQueries, + AuthorRepo: s.AuthorRepo, + UserRepo: s.UserRepo, + TagRepo: s.TagRepo, + CategoryRepo: s.CategoryRepo, + BookRepo: s.BookRepo, + PublisherRepo: s.PublisherRepo, + SourceRepo: s.SourceRepo, + TranslationRepo: s.TranslationRepo, + CopyrightRepo: s.CopyrightRepo, + MonetizationRepo: s.MonetizationRepo, + CommentRepo: s.CommentRepo, + LikeRepo: s.LikeRepo, + BookmarkRepo: s.BookmarkRepo, + CollectionRepo: s.CollectionRepo, + } } // setupTestData creates initial test data @@ -322,48 +356,8 @@ func (s *IntegrationTestSuite) SetupTest() { // GetResolver returns a properly configured GraphQL resolver for testing func (s *IntegrationTestSuite) GetResolver() *graph.Resolver { - // Initialize repositories - workRepo := sql.NewWorkRepository(s.DB) - userRepo := sql.NewUserRepository(s.DB) - authorRepo := sql.NewAuthorRepository(s.DB) - translationRepo := sql.NewTranslationRepository(s.DB) - copyrightRepo := sql.NewCopyrightRepository(s.DB) - bookRepo := sql.NewBookRepository(s.DB) - publisherRepo := sql.NewPublisherRepository(s.DB) - sourceRepo := sql.NewSourceRepository(s.DB) - monetizationRepo := sql.NewMonetizationRepository(s.DB) - - // Initialize application services - workCommands := work.NewWorkCommands(workRepo, &MockAnalyzer{}) - workQueries := work.NewWorkQueries(workRepo) - - jwtManager := auth_platform.NewJWTManager() - authCommands := auth.NewAuthCommands(userRepo, jwtManager) - authQueries := auth.NewAuthQueries(userRepo, jwtManager) - - copyrightCommands := copyright.NewCopyrightCommands(copyrightRepo) - copyrightQueries := copyright.NewCopyrightQueries(copyrightRepo, workRepo, authorRepo, bookRepo, publisherRepo, sourceRepo) - - localizationService := localization.NewService(translationRepo) - - searchService := search.NewIndexService(localizationService, translationRepo) - - monetizationCommands := monetization.NewMonetizationCommands(monetizationRepo) - monetizationQueries := monetization.NewMonetizationQueries(monetizationRepo, workRepo, authorRepo, bookRepo, publisherRepo, sourceRepo) - return &graph.Resolver{ - App: &app.Application{ - WorkCommands: workCommands, - WorkQueries: workQueries, - AuthCommands: authCommands, - AuthQueries: authQueries, - CopyrightCommands: copyrightCommands, - CopyrightQueries: copyrightQueries, - Localization: localizationService, - Search: searchService, - MonetizationCommands: monetizationCommands, - MonetizationQueries: monetizationQueries, - }, + App: s.App, } } @@ -405,3 +399,21 @@ func (s *IntegrationTestSuite) CleanupTestData() { s.DB.Exec("DELETE FROM users") } } + +// CreateAuthenticatedUser creates a user and returns the user and an auth token +func (s *IntegrationTestSuite) CreateAuthenticatedUser(username, email string, role domain.UserRole) (*domain.User, string) { + user := &domain.User{ + Username: username, + Email: email, + Role: role, + Password: "password", // Not used for token generation, but good to have + } + err := s.UserRepo.Create(context.Background(), user) + s.Require().NoError(err) + + jwtManager := auth_platform.NewJWTManager() + token, err := jwtManager.GenerateToken(user) + s.Require().NoError(err) + + return user, token +}