From f45b5940cb39a97fa1078023596b081f7d1b78e8 Mon Sep 17 00:00:00 2001 From: cowsed Date: Thu, 30 Jul 2026 16:47:15 -0400 Subject: [PATCH 01/22] testing db on demand --- cmd/make-backend/main.go | 3 +- go.mod | 53 ++++++++++++++++++ go.sum | 96 ++++++++++++++++++++++++++++++++ internal/database/models/zone.go | 1 + internal/database/setup.go | 51 +++++++++++++++++ 5 files changed, 203 insertions(+), 1 deletion(-) diff --git a/cmd/make-backend/main.go b/cmd/make-backend/main.go index 5e03d452..98aeb365 100644 --- a/cmd/make-backend/main.go +++ b/cmd/make-backend/main.go @@ -60,10 +60,11 @@ func main() { } // Database - db, err := database.SetupDB() + db, df, err := database.SetupTestDB() if err != nil { log.Fatalf("Failed to setup DB: %s", err) } + defer df() defer db.Close() store := database.NewStore(db) diff --git a/go.mod b/go.mod index 225ad6bf..03fad0b2 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,59 @@ require ( github.com/vektah/gqlparser/v2 v2.5.35 ) +require ( + dario.cat/mergo v1.0.2 // indirect + github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/containerd/errdefs v1.0.0 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/go-connections v0.7.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/ebitengine/purego v0.10.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/klauspost/compress v1.18.5 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.10 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/go-archive v0.2.0 // indirect + github.com/moby/moby/api v1.55.0 // indirect + github.com/moby/moby/client v0.5.0 // indirect + github.com/moby/patternmatcher v0.6.1 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/moby/sys/user v0.4.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect + github.com/moby/term v0.5.2 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect + github.com/shirou/gopsutil/v4 v4.26.5 // indirect + github.com/sirupsen/logrus v1.9.4 // indirect + github.com/stretchr/testify v1.11.1 // indirect + github.com/testcontainers/testcontainers-go v0.43.0 // indirect + github.com/testcontainers/testcontainers-go/modules/postgres v0.43.0 // indirect + github.com/tklauser/go-sysconf v0.3.16 // indirect + github.com/tklauser/numcpus v0.11.0 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect + go.opentelemetry.io/otel v1.43.0 // indirect + go.opentelemetry.io/otel/metric v1.43.0 // indirect + go.opentelemetry.io/otel/trace v1.43.0 // indirect + golang.org/x/sys v0.46.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + require ( github.com/agnivade/levenshtein v1.2.1 // indirect github.com/alexedwards/scs/postgresstore v0.0.0-20251002162104-209de6e426de diff --git a/go.sum b/go.sum index b31c8379..c66fea2a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,11 @@ +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= github.com/99designs/gqlgen v0.17.93 h1:oqLJS61cSp3YraGIowQPtyrUYfC8LpUFpQTeoFHAVKQ= github.com/99designs/gqlgen v0.17.93/go.mod h1:cXtBb9IeSiGflq69Io7DIAZY4JQJRinpIUgkNm8jEU0= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM= github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= github.com/alexedwards/scs/postgresstore v0.0.0-20251002162104-209de6e426de h1:LDrMkjj4OCCQsq9SvIPQV1l3leMxqXZTCTxDFwMrqTE= @@ -11,8 +17,22 @@ github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdK github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= github.com/beevik/etree v1.5.0 h1:iaQZFSDS+3kYZiGoc9uKeOkUY3nYMXOKLl6KIJxiJWs= github.com/beevik/etree v1.5.0/go.mod h1:gPNJNaBGVZ9AwsidazFZyygnd+0pAU38N4D+WemwKNs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/coder/websocket v1.8.15 h1:6B2JPeOGlpff2Uz6vOEH1Vzpi0iUz20A+lPVhPHtNUA= github.com/coder/websocket v1.8.15/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/crewjam/saml v0.5.1 h1:g+mfp0CrLuLRZCK793PgJcZeg5dS/0CDwoeAX2zcwNI= github.com/crewjam/saml v0.5.1/go.mod h1:r0fDkmFe5URDgPrmtH0IYokva6fac3AUdstiPhyEolQ= @@ -21,14 +41,32 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c= +github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU= +github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/google/go-cmp v0.5.6/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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -44,6 +82,8 @@ github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwA github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= +github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= +github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -53,21 +93,49 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.4.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ= github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU= github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To= github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs= github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8= +github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU= +github.com/moby/moby/api v1.55.0 h1:2/sexvQyqIWS8pRSCFddBfpW2qE7vR7FCL+vN8pxwMc= +github.com/moby/moby/api v1.55.0/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= +github.com/moby/moby/client v0.5.0 h1:5XhyPk2fuOWf6RlSFa3MkIIgDZkF25xToXW8Q/BH7cc= +github.com/moby/moby/client v0.5.0/go.mod h1:rcVpF8ncl9vo5gaIBdol6CnbEtSj1uxMvEV/UrykF/s= +github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U= +github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= +github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= +github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= +github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/mochi-mqtt/server/v2 v2.7.9 h1:y0g4vrSLAag7T07l2oCzOa/+nKVLoazKEWAArwqBNYI= github.com/mochi-mqtt/server/v2 v2.7.9/go.mod h1:lZD3j35AVNqJL5cezlnSkuG05c0FCHSsfAKSPBOSbqc= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/pressly/goose/v3 v3.27.2 h1:FjKNzcmMdGrQlSIu5alMSmakQtJFBgtw+A0bb1p/LC8= github.com/pressly/goose/v3 v3.27.2/go.mod h1:qWW+/8dkVtJYjJrbIpwD5xxnEJTUKvxkQ9JKQp9LaIM= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -80,16 +148,40 @@ github.com/russellhaering/goxmldsig v1.4.0 h1:8UcDh/xGyQiyrW+Fq5t8f+l2DLB1+zlhYz github.com/russellhaering/goxmldsig v1.4.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw= github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas= +github.com/shirou/gopsutil/v4 v4.26.5 h1:RPcBXkpz7kOj9PqGFQOlBPZHsyaPvPVQc098y9RmCNM= +github.com/shirou/gopsutil/v4 v4.26.5/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/sosodev/duration v1.4.0 h1:35ed0KiVFriGHHzZZJaZLgmTEEICIyt8Sx0RQfj9IjE= github.com/sosodev/duration v1.4.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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/testcontainers/testcontainers-go v0.43.0 h1:oEQx5MW2DGd9z3AeEQfB2lPM0eLs7ztyaGRu75bFo5A= +github.com/testcontainers/testcontainers-go v0.43.0/go.mod h1:+VxkT2NQnKOZPKi6praMuMKYHYyOGXr0XSBSlSMCzFo= +github.com/testcontainers/testcontainers-go/modules/postgres v0.43.0 h1:ShNOFYAF4lKHvdIG258hi69bSxC88uXnxJkJvNs/IVs= +github.com/testcontainers/testcontainers-go/modules/postgres v0.43.0/go.mod h1:vdq5/RqmGfWeefzyfcVI/pID1rzmc1TDvqXa15bPJks= +github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= +github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= +github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= +github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= github.com/urfave/cli/v3 v3.10.0 h1:0aU8yOObVDMkM13Cj4G+zb4P0PdeJMec65f81Ak1ioM= github.com/urfave/cli/v3 v3.10.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso= github.com/vektah/gqlparser/v2 v2.5.35 h1:LEr/wXnTKkOqNn+4tNClYclksXN2781VoBFzzFW51Dk= github.com/vektah/gqlparser/v2 v2.5.35/go.mod h1:cAJ9qwVgPaUkWv6Gn8vn0mqOE0Ui5Pn56wNy5396XWo= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= @@ -102,12 +194,16 @@ golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= golang.org/x/tools v0.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk= golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/database/models/zone.go b/internal/database/models/zone.go index 370ee8ff..18cd275c 100644 --- a/internal/database/models/zone.go +++ b/internal/database/models/zone.go @@ -1,5 +1,6 @@ package models +// a zone is a thing type Zone struct { Id int MakerspaceId int diff --git a/internal/database/setup.go b/internal/database/setup.go index 027b047a..37717f1a 100644 --- a/internal/database/setup.go +++ b/internal/database/setup.go @@ -1,15 +1,66 @@ package database import ( + "context" "database/sql" "fmt" "log" + "log/slog" "os" _ "github.com/lib/pq" "github.com/pressly/goose/v3" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/postgres" ) +func SetupTestDB() (*sql.DB, func(), error) { + ctx := context.Background() + + dbName := "testdb" + dbUser := "test_user" + dbPassword := "test_password" + + postgresContainer, err := postgres.Run(ctx, + "postgres:16-alpine", + // postgres.WithInitScripts(filepath.Join("testdata", "init-user-db.sh")), + // postgres.WithConfigFile(filepath.Join("testdata", "my-postgres.conf")), + postgres.WithDatabase(dbName), + postgres.WithUsername(dbUser), + postgres.WithPassword(dbPassword), + postgres.BasicWaitStrategies(), + ) + deferer := func() { + if err := testcontainers.TerminateContainer(postgresContainer); err != nil { + log.Printf("failed to terminate container: %s", err) + } + } + if err != nil { + log.Printf("failed to start container: %s", err) + return nil, func() {}, err + } + + connStr := postgresContainer.MustConnectionString(ctx, "sslmode=disable") + slog.Info("connecting to test postgres", "conn", connStr) + db, err := sql.Open("postgres", connStr) + if err != nil { + log.Fatal(err) + } + + if err := db.Ping(); err != nil { + return nil, deferer, err + } + + slog.Info("Pinged DB") + err = migrateDB(db) + if err != nil { + return db, deferer, err + } + + return db, deferer, nil + +} + func SetupDB() (*sql.DB, error) { db, err := createDB() if err != nil { From 4b571558b07ddf5f1a210ca0763efe99154ac6b2 Mon Sep 17 00:00:00 2001 From: cowsed Date: Mon, 10 Aug 2026 09:26:57 -0400 Subject: [PATCH 02/22] graphql for groups init --- internal/database/repos/group_repo.go | 41 +- internal/gql/generated.go | 1004 ++++++++++++++++++++- internal/gql/resolvers/group.resolvers.go | 65 ++ internal/gql/schema/group.graphqls | 37 + 4 files changed, 1118 insertions(+), 29 deletions(-) create mode 100644 internal/gql/resolvers/group.resolvers.go create mode 100644 internal/gql/schema/group.graphqls diff --git a/internal/database/repos/group_repo.go b/internal/database/repos/group_repo.go index dc47d320..5f910d96 100644 --- a/internal/database/repos/group_repo.go +++ b/internal/database/repos/group_repo.go @@ -26,6 +26,8 @@ type GroupRepository interface { GetDirectGroupMembers(ctx context.Context, groupId int) ([]models.MembershipToGroup, error) IsUserInGroup(ctx context.Context, userId int, groupId int) (bool, error) + + AllGroupsUserIsMemberOf(ctx context.Context, userId int) ([]models.MembershipToUser, error) IsUserInGroupDirectly(ctx context.Context, userId int, groupId int) (bool, error) // add a user to a group AddUserToGroup(ctx context.Context, userId int, groupId int, perms models.GroupViewPermission) error @@ -33,20 +35,40 @@ type GroupRepository interface { // return true if removed, false if the user was not removed from that group RemoveUserFromGroup(ctx context.Context, userId int, groupId int) (bool, error) + CanUserManageGroup(ctx context.Context, managerUser, managedGroup int) (bool, error) CanGroupManageGroup(ctx context.Context, managerGroup, managedGroup int) (bool, error) AllGroupsGroupCanManage(ctx context.Context, userId int) ([]int, error) AllGroupsVisibleToGroup(ctx context.Context, groupId int) ([]int, error) - AllGroupsUserIsMemberOf(ctx context.Context, userId int) ([]models.MembershipToUser, error) AllGroupsUserCanManage(ctx context.Context, userId int) ([]int, error) AllGroupsUserVisibleToUser(ctx context.Context, userId int) ([]int, error) + IsGroupVisibleToUser(ctx context.Context, userId int, groupId int) (bool, models.GroupViewPermission, error) } type GroupRepo struct { DB *sql.DB } +func (g *GroupRepo) IsGroupVisibleToUser(ctx context.Context, userId int, groupId int) (bool, models.GroupViewPermission, error) { + // if can manage -> see all + canManage, err := g.CanUserManageGroup(ctx, userId, groupId) + if err != nil { + return false, models.GroupViewPermission_SeeNone, fmt.Errorf("failed to check if group is visible to user: %w", err) + + } + if canManage { + return true, models.GroupViewPermission_SeeAll, nil + } + // if inside + + // if see none -> false, see none + // if see some -> true, see self + // if see all -> true, see all + panic("unimplemented") + +} + func (g *GroupRepo) AddSubgroupToGroup(ctx context.Context, subgroupID, supergroupID int, permissions models.GroupViewPermission) error { query := `INSERT INTO group_direct_subgroups (group_id, subgroup_id, view_permission) VALUES ($1, $2, $3)` @@ -229,6 +251,23 @@ func (g *GroupRepo) CanGroupManageGroup(ctx context.Context, managerGroup int, m return exists, nil } +func (g *GroupRepo) CanUserManageGroup(ctx context.Context, managerUser int, managedGroup int) (bool, error) { + var exists bool + + query := ` + SELECT EXISTS(SELECT 1 + from group_management gm + left join group_membership m on m.group_id = gm.manager_group_id + where m.user_id = $1 and gm.group_id = $2) + ` + err := g.DB.QueryRow(query, managerUser, managedGroup).Scan(&exists) + + if err != nil { + return false, err + } + return exists, nil +} + func (g *GroupRepo) IsUserInGroup(ctx context.Context, userId int, groupId int) (bool, error) { var exists bool diff --git a/internal/gql/generated.go b/internal/gql/generated.go index 6d667d6f..a4b9d222 100644 --- a/internal/gql/generated.go +++ b/internal/gql/generated.go @@ -152,6 +152,13 @@ type ComplexityRoot struct { Name func(childComplexity int) int } + Group struct { + Description func(childComplexity int) int + Id func(childComplexity int) int + ManagerId func(childComplexity int) int + Name func(childComplexity int) int + } + Hold struct { CreateDate func(childComplexity int) int CreatorId func(childComplexity int) int @@ -186,6 +193,11 @@ type ComplexityRoot struct { Zones func(childComplexity int) int } + MembershipToGroup struct { + UserId func(childComplexity int) int + ViewPermission func(childComplexity int) int + } + Mutation struct { CreateMakerspace func(childComplexity int, name string, hidden bool) int DeleteMakerspace func(childComplexity int, id int) int @@ -213,13 +225,19 @@ type ComplexityRoot struct { } Query struct { - AccessDevice func(childComplexity int, id int) int - CurrentUser func(childComplexity int) int - Device func(childComplexity int, id int) int - Makerspace func(childComplexity int, id int) int - User func(childComplexity int, id int) int - Zone func(childComplexity int, id int) int - ZonesByMakerspaceID func(childComplexity int, makerspaceID int) int + AccessDevice func(childComplexity int, id int) int + CanGroupManageGroup func(childComplexity int, managerID int, groupID int) int + CanUserManageGroup func(childComplexity int, managerID int, groupID int) int + CurrentUser func(childComplexity int) int + Device func(childComplexity int, id int) int + GroupByID func(childComplexity int, id int) int + IsUserInGroup func(childComplexity int, userID int, groupID int) int + IsUserInGroupDirectly func(childComplexity int, userID int, groupID int) int + Makerspace func(childComplexity int, id int) int + MembersOfGroup func(childComplexity int, groupID int) int + User func(childComplexity int, id int) int + Zone func(childComplexity int, id int) int + ZonesByMakerspaceID func(childComplexity int, makerspaceID int) int } Reservation struct { @@ -324,6 +342,12 @@ type QueryResolver interface { Makerspace(ctx context.Context, id int) (*models.Makerspace, error) Device(ctx context.Context, id int) (*models.Device, error) AccessDevice(ctx context.Context, id int) (*models.AccessDevice, error) + GroupByID(ctx context.Context, id int) (*models.Group, error) + MembersOfGroup(ctx context.Context, groupID int) ([]*models.MembershipToGroup, error) + IsUserInGroup(ctx context.Context, userID int, groupID int) (bool, error) + IsUserInGroupDirectly(ctx context.Context, userID int, groupID int) (bool, error) + CanGroupManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) + CanUserManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) User(ctx context.Context, id int) (*models.User, error) CurrentUser(ctx context.Context) (*models.User, error) Zone(ctx context.Context, id int) (*models.Zone, error) @@ -747,6 +771,31 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.ComplexityRoot.EquipmentInstance.Name(childComplexity), true + case "Group.description": + if e.ComplexityRoot.Group.Description == nil { + break + } + + return e.ComplexityRoot.Group.Description(childComplexity), true + case "Group.id": + if e.ComplexityRoot.Group.Id == nil { + break + } + + return e.ComplexityRoot.Group.Id(childComplexity), true + case "Group.manager_id": + if e.ComplexityRoot.Group.ManagerId == nil { + break + } + + return e.ComplexityRoot.Group.ManagerId(childComplexity), true + case "Group.name": + if e.ComplexityRoot.Group.Name == nil { + break + } + + return e.ComplexityRoot.Group.Name(childComplexity), true + case "Hold.create_date": if e.ComplexityRoot.Hold.CreateDate == nil { break @@ -883,6 +932,19 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.ComplexityRoot.Makerspace.Zones(childComplexity), true + case "MembershipToGroup.UserId": + if e.ComplexityRoot.MembershipToGroup.UserId == nil { + break + } + + return e.ComplexityRoot.MembershipToGroup.UserId(childComplexity), true + case "MembershipToGroup.ViewPermission": + if e.ComplexityRoot.MembershipToGroup.ViewPermission == nil { + break + } + + return e.ComplexityRoot.MembershipToGroup.ViewPermission(childComplexity), true + case "Mutation.createMakerspace": if e.ComplexityRoot.Mutation.CreateMakerspace == nil { break @@ -992,6 +1054,28 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Query.AccessDevice(childComplexity, args["id"].(int)), true + case "Query.canGroupManageGroup": + if e.ComplexityRoot.Query.CanGroupManageGroup == nil { + break + } + + args, err := ec.field_Query_canGroupManageGroup_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.CanGroupManageGroup(childComplexity, args["managerID"].(int), args["groupID"].(int)), true + case "Query.canUserManageGroup": + if e.ComplexityRoot.Query.CanUserManageGroup == nil { + break + } + + args, err := ec.field_Query_canUserManageGroup_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.CanUserManageGroup(childComplexity, args["managerID"].(int), args["groupID"].(int)), true case "Query.currentUser": if e.ComplexityRoot.Query.CurrentUser == nil { break @@ -1009,7 +1093,40 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Query.Device(childComplexity, args["id"].(int)), true + case "Query.groupById": + if e.ComplexityRoot.Query.GroupByID == nil { + break + } + + args, err := ec.field_Query_groupById_args(ctx, rawArgs) + if err != nil { + return 0, false + } + return e.ComplexityRoot.Query.GroupByID(childComplexity, args["id"].(int)), true + + case "Query.isUserInGroup": + if e.ComplexityRoot.Query.IsUserInGroup == nil { + break + } + + args, err := ec.field_Query_isUserInGroup_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.IsUserInGroup(childComplexity, args["userID"].(int), args["groupID"].(int)), true + case "Query.isUserInGroupDirectly": + if e.ComplexityRoot.Query.IsUserInGroupDirectly == nil { + break + } + + args, err := ec.field_Query_isUserInGroupDirectly_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.IsUserInGroupDirectly(childComplexity, args["userID"].(int), args["groupID"].(int)), true case "Query.makerspace": if e.ComplexityRoot.Query.Makerspace == nil { break @@ -1021,6 +1138,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Query.Makerspace(childComplexity, args["id"].(int)), true + case "Query.membersOfGroup": + if e.ComplexityRoot.Query.MembersOfGroup == nil { + break + } + + args, err := ec.field_Query_membersOfGroup_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.MembersOfGroup(childComplexity, args["groupID"].(int)), true case "Query.user": if e.ComplexityRoot.Query.User == nil { break @@ -1457,7 +1585,7 @@ func newExecutionContext( } } -//go:embed "schema/access_channel.graphqls" "schema/announcement.graphqls" "schema/card.graphqls" "schema/device.graphqls" "schema/equipment.graphqls" "schema/hold.graphqls" "schema/hours.graphqls" "schema/image.graphqls" "schema/link.graphqls" "schema/makerspace.graphqls" "schema/organization.graphqls" "schema/reservation.graphqls" "schema/restriction.graphqls" "schema/training.graphqls" "schema/user.graphqls" "schema/zones.graphqls" +//go:embed "schema/access_channel.graphqls" "schema/announcement.graphqls" "schema/card.graphqls" "schema/device.graphqls" "schema/equipment.graphqls" "schema/group.graphqls" "schema/hold.graphqls" "schema/hours.graphqls" "schema/image.graphqls" "schema/link.graphqls" "schema/makerspace.graphqls" "schema/organization.graphqls" "schema/reservation.graphqls" "schema/restriction.graphqls" "schema/training.graphqls" "schema/user.graphqls" "schema/zones.graphqls" var sourcesFS embed.FS func sourceData(filename string) string { @@ -1474,6 +1602,7 @@ var sources = []*ast.Source{ {Name: "schema/card.graphqls", Input: sourceData("schema/card.graphqls"), BuiltIn: false}, {Name: "schema/device.graphqls", Input: sourceData("schema/device.graphqls"), BuiltIn: false}, {Name: "schema/equipment.graphqls", Input: sourceData("schema/equipment.graphqls"), BuiltIn: false}, + {Name: "schema/group.graphqls", Input: sourceData("schema/group.graphqls"), BuiltIn: false}, {Name: "schema/hold.graphqls", Input: sourceData("schema/hold.graphqls"), BuiltIn: false}, {Name: "schema/hours.graphqls", Input: sourceData("schema/hours.graphqls"), BuiltIn: false}, {Name: "schema/image.graphqls", Input: sourceData("schema/image.graphqls"), BuiltIn: false}, @@ -1574,6 +1703,20 @@ func (ec *executionContext) childFields_Device(ctx context.Context, field graphq return nil, fmt.Errorf("no field named %q was found under type Device", field.Name) } +func (ec *executionContext) childFields_Group(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Group_id(ctx, field) + case "manager_id": + return ec.fieldContext_Group_manager_id(ctx, field) + case "name": + return ec.fieldContext_Group_name(ctx, field) + case "description": + return ec.fieldContext_Group_description(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Group", field.Name) +} + func (ec *executionContext) childFields_Makerspace(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "id": @@ -1600,6 +1743,16 @@ func (ec *executionContext) childFields_Makerspace(ctx context.Context, field gr return nil, fmt.Errorf("no field named %q was found under type Makerspace", field.Name) } +func (ec *executionContext) childFields_MembershipToGroup(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "UserId": + return ec.fieldContext_MembershipToGroup_UserId(ctx, field) + case "ViewPermission": + return ec.fieldContext_MembershipToGroup_ViewPermission(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type MembershipToGroup", field.Name) +} + func (ec *executionContext) childFields_OptionBlockOption(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "text": @@ -1834,6 +1987,50 @@ func (ec *executionContext) field_Query_accessDevice_args(ctx context.Context, r return args, nil } +func (ec *executionContext) field_Query_canGroupManageGroup_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, "managerID", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["managerID"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "groupID", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["groupID"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Query_canUserManageGroup_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, "managerID", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["managerID"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "groupID", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["groupID"] = arg1 + return args, nil +} + func (ec *executionContext) field_Query_device_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -1848,6 +2045,64 @@ func (ec *executionContext) field_Query_device_args(ctx context.Context, rawArgs return args, nil } +func (ec *executionContext) field_Query_groupById_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, "id", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_isUserInGroupDirectly_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, "userID", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["userID"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "groupID", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["groupID"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Query_isUserInGroup_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, "userID", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["userID"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "groupID", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["groupID"] = arg1 + return args, nil +} + func (ec *executionContext) field_Query_makerspace_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -1862,6 +2117,20 @@ func (ec *executionContext) field_Query_makerspace_args(ctx context.Context, raw return args, nil } +func (ec *executionContext) field_Query_membersOfGroup_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, "groupID", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["groupID"] = arg0 + return args, 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{} @@ -3503,6 +3772,98 @@ func (ec *executionContext) fieldContext_EquipmentInstance_access_channel_id(_ c return graphql.NewScalarFieldContext("EquipmentInstance", field, false, false, errors.New("field of type ID does not have child fields")) } +func (ec *executionContext) _Group_id(ctx context.Context, field graphql.CollectedField, obj *models.Group) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Group_id(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Id, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int) graphql.Marshaler { + return ec.marshalNID2int(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Group_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Group", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _Group_manager_id(ctx context.Context, field graphql.CollectedField, obj *models.Group) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Group_manager_id(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ManagerId, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int) graphql.Marshaler { + return ec.marshalNID2int(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Group_manager_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Group", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _Group_name(ctx context.Context, field graphql.CollectedField, obj *models.Group) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Group_name(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Name, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Group_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Group", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _Group_description(ctx context.Context, field graphql.CollectedField, obj *models.Group) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Group_description(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Description, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Group_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Group", field, false, false, errors.New("field of type String does not have child fields")) +} + func (ec *executionContext) _Hold_id(ctx context.Context, field graphql.CollectedField, obj *models.Hold) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -4018,17 +4379,16 @@ func (ec *executionContext) fieldContext_Makerspace_hours(_ context.Context, fie return graphql.NewScalarFieldContext("Makerspace", field, true, true, errors.New("field of type MakerspaceHours does not have child fields")) } -func (ec *executionContext) _Mutation_createMakerspace(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _MembershipToGroup_UserId(ctx context.Context, field graphql.CollectedField, obj *models.MembershipToGroup) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, ec.OperationContext, field, func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.fieldContext_Mutation_createMakerspace(ctx, field) + return ec.fieldContext_MembershipToGroup_UserId(ctx, field) }, func(ctx context.Context) (any, error) { - fc := graphql.GetFieldContext(ctx) - return ec.Resolvers.Mutation().CreateMakerspace(ctx, fc.Args["name"].(string), fc.Args["hidden"].(bool)) + return obj.UserId, nil }, nil, func(ctx context.Context, selections ast.SelectionSet, v int) graphql.Marshaler { @@ -4038,9 +4398,56 @@ func (ec *executionContext) _Mutation_createMakerspace(ctx context.Context, fiel true, ) } -func (ec *executionContext) fieldContext_Mutation_createMakerspace(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Mutation", +func (ec *executionContext) fieldContext_MembershipToGroup_UserId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("MembershipToGroup", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _MembershipToGroup_ViewPermission(ctx context.Context, field graphql.CollectedField, obj *models.MembershipToGroup) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_MembershipToGroup_ViewPermission(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ViewPermission, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v models.GroupViewPermission) graphql.Marshaler { + return ec.marshalNGroupViewPermission2makeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupViewPermission(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_MembershipToGroup_ViewPermission(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("MembershipToGroup", field, false, false, errors.New("field of type GroupViewPermission does not have child fields")) +} + +func (ec *executionContext) _Mutation_createMakerspace(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Mutation_createMakerspace(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Mutation().CreateMakerspace(ctx, fc.Args["name"].(string), fc.Args["hidden"].(bool)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int) graphql.Marshaler { + return ec.marshalNID2int(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Mutation_createMakerspace(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", Field: field, IsMethod: true, IsResolver: true, @@ -4452,17 +4859,281 @@ func (ec *executionContext) _Query_device(ctx context.Context, field graphql.Col return ec.marshalODevice2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐDevice(ctx, selections, v) }, true, - false, + false, + ) +} +func (ec *executionContext) fieldContext_Query_device(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Device(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_device_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_accessDevice(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_accessDevice(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().AccessDevice(ctx, fc.Args["id"].(int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *models.AccessDevice) graphql.Marshaler { + return ec.marshalOAccessDevice2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐAccessDevice(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Query_accessDevice(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_AccessDevice(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_accessDevice_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_groupById(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_groupById(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().GroupByID(ctx, fc.Args["id"].(int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *models.Group) graphql.Marshaler { + return ec.marshalNGroup2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroup(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_groupById(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Group(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_groupById_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_membersOfGroup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_membersOfGroup(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().MembersOfGroup(ctx, fc.Args["groupID"].(int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []*models.MembershipToGroup) graphql.Marshaler { + return ec.marshalNMembershipToGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐMembershipToGroupᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_membersOfGroup(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_MembershipToGroup(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_membersOfGroup_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_isUserInGroup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_isUserInGroup(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().IsUserInGroup(ctx, fc.Args["userID"].(int), fc.Args["groupID"].(int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_isUserInGroup(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_isUserInGroup_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_isUserInGroupDirectly(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_isUserInGroupDirectly(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().IsUserInGroupDirectly(ctx, fc.Args["userID"].(int), fc.Args["groupID"].(int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_isUserInGroupDirectly(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_isUserInGroupDirectly_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_canGroupManageGroup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_canGroupManageGroup(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().CanGroupManageGroup(ctx, fc.Args["managerID"].(int), fc.Args["groupID"].(int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, ) } -func (ec *executionContext) fieldContext_Query_device(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_canGroupManageGroup(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.childFields_Device(ctx, field) + return nil, errors.New("field of type Boolean does not have child fields") }, } defer func() { @@ -4472,41 +5143,41 @@ func (ec *executionContext) fieldContext_Query_device(ctx context.Context, field } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_device_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_canGroupManageGroup_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } return fc, nil } -func (ec *executionContext) _Query_accessDevice(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _Query_canUserManageGroup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, ec.OperationContext, field, func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.fieldContext_Query_accessDevice(ctx, field) + return ec.fieldContext_Query_canUserManageGroup(ctx, field) }, func(ctx context.Context) (any, error) { fc := graphql.GetFieldContext(ctx) - return ec.Resolvers.Query().AccessDevice(ctx, fc.Args["id"].(int)) + return ec.Resolvers.Query().CanUserManageGroup(ctx, fc.Args["managerID"].(int), fc.Args["groupID"].(int)) }, nil, - func(ctx context.Context, selections ast.SelectionSet, v *models.AccessDevice) graphql.Marshaler { - return ec.marshalOAccessDevice2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐAccessDevice(ctx, selections, v) + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) }, true, - false, + true, ) } -func (ec *executionContext) fieldContext_Query_accessDevice(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_canUserManageGroup(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.childFields_AccessDevice(ctx, field) + return nil, errors.New("field of type Boolean does not have child fields") }, } defer func() { @@ -4516,7 +5187,7 @@ func (ec *executionContext) fieldContext_Query_accessDevice(ctx context.Context, } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_accessDevice_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_canUserManageGroup_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } @@ -7848,6 +8519,59 @@ func (ec *executionContext) _EquipmentInstance(ctx context.Context, sel ast.Sele return out } +var groupImplementors = []string{"Group"} + +func (ec *executionContext) _Group(ctx context.Context, sel ast.SelectionSet, obj *models.Group) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, groupImplementors) + + out := graphql.NewFieldSet(fields) + deferredFieldSet := graphql.NewFieldSet(nil) + deferLabelToView := make(map[string]*graphql.FieldSetView) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Group") + case "id": + out.Values[i] = ec._Group_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "manager_id": + out.Values[i] = ec._Group_manager_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "name": + out.Values[i] = ec._Group_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "description": + out.Values[i] = ec._Group_description(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferLabelToView), math.MaxInt32))) + + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Defers: deferLabelToView, + Path: graphql.GetPath(ctx), + FieldSet: deferredFieldSet, + Context: ctx, + }) + + return out +} + var holdImplementors = []string{"Hold"} func (ec *executionContext) _Hold(ctx context.Context, sel ast.SelectionSet, obj *models.Hold) graphql.Marshaler { @@ -8156,6 +8880,49 @@ func (ec *executionContext) _Makerspace(ctx context.Context, sel ast.SelectionSe return out } +var membershipToGroupImplementors = []string{"MembershipToGroup"} + +func (ec *executionContext) _MembershipToGroup(ctx context.Context, sel ast.SelectionSet, obj *models.MembershipToGroup) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, membershipToGroupImplementors) + + out := graphql.NewFieldSet(fields) + deferredFieldSet := graphql.NewFieldSet(nil) + deferLabelToView := make(map[string]*graphql.FieldSetView) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("MembershipToGroup") + case "UserId": + out.Values[i] = ec._MembershipToGroup_UserId(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "ViewPermission": + out.Values[i] = ec._MembershipToGroup_ViewPermission(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferLabelToView), math.MaxInt32))) + + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Defers: deferLabelToView, + Path: graphql.GetPath(ctx), + FieldSet: deferredFieldSet, + Context: ctx, + }) + + return out +} + var mutationImplementors = []string{"Mutation"} func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { @@ -8488,6 +9255,138 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "groupById": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_groupById(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "membersOfGroup": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_membersOfGroup(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "isUserInGroup": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_isUserInGroup(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "isUserInGroupDirectly": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_isUserInGroupDirectly(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "canGroupManageGroup": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_canGroupManageGroup(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "canUserManageGroup": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_canUserManageGroup(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "user": field := field @@ -9654,6 +10553,29 @@ func (ec *executionContext) marshalNDevice2makeᚑbackendᚋinternalᚋdatabase return ec._Device(ctx, sel, &v) } +func (ec *executionContext) marshalNGroup2makeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroup(ctx context.Context, sel ast.SelectionSet, v models.Group) graphql.Marshaler { + return ec._Group(ctx, sel, &v) +} + +func (ec *executionContext) marshalNGroup2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroup(ctx context.Context, sel ast.SelectionSet, v *models.Group) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._Group(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNGroupViewPermission2makeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupViewPermission(ctx context.Context, v any) (models.GroupViewPermission, error) { + res, err := ec.unmarshalInputGroupViewPermission(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNGroupViewPermission2makeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupViewPermission(ctx context.Context, sel ast.SelectionSet, v models.GroupViewPermission) graphql.Marshaler { + return ec._GroupViewPermission(ctx, sel, &v) +} + func (ec *executionContext) unmarshalNID2int(ctx context.Context, v any) (int, error) { res, err := graphql.UnmarshalInt(v) return res, graphql.ErrorOnPath(ctx, err) @@ -9712,6 +10634,32 @@ func (ec *executionContext) marshalNMakerspaceHours2ᚕmakeᚑbackendᚋinternal return ret } +func (ec *executionContext) marshalNMembershipToGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐMembershipToGroupᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.MembershipToGroup) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalNMembershipToGroup2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐMembershipToGroup(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNMembershipToGroup2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐMembershipToGroup(ctx context.Context, sel ast.SelectionSet, v *models.MembershipToGroup) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._MembershipToGroup(ctx, sel, v) +} + func (ec *executionContext) marshalNOptionBlockOption2makeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐOptionBlockOption(ctx context.Context, sel ast.SelectionSet, v models.OptionBlockOption) graphql.Marshaler { return ec._OptionBlockOption(ctx, sel, &v) } diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go new file mode 100644 index 00000000..844ba278 --- /dev/null +++ b/internal/gql/resolvers/group.resolvers.go @@ -0,0 +1,65 @@ +package resolvers + +// 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.93 + +import ( + "context" + "fmt" + "make-backend/internal/auth" + "make-backend/internal/database/models" +) + +// GroupByID is the resolver for the groupById field. +func (r *queryResolver) GroupByID(ctx context.Context, id int) (*models.Group, error) { + userID := ctx.Value(auth.UserContextKey{}).(int) + + group, err := r.Store.Groups.GetGroupById(ctx, id) + if err != nil { + return nil, err + } + visible, how, err := r.Store.Groups.IsGroupVisibleToUser(ctx, userID, group.Id) + if err != nil { + return nil, err + } + if !visible || how != models.GroupViewPermission_SeeAll { + return nil, fmt.Errorf("group does not exist or user does not have permission to see it") + } + return group, nil +} + +// MembersOfGroup is the resolver for the membersOfGroup field. +func (r *queryResolver) MembersOfGroup(ctx context.Context, groupID int) ([]*models.MembershipToGroup, error) { + userID := ctx.Value(auth.UserContextKey{}).(int) + visible, how, err := r.Store.Groups.IsGroupVisibleToUser(ctx, userID, groupID) + if err != nil { + return nil, err + } + if !visible || how != models.GroupViewPermission_SeeAll { + return nil, fmt.Errorf("group does not exist or user does not have permission to see it") + } + + // return +} + +// IsUserInGroup is the resolver for the isUserInGroup field. +func (r *queryResolver) IsUserInGroup(ctx context.Context, userID int, groupID int) (bool, error) { + panic(fmt.Errorf("not implemented: IsUserInGroup - isUserInGroup")) +} + +// IsUserInGroupDirectly is the resolver for the isUserInGroupDirectly field. +func (r *queryResolver) IsUserInGroupDirectly(ctx context.Context, userID int, groupID int) (bool, error) { + panic(fmt.Errorf("not implemented: IsUserInGroupDirectly - isUserInGroupDirectly")) +} + +// CanGroupManageGroup is the resolver for the canGroupManageGroup field. +func (r *queryResolver) CanGroupManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) { + panic(fmt.Errorf("not implemented: CanGroupManageGroup - canGroupManageGroup")) +} + +// CanUserManageGroup is the resolver for the canUserManageGroup field. +func (r *queryResolver) CanUserManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) { + panic(fmt.Errorf("not implemented: CanUserManageGroup - canUserManageGroup")) +} diff --git a/internal/gql/schema/group.graphqls b/internal/gql/schema/group.graphqls new file mode 100644 index 00000000..1e8175c0 --- /dev/null +++ b/internal/gql/schema/group.graphqls @@ -0,0 +1,37 @@ + + + +type Group { + id: ID! + manager_id: ID! + name: String! + description: String! +} + + +enum GroupViewPermission { + SEE_NONE + SEE_SELF + SEE_ALL +} + + +type MembershipToGroup { + UserId: ID! + ViewPermission: GroupViewPermission! +} + + + + +extend type Query { + + groupById(id: ID!): Group! + + membersOfGroup(groupID: ID!): [MembershipToGroup!]! + isUserInGroup(userID: ID!, groupID: ID!): Boolean! + isUserInGroupDirectly(userID: ID!, groupID: ID!): Boolean! + + canGroupManageGroup(managerID: ID!, groupID: ID!): Boolean! + canUserManageGroup(managerID: ID!, groupID: ID!): Boolean! +} \ No newline at end of file From 96558de33c8907ef9fa7cab1e45193e5486ac28a Mon Sep 17 00:00:00 2001 From: cowsed Date: Mon, 10 Aug 2026 10:51:08 -0400 Subject: [PATCH 03/22] more graphql and db tests --- cmd/make-backend/main.go | 3 +- go.mod | 4 +- go.sum | 36 ++- internal/database/group_test.go | 280 ++++++++++++++++++++++ internal/database/models/group.go | 39 +++ internal/database/setup.go | 51 ---- internal/gql/generated.go | 5 +- internal/gql/resolvers/group.resolvers.go | 8 +- 8 files changed, 364 insertions(+), 62 deletions(-) create mode 100644 internal/database/group_test.go diff --git a/cmd/make-backend/main.go b/cmd/make-backend/main.go index 98aeb365..5e03d452 100644 --- a/cmd/make-backend/main.go +++ b/cmd/make-backend/main.go @@ -60,11 +60,10 @@ func main() { } // Database - db, df, err := database.SetupTestDB() + db, err := database.SetupDB() if err != nil { log.Fatalf("Failed to setup DB: %s", err) } - defer df() defer db.Close() store := database.NewStore(db) diff --git a/go.mod b/go.mod index 03fad0b2..b5f2031f 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,8 @@ require ( github.com/joho/godotenv v1.5.1 github.com/lib/pq v1.12.3 github.com/pressly/goose/v3 v3.27.2 + github.com/testcontainers/testcontainers-go v0.43.0 + github.com/testcontainers/testcontainers-go/modules/postgres v0.43.0 github.com/vektah/gqlparser/v2 v2.5.35 ) @@ -50,8 +52,6 @@ require ( github.com/shirou/gopsutil/v4 v4.26.5 // indirect github.com/sirupsen/logrus v1.9.4 // indirect github.com/stretchr/testify v1.11.1 // indirect - github.com/testcontainers/testcontainers-go v0.43.0 // indirect - github.com/testcontainers/testcontainers-go/modules/postgres v0.43.0 // indirect github.com/tklauser/go-sysconf v0.3.16 // indirect github.com/tklauser/numcpus v0.11.0 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect diff --git a/go.sum b/go.sum index c66fea2a..93a214ed 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= github.com/99designs/gqlgen v0.17.93 h1:oqLJS61cSp3YraGIowQPtyrUYfC8LpUFpQTeoFHAVKQ= github.com/99designs/gqlgen v0.17.93/go.mod h1:cXtBb9IeSiGflq69Io7DIAZY4JQJRinpIUgkNm8jEU0= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -34,6 +36,8 @@ github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7np github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/crewjam/saml v0.5.1 h1:g+mfp0CrLuLRZCK793PgJcZeg5dS/0CDwoeAX2zcwNI= github.com/crewjam/saml v0.5.1/go.mod h1:r0fDkmFe5URDgPrmtH0IYokva6fac3AUdstiPhyEolQ= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -67,14 +71,22 @@ github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7Lk github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/google/go-cmp v0.5.6/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.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +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.10.0 h1:VhSvgU2jSli8o3AqIEOTJr7rZwAEUVo4E4XhR94Zfr0= +github.com/jackc/pgx/v5 v5.10.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= +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/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= @@ -87,8 +99,11 @@ github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.4.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ= @@ -101,6 +116,8 @@ github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To= github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs= github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= +github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI= +github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o= github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= @@ -142,6 +159,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94 github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/russellhaering/goxmldsig v1.4.0 h1:8UcDh/xGyQiyrW+Fq5t8f+l2DLB1+zlhYzkPUJ7Qhys= @@ -155,6 +174,8 @@ github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC4 github.com/sosodev/duration v1.4.0 h1:35ed0KiVFriGHHzZZJaZLgmTEEICIyt8Sx0RQfj9IjE= github.com/sosodev/duration v1.4.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= @@ -180,6 +201,10 @@ go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -199,6 +224,8 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= golang.org/x/tools v0.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk= @@ -206,6 +233,7 @@ golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -214,6 +242,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= modernc.org/libc v1.73.4 h1:+ra4Ui8ngyt8HDcO1FTDPWlkAh6yOdaO2yAoh8MddQA= modernc.org/libc v1.73.4/go.mod h1:DXZ3eO8qMCNn2SnmTNCiC71nJ9Rcq3PsnpU6Vc4rWK8= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= @@ -222,3 +252,5 @@ modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= modernc.org/sqlite v1.53.0 h1:20WG8N9q4ji/dEqGk4uiI0c6OPjSeLTNYGFCc3+7c1M= modernc.org/sqlite v1.53.0/go.mod h1:xoEpOIpGrgT48H5iiyt/YXPCZPEzlfmfFwtk8Lklw8s= +pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= +pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= diff --git a/internal/database/group_test.go b/internal/database/group_test.go new file mode 100644 index 00000000..4e2305c2 --- /dev/null +++ b/internal/database/group_test.go @@ -0,0 +1,280 @@ +package database + +import ( + "context" + "database/sql" + "embed" + "fmt" + "log" + "log/slog" + "make-backend/internal/database/models" + "sync" + "testing" + + "github.com/pressly/goose/v3" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/postgres" +) + +type testContext struct { + users []struct { + id int + email string + } + beatlesMusicians models.Group + beatlesManagers models.Group + brits models.Group +} + +var localContext testContext = testContext{ + users: []struct { + id int + email string + }{ + {email: "brian@beatles.com"}, + {email: "john@beatles.com"}, + {email: "paul@beatles.com"}, + {email: "george@beatles.com"}, + {email: "ringo@beatles.com"}, + }, +} + +func setupTestDB(t *testing.T) (*sql.DB, func(), error) { + ctx := context.Background() + + dbName := "testdb" + dbUser := "test_user" + dbPassword := "test_password" + + postgresContainer, err := postgres.Run(ctx, + "postgres:16-alpine", + postgres.WithDatabase(dbName), + postgres.WithUsername(dbUser), + postgres.WithPassword(dbPassword), + postgres.BasicWaitStrategies(), + ) + deferer := func() { + if err := testcontainers.TerminateContainer(postgresContainer); err != nil { + t.Logf("failed to terminate container: %s", err) + } + } + if err != nil { + t.Logf("failed to start container: %s", err) + return nil, func() {}, err + } + + connStr := postgresContainer.MustConnectionString(ctx, "sslmode=disable") + slog.Info("connecting to test postgres", "conn", connStr) + + db, err := sql.Open("postgres", connStr) + if err != nil { + log.Fatal(err) + } + + if err := db.Ping(); err != nil { + return nil, deferer, err + } + + err = migrateTestDB(t, db) + if err != nil { + return db, deferer, err + } + + store := NewStore(db) + fillTestData(t, store) + + return db, deferer, nil + +} + +//go:embed migrations/*.sql +var testEmbedMigrations embed.FS + +func migrateTestDB(t *testing.T, db *sql.DB) error { + // Migrations + t.Log("Running migrations...") + goose.SetBaseFS(testEmbedMigrations) + if err := goose.SetDialect("postgres"); err != nil { + return fmt.Errorf("Failed to set goose dialect: %w", err) + } + + if err := goose.Up(db, "migrations"); err != nil { + return fmt.Errorf("Failed to run migrations: %w", err) + } + return nil +} + +func fillTestUsers(t *testing.T, store *Store) { + for i, u := range localContext.users { + id, err := store.Users.CreateUser(t.Context(), u.email) + if err != nil { + t.Fatal("failed to add test user", err) + } + localContext.users[i].id = id + } +} + +func makeTestGroups(t *testing.T, store *Store) { + managerGroupID, err := store.Groups.GetAdminGroupId(t.Context()) + if err != nil { + t.Fatal("Failed to find root group", err) + } + localContext.beatlesManagers, err = store.Groups.CreateGroup(t.Context(), models.Group{ + ManagerId: managerGroupID, + Name: "The Beatles Managers", + Description: "", + }) + if err != nil { + t.Fatal("failed to create manager group", err) + } + localContext.beatlesMusicians, err = store.Groups.CreateGroup(t.Context(), models.Group{ + ManagerId: localContext.beatlesManagers.Id, + Name: "The beatles musicians", + Description: "the members of the beatles", + }) + if err != nil { + t.Fatal("failed to create musician group", err) + } + + localContext.brits, err = store.Groups.CreateGroup(t.Context(), models.Group{ + ManagerId: managerGroupID, + Name: "British People", + Description: "", + }) + if err != nil { + t.Fatal("failed to create british group", err) + } + + err = store.Groups.AddSubgroupToGroup(t.Context(), localContext.beatlesMusicians.Id, localContext.brits.Id, models.GroupViewPermission_SeeSelf) + if err != nil { + t.Fatal("Failed to add beatles subgroup to british super group") + } + + err = store.Groups.AddSubgroupToGroup(t.Context(), localContext.beatlesManagers.Id, localContext.brits.Id, models.GroupViewPermission_SeeSelf) + if err != nil { + t.Fatal("Failed to add beatles managers subgroup to british super group") + } +} + +func addUsersToTestGroups(t *testing.T, store *Store) { + for _, email := range []string{ + "john@beatles.com", + "paul@beatles.com", + "george@beatles.com", + "ringo@beatles.com", + } { + user, err := store.Users.GetUserByEmail(t.Context(), email) + if err != nil { + t.Fatalf("couldn't find user with email '%s': %v", email, err) + } + err = store.Groups.AddUserToGroup(t.Context(), user.Id, localContext.beatlesMusicians.Id, models.GroupViewPermission_SeeAll) + if err != nil { + t.Fatalf("Failed to add %+v to group %+v", user, localContext.beatlesMusicians) + } + } + + user, err := store.Users.GetUserByEmail(t.Context(), "brian@beatles.com") + if err != nil { + t.Fatalf("couldn't find user with email '%s': %v", "brian@beatles.com", err) + } + err = store.Groups.AddUserToGroup(t.Context(), user.Id, localContext.beatlesManagers.Id, models.GroupViewPermission_SeeAll) + if err != nil { + t.Fatalf("Failed to add %+v to group %+v", user, localContext.beatlesManagers) + } + +} + +func fillTestData(t *testing.T, store *Store) { + fillTestUsers(t, store) + makeTestGroups(t, store) + addUsersToTestGroups(t, store) + +} + +var localLock sync.Mutex +var localDB *sql.DB = nil +var localStore *Store = nil +var localCleanup func() = func() {} + +func verifyDb(t *testing.T) (*sql.DB, *Store) { + if testing.Short() { + t.Skip("Skipping db test in short mode.") + return nil, nil + } + localLock.Lock() + defer localLock.Unlock() + if localDB != nil { + return localDB, localStore + } + var err error + localDB, localCleanup, err = setupTestDB(t) + if err != nil { + t.Fatal("Failed to setup test DB", err) + } + localStore = NewStore(localDB) + return localDB, localStore +} + +func TestAddedUsers(t *testing.T) { + if testing.Short() { + t.Skip("Skipping db test in short mode.") + } + _, store := verifyDb(t) + for _, user := range localContext.users { + user, err := store.Users.GetUserByEmail(t.Context(), user.email) + if err != nil { + t.Fatalf("Failed to find user with email '%s': %v", user.Email, err) + } + } +} + +func TestGroupMembership(t *testing.T) { + if testing.Short() { + t.Skip("Skipping db test in short mode.") + } + _, store := verifyDb(t) + for _, email := range []string{ + "john@beatles.com", + "paul@beatles.com", + "george@beatles.com", + "ringo@beatles.com", + } { + user, err := store.Users.GetUserByEmail(t.Context(), email) + if err != nil { + t.Fatalf("couldn't find user with email '%s': %v", email, err) + } + inGroup, err := store.Groups.IsUserInGroup(t.Context(), user.Id, localContext.beatlesMusicians.Id) + if err != nil { + t.Fatalf("couldn't check user in group for email '%s': %v", email, err) + } + if !inGroup { + t.Fatalf("user with email '%s' should be in group '%s' but wasn't", email, localContext.beatlesMusicians.Name) + } + } +} + +func TestSubgroupMembership(t *testing.T) { + if testing.Short() { + t.Skip("Skipping db test in short mode.") + } + _, store := verifyDb(t) + for _, email := range []string{ + "john@beatles.com", + "paul@beatles.com", + "george@beatles.com", + "ringo@beatles.com", + "brian@beatles.com", + } { + user, err := store.Users.GetUserByEmail(t.Context(), email) + if err != nil { + t.Fatalf("couldn't find user with email '%s': %v", email, err) + } + inGroup, err := store.Groups.IsUserInGroup(t.Context(), user.Id, localContext.brits.Id) + if err != nil { + t.Fatalf("couldn't check user in group for email '%s': %v", email, err) + } + if !inGroup { + t.Fatalf("user with email '%s' should be in group '%s' via subgroup but wasn't", email, localContext.beatlesMusicians.Name) + } + } +} diff --git a/internal/database/models/group.go b/internal/database/models/group.go index 2f949cf5..a714021d 100644 --- a/internal/database/models/group.go +++ b/internal/database/models/group.go @@ -1,5 +1,11 @@ package models +import ( + "fmt" + "io" + "strconv" +) + // Determines how users see the group theyre a part of type GroupViewPermission int @@ -46,3 +52,36 @@ type SubgroupLink struct { SubgroupId int ViewPermission GroupViewPermission } + +func (e GroupViewPermission) MarshalGQL(w io.Writer) { + var s string + switch e { + case GroupViewPermission_SeeAll: + s = "SEE_ALL" + case GroupViewPermission_SeeSelf: + s = "SEE_SELF" + case GroupViewPermission_SeeNone: + s = "SEE_NONE" + default: + s = "" + } + w.Write([]byte(strconv.Quote(s))) +} + +func (e *GroupViewPermission) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enum must be a string") + } + switch str { + case "SEE_ALL": + *e = GroupViewPermission_SeeAll + case "SEE_SELF": + *e = GroupViewPermission_SeeSelf + case "SEE_NONE": + *e = GroupViewPermission_SeeNone + default: + return fmt.Errorf("invalid GroupViewPermission value: %s", str) + } + return nil +} diff --git a/internal/database/setup.go b/internal/database/setup.go index 37717f1a..027b047a 100644 --- a/internal/database/setup.go +++ b/internal/database/setup.go @@ -1,66 +1,15 @@ package database import ( - "context" "database/sql" "fmt" "log" - "log/slog" "os" _ "github.com/lib/pq" "github.com/pressly/goose/v3" - "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/modules/postgres" ) -func SetupTestDB() (*sql.DB, func(), error) { - ctx := context.Background() - - dbName := "testdb" - dbUser := "test_user" - dbPassword := "test_password" - - postgresContainer, err := postgres.Run(ctx, - "postgres:16-alpine", - // postgres.WithInitScripts(filepath.Join("testdata", "init-user-db.sh")), - // postgres.WithConfigFile(filepath.Join("testdata", "my-postgres.conf")), - postgres.WithDatabase(dbName), - postgres.WithUsername(dbUser), - postgres.WithPassword(dbPassword), - postgres.BasicWaitStrategies(), - ) - deferer := func() { - if err := testcontainers.TerminateContainer(postgresContainer); err != nil { - log.Printf("failed to terminate container: %s", err) - } - } - if err != nil { - log.Printf("failed to start container: %s", err) - return nil, func() {}, err - } - - connStr := postgresContainer.MustConnectionString(ctx, "sslmode=disable") - slog.Info("connecting to test postgres", "conn", connStr) - db, err := sql.Open("postgres", connStr) - if err != nil { - log.Fatal(err) - } - - if err := db.Ping(); err != nil { - return nil, deferer, err - } - - slog.Info("Pinged DB") - err = migrateDB(db) - if err != nil { - return db, deferer, err - } - - return db, deferer, nil - -} - func SetupDB() (*sql.DB, error) { db, err := createDB() if err != nil { diff --git a/internal/gql/generated.go b/internal/gql/generated.go index a4b9d222..027daadf 100644 --- a/internal/gql/generated.go +++ b/internal/gql/generated.go @@ -10568,12 +10568,13 @@ func (ec *executionContext) marshalNGroup2ᚖmakeᚑbackendᚋinternalᚋdatabas } func (ec *executionContext) unmarshalNGroupViewPermission2makeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupViewPermission(ctx context.Context, v any) (models.GroupViewPermission, error) { - res, err := ec.unmarshalInputGroupViewPermission(ctx, v) + var res models.GroupViewPermission + err := res.UnmarshalGQL(v) return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalNGroupViewPermission2makeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupViewPermission(ctx context.Context, sel ast.SelectionSet, v models.GroupViewPermission) graphql.Marshaler { - return ec._GroupViewPermission(ctx, sel, &v) + return v } func (ec *executionContext) unmarshalNID2int(ctx context.Context, v any) (int, error) { diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index 844ba278..fc8d7281 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -37,11 +37,13 @@ func (r *queryResolver) MembersOfGroup(ctx context.Context, groupID int) ([]*mod if err != nil { return nil, err } - if !visible || how != models.GroupViewPermission_SeeAll { + if !visible || how == models.GroupViewPermission_SeeNone { return nil, fmt.Errorf("group does not exist or user does not have permission to see it") } - - // return + if how == models.GroupViewPermission_SeeSelf { + // user := getU + } + panic("agh") } // IsUserInGroup is the resolver for the isUserInGroup field. From e95c5ea11511cae2ec1a45f4147b9e7e71f27cb4 Mon Sep 17 00:00:00 2001 From: cowsed Date: Mon, 10 Aug 2026 11:21:33 -0400 Subject: [PATCH 04/22] finished round one of resolvers --- internal/gql/resolvers/group.resolvers.go | 74 +++++++++++++++++++++-- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index fc8d7281..9a20771b 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -40,28 +40,90 @@ func (r *queryResolver) MembersOfGroup(ctx context.Context, groupID int) ([]*mod if !visible || how == models.GroupViewPermission_SeeNone { return nil, fmt.Errorf("group does not exist or user does not have permission to see it") } + if how == models.GroupViewPermission_SeeSelf { - // user := getU + user, err := r.Store.Users.GetUserById(ctx, userID) + if err != nil { + return nil, fmt.Errorf("could not find querying user %w", err) + } + return []*models.MembershipToGroup{{ + UserId: user.Id, + ViewPermission: how, + }}, nil + } + members, err := r.Store.Groups.GetGroupMembers(ctx, groupID) + if !visible || how == models.GroupViewPermission_SeeNone { + return nil, fmt.Errorf("error finding group members: %w", err) + } + members2 := []*models.MembershipToGroup{} + for _, member := range members { + members2 = append(members2, &member) } - panic("agh") + return members2, nil } // IsUserInGroup is the resolver for the isUserInGroup field. func (r *queryResolver) IsUserInGroup(ctx context.Context, userID int, groupID int) (bool, error) { - panic(fmt.Errorf("not implemented: IsUserInGroup - isUserInGroup")) + askingUserID := ctx.Value(auth.UserContextKey{}).(int) + + visibleToAsker, howToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) + if err != nil { + return false, err + } + if !visibleToAsker || howToAsker == models.GroupViewPermission_SeeNone { + return false, fmt.Errorf("group does not exist or user has invalid permissions to query it") + } + + return r.Store.Groups.IsUserInGroup(ctx, userID, groupID) } // IsUserInGroupDirectly is the resolver for the isUserInGroupDirectly field. func (r *queryResolver) IsUserInGroupDirectly(ctx context.Context, userID int, groupID int) (bool, error) { - panic(fmt.Errorf("not implemented: IsUserInGroupDirectly - isUserInGroupDirectly")) + askingUserID := ctx.Value(auth.UserContextKey{}).(int) + + visibleToAsker, howToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) + if err != nil { + return false, err + } + if !visibleToAsker || howToAsker == models.GroupViewPermission_SeeNone { + return false, fmt.Errorf("group does not exist or user has invalid permissions to query it") + } + + return r.Store.Groups.IsUserInGroupDirectly(ctx, userID, groupID) + } // CanGroupManageGroup is the resolver for the canGroupManageGroup field. func (r *queryResolver) CanGroupManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) { - panic(fmt.Errorf("not implemented: CanGroupManageGroup - canGroupManageGroup")) + askingUserID := ctx.Value(auth.UserContextKey{}).(int) + + managerVisibleToAsker, _, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, managerID) + if err != nil { + return false, err + } + if !managerVisibleToAsker { + return false, fmt.Errorf("manager group does not exist or user has invalid permissions to query it") + } + managedVisibleToAsker, _, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) + if err != nil { + return false, err + } + if !managedVisibleToAsker { + return false, fmt.Errorf("managed group does not exist or user has invalid permissions to query it") + } + return r.Store.Groups.CanGroupManageGroup(ctx, managerID, groupID) } // CanUserManageGroup is the resolver for the canUserManageGroup field. func (r *queryResolver) CanUserManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) { - panic(fmt.Errorf("not implemented: CanUserManageGroup - canUserManageGroup")) + askingUserID := ctx.Value(auth.UserContextKey{}).(int) + + visibleToAsker, _, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) + if err != nil { + return false, err + } + if !visibleToAsker { + return false, fmt.Errorf("group does not exist or user has invalid permissions to query it") + } + return r.Store.Groups.CanUserManageGroup(ctx, managerID, groupID) } From d0c264dc5c9da2097e0cfb5de3953e9ba5a3da33 Mon Sep 17 00:00:00 2001 From: cowsed Date: Mon, 10 Aug 2026 11:48:44 -0400 Subject: [PATCH 05/22] changes to group repo interface for resolvers --- coverage.out | 3966 +++++++++++++++++++++ internal/database/group_test.go | 4 +- internal/database/repos/group_repo.go | 74 +- internal/gql/resolvers/group.resolvers.go | 36 +- internal/logging/audit_log.go | 9 +- internal/logging/audit_log_test.go | 23 + 6 files changed, 4070 insertions(+), 42 deletions(-) create mode 100644 coverage.out diff --git a/coverage.out b/coverage.out new file mode 100644 index 00000000..af58a88c --- /dev/null +++ b/coverage.out @@ -0,0 +1,3966 @@ +mode: set +make-backend/internal/database/setup.go:13.33,15.16 2 0 +make-backend/internal/database/setup.go:15.16,17.3 1 0 +make-backend/internal/database/setup.go:18.2,19.16 2 0 +make-backend/internal/database/setup.go:19.16,21.3 1 0 +make-backend/internal/database/setup.go:22.2,22.16 1 0 +make-backend/internal/database/setup.go:25.34,32.16 4 0 +make-backend/internal/database/setup.go:32.16,34.3 1 0 +make-backend/internal/database/setup.go:36.2,36.34 1 0 +make-backend/internal/database/setup.go:36.34,38.3 1 0 +make-backend/internal/database/setup.go:40.2,40.16 1 0 +make-backend/internal/database/setup.go:43.34,47.53 3 0 +make-backend/internal/database/setup.go:47.53,49.3 1 0 +make-backend/internal/database/setup.go:51.2,51.51 1 0 +make-backend/internal/database/setup.go:51.51,53.3 1 0 +make-backend/internal/database/setup.go:54.2,54.12 1 0 +make-backend/internal/database/store.go:22.34,32.2 1 1 +make-backend/cmd/migrate/down.go:12.13,16.16 3 0 +make-backend/cmd/migrate/down.go:16.16,18.3 1 0 +make-backend/cmd/migrate/down.go:19.2,22.53 3 0 +make-backend/cmd/migrate/down.go:22.53,24.3 1 0 +make-backend/cmd/migrate/down.go:26.2,26.53 1 0 +make-backend/cmd/migrate/down.go:26.53,28.3 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:18.84,20.2 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:22.77,24.9 2 0 +make-backend/internal/api/acs/acs_orchestrator.go:24.9,26.3 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:27.2,27.12 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:30.113,31.24 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:34.85,35.24 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:37.84,38.24 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:41.128,42.24 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:45.107,47.16 2 0 +make-backend/internal/api/acs/acs_orchestrator.go:47.16,50.3 2 0 +make-backend/internal/api/acs/acs_orchestrator.go:51.2,57.25 2 0 +make-backend/internal/api/acs/acs_orchestrator.go:57.25,60.3 2 0 +make-backend/internal/api/acs/acs_orchestrator.go:60.8,61.25 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:66.90,67.24 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:70.116,71.24 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:74.110,75.24 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:78.96,79.24 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:82.100,83.24 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:86.76,87.24 1 0 +make-backend/internal/api/acs/acs_orchestrator.go:90.101,91.24 1 0 +make-backend/cmd/make-backend/main.go:35.13,43.2 5 0 +make-backend/cmd/make-backend/main.go:48.13,52.12 4 0 +make-backend/cmd/make-backend/main.go:52.12,55.3 2 0 +make-backend/cmd/make-backend/main.go:57.2,58.16 2 0 +make-backend/cmd/make-backend/main.go:58.16,60.3 1 0 +make-backend/cmd/make-backend/main.go:63.2,64.16 2 0 +make-backend/cmd/make-backend/main.go:64.16,66.3 1 0 +make-backend/cmd/make-backend/main.go:67.2,84.31 13 0 +make-backend/cmd/make-backend/main.go:88.74,95.58 5 0 +make-backend/cmd/make-backend/main.go:95.58,96.45 1 0 +make-backend/cmd/make-backend/main.go:96.45,99.4 2 0 +make-backend/cmd/make-backend/main.go:99.9,102.4 2 0 +make-backend/cmd/make-backend/main.go:104.2,106.12 2 0 +make-backend/cmd/make-backend/main.go:106.12,108.3 1 0 +make-backend/cmd/make-backend/main.go:110.2,110.15 1 0 +make-backend/cmd/make-backend/main.go:114.98,158.12 23 0 +make-backend/cmd/make-backend/main.go:158.12,160.3 1 0 +make-backend/cmd/make-backend/main.go:162.2,162.15 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:39.32,41.2 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:44.42,49.2 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:52.83,53.91 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:53.91,55.3 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:57.2,59.16 3 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:59.16,62.3 2 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:63.2,64.16 2 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:64.16,67.3 2 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:68.2,68.11 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:72.79,74.69 2 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:74.69,76.12 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:76.12,78.4 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:78.9,80.4 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:84.2,85.11 2 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:85.11,87.3 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:87.8,89.3 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:91.2,91.11 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:99.35,101.2 1 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:105.73,109.21 2 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:109.21,112.3 2 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:113.2,113.45 1 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:113.45,115.3 1 0 +make-backend/internal/api/acs/acs-mqtt/auth.go:116.2,116.38 1 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:116.38,117.27 1 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:117.27,119.12 1 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:121.3,121.28 1 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:121.28,124.4 1 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:126.2,126.46 1 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:129.76,131.31 2 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:131.31,133.15 2 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:133.15,134.12 1 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:136.3,136.20 1 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:136.20,138.4 1 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:138.9,140.4 1 1 +make-backend/internal/api/acs/acs-mqtt/auth.go:144.2,144.14 1 1 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:24.147,33.2 2 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:35.43,37.2 1 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:39.76,41.16 2 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:41.16,43.3 1 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:44.2,45.16 2 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:45.16,47.3 1 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:48.2,48.12 1 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:51.122,54.16 3 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:54.16,57.3 2 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:58.2,58.13 1 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:61.107,65.16 3 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:65.16,68.3 2 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:69.2,69.13 1 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:72.123,75.16 3 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:75.16,78.3 2 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:79.2,79.13 1 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:82.118,85.16 3 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:85.16,88.3 2 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:89.2,89.13 1 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:92.100,96.16 3 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:96.16,99.3 2 0 +make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:100.2,100.13 1 0 +make-backend/internal/api/acs/acs-mqtt/server.go:24.37,26.2 1 0 +make-backend/internal/api/acs/acs-mqtt/server.go:28.104,39.32 3 0 +make-backend/internal/api/acs/acs-mqtt/server.go:39.32,41.3 1 0 +make-backend/internal/api/acs/acs-mqtt/server.go:41.8,43.3 1 0 +make-backend/internal/api/acs/acs-mqtt/server.go:44.2,44.26 1 0 +make-backend/internal/api/acs/acs-mqtt/server.go:44.26,46.3 1 0 +make-backend/internal/api/acs/acs-mqtt/server.go:48.2,53.16 4 0 +make-backend/internal/api/acs/acs-mqtt/server.go:53.16,55.3 1 0 +make-backend/internal/api/acs/acs-mqtt/server.go:57.2,58.89 2 0 +make-backend/internal/logging/audit_log.go:16.117,22.16 5 0 +make-backend/internal/logging/audit_log.go:22.16,24.3 1 0 +make-backend/internal/logging/audit_log.go:27.111,33.16 5 0 +make-backend/internal/logging/audit_log.go:33.16,35.3 1 0 +make-backend/internal/logging/audit_log.go:38.146,43.16 4 0 +make-backend/internal/logging/audit_log.go:43.16,45.3 1 0 +make-backend/internal/logging/audit_log.go:47.140,52.16 4 0 +make-backend/internal/logging/audit_log.go:52.16,54.3 1 0 +make-backend/internal/logging/audit_log.go:60.96,61.24 1 1 +make-backend/internal/logging/audit_log.go:61.24,65.3 3 1 +make-backend/internal/logging/audit_log.go:66.2,66.34 1 1 +make-backend/internal/logging/audit_log.go:66.34,69.3 2 1 +make-backend/internal/logging/audit_log.go:76.84,80.39 3 1 +make-backend/internal/logging/audit_log.go:80.39,81.25 1 1 +make-backend/internal/logging/audit_log.go:81.25,83.9 2 1 +make-backend/internal/logging/audit_log.go:85.3,85.26 1 1 +make-backend/internal/logging/audit_log.go:85.26,87.4 1 1 +make-backend/internal/logging/audit_log.go:89.3,89.65 1 1 +make-backend/internal/logging/audit_log.go:92.2,93.50 2 1 +make-backend/internal/logging/audit_log.go:93.50,95.3 1 1 +make-backend/internal/logging/audit_log.go:96.2,96.13 1 1 +make-backend/internal/logging/audit_log.go:101.79,103.36 2 1 +make-backend/internal/logging/audit_log.go:103.36,105.29 2 1 +make-backend/internal/logging/audit_log.go:105.29,107.4 1 1 +make-backend/internal/logging/audit_log.go:107.9,109.4 1 1 +make-backend/internal/logging/audit_log.go:110.3,111.22 2 1 +make-backend/internal/logging/audit_log.go:113.2,113.64 1 1 +make-backend/internal/logging/audit_log.go:117.80,119.36 2 1 +make-backend/internal/logging/audit_log.go:119.36,120.17 1 1 +make-backend/internal/logging/audit_log.go:120.17,122.4 1 1 +make-backend/internal/logging/audit_log.go:123.3,124.29 2 1 +make-backend/internal/logging/audit_log.go:124.29,126.4 1 1 +make-backend/internal/logging/audit_log.go:126.9,128.4 1 1 +make-backend/internal/logging/audit_log.go:129.3,130.63 2 1 +make-backend/internal/logging/audit_log.go:132.2,132.64 1 1 +make-backend/internal/logging/logger.go:10.47,15.2 1 0 +make-backend/internal/gql/directives/directives.go:12.72,14.9 2 0 +make-backend/internal/gql/directives/directives.go:14.9,16.3 1 0 +make-backend/internal/gql/directives/directives.go:18.2,19.16 2 0 +make-backend/internal/gql/directives/directives.go:19.16,21.3 1 0 +make-backend/internal/gql/directives/directives.go:23.2,23.24 1 0 +make-backend/internal/gql/directives/directives.go:26.74,28.9 2 0 +make-backend/internal/gql/directives/directives.go:28.9,30.3 1 0 +make-backend/internal/gql/directives/directives.go:32.2,33.16 2 0 +make-backend/internal/gql/directives/directives.go:33.16,35.3 1 0 +make-backend/internal/gql/directives/directives.go:37.2,37.21 1 0 +make-backend/internal/gql/directives/directives.go:40.72,42.9 2 0 +make-backend/internal/gql/directives/directives.go:42.9,44.3 1 0 +make-backend/internal/gql/directives/directives.go:46.2,47.16 2 0 +make-backend/internal/gql/directives/directives.go:47.16,49.3 1 0 +make-backend/internal/gql/directives/directives.go:51.2,51.19 1 0 +make-backend/internal/gql/directives/directives.go:54.74,56.9 2 0 +make-backend/internal/gql/directives/directives.go:56.9,58.3 1 0 +make-backend/internal/gql/directives/directives.go:60.2,61.16 2 0 +make-backend/internal/gql/directives/directives.go:61.16,63.3 1 0 +make-backend/internal/gql/directives/directives.go:65.2,65.21 1 0 +make-backend/internal/gql/directives/directives.go:68.48,70.15 2 0 +make-backend/internal/gql/directives/directives.go:70.15,72.3 1 0 +make-backend/internal/gql/directives/directives.go:74.2,75.9 2 0 +make-backend/internal/gql/directives/directives.go:75.9,77.3 1 0 +make-backend/internal/gql/directives/directives.go:79.2,80.9 2 0 +make-backend/internal/gql/directives/directives.go:80.9,82.3 1 0 +make-backend/internal/gql/directives/directives.go:84.2,84.34 1 0 +make-backend/internal/gql/directives/directives.go:87.77,89.15 2 0 +make-backend/internal/gql/directives/directives.go:89.15,91.3 1 0 +make-backend/internal/gql/directives/directives.go:93.2,94.9 2 0 +make-backend/internal/gql/directives/directives.go:94.9,96.3 1 0 +make-backend/internal/gql/directives/directives.go:98.2,99.9 2 0 +make-backend/internal/gql/directives/directives.go:99.9,101.3 1 0 +make-backend/internal/gql/directives/directives.go:103.2,104.16 2 0 +make-backend/internal/gql/directives/directives.go:104.16,106.3 1 0 +make-backend/internal/gql/directives/directives.go:108.2,108.24 1 0 +make-backend/internal/gql/directives/directives.go:111.75,113.15 2 0 +make-backend/internal/gql/directives/directives.go:113.15,115.3 1 0 +make-backend/internal/gql/directives/directives.go:117.2,118.9 2 0 +make-backend/internal/gql/directives/directives.go:118.9,120.3 1 0 +make-backend/internal/gql/directives/directives.go:122.2,123.9 2 0 +make-backend/internal/gql/directives/directives.go:123.9,125.3 1 0 +make-backend/internal/gql/directives/directives.go:127.2,128.16 2 0 +make-backend/internal/gql/directives/directives.go:128.16,130.3 1 0 +make-backend/internal/gql/directives/directives.go:132.2,132.22 1 0 +make-backend/internal/gql/directives/directives.go:135.77,137.15 2 0 +make-backend/internal/gql/directives/directives.go:137.15,139.3 1 0 +make-backend/internal/gql/directives/directives.go:141.2,142.9 2 0 +make-backend/internal/gql/directives/directives.go:142.9,144.3 1 0 +make-backend/internal/gql/directives/directives.go:146.2,147.9 2 0 +make-backend/internal/gql/directives/directives.go:147.9,149.3 1 0 +make-backend/internal/gql/directives/directives.go:151.2,152.16 2 0 +make-backend/internal/gql/directives/directives.go:152.16,154.3 1 0 +make-backend/internal/gql/directives/directives.go:156.2,156.24 1 0 +make-backend/internal/gql/directives/directives.go:159.65,160.101 1 0 +make-backend/internal/gql/directives/directives.go:160.101,162.17 2 0 +make-backend/internal/gql/directives/directives.go:162.17,164.4 1 0 +make-backend/internal/gql/directives/directives.go:166.3,166.12 1 0 +make-backend/internal/gql/directives/directives.go:166.12,168.4 1 0 +make-backend/internal/gql/directives/directives.go:168.9,170.4 1 0 +make-backend/internal/gql/directives/directives.go:173.2,173.103 1 0 +make-backend/internal/gql/directives/directives.go:173.103,175.17 2 0 +make-backend/internal/gql/directives/directives.go:175.17,177.4 1 0 +make-backend/internal/gql/directives/directives.go:179.3,179.14 1 0 +make-backend/internal/gql/directives/directives.go:179.14,181.4 1 0 +make-backend/internal/gql/directives/directives.go:181.9,183.4 1 0 +make-backend/internal/gql/directives/directives.go:186.2,186.101 1 0 +make-backend/internal/gql/directives/directives.go:186.101,188.17 2 0 +make-backend/internal/gql/directives/directives.go:188.17,190.4 1 0 +make-backend/internal/gql/directives/directives.go:192.3,192.12 1 0 +make-backend/internal/gql/directives/directives.go:192.12,194.4 1 0 +make-backend/internal/gql/directives/directives.go:194.9,196.4 1 0 +make-backend/internal/gql/directives/directives.go:199.2,199.103 1 0 +make-backend/internal/gql/directives/directives.go:199.103,201.17 2 0 +make-backend/internal/gql/directives/directives.go:201.17,203.4 1 0 +make-backend/internal/gql/directives/directives.go:205.3,205.14 1 0 +make-backend/internal/gql/directives/directives.go:205.14,207.4 1 0 +make-backend/internal/gql/directives/directives.go:207.9,209.4 1 0 +make-backend/internal/gql/directives/directives.go:212.2,212.100 1 0 +make-backend/internal/gql/directives/directives.go:212.100,214.17 2 0 +make-backend/internal/gql/directives/directives.go:214.17,216.4 1 0 +make-backend/internal/gql/directives/directives.go:218.3,218.11 1 0 +make-backend/internal/gql/directives/directives.go:218.11,220.4 1 0 +make-backend/internal/gql/directives/directives.go:220.9,222.4 1 0 +make-backend/internal/gql/directives/directives.go:225.2,225.106 1 0 +make-backend/internal/gql/directives/directives.go:225.106,227.17 2 0 +make-backend/internal/gql/directives/directives.go:227.17,229.4 1 0 +make-backend/internal/gql/directives/directives.go:231.3,231.17 1 0 +make-backend/internal/gql/directives/directives.go:231.17,233.4 1 0 +make-backend/internal/gql/directives/directives.go:233.9,235.4 1 0 +make-backend/internal/gql/directives/directives.go:238.2,238.104 1 0 +make-backend/internal/gql/directives/directives.go:238.104,240.17 2 0 +make-backend/internal/gql/directives/directives.go:240.17,242.4 1 0 +make-backend/internal/gql/directives/directives.go:244.3,244.15 1 0 +make-backend/internal/gql/directives/directives.go:244.15,246.4 1 0 +make-backend/internal/gql/directives/directives.go:246.9,248.4 1 0 +make-backend/internal/gql/directives/directives.go:251.2,251.106 1 0 +make-backend/internal/gql/directives/directives.go:251.106,253.17 2 0 +make-backend/internal/gql/directives/directives.go:253.17,255.4 1 0 +make-backend/internal/gql/directives/directives.go:257.3,257.17 1 0 +make-backend/internal/gql/directives/directives.go:257.17,259.4 1 0 +make-backend/internal/gql/directives/directives.go:259.9,261.4 1 0 +make-backend/internal/gql/directives/directives.go:264.2,264.107 1 0 +make-backend/internal/gql/directives/directives.go:264.107,266.17 2 0 +make-backend/internal/gql/directives/directives.go:266.17,268.4 1 0 +make-backend/internal/gql/directives/directives.go:270.3,271.17 2 0 +make-backend/internal/gql/directives/directives.go:271.17,273.4 1 0 +make-backend/internal/gql/directives/directives.go:275.3,275.20 1 0 +make-backend/internal/gql/directives/directives.go:275.20,277.4 1 0 +make-backend/internal/gql/directives/directives.go:277.9,279.4 1 0 +make-backend/internal/api/rest/api.go:5.44,7.2 0 0 +make-backend/internal/auth/middleware.go:12.96,13.71 1 0 +make-backend/internal/auth/middleware.go:13.71,17.17 2 0 +make-backend/internal/auth/middleware.go:17.17,20.4 2 0 +make-backend/internal/auth/middleware.go:22.3,22.23 1 0 +make-backend/internal/auth/saml.go:20.96,23.18 3 0 +make-backend/internal/auth/saml.go:23.18,25.3 1 0 +make-backend/internal/auth/saml.go:26.2,26.17 1 0 +make-backend/internal/auth/saml.go:26.17,28.3 1 0 +make-backend/internal/auth/saml.go:30.2,31.16 2 0 +make-backend/internal/auth/saml.go:31.16,33.3 1 0 +make-backend/internal/auth/saml.go:35.2,36.16 2 0 +make-backend/internal/auth/saml.go:36.16,38.3 1 0 +make-backend/internal/auth/saml.go:40.2,41.16 2 0 +make-backend/internal/auth/saml.go:41.16,43.3 1 0 +make-backend/internal/auth/saml.go:45.2,46.16 2 0 +make-backend/internal/auth/saml.go:46.16,48.3 1 0 +make-backend/internal/auth/saml.go:50.2,51.20 2 0 +make-backend/internal/auth/saml.go:51.20,53.3 1 0 +make-backend/internal/auth/saml.go:55.2,56.16 2 0 +make-backend/internal/auth/saml.go:56.16,58.3 1 0 +make-backend/internal/auth/saml.go:60.2,69.16 3 0 +make-backend/internal/auth/saml.go:69.16,71.3 1 0 +make-backend/internal/auth/saml.go:73.2,78.15 2 0 +make-backend/internal/auth/saml.go:86.116,90.16 3 0 +make-backend/internal/auth/saml.go:90.16,92.3 1 0 +make-backend/internal/auth/saml.go:94.2,96.12 2 0 +make-backend/internal/auth/saml.go:99.89,101.2 1 0 +make-backend/internal/auth/saml.go:105.81,106.53 1 0 +make-backend/internal/auth/saml.go:106.53,108.3 1 0 +make-backend/internal/auth/saml.go:110.2,110.33 1 0 +make-backend/internal/auth/sessions.go:10.52,16.2 3 0 +make-backend/internal/database/models/device.go:31.39,36.2 1 0 +make-backend/internal/database/models/device.go:38.62,40.16 2 0 +make-backend/internal/database/models/device.go:40.16,42.3 1 0 +make-backend/internal/database/models/device.go:43.2,43.31 1 0 +make-backend/internal/database/models/device.go:48.60,52.2 3 0 +make-backend/internal/database/models/device.go:54.49,57.25 2 0 +make-backend/internal/database/models/device.go:57.25,59.3 1 0 +make-backend/internal/database/models/device.go:62.2,64.16 3 0 +make-backend/internal/database/models/device.go:64.16,66.3 1 0 +make-backend/internal/database/models/device.go:69.2,79.16 7 0 +make-backend/internal/database/models/device.go:79.16,81.3 1 0 +make-backend/internal/database/models/device.go:84.2,92.43 5 0 +make-backend/internal/database/models/device.go:101.51,102.18 1 0 +make-backend/internal/database/models/device.go:102.18,105.3 2 0 +make-backend/internal/database/models/device.go:107.2,108.9 2 0 +make-backend/internal/database/models/device.go:108.9,110.3 1 0 +make-backend/internal/database/models/device.go:112.2,112.33 1 0 +make-backend/internal/database/models/device.go:115.58,117.2 1 0 +make-backend/internal/database/models/device.go:143.50,144.18 1 0 +make-backend/internal/database/models/device.go:144.18,146.3 1 0 +make-backend/internal/database/models/device.go:148.2,149.9 2 0 +make-backend/internal/database/models/device.go:149.9,151.3 1 0 +make-backend/internal/database/models/device.go:153.2,153.33 1 0 +make-backend/internal/database/models/device.go:156.57,158.2 1 0 +make-backend/internal/database/models/equipment.go:21.42,26.2 1 0 +make-backend/internal/database/models/equipment.go:35.50,40.2 1 0 +make-backend/internal/database/models/group.go:56.54,58.11 2 0 +make-backend/internal/database/models/group.go:59.34,60.16 1 0 +make-backend/internal/database/models/group.go:61.35,62.17 1 0 +make-backend/internal/database/models/group.go:63.35,64.17 1 0 +make-backend/internal/database/models/group.go:65.10,66.9 1 0 +make-backend/internal/database/models/group.go:68.2,68.35 1 0 +make-backend/internal/database/models/group.go:71.65,73.9 2 0 +make-backend/internal/database/models/group.go:73.9,75.3 1 0 +make-backend/internal/database/models/group.go:76.2,76.13 1 0 +make-backend/internal/database/models/group.go:77.17,78.34 1 0 +make-backend/internal/database/models/group.go:79.18,80.35 1 0 +make-backend/internal/database/models/group.go:81.18,82.35 1 0 +make-backend/internal/database/models/group.go:83.10,84.66 1 0 +make-backend/internal/database/models/group.go:86.2,86.12 1 0 +make-backend/internal/database/models/hours.go:17.42,17.43 0 0 +make-backend/internal/database/models/hours.go:27.42,27.43 0 0 +make-backend/internal/database/models/makerspace.go:14.43,19.2 1 0 +make-backend/internal/database/models/training.go:20.37,20.38 0 0 +make-backend/internal/database/models/training.go:21.37,21.38 0 0 +make-backend/internal/database/models/training.go:29.38,29.39 0 0 +make-backend/internal/database/models/training.go:30.38,30.39 0 0 +make-backend/internal/database/models/training.go:46.39,46.40 0 0 +make-backend/internal/database/models/training.go:47.37,48.27 1 0 +make-backend/internal/database/models/training.go:48.27,50.3 1 0 +make-backend/internal/database/models/training.go:62.44,62.45 0 0 +make-backend/internal/database/models/training.go:63.42,65.2 1 0 +make-backend/internal/database/models/training.go:70.65,72.60 2 0 +make-backend/internal/database/models/training.go:72.60,74.3 1 0 +make-backend/internal/database/models/training.go:76.2,78.35 2 0 +make-backend/internal/database/models/training.go:78.35,82.60 2 0 +make-backend/internal/database/models/training.go:82.60,84.4 1 0 +make-backend/internal/database/models/training.go:86.3,87.28 2 0 +make-backend/internal/database/models/training.go:88.15,90.50 2 0 +make-backend/internal/database/models/training.go:90.50,92.5 1 0 +make-backend/internal/database/models/training.go:93.4,93.14 1 0 +make-backend/internal/database/models/training.go:95.16,97.50 2 0 +make-backend/internal/database/models/training.go:97.50,99.5 1 0 +make-backend/internal/database/models/training.go:100.4,100.14 1 0 +make-backend/internal/database/models/training.go:102.40,104.50 2 0 +make-backend/internal/database/models/training.go:104.50,106.5 1 0 +make-backend/internal/database/models/training.go:107.4,107.14 1 0 +make-backend/internal/database/models/training.go:109.23,111.50 2 0 +make-backend/internal/database/models/training.go:111.50,113.5 1 0 +make-backend/internal/database/models/training.go:114.4,114.14 1 0 +make-backend/internal/database/models/training.go:116.11,117.74 1 0 +make-backend/internal/database/models/training.go:120.3,120.31 1 0 +make-backend/internal/database/models/training.go:123.2,123.12 1 0 +make-backend/internal/database/models/training.go:133.51,135.9 2 0 +make-backend/internal/database/models/training.go:135.9,137.3 1 0 +make-backend/internal/database/models/training.go:139.2,139.33 1 0 +make-backend/internal/database/models/user.go:24.33,26.2 1 0 +make-backend/internal/database/models/user.go:27.37,29.2 1 0 +make-backend/internal/database/repos/audit_log_repo.go:30.48,32.2 1 0 +make-backend/internal/database/repos/audit_log_repo.go:44.175,48.16 3 0 +make-backend/internal/database/repos/audit_log_repo.go:48.16,50.3 1 0 +make-backend/internal/database/repos/audit_log_repo.go:52.2,55.16 3 0 +make-backend/internal/database/repos/audit_log_repo.go:55.16,57.3 1 0 +make-backend/internal/database/repos/audit_log_repo.go:59.2,59.23 1 0 +make-backend/internal/database/repos/audit_log_repo.go:62.121,65.38 3 0 +make-backend/internal/database/repos/audit_log_repo.go:65.38,68.3 2 0 +make-backend/internal/database/repos/audit_log_repo.go:69.2,75.65 2 0 +make-backend/internal/database/repos/audit_log_repo.go:75.65,78.3 1 0 +make-backend/internal/database/repos/audit_log_repo.go:78.8,78.71 1 0 +make-backend/internal/database/repos/audit_log_repo.go:78.71,81.3 2 0 +make-backend/internal/database/repos/audit_log_repo.go:81.8,85.33 3 0 +make-backend/internal/database/repos/audit_log_repo.go:85.33,87.4 1 0 +make-backend/internal/database/repos/audit_log_repo.go:88.3,89.52 2 0 +make-backend/internal/database/repos/audit_log_repo.go:92.2,92.35 1 0 +make-backend/internal/database/repos/audit_log_repo.go:92.35,96.3 3 0 +make-backend/internal/database/repos/audit_log_repo.go:97.2,97.33 1 0 +make-backend/internal/database/repos/audit_log_repo.go:97.33,101.3 3 0 +make-backend/internal/database/repos/audit_log_repo.go:103.2,109.27 2 0 +make-backend/internal/database/repos/audit_log_repo.go:109.27,110.22 1 0 +make-backend/internal/database/repos/audit_log_repo.go:110.22,112.4 1 0 +make-backend/internal/database/repos/audit_log_repo.go:112.9,112.28 1 0 +make-backend/internal/database/repos/audit_log_repo.go:112.28,117.4 3 0 +make-backend/internal/database/repos/audit_log_repo.go:120.2,120.29 1 0 +make-backend/internal/database/repos/audit_log_repo.go:120.29,125.3 4 0 +make-backend/internal/database/repos/audit_log_repo.go:127.2,132.16 4 0 +make-backend/internal/database/repos/audit_log_repo.go:132.16,134.3 1 0 +make-backend/internal/database/repos/audit_log_repo.go:135.2,136.18 2 0 +make-backend/internal/database/repos/audit_log_repo.go:136.18,147.17 3 0 +make-backend/internal/database/repos/audit_log_repo.go:147.17,149.4 1 0 +make-backend/internal/database/repos/audit_log_repo.go:150.3,150.27 1 0 +make-backend/internal/database/repos/audit_log_repo.go:153.2,153.35 1 0 +make-backend/internal/database/repos/audit_log_repo.go:153.35,155.3 1 0 +make-backend/internal/database/repos/audit_log_repo.go:157.2,157.18 1 0 +make-backend/internal/database/repos/device_repo.go:22.89,49.16 4 0 +make-backend/internal/database/repos/device_repo.go:49.16,51.3 1 0 +make-backend/internal/database/repos/device_repo.go:53.2,53.31 1 0 +make-backend/internal/database/repos/device_repo.go:56.92,83.16 4 0 +make-backend/internal/database/repos/device_repo.go:83.16,85.3 1 0 +make-backend/internal/database/repos/device_repo.go:87.2,87.31 1 0 +make-backend/internal/database/repos/device_repo.go:90.101,136.16 4 0 +make-backend/internal/database/repos/device_repo.go:136.16,138.3 1 0 +make-backend/internal/database/repos/device_repo.go:140.2,140.28 1 0 +make-backend/internal/database/repos/device_repo.go:143.142,155.16 4 0 +make-backend/internal/database/repos/device_repo.go:155.16,157.3 1 0 +make-backend/internal/database/repos/device_repo.go:159.2,159.36 1 0 +make-backend/internal/database/repos/device_repo.go:162.122,193.16 4 0 +make-backend/internal/database/repos/device_repo.go:193.16,195.3 1 0 +make-backend/internal/database/repos/device_repo.go:197.2,197.35 1 0 +make-backend/internal/database/repos/device_repo.go:200.157,219.16 4 0 +make-backend/internal/database/repos/device_repo.go:219.16,221.3 1 0 +make-backend/internal/database/repos/device_repo.go:223.2,223.28 1 0 +make-backend/internal/database/repos/equipment_repo.go:17.98,56.16 4 0 +make-backend/internal/database/repos/equipment_repo.go:56.16,58.3 1 0 +make-backend/internal/database/repos/equipment_repo.go:60.2,60.31 1 0 +make-backend/internal/database/repos/group_repo.go:54.102,57.16 2 0 +make-backend/internal/database/repos/group_repo.go:57.16,59.3 1 0 +make-backend/internal/database/repos/group_repo.go:60.2,60.15 1 0 +make-backend/internal/database/repos/group_repo.go:60.15,62.3 1 0 +make-backend/internal/database/repos/group_repo.go:65.2,66.16 2 0 +make-backend/internal/database/repos/group_repo.go:66.16,68.3 1 0 +make-backend/internal/database/repos/group_repo.go:70.2,70.15 1 0 +make-backend/internal/database/repos/group_repo.go:70.15,71.14 1 0 +make-backend/internal/database/repos/group_repo.go:72.42,73.20 1 0 +make-backend/internal/database/repos/group_repo.go:74.43,75.21 1 0 +make-backend/internal/database/repos/group_repo.go:76.43,77.20 1 0 +make-backend/internal/database/repos/group_repo.go:78.11,79.64 1 0 +make-backend/internal/database/repos/group_repo.go:87.2,87.24 1 0 +make-backend/internal/database/repos/group_repo.go:90.111,93.16 2 0 +make-backend/internal/database/repos/group_repo.go:93.16,95.3 1 0 +make-backend/internal/database/repos/group_repo.go:96.2,96.15 1 0 +make-backend/internal/database/repos/group_repo.go:96.15,98.3 1 0 +make-backend/internal/database/repos/group_repo.go:103.2,103.24 1 0 +make-backend/internal/database/repos/group_repo.go:107.137,111.16 3 0 +make-backend/internal/database/repos/group_repo.go:111.16,113.3 1 0 +make-backend/internal/database/repos/group_repo.go:115.2,115.12 1 0 +make-backend/internal/database/repos/group_repo.go:118.105,122.16 3 0 +make-backend/internal/database/repos/group_repo.go:122.16,124.3 1 0 +make-backend/internal/database/repos/group_repo.go:126.2,127.18 2 0 +make-backend/internal/database/repos/group_repo.go:127.18,134.17 4 0 +make-backend/internal/database/repos/group_repo.go:134.17,136.4 1 0 +make-backend/internal/database/repos/group_repo.go:137.3,137.30 1 0 +make-backend/internal/database/repos/group_repo.go:140.2,140.35 1 0 +make-backend/internal/database/repos/group_repo.go:140.35,142.3 1 0 +make-backend/internal/database/repos/group_repo.go:144.2,144.19 1 0 +make-backend/internal/database/repos/group_repo.go:149.99,154.16 3 0 +make-backend/internal/database/repos/group_repo.go:154.16,156.3 1 0 +make-backend/internal/database/repos/group_repo.go:158.2,159.18 2 0 +make-backend/internal/database/repos/group_repo.go:159.18,166.17 4 0 +make-backend/internal/database/repos/group_repo.go:166.17,168.4 1 0 +make-backend/internal/database/repos/group_repo.go:169.3,169.30 1 0 +make-backend/internal/database/repos/group_repo.go:172.2,172.35 1 0 +make-backend/internal/database/repos/group_repo.go:172.35,174.3 1 0 +make-backend/internal/database/repos/group_repo.go:176.2,176.19 1 0 +make-backend/internal/database/repos/group_repo.go:181.96,185.16 3 0 +make-backend/internal/database/repos/group_repo.go:185.16,187.3 1 0 +make-backend/internal/database/repos/group_repo.go:188.2,191.18 3 0 +make-backend/internal/database/repos/group_repo.go:191.18,194.17 3 0 +make-backend/internal/database/repos/group_repo.go:194.17,196.4 1 0 +make-backend/internal/database/repos/group_repo.go:197.3,197.33 1 0 +make-backend/internal/database/repos/group_repo.go:200.2,200.35 1 0 +make-backend/internal/database/repos/group_repo.go:200.35,202.3 1 0 +make-backend/internal/database/repos/group_repo.go:203.2,203.20 1 0 +make-backend/internal/database/repos/group_repo.go:207.92,215.16 3 0 +make-backend/internal/database/repos/group_repo.go:215.16,217.3 1 0 +make-backend/internal/database/repos/group_repo.go:218.2,221.18 3 0 +make-backend/internal/database/repos/group_repo.go:221.18,224.17 3 0 +make-backend/internal/database/repos/group_repo.go:224.17,226.4 1 0 +make-backend/internal/database/repos/group_repo.go:227.3,227.33 1 0 +make-backend/internal/database/repos/group_repo.go:230.2,230.35 1 0 +make-backend/internal/database/repos/group_repo.go:230.35,232.3 1 0 +make-backend/internal/database/repos/group_repo.go:233.2,233.20 1 0 +make-backend/internal/database/repos/group_repo.go:236.113,240.16 3 0 +make-backend/internal/database/repos/group_repo.go:240.16,242.3 1 0 +make-backend/internal/database/repos/group_repo.go:243.2,246.18 3 0 +make-backend/internal/database/repos/group_repo.go:246.18,252.17 3 0 +make-backend/internal/database/repos/group_repo.go:252.17,254.4 1 0 +make-backend/internal/database/repos/group_repo.go:255.3,255.33 1 0 +make-backend/internal/database/repos/group_repo.go:258.2,258.35 1 0 +make-backend/internal/database/repos/group_repo.go:258.35,260.3 1 0 +make-backend/internal/database/repos/group_repo.go:262.2,262.20 1 0 +make-backend/internal/database/repos/group_repo.go:267.96,268.24 1 0 +make-backend/internal/database/repos/group_repo.go:272.94,273.24 1 0 +make-backend/internal/database/repos/group_repo.go:277.112,283.16 4 0 +make-backend/internal/database/repos/group_repo.go:283.16,285.3 1 0 +make-backend/internal/database/repos/group_repo.go:286.2,286.20 1 0 +make-backend/internal/database/repos/group_repo.go:289.110,300.16 4 0 +make-backend/internal/database/repos/group_repo.go:300.16,302.3 1 0 +make-backend/internal/database/repos/group_repo.go:303.2,303.20 1 0 +make-backend/internal/database/repos/group_repo.go:306.123,312.16 4 0 +make-backend/internal/database/repos/group_repo.go:312.16,314.3 1 0 +make-backend/internal/database/repos/group_repo.go:315.2,315.25 1 0 +make-backend/internal/database/repos/group_repo.go:318.131,324.16 4 0 +make-backend/internal/database/repos/group_repo.go:324.16,326.3 1 0 +make-backend/internal/database/repos/group_repo.go:327.2,327.25 1 0 +make-backend/internal/database/repos/group_repo.go:331.71,338.16 4 0 +make-backend/internal/database/repos/group_repo.go:338.16,340.3 1 0 +make-backend/internal/database/repos/group_repo.go:342.2,342.23 1 0 +make-backend/internal/database/repos/group_repo.go:345.96,351.16 4 0 +make-backend/internal/database/repos/group_repo.go:351.16,353.3 1 0 +make-backend/internal/database/repos/group_repo.go:355.2,355.20 1 0 +make-backend/internal/database/repos/group_repo.go:358.96,364.16 4 0 +make-backend/internal/database/repos/group_repo.go:364.16,366.3 1 0 +make-backend/internal/database/repos/group_repo.go:368.2,368.20 1 0 +make-backend/internal/database/repos/group_repo.go:372.86,389.16 5 0 +make-backend/internal/database/repos/group_repo.go:389.16,391.3 1 0 +make-backend/internal/database/repos/group_repo.go:392.2,392.22 1 0 +make-backend/internal/database/repos/group_repo.go:392.22,395.3 1 0 +make-backend/internal/database/repos/group_repo.go:395.8,397.3 1 0 +make-backend/internal/database/repos/group_repo.go:399.2,399.21 1 0 +make-backend/internal/database/repos/group_repo.go:403.128,408.16 3 0 +make-backend/internal/database/repos/group_repo.go:408.16,410.3 1 0 +make-backend/internal/database/repos/group_repo.go:412.2,412.12 1 0 +make-backend/internal/database/repos/group_repo.go:415.107,419.16 3 0 +make-backend/internal/database/repos/group_repo.go:419.16,421.3 1 0 +make-backend/internal/database/repos/group_repo.go:423.2,424.18 2 0 +make-backend/internal/database/repos/group_repo.go:424.18,430.17 3 0 +make-backend/internal/database/repos/group_repo.go:430.17,432.4 1 0 +make-backend/internal/database/repos/group_repo.go:433.3,433.36 1 0 +make-backend/internal/database/repos/group_repo.go:436.2,436.35 1 0 +make-backend/internal/database/repos/group_repo.go:436.35,438.3 1 0 +make-backend/internal/database/repos/group_repo.go:440.2,440.21 1 0 +make-backend/internal/database/repos/group_repo.go:444.113,448.16 3 0 +make-backend/internal/database/repos/group_repo.go:448.16,450.3 1 0 +make-backend/internal/database/repos/group_repo.go:452.2,453.18 2 0 +make-backend/internal/database/repos/group_repo.go:453.18,459.17 3 0 +make-backend/internal/database/repos/group_repo.go:459.17,461.4 1 0 +make-backend/internal/database/repos/group_repo.go:462.3,462.36 1 0 +make-backend/internal/database/repos/group_repo.go:465.2,465.35 1 0 +make-backend/internal/database/repos/group_repo.go:465.35,467.3 1 0 +make-backend/internal/database/repos/group_repo.go:469.2,469.21 1 0 +make-backend/internal/database/repos/group_repo.go:472.101,475.16 3 0 +make-backend/internal/database/repos/group_repo.go:475.16,477.3 1 0 +make-backend/internal/database/repos/group_repo.go:478.2,479.16 2 0 +make-backend/internal/database/repos/group_repo.go:479.16,481.3 1 0 +make-backend/internal/database/repos/group_repo.go:482.2,482.21 1 0 +make-backend/internal/database/repos/image_repo.go:17.86,27.16 4 0 +make-backend/internal/database/repos/image_repo.go:27.16,29.3 1 0 +make-backend/internal/database/repos/image_repo.go:31.2,31.27 1 0 +make-backend/internal/database/repos/makerspace_repo.go:23.101,49.16 4 0 +make-backend/internal/database/repos/makerspace_repo.go:49.16,51.3 1 0 +make-backend/internal/database/repos/makerspace_repo.go:53.2,53.32 1 0 +make-backend/internal/database/repos/makerspace_repo.go:56.103,62.16 4 0 +make-backend/internal/database/repos/makerspace_repo.go:62.16,64.3 1 0 +make-backend/internal/database/repos/makerspace_repo.go:66.2,66.23 1 0 +make-backend/internal/database/repos/makerspace_repo.go:69.86,73.16 3 0 +make-backend/internal/database/repos/makerspace_repo.go:73.16,75.3 1 0 +make-backend/internal/database/repos/makerspace_repo.go:77.2,77.18 1 0 +make-backend/internal/database/repos/makerspace_repo.go:80.96,84.16 3 0 +make-backend/internal/database/repos/makerspace_repo.go:84.16,86.3 1 0 +make-backend/internal/database/repos/makerspace_repo.go:88.2,88.12 1 0 +make-backend/internal/database/repos/makerspace_repo.go:91.94,95.16 3 0 +make-backend/internal/database/repos/makerspace_repo.go:95.16,97.3 1 0 +make-backend/internal/database/repos/makerspace_repo.go:99.2,99.12 1 0 +make-backend/internal/database/repos/makerspace_repo.go:102.102,121.16 3 0 +make-backend/internal/database/repos/makerspace_repo.go:121.16,123.3 1 0 +make-backend/internal/database/repos/makerspace_repo.go:124.2,127.18 3 0 +make-backend/internal/database/repos/makerspace_repo.go:127.18,144.17 3 0 +make-backend/internal/database/repos/makerspace_repo.go:144.17,146.4 1 0 +make-backend/internal/database/repos/makerspace_repo.go:148.3,148.31 1 0 +make-backend/internal/database/repos/makerspace_repo.go:151.2,151.35 1 0 +make-backend/internal/database/repos/makerspace_repo.go:151.35,153.3 1 0 +make-backend/internal/database/repos/makerspace_repo.go:155.2,155.19 1 0 +make-backend/internal/database/repos/makerspace_repo.go:158.114,169.16 3 0 +make-backend/internal/database/repos/makerspace_repo.go:169.16,171.3 1 0 +make-backend/internal/database/repos/makerspace_repo.go:172.2,175.18 3 0 +make-backend/internal/database/repos/makerspace_repo.go:175.18,186.17 3 0 +make-backend/internal/database/repos/makerspace_repo.go:186.17,188.4 1 0 +make-backend/internal/database/repos/makerspace_repo.go:190.3,190.55 1 0 +make-backend/internal/database/repos/makerspace_repo.go:193.2,193.35 1 0 +make-backend/internal/database/repos/makerspace_repo.go:193.35,195.3 1 0 +make-backend/internal/database/repos/makerspace_repo.go:197.2,197.27 1 0 +make-backend/internal/database/repos/user_repo.go:25.83,58.16 4 0 +make-backend/internal/database/repos/user_repo.go:58.16,60.3 1 0 +make-backend/internal/database/repos/user_repo.go:62.2,62.26 1 0 +make-backend/internal/database/repos/user_repo.go:65.92,98.16 4 0 +make-backend/internal/database/repos/user_repo.go:98.16,100.3 1 0 +make-backend/internal/database/repos/user_repo.go:102.2,102.26 1 0 +make-backend/internal/database/repos/user_repo.go:105.79,111.16 4 0 +make-backend/internal/database/repos/user_repo.go:111.16,113.3 1 0 +make-backend/internal/database/repos/user_repo.go:115.2,115.20 1 0 +make-backend/internal/database/repos/user_repo.go:118.73,124.16 4 0 +make-backend/internal/database/repos/user_repo.go:124.16,126.3 1 0 +make-backend/internal/database/repos/user_repo.go:128.2,128.23 1 0 +make-backend/internal/database/repos/user_repo.go:131.71,137.16 4 0 +make-backend/internal/database/repos/user_repo.go:137.16,139.3 1 0 +make-backend/internal/database/repos/user_repo.go:141.2,141.21 1 0 +make-backend/internal/database/repos/user_repo.go:144.73,150.16 4 0 +make-backend/internal/database/repos/user_repo.go:150.16,152.3 1 0 +make-backend/internal/database/repos/user_repo.go:154.2,154.23 1 0 +make-backend/internal/database/repos/user_repo.go:157.100,163.16 4 0 +make-backend/internal/database/repos/user_repo.go:163.16,165.3 1 0 +make-backend/internal/database/repos/user_repo.go:167.2,167.23 1 0 +make-backend/internal/database/repos/user_repo.go:170.98,176.16 4 0 +make-backend/internal/database/repos/user_repo.go:176.16,178.3 1 0 +make-backend/internal/database/repos/user_repo.go:180.2,180.21 1 0 +make-backend/internal/database/repos/user_repo.go:183.99,189.16 4 0 +make-backend/internal/database/repos/user_repo.go:189.16,191.3 1 0 +make-backend/internal/database/repos/user_repo.go:193.2,193.23 1 0 +make-backend/internal/database/repos/zone_repo.go:18.83,36.16 4 0 +make-backend/internal/database/repos/zone_repo.go:36.16,38.3 1 0 +make-backend/internal/database/repos/zone_repo.go:40.2,40.26 1 0 +make-backend/internal/database/repos/zone_repo.go:43.106,47.16 3 0 +make-backend/internal/database/repos/zone_repo.go:47.16,49.3 1 0 +make-backend/internal/database/repos/zone_repo.go:50.2,54.18 3 0 +make-backend/internal/database/repos/zone_repo.go:54.18,58.17 3 0 +make-backend/internal/database/repos/zone_repo.go:58.17,60.4 1 0 +make-backend/internal/database/repos/zone_repo.go:62.3,62.31 1 0 +make-backend/internal/database/repos/zone_repo.go:65.2,65.34 1 0 +make-backend/internal/database/repos/zone_repo.go:65.34,67.3 1 0 +make-backend/internal/database/repos/zone_repo.go:69.2,69.19 1 0 +make-backend/internal/gql/scalars/clock_time.go:11.54,12.46 1 0 +make-backend/internal/gql/scalars/clock_time.go:12.46,14.3 1 0 +make-backend/internal/gql/scalars/clock_time.go:17.51,19.9 2 0 +make-backend/internal/gql/scalars/clock_time.go:19.9,21.3 1 0 +make-backend/internal/gql/scalars/clock_time.go:23.2,23.36 1 0 +make-backend/internal/gql/scalars/date.go:11.49,12.46 1 0 +make-backend/internal/gql/scalars/date.go:12.46,14.3 1 0 +make-backend/internal/gql/scalars/date.go:17.46,19.9 2 0 +make-backend/internal/gql/scalars/date.go:19.9,21.3 1 0 +make-backend/internal/gql/scalars/date.go:23.2,23.38 1 0 +make-backend/internal/gql/generated.go:27.63,29.2 1 0 +make-backend/internal/gql/generated.go:366.49,367.25 1 0 +make-backend/internal/gql/generated.go:367.25,369.3 1 0 +make-backend/internal/gql/generated.go:370.2,370.21 1 0 +make-backend/internal/gql/generated.go:373.141,376.32 3 0 +make-backend/internal/gql/generated.go:378.34,379.54 1 0 +make-backend/internal/gql/generated.go:379.54,380.9 1 0 +make-backend/internal/gql/generated.go:383.3,383.73 1 0 +make-backend/internal/gql/generated.go:384.33,385.53 1 0 +make-backend/internal/gql/generated.go:385.53,386.9 1 0 +make-backend/internal/gql/generated.go:389.3,389.72 1 0 +make-backend/internal/gql/generated.go:390.26,391.47 1 0 +make-backend/internal/gql/generated.go:391.47,392.9 1 0 +make-backend/internal/gql/generated.go:395.3,395.66 1 0 +make-backend/internal/gql/generated.go:396.29,397.50 1 0 +make-backend/internal/gql/generated.go:397.50,398.9 1 0 +make-backend/internal/gql/generated.go:401.3,401.69 1 0 +make-backend/internal/gql/generated.go:402.37,403.57 1 0 +make-backend/internal/gql/generated.go:403.57,404.9 1 0 +make-backend/internal/gql/generated.go:407.3,407.76 1 0 +make-backend/internal/gql/generated.go:409.34,410.55 1 0 +make-backend/internal/gql/generated.go:410.55,411.9 1 0 +make-backend/internal/gql/generated.go:414.3,414.74 1 0 +make-backend/internal/gql/generated.go:415.28,416.49 1 0 +make-backend/internal/gql/generated.go:416.49,417.9 1 0 +make-backend/internal/gql/generated.go:420.3,420.68 1 0 +make-backend/internal/gql/generated.go:421.30,422.51 1 0 +make-backend/internal/gql/generated.go:422.51,423.9 1 0 +make-backend/internal/gql/generated.go:426.3,426.70 1 0 +make-backend/internal/gql/generated.go:428.37,429.58 1 0 +make-backend/internal/gql/generated.go:429.58,430.9 1 0 +make-backend/internal/gql/generated.go:433.3,433.77 1 0 +make-backend/internal/gql/generated.go:434.29,435.50 1 0 +make-backend/internal/gql/generated.go:435.50,436.9 1 0 +make-backend/internal/gql/generated.go:439.3,439.69 1 0 +make-backend/internal/gql/generated.go:441.31,442.52 1 0 +make-backend/internal/gql/generated.go:442.52,443.9 1 0 +make-backend/internal/gql/generated.go:446.3,446.71 1 0 +make-backend/internal/gql/generated.go:447.39,448.58 1 0 +make-backend/internal/gql/generated.go:448.58,449.9 1 0 +make-backend/internal/gql/generated.go:452.3,452.77 1 0 +make-backend/internal/gql/generated.go:453.29,454.50 1 0 +make-backend/internal/gql/generated.go:454.50,455.9 1 0 +make-backend/internal/gql/generated.go:458.3,458.69 1 0 +make-backend/internal/gql/generated.go:459.28,460.49 1 0 +make-backend/internal/gql/generated.go:460.49,461.9 1 0 +make-backend/internal/gql/generated.go:464.3,464.68 1 0 +make-backend/internal/gql/generated.go:465.34,466.54 1 0 +make-backend/internal/gql/generated.go:466.54,467.9 1 0 +make-backend/internal/gql/generated.go:470.3,470.73 1 0 +make-backend/internal/gql/generated.go:471.42,472.62 1 0 +make-backend/internal/gql/generated.go:472.62,473.9 1 0 +make-backend/internal/gql/generated.go:476.3,476.81 1 0 +make-backend/internal/gql/generated.go:477.40,478.60 1 0 +make-backend/internal/gql/generated.go:478.60,479.9 1 0 +make-backend/internal/gql/generated.go:482.3,482.79 1 0 +make-backend/internal/gql/generated.go:483.36,484.56 1 0 +make-backend/internal/gql/generated.go:484.56,485.9 1 0 +make-backend/internal/gql/generated.go:488.3,488.75 1 0 +make-backend/internal/gql/generated.go:489.36,490.56 1 0 +make-backend/internal/gql/generated.go:490.56,491.9 1 0 +make-backend/internal/gql/generated.go:494.3,494.75 1 0 +make-backend/internal/gql/generated.go:496.42,497.61 1 0 +make-backend/internal/gql/generated.go:497.61,498.9 1 0 +make-backend/internal/gql/generated.go:501.3,501.80 1 0 +make-backend/internal/gql/generated.go:502.47,503.66 1 0 +make-backend/internal/gql/generated.go:503.66,504.9 1 0 +make-backend/internal/gql/generated.go:507.3,507.85 1 0 +make-backend/internal/gql/generated.go:508.37,509.58 1 0 +make-backend/internal/gql/generated.go:509.58,510.9 1 0 +make-backend/internal/gql/generated.go:513.3,513.77 1 0 +make-backend/internal/gql/generated.go:515.27,516.48 1 0 +make-backend/internal/gql/generated.go:516.48,517.9 1 0 +make-backend/internal/gql/generated.go:520.3,520.67 1 0 +make-backend/internal/gql/generated.go:521.25,522.46 1 0 +make-backend/internal/gql/generated.go:522.46,523.9 1 0 +make-backend/internal/gql/generated.go:526.3,526.65 1 0 +make-backend/internal/gql/generated.go:527.36,528.56 1 0 +make-backend/internal/gql/generated.go:528.56,529.9 1 0 +make-backend/internal/gql/generated.go:532.3,532.75 1 0 +make-backend/internal/gql/generated.go:533.28,534.49 1 0 +make-backend/internal/gql/generated.go:534.49,535.9 1 0 +make-backend/internal/gql/generated.go:538.3,538.68 1 0 +make-backend/internal/gql/generated.go:540.29,541.49 1 0 +make-backend/internal/gql/generated.go:541.49,542.9 1 0 +make-backend/internal/gql/generated.go:545.3,545.68 1 0 +make-backend/internal/gql/generated.go:546.30,547.50 1 0 +make-backend/internal/gql/generated.go:547.50,548.9 1 0 +make-backend/internal/gql/generated.go:551.3,551.69 1 0 +make-backend/internal/gql/generated.go:553.33,554.53 1 0 +make-backend/internal/gql/generated.go:554.53,555.9 1 0 +make-backend/internal/gql/generated.go:558.3,558.72 1 0 +make-backend/internal/gql/generated.go:559.29,560.50 1 0 +make-backend/internal/gql/generated.go:560.50,561.9 1 0 +make-backend/internal/gql/generated.go:564.3,564.69 1 0 +make-backend/internal/gql/generated.go:565.34,566.53 1 0 +make-backend/internal/gql/generated.go:566.53,567.9 1 0 +make-backend/internal/gql/generated.go:570.3,570.72 1 0 +make-backend/internal/gql/generated.go:571.36,572.56 1 0 +make-backend/internal/gql/generated.go:572.56,573.9 1 0 +make-backend/internal/gql/generated.go:576.3,576.75 1 0 +make-backend/internal/gql/generated.go:577.32,578.52 1 0 +make-backend/internal/gql/generated.go:578.52,579.9 1 0 +make-backend/internal/gql/generated.go:582.3,582.71 1 0 +make-backend/internal/gql/generated.go:584.25,585.46 1 0 +make-backend/internal/gql/generated.go:585.46,586.9 1 0 +make-backend/internal/gql/generated.go:589.3,589.65 1 0 +make-backend/internal/gql/generated.go:590.25,591.46 1 0 +make-backend/internal/gql/generated.go:591.46,592.9 1 0 +make-backend/internal/gql/generated.go:595.3,595.65 1 0 +make-backend/internal/gql/generated.go:596.19,597.40 1 0 +make-backend/internal/gql/generated.go:597.40,598.9 1 0 +make-backend/internal/gql/generated.go:601.3,601.59 1 0 +make-backend/internal/gql/generated.go:602.26,603.46 1 0 +make-backend/internal/gql/generated.go:603.46,604.9 1 0 +make-backend/internal/gql/generated.go:607.3,607.65 1 0 +make-backend/internal/gql/generated.go:608.30,609.50 1 0 +make-backend/internal/gql/generated.go:609.50,610.9 1 0 +make-backend/internal/gql/generated.go:613.3,613.69 1 0 +make-backend/internal/gql/generated.go:614.21,615.42 1 0 +make-backend/internal/gql/generated.go:615.42,616.9 1 0 +make-backend/internal/gql/generated.go:619.3,619.61 1 0 +make-backend/internal/gql/generated.go:620.23,621.44 1 0 +make-backend/internal/gql/generated.go:621.44,622.9 1 0 +make-backend/internal/gql/generated.go:625.3,625.63 1 0 +make-backend/internal/gql/generated.go:626.19,627.40 1 0 +make-backend/internal/gql/generated.go:627.40,628.9 1 0 +make-backend/internal/gql/generated.go:631.3,631.59 1 0 +make-backend/internal/gql/generated.go:632.32,633.52 1 0 +make-backend/internal/gql/generated.go:633.52,634.9 1 0 +make-backend/internal/gql/generated.go:637.3,637.71 1 0 +make-backend/internal/gql/generated.go:639.30,640.50 1 0 +make-backend/internal/gql/generated.go:640.50,641.9 1 0 +make-backend/internal/gql/generated.go:644.3,644.69 1 0 +make-backend/internal/gql/generated.go:645.29,646.49 1 0 +make-backend/internal/gql/generated.go:646.49,647.9 1 0 +make-backend/internal/gql/generated.go:650.3,650.68 1 0 +make-backend/internal/gql/generated.go:651.25,652.46 1 0 +make-backend/internal/gql/generated.go:652.46,653.9 1 0 +make-backend/internal/gql/generated.go:656.3,656.65 1 0 +make-backend/internal/gql/generated.go:658.31,659.52 1 0 +make-backend/internal/gql/generated.go:659.52,660.9 1 0 +make-backend/internal/gql/generated.go:663.3,663.71 1 0 +make-backend/internal/gql/generated.go:664.26,665.47 1 0 +make-backend/internal/gql/generated.go:665.47,666.9 1 0 +make-backend/internal/gql/generated.go:669.3,669.66 1 0 +make-backend/internal/gql/generated.go:670.22,671.43 1 0 +make-backend/internal/gql/generated.go:671.43,672.9 1 0 +make-backend/internal/gql/generated.go:675.3,675.62 1 0 +make-backend/internal/gql/generated.go:676.28,677.48 1 0 +make-backend/internal/gql/generated.go:677.48,678.9 1 0 +make-backend/internal/gql/generated.go:681.3,681.67 1 0 +make-backend/internal/gql/generated.go:682.24,683.45 1 0 +make-backend/internal/gql/generated.go:683.45,684.9 1 0 +make-backend/internal/gql/generated.go:687.3,687.64 1 0 +make-backend/internal/gql/generated.go:688.33,689.53 1 0 +make-backend/internal/gql/generated.go:689.53,690.9 1 0 +make-backend/internal/gql/generated.go:693.3,693.72 1 0 +make-backend/internal/gql/generated.go:694.38,695.57 1 0 +make-backend/internal/gql/generated.go:695.57,696.9 1 0 +make-backend/internal/gql/generated.go:699.3,699.76 1 0 +make-backend/internal/gql/generated.go:700.36,701.56 1 0 +make-backend/internal/gql/generated.go:701.56,702.9 1 0 +make-backend/internal/gql/generated.go:705.3,705.75 1 0 +make-backend/internal/gql/generated.go:706.30,707.51 1 0 +make-backend/internal/gql/generated.go:707.51,708.9 1 0 +make-backend/internal/gql/generated.go:711.3,711.70 1 0 +make-backend/internal/gql/generated.go:712.44,713.64 1 0 +make-backend/internal/gql/generated.go:713.64,714.9 1 0 +make-backend/internal/gql/generated.go:717.3,717.83 1 0 +make-backend/internal/gql/generated.go:718.36,719.56 1 0 +make-backend/internal/gql/generated.go:719.56,720.9 1 0 +make-backend/internal/gql/generated.go:723.3,723.75 1 0 +make-backend/internal/gql/generated.go:724.32,725.51 1 0 +make-backend/internal/gql/generated.go:725.51,726.9 1 0 +make-backend/internal/gql/generated.go:729.3,729.70 1 0 +make-backend/internal/gql/generated.go:730.27,731.47 1 0 +make-backend/internal/gql/generated.go:731.47,732.9 1 0 +make-backend/internal/gql/generated.go:735.3,735.66 1 0 +make-backend/internal/gql/generated.go:736.28,737.48 1 0 +make-backend/internal/gql/generated.go:737.48,738.9 1 0 +make-backend/internal/gql/generated.go:741.3,741.67 1 0 +make-backend/internal/gql/generated.go:742.27,743.47 1 0 +make-backend/internal/gql/generated.go:743.47,744.9 1 0 +make-backend/internal/gql/generated.go:747.3,747.66 1 0 +make-backend/internal/gql/generated.go:749.45,750.64 1 0 +make-backend/internal/gql/generated.go:750.64,751.9 1 0 +make-backend/internal/gql/generated.go:754.3,754.83 1 0 +make-backend/internal/gql/generated.go:755.40,756.60 1 0 +make-backend/internal/gql/generated.go:756.60,757.9 1 0 +make-backend/internal/gql/generated.go:760.3,760.79 1 0 +make-backend/internal/gql/generated.go:761.30,762.51 1 0 +make-backend/internal/gql/generated.go:762.51,763.9 1 0 +make-backend/internal/gql/generated.go:766.3,766.70 1 0 +make-backend/internal/gql/generated.go:767.32,768.53 1 0 +make-backend/internal/gql/generated.go:768.53,769.9 1 0 +make-backend/internal/gql/generated.go:772.3,772.72 1 0 +make-backend/internal/gql/generated.go:774.27,775.48 1 0 +make-backend/internal/gql/generated.go:775.48,776.9 1 0 +make-backend/internal/gql/generated.go:779.3,779.67 1 0 +make-backend/internal/gql/generated.go:780.18,781.39 1 0 +make-backend/internal/gql/generated.go:781.39,782.9 1 0 +make-backend/internal/gql/generated.go:785.3,785.58 1 0 +make-backend/internal/gql/generated.go:786.26,787.46 1 0 +make-backend/internal/gql/generated.go:787.46,788.9 1 0 +make-backend/internal/gql/generated.go:791.3,791.65 1 0 +make-backend/internal/gql/generated.go:792.20,793.41 1 0 +make-backend/internal/gql/generated.go:793.41,794.9 1 0 +make-backend/internal/gql/generated.go:797.3,797.60 1 0 +make-backend/internal/gql/generated.go:799.26,800.46 1 0 +make-backend/internal/gql/generated.go:800.46,801.9 1 0 +make-backend/internal/gql/generated.go:804.3,804.65 1 0 +make-backend/internal/gql/generated.go:805.25,806.45 1 0 +make-backend/internal/gql/generated.go:806.45,807.9 1 0 +make-backend/internal/gql/generated.go:810.3,810.64 1 0 +make-backend/internal/gql/generated.go:811.17,812.38 1 0 +make-backend/internal/gql/generated.go:812.38,813.9 1 0 +make-backend/internal/gql/generated.go:816.3,816.57 1 0 +make-backend/internal/gql/generated.go:817.21,818.42 1 0 +make-backend/internal/gql/generated.go:818.42,819.9 1 0 +make-backend/internal/gql/generated.go:822.3,822.61 1 0 +make-backend/internal/gql/generated.go:823.26,824.46 1 0 +make-backend/internal/gql/generated.go:824.46,825.9 1 0 +make-backend/internal/gql/generated.go:828.3,828.65 1 0 +make-backend/internal/gql/generated.go:829.25,830.45 1 0 +make-backend/internal/gql/generated.go:830.45,831.9 1 0 +make-backend/internal/gql/generated.go:834.3,834.64 1 0 +make-backend/internal/gql/generated.go:835.24,836.44 1 0 +make-backend/internal/gql/generated.go:836.44,837.9 1 0 +make-backend/internal/gql/generated.go:840.3,840.63 1 0 +make-backend/internal/gql/generated.go:842.18,843.39 1 0 +make-backend/internal/gql/generated.go:843.39,844.9 1 0 +make-backend/internal/gql/generated.go:847.3,847.58 1 0 +make-backend/internal/gql/generated.go:848.26,849.47 1 0 +make-backend/internal/gql/generated.go:849.47,850.9 1 0 +make-backend/internal/gql/generated.go:853.3,853.66 1 0 +make-backend/internal/gql/generated.go:855.29,856.49 1 0 +make-backend/internal/gql/generated.go:856.49,857.9 1 0 +make-backend/internal/gql/generated.go:860.3,860.68 1 0 +make-backend/internal/gql/generated.go:861.28,862.49 1 0 +make-backend/internal/gql/generated.go:862.49,863.9 1 0 +make-backend/internal/gql/generated.go:866.3,866.68 1 0 +make-backend/internal/gql/generated.go:867.25,868.46 1 0 +make-backend/internal/gql/generated.go:868.46,869.9 1 0 +make-backend/internal/gql/generated.go:872.3,872.65 1 0 +make-backend/internal/gql/generated.go:874.32,875.53 1 0 +make-backend/internal/gql/generated.go:875.53,876.9 1 0 +make-backend/internal/gql/generated.go:879.3,879.72 1 0 +make-backend/internal/gql/generated.go:880.29,881.49 1 0 +make-backend/internal/gql/generated.go:881.49,882.9 1 0 +make-backend/internal/gql/generated.go:885.3,885.68 1 0 +make-backend/internal/gql/generated.go:886.27,887.48 1 0 +make-backend/internal/gql/generated.go:887.48,888.9 1 0 +make-backend/internal/gql/generated.go:891.3,891.67 1 0 +make-backend/internal/gql/generated.go:892.26,893.47 1 0 +make-backend/internal/gql/generated.go:893.47,894.9 1 0 +make-backend/internal/gql/generated.go:897.3,897.66 1 0 +make-backend/internal/gql/generated.go:898.23,899.44 1 0 +make-backend/internal/gql/generated.go:899.44,900.9 1 0 +make-backend/internal/gql/generated.go:903.3,903.63 1 0 +make-backend/internal/gql/generated.go:904.29,905.49 1 0 +make-backend/internal/gql/generated.go:905.49,906.9 1 0 +make-backend/internal/gql/generated.go:909.3,909.68 1 0 +make-backend/internal/gql/generated.go:910.25,911.46 1 0 +make-backend/internal/gql/generated.go:911.46,912.9 1 0 +make-backend/internal/gql/generated.go:915.3,915.65 1 0 +make-backend/internal/gql/generated.go:916.29,917.50 1 0 +make-backend/internal/gql/generated.go:917.50,918.9 1 0 +make-backend/internal/gql/generated.go:921.3,921.69 1 0 +make-backend/internal/gql/generated.go:922.29,923.50 1 0 +make-backend/internal/gql/generated.go:923.50,924.9 1 0 +make-backend/internal/gql/generated.go:927.3,927.69 1 0 +make-backend/internal/gql/generated.go:928.26,929.47 1 0 +make-backend/internal/gql/generated.go:929.47,930.9 1 0 +make-backend/internal/gql/generated.go:933.3,933.66 1 0 +make-backend/internal/gql/generated.go:935.34,936.55 1 0 +make-backend/internal/gql/generated.go:936.55,937.9 1 0 +make-backend/internal/gql/generated.go:940.3,940.74 1 0 +make-backend/internal/gql/generated.go:941.42,942.63 1 0 +make-backend/internal/gql/generated.go:942.63,943.9 1 0 +make-backend/internal/gql/generated.go:946.3,946.82 1 0 +make-backend/internal/gql/generated.go:948.35,949.56 1 0 +make-backend/internal/gql/generated.go:949.56,950.9 1 0 +make-backend/internal/gql/generated.go:953.3,954.17 2 0 +make-backend/internal/gql/generated.go:954.17,956.4 1 0 +make-backend/internal/gql/generated.go:958.3,958.121 1 0 +make-backend/internal/gql/generated.go:959.35,960.56 1 0 +make-backend/internal/gql/generated.go:960.56,961.9 1 0 +make-backend/internal/gql/generated.go:964.3,965.17 2 0 +make-backend/internal/gql/generated.go:965.17,967.4 1 0 +make-backend/internal/gql/generated.go:969.3,969.93 1 0 +make-backend/internal/gql/generated.go:971.33,972.54 1 0 +make-backend/internal/gql/generated.go:972.54,973.9 1 0 +make-backend/internal/gql/generated.go:976.3,976.73 1 0 +make-backend/internal/gql/generated.go:977.30,978.50 1 0 +make-backend/internal/gql/generated.go:978.50,979.9 1 0 +make-backend/internal/gql/generated.go:982.3,982.69 1 0 +make-backend/internal/gql/generated.go:983.29,984.50 1 0 +make-backend/internal/gql/generated.go:984.50,985.9 1 0 +make-backend/internal/gql/generated.go:988.3,988.69 1 0 +make-backend/internal/gql/generated.go:989.26,990.47 1 0 +make-backend/internal/gql/generated.go:990.47,991.9 1 0 +make-backend/internal/gql/generated.go:994.3,994.66 1 0 +make-backend/internal/gql/generated.go:995.29,996.50 1 0 +make-backend/internal/gql/generated.go:996.50,997.9 1 0 +make-backend/internal/gql/generated.go:1000.3,1000.69 1 0 +make-backend/internal/gql/generated.go:1001.26,1002.47 1 0 +make-backend/internal/gql/generated.go:1002.47,1003.9 1 0 +make-backend/internal/gql/generated.go:1006.3,1006.66 1 0 +make-backend/internal/gql/generated.go:1008.35,1009.56 1 0 +make-backend/internal/gql/generated.go:1009.56,1010.9 1 0 +make-backend/internal/gql/generated.go:1013.3,1013.75 1 0 +make-backend/internal/gql/generated.go:1014.32,1015.53 1 0 +make-backend/internal/gql/generated.go:1015.53,1016.9 1 0 +make-backend/internal/gql/generated.go:1019.3,1019.72 1 0 +make-backend/internal/gql/generated.go:1021.35,1022.55 1 0 +make-backend/internal/gql/generated.go:1022.55,1023.9 1 0 +make-backend/internal/gql/generated.go:1026.3,1026.74 1 0 +make-backend/internal/gql/generated.go:1027.28,1028.49 1 0 +make-backend/internal/gql/generated.go:1028.49,1029.9 1 0 +make-backend/internal/gql/generated.go:1032.3,1032.68 1 0 +make-backend/internal/gql/generated.go:1033.25,1034.46 1 0 +make-backend/internal/gql/generated.go:1034.46,1035.9 1 0 +make-backend/internal/gql/generated.go:1038.3,1038.65 1 0 +make-backend/internal/gql/generated.go:1039.28,1040.49 1 0 +make-backend/internal/gql/generated.go:1040.49,1041.9 1 0 +make-backend/internal/gql/generated.go:1044.3,1044.68 1 0 +make-backend/internal/gql/generated.go:1046.28,1047.49 1 0 +make-backend/internal/gql/generated.go:1047.49,1048.9 1 0 +make-backend/internal/gql/generated.go:1051.3,1052.17 2 0 +make-backend/internal/gql/generated.go:1052.17,1054.4 1 0 +make-backend/internal/gql/generated.go:1056.3,1056.86 1 0 +make-backend/internal/gql/generated.go:1057.35,1058.56 1 0 +make-backend/internal/gql/generated.go:1058.56,1059.9 1 0 +make-backend/internal/gql/generated.go:1062.3,1063.17 2 0 +make-backend/internal/gql/generated.go:1063.17,1065.4 1 0 +make-backend/internal/gql/generated.go:1067.3,1067.123 1 0 +make-backend/internal/gql/generated.go:1068.34,1069.55 1 0 +make-backend/internal/gql/generated.go:1069.55,1070.9 1 0 +make-backend/internal/gql/generated.go:1073.3,1074.17 2 0 +make-backend/internal/gql/generated.go:1074.17,1076.4 1 0 +make-backend/internal/gql/generated.go:1078.3,1078.122 1 0 +make-backend/internal/gql/generated.go:1079.27,1080.48 1 0 +make-backend/internal/gql/generated.go:1080.48,1081.9 1 0 +make-backend/internal/gql/generated.go:1084.3,1084.67 1 0 +make-backend/internal/gql/generated.go:1085.22,1086.43 1 0 +make-backend/internal/gql/generated.go:1086.43,1087.9 1 0 +make-backend/internal/gql/generated.go:1090.3,1091.17 2 0 +make-backend/internal/gql/generated.go:1091.17,1093.4 1 0 +make-backend/internal/gql/generated.go:1095.3,1095.80 1 0 +make-backend/internal/gql/generated.go:1096.25,1097.46 1 0 +make-backend/internal/gql/generated.go:1097.46,1098.9 1 0 +make-backend/internal/gql/generated.go:1101.3,1102.17 2 0 +make-backend/internal/gql/generated.go:1102.17,1104.4 1 0 +make-backend/internal/gql/generated.go:1106.3,1106.83 1 0 +make-backend/internal/gql/generated.go:1108.29,1109.50 1 0 +make-backend/internal/gql/generated.go:1109.50,1110.9 1 0 +make-backend/internal/gql/generated.go:1113.3,1114.17 2 0 +make-backend/internal/gql/generated.go:1114.17,1116.4 1 0 +make-backend/internal/gql/generated.go:1118.3,1118.114 1 0 +make-backend/internal/gql/generated.go:1119.37,1120.58 1 0 +make-backend/internal/gql/generated.go:1120.58,1121.9 1 0 +make-backend/internal/gql/generated.go:1124.3,1125.17 2 0 +make-backend/internal/gql/generated.go:1125.17,1127.4 1 0 +make-backend/internal/gql/generated.go:1129.3,1129.122 1 0 +make-backend/internal/gql/generated.go:1130.26,1131.47 1 0 +make-backend/internal/gql/generated.go:1131.47,1132.9 1 0 +make-backend/internal/gql/generated.go:1135.3,1136.17 2 0 +make-backend/internal/gql/generated.go:1136.17,1138.4 1 0 +make-backend/internal/gql/generated.go:1140.3,1140.84 1 0 +make-backend/internal/gql/generated.go:1141.30,1142.51 1 0 +make-backend/internal/gql/generated.go:1142.51,1143.9 1 0 +make-backend/internal/gql/generated.go:1146.3,1147.17 2 0 +make-backend/internal/gql/generated.go:1147.17,1149.4 1 0 +make-backend/internal/gql/generated.go:1151.3,1151.93 1 0 +make-backend/internal/gql/generated.go:1152.20,1153.41 1 0 +make-backend/internal/gql/generated.go:1153.41,1154.9 1 0 +make-backend/internal/gql/generated.go:1157.3,1158.17 2 0 +make-backend/internal/gql/generated.go:1158.17,1160.4 1 0 +make-backend/internal/gql/generated.go:1162.3,1162.78 1 0 +make-backend/internal/gql/generated.go:1163.20,1164.41 1 0 +make-backend/internal/gql/generated.go:1164.41,1165.9 1 0 +make-backend/internal/gql/generated.go:1168.3,1169.17 2 0 +make-backend/internal/gql/generated.go:1169.17,1171.4 1 0 +make-backend/internal/gql/generated.go:1173.3,1173.78 1 0 +make-backend/internal/gql/generated.go:1174.35,1175.56 1 0 +make-backend/internal/gql/generated.go:1175.56,1176.9 1 0 +make-backend/internal/gql/generated.go:1179.3,1180.17 2 0 +make-backend/internal/gql/generated.go:1180.17,1182.4 1 0 +make-backend/internal/gql/generated.go:1184.3,1184.104 1 0 +make-backend/internal/gql/generated.go:1186.30,1187.51 1 0 +make-backend/internal/gql/generated.go:1187.51,1188.9 1 0 +make-backend/internal/gql/generated.go:1191.3,1191.70 1 0 +make-backend/internal/gql/generated.go:1192.33,1193.54 1 0 +make-backend/internal/gql/generated.go:1193.54,1194.9 1 0 +make-backend/internal/gql/generated.go:1197.3,1197.73 1 0 +make-backend/internal/gql/generated.go:1198.30,1199.50 1 0 +make-backend/internal/gql/generated.go:1199.50,1200.9 1 0 +make-backend/internal/gql/generated.go:1203.3,1203.69 1 0 +make-backend/internal/gql/generated.go:1204.34,1205.54 1 0 +make-backend/internal/gql/generated.go:1205.54,1206.9 1 0 +make-backend/internal/gql/generated.go:1209.3,1209.73 1 0 +make-backend/internal/gql/generated.go:1210.24,1211.45 1 0 +make-backend/internal/gql/generated.go:1211.45,1212.9 1 0 +make-backend/internal/gql/generated.go:1215.3,1215.64 1 0 +make-backend/internal/gql/generated.go:1216.37,1217.57 1 0 +make-backend/internal/gql/generated.go:1217.57,1218.9 1 0 +make-backend/internal/gql/generated.go:1221.3,1221.76 1 0 +make-backend/internal/gql/generated.go:1222.32,1223.52 1 0 +make-backend/internal/gql/generated.go:1223.52,1224.9 1 0 +make-backend/internal/gql/generated.go:1227.3,1227.71 1 0 +make-backend/internal/gql/generated.go:1228.29,1229.49 1 0 +make-backend/internal/gql/generated.go:1229.49,1230.9 1 0 +make-backend/internal/gql/generated.go:1233.3,1233.68 1 0 +make-backend/internal/gql/generated.go:1235.33,1236.53 1 0 +make-backend/internal/gql/generated.go:1236.53,1237.9 1 0 +make-backend/internal/gql/generated.go:1240.3,1240.72 1 0 +make-backend/internal/gql/generated.go:1241.32,1242.52 1 0 +make-backend/internal/gql/generated.go:1242.52,1243.9 1 0 +make-backend/internal/gql/generated.go:1246.3,1246.71 1 0 +make-backend/internal/gql/generated.go:1247.24,1248.45 1 0 +make-backend/internal/gql/generated.go:1248.45,1249.9 1 0 +make-backend/internal/gql/generated.go:1252.3,1252.64 1 0 +make-backend/internal/gql/generated.go:1253.35,1254.55 1 0 +make-backend/internal/gql/generated.go:1254.55,1255.9 1 0 +make-backend/internal/gql/generated.go:1258.3,1258.74 1 0 +make-backend/internal/gql/generated.go:1259.28,1260.49 1 0 +make-backend/internal/gql/generated.go:1260.49,1261.9 1 0 +make-backend/internal/gql/generated.go:1264.3,1264.68 1 0 +make-backend/internal/gql/generated.go:1265.31,1266.51 1 0 +make-backend/internal/gql/generated.go:1266.51,1267.9 1 0 +make-backend/internal/gql/generated.go:1270.3,1270.70 1 0 +make-backend/internal/gql/generated.go:1272.38,1273.59 1 0 +make-backend/internal/gql/generated.go:1273.59,1274.9 1 0 +make-backend/internal/gql/generated.go:1277.3,1277.78 1 0 +make-backend/internal/gql/generated.go:1278.33,1279.54 1 0 +make-backend/internal/gql/generated.go:1279.54,1280.9 1 0 +make-backend/internal/gql/generated.go:1283.3,1283.73 1 0 +make-backend/internal/gql/generated.go:1284.35,1285.55 1 0 +make-backend/internal/gql/generated.go:1285.55,1286.9 1 0 +make-backend/internal/gql/generated.go:1289.3,1289.74 1 0 +make-backend/internal/gql/generated.go:1290.34,1291.55 1 0 +make-backend/internal/gql/generated.go:1291.55,1292.9 1 0 +make-backend/internal/gql/generated.go:1295.3,1295.74 1 0 +make-backend/internal/gql/generated.go:1296.31,1297.52 1 0 +make-backend/internal/gql/generated.go:1297.52,1298.9 1 0 +make-backend/internal/gql/generated.go:1301.3,1301.71 1 0 +make-backend/internal/gql/generated.go:1302.31,1303.52 1 0 +make-backend/internal/gql/generated.go:1303.52,1304.9 1 0 +make-backend/internal/gql/generated.go:1307.3,1307.71 1 0 +make-backend/internal/gql/generated.go:1309.33,1310.53 1 0 +make-backend/internal/gql/generated.go:1310.53,1311.9 1 0 +make-backend/internal/gql/generated.go:1314.3,1314.72 1 0 +make-backend/internal/gql/generated.go:1315.29,1316.50 1 0 +make-backend/internal/gql/generated.go:1316.50,1317.9 1 0 +make-backend/internal/gql/generated.go:1320.3,1320.69 1 0 +make-backend/internal/gql/generated.go:1321.36,1322.56 1 0 +make-backend/internal/gql/generated.go:1322.56,1323.9 1 0 +make-backend/internal/gql/generated.go:1326.3,1326.75 1 0 +make-backend/internal/gql/generated.go:1327.32,1328.52 1 0 +make-backend/internal/gql/generated.go:1328.52,1329.9 1 0 +make-backend/internal/gql/generated.go:1332.3,1332.71 1 0 +make-backend/internal/gql/generated.go:1333.35,1334.55 1 0 +make-backend/internal/gql/generated.go:1334.55,1335.9 1 0 +make-backend/internal/gql/generated.go:1338.3,1338.74 1 0 +make-backend/internal/gql/generated.go:1340.27,1341.47 1 0 +make-backend/internal/gql/generated.go:1341.47,1342.9 1 0 +make-backend/internal/gql/generated.go:1345.3,1345.66 1 0 +make-backend/internal/gql/generated.go:1346.21,1347.42 1 0 +make-backend/internal/gql/generated.go:1347.42,1348.9 1 0 +make-backend/internal/gql/generated.go:1351.3,1351.61 1 0 +make-backend/internal/gql/generated.go:1352.25,1353.46 1 0 +make-backend/internal/gql/generated.go:1353.46,1354.9 1 0 +make-backend/internal/gql/generated.go:1357.3,1357.65 1 0 +make-backend/internal/gql/generated.go:1358.26,1359.46 1 0 +make-backend/internal/gql/generated.go:1359.46,1360.9 1 0 +make-backend/internal/gql/generated.go:1363.3,1363.65 1 0 +make-backend/internal/gql/generated.go:1365.28,1366.48 1 0 +make-backend/internal/gql/generated.go:1366.48,1367.9 1 0 +make-backend/internal/gql/generated.go:1370.3,1370.67 1 0 +make-backend/internal/gql/generated.go:1371.27,1372.48 1 0 +make-backend/internal/gql/generated.go:1372.48,1373.9 1 0 +make-backend/internal/gql/generated.go:1376.3,1376.67 1 0 +make-backend/internal/gql/generated.go:1377.24,1378.45 1 0 +make-backend/internal/gql/generated.go:1378.45,1379.9 1 0 +make-backend/internal/gql/generated.go:1382.3,1382.64 1 0 +make-backend/internal/gql/generated.go:1384.25,1385.46 1 0 +make-backend/internal/gql/generated.go:1385.46,1386.9 1 0 +make-backend/internal/gql/generated.go:1389.3,1389.65 1 0 +make-backend/internal/gql/generated.go:1390.21,1391.42 1 0 +make-backend/internal/gql/generated.go:1391.42,1392.9 1 0 +make-backend/internal/gql/generated.go:1395.3,1395.61 1 0 +make-backend/internal/gql/generated.go:1396.32,1397.52 1 0 +make-backend/internal/gql/generated.go:1397.52,1398.9 1 0 +make-backend/internal/gql/generated.go:1401.3,1401.71 1 0 +make-backend/internal/gql/generated.go:1402.23,1403.44 1 0 +make-backend/internal/gql/generated.go:1403.44,1404.9 1 0 +make-backend/internal/gql/generated.go:1407.3,1407.63 1 0 +make-backend/internal/gql/generated.go:1409.20,1410.41 1 0 +make-backend/internal/gql/generated.go:1410.41,1411.9 1 0 +make-backend/internal/gql/generated.go:1414.3,1414.60 1 0 +make-backend/internal/gql/generated.go:1415.23,1416.44 1 0 +make-backend/internal/gql/generated.go:1416.44,1417.9 1 0 +make-backend/internal/gql/generated.go:1420.3,1420.63 1 0 +make-backend/internal/gql/generated.go:1421.23,1422.43 1 0 +make-backend/internal/gql/generated.go:1422.43,1423.9 1 0 +make-backend/internal/gql/generated.go:1426.3,1426.62 1 0 +make-backend/internal/gql/generated.go:1427.20,1428.41 1 0 +make-backend/internal/gql/generated.go:1428.41,1429.9 1 0 +make-backend/internal/gql/generated.go:1432.3,1432.60 1 0 +make-backend/internal/gql/generated.go:1433.24,1434.45 1 0 +make-backend/internal/gql/generated.go:1434.45,1435.9 1 0 +make-backend/internal/gql/generated.go:1438.3,1438.64 1 0 +make-backend/internal/gql/generated.go:1439.28,1440.48 1 0 +make-backend/internal/gql/generated.go:1440.48,1441.9 1 0 +make-backend/internal/gql/generated.go:1444.3,1444.67 1 0 +make-backend/internal/gql/generated.go:1445.17,1446.38 1 0 +make-backend/internal/gql/generated.go:1446.38,1447.9 1 0 +make-backend/internal/gql/generated.go:1450.3,1450.57 1 0 +make-backend/internal/gql/generated.go:1451.24,1452.44 1 0 +make-backend/internal/gql/generated.go:1452.44,1453.9 1 0 +make-backend/internal/gql/generated.go:1456.3,1456.63 1 0 +make-backend/internal/gql/generated.go:1457.23,1458.44 1 0 +make-backend/internal/gql/generated.go:1458.44,1459.9 1 0 +make-backend/internal/gql/generated.go:1462.3,1462.63 1 0 +make-backend/internal/gql/generated.go:1463.20,1464.41 1 0 +make-backend/internal/gql/generated.go:1464.41,1465.9 1 0 +make-backend/internal/gql/generated.go:1468.3,1468.60 1 0 +make-backend/internal/gql/generated.go:1469.23,1470.44 1 0 +make-backend/internal/gql/generated.go:1470.44,1471.9 1 0 +make-backend/internal/gql/generated.go:1474.3,1474.63 1 0 +make-backend/internal/gql/generated.go:1475.29,1476.49 1 0 +make-backend/internal/gql/generated.go:1476.49,1477.9 1 0 +make-backend/internal/gql/generated.go:1480.3,1480.68 1 0 +make-backend/internal/gql/generated.go:1482.21,1483.42 1 0 +make-backend/internal/gql/generated.go:1483.42,1484.9 1 0 +make-backend/internal/gql/generated.go:1487.3,1487.61 1 0 +make-backend/internal/gql/generated.go:1488.17,1489.38 1 0 +make-backend/internal/gql/generated.go:1489.38,1490.9 1 0 +make-backend/internal/gql/generated.go:1493.3,1493.57 1 0 +make-backend/internal/gql/generated.go:1494.28,1495.48 1 0 +make-backend/internal/gql/generated.go:1495.48,1496.9 1 0 +make-backend/internal/gql/generated.go:1499.3,1499.67 1 0 +make-backend/internal/gql/generated.go:1500.19,1501.40 1 0 +make-backend/internal/gql/generated.go:1501.40,1502.9 1 0 +make-backend/internal/gql/generated.go:1505.3,1505.59 1 0 +make-backend/internal/gql/generated.go:1508.2,1508.17 1 0 +make-backend/internal/gql/generated.go:1511.78,1517.35 5 0 +make-backend/internal/gql/generated.go:1518.17,1519.54 1 0 +make-backend/internal/gql/generated.go:1519.54,1522.13 3 0 +make-backend/internal/gql/generated.go:1522.13,1526.5 3 0 +make-backend/internal/gql/generated.go:1526.10,1527.50 1 0 +make-backend/internal/gql/generated.go:1527.50,1534.6 6 0 +make-backend/internal/gql/generated.go:1534.11,1536.6 1 0 +make-backend/internal/gql/generated.go:1538.4,1541.42 4 0 +make-backend/internal/gql/generated.go:1541.42,1544.5 2 0 +make-backend/internal/gql/generated.go:1546.4,1546.20 1 0 +make-backend/internal/gql/generated.go:1548.20,1549.54 1 0 +make-backend/internal/gql/generated.go:1549.54,1550.14 1 0 +make-backend/internal/gql/generated.go:1550.14,1552.5 1 0 +make-backend/internal/gql/generated.go:1553.4,1561.5 6 0 +make-backend/internal/gql/generated.go:1564.10,1565.86 1 0 +make-backend/internal/gql/generated.go:1577.21,1586.2 1 0 +make-backend/internal/gql/generated.go:1591.41,1593.16 2 0 +make-backend/internal/gql/generated.go:1593.16,1594.68 1 0 +make-backend/internal/gql/generated.go:1596.2,1596.21 1 0 +make-backend/internal/gql/generated.go:1624.139,1625.20 1 0 +make-backend/internal/gql/generated.go:1626.12,1627.56 1 0 +make-backend/internal/gql/generated.go:1628.14,1629.58 1 0 +make-backend/internal/gql/generated.go:1630.18,1631.62 1 0 +make-backend/internal/gql/generated.go:1633.2,1633.94 1 0 +make-backend/internal/gql/generated.go:1636.140,1637.20 1 0 +make-backend/internal/gql/generated.go:1638.12,1639.57 1 0 +make-backend/internal/gql/generated.go:1640.20,1641.65 1 0 +make-backend/internal/gql/generated.go:1643.2,1643.95 1 0 +make-backend/internal/gql/generated.go:1646.136,1647.20 1 0 +make-backend/internal/gql/generated.go:1648.16,1649.57 1 0 +make-backend/internal/gql/generated.go:1650.18,1651.59 1 0 +make-backend/internal/gql/generated.go:1652.23,1653.64 1 0 +make-backend/internal/gql/generated.go:1654.26,1655.67 1 0 +make-backend/internal/gql/generated.go:1656.21,1657.62 1 0 +make-backend/internal/gql/generated.go:1658.23,1659.64 1 0 +make-backend/internal/gql/generated.go:1660.15,1661.56 1 0 +make-backend/internal/gql/generated.go:1662.27,1663.68 1 0 +make-backend/internal/gql/generated.go:1664.29,1665.70 1 0 +make-backend/internal/gql/generated.go:1667.2,1667.91 1 0 +make-backend/internal/gql/generated.go:1670.141,1671.20 1 0 +make-backend/internal/gql/generated.go:1672.24,1673.70 1 0 +make-backend/internal/gql/generated.go:1674.29,1675.75 1 0 +make-backend/internal/gql/generated.go:1676.19,1677.65 1 0 +make-backend/internal/gql/generated.go:1679.2,1679.96 1 0 +make-backend/internal/gql/generated.go:1682.130,1683.20 1 0 +make-backend/internal/gql/generated.go:1684.12,1685.47 1 0 +make-backend/internal/gql/generated.go:1686.14,1687.49 1 0 +make-backend/internal/gql/generated.go:1688.12,1689.47 1 0 +make-backend/internal/gql/generated.go:1690.16,1691.51 1 0 +make-backend/internal/gql/generated.go:1692.18,1693.53 1 0 +make-backend/internal/gql/generated.go:1694.18,1695.53 1 0 +make-backend/internal/gql/generated.go:1696.25,1697.60 1 0 +make-backend/internal/gql/generated.go:1698.19,1699.54 1 0 +make-backend/internal/gql/generated.go:1700.23,1701.58 1 0 +make-backend/internal/gql/generated.go:1703.2,1703.85 1 0 +make-backend/internal/gql/generated.go:1706.129,1707.20 1 0 +make-backend/internal/gql/generated.go:1708.12,1709.46 1 0 +make-backend/internal/gql/generated.go:1710.20,1711.54 1 0 +make-backend/internal/gql/generated.go:1712.14,1713.48 1 0 +make-backend/internal/gql/generated.go:1714.21,1715.55 1 0 +make-backend/internal/gql/generated.go:1717.2,1717.84 1 0 +make-backend/internal/gql/generated.go:1720.134,1721.20 1 0 +make-backend/internal/gql/generated.go:1722.12,1723.51 1 0 +make-backend/internal/gql/generated.go:1724.14,1725.53 1 0 +make-backend/internal/gql/generated.go:1726.18,1727.57 1 0 +make-backend/internal/gql/generated.go:1728.21,1729.60 1 0 +make-backend/internal/gql/generated.go:1730.18,1731.57 1 0 +make-backend/internal/gql/generated.go:1732.18,1733.57 1 0 +make-backend/internal/gql/generated.go:1734.16,1735.55 1 0 +make-backend/internal/gql/generated.go:1736.18,1737.57 1 0 +make-backend/internal/gql/generated.go:1738.15,1739.54 1 0 +make-backend/internal/gql/generated.go:1740.15,1741.54 1 0 +make-backend/internal/gql/generated.go:1743.2,1743.89 1 0 +make-backend/internal/gql/generated.go:1746.141,1747.20 1 0 +make-backend/internal/gql/generated.go:1748.16,1749.62 1 0 +make-backend/internal/gql/generated.go:1750.24,1751.70 1 0 +make-backend/internal/gql/generated.go:1753.2,1753.96 1 0 +make-backend/internal/gql/generated.go:1756.141,1757.20 1 0 +make-backend/internal/gql/generated.go:1758.14,1759.60 1 0 +make-backend/internal/gql/generated.go:1760.17,1761.63 1 0 +make-backend/internal/gql/generated.go:1763.2,1763.96 1 0 +make-backend/internal/gql/generated.go:1766.128,1767.20 1 0 +make-backend/internal/gql/generated.go:1768.12,1769.45 1 0 +make-backend/internal/gql/generated.go:1770.15,1771.48 1 0 +make-backend/internal/gql/generated.go:1772.19,1773.52 1 0 +make-backend/internal/gql/generated.go:1774.18,1775.51 1 0 +make-backend/internal/gql/generated.go:1776.18,1777.51 1 0 +make-backend/internal/gql/generated.go:1778.19,1779.52 1 0 +make-backend/internal/gql/generated.go:1780.24,1781.57 1 0 +make-backend/internal/gql/generated.go:1782.18,1783.51 1 0 +make-backend/internal/gql/generated.go:1784.15,1785.48 1 0 +make-backend/internal/gql/generated.go:1786.15,1787.48 1 0 +make-backend/internal/gql/generated.go:1788.23,1789.56 1 0 +make-backend/internal/gql/generated.go:1790.18,1791.51 1 0 +make-backend/internal/gql/generated.go:1793.2,1793.83 1 0 +make-backend/internal/gql/generated.go:1796.128,1797.20 1 0 +make-backend/internal/gql/generated.go:1798.12,1799.45 1 0 +make-backend/internal/gql/generated.go:1800.23,1801.56 1 0 +make-backend/internal/gql/generated.go:1802.14,1803.47 1 0 +make-backend/internal/gql/generated.go:1804.16,1805.49 1 0 +make-backend/internal/gql/generated.go:1807.2,1807.83 1 0 +make-backend/internal/gql/generated.go:1810.135,1811.20 1 0 +make-backend/internal/gql/generated.go:1812.14,1813.54 1 0 +make-backend/internal/gql/generated.go:1814.21,1815.61 1 0 +make-backend/internal/gql/generated.go:1816.22,1817.62 1 0 +make-backend/internal/gql/generated.go:1818.19,1819.59 1 0 +make-backend/internal/gql/generated.go:1820.14,1821.54 1 0 +make-backend/internal/gql/generated.go:1823.2,1823.90 1 0 +make-backend/internal/gql/generated.go:1826.135,1827.20 1 0 +make-backend/internal/gql/generated.go:1828.14,1829.54 1 0 +make-backend/internal/gql/generated.go:1830.21,1831.61 1 0 +make-backend/internal/gql/generated.go:1832.22,1833.62 1 0 +make-backend/internal/gql/generated.go:1834.27,1835.67 1 0 +make-backend/internal/gql/generated.go:1837.2,1837.90 1 0 +make-backend/internal/gql/generated.go:1840.131,1841.20 1 0 +make-backend/internal/gql/generated.go:1842.14,1843.50 1 0 +make-backend/internal/gql/generated.go:1844.21,1845.57 1 0 +make-backend/internal/gql/generated.go:1846.14,1847.50 1 0 +make-backend/internal/gql/generated.go:1848.14,1849.50 1 0 +make-backend/internal/gql/generated.go:1850.22,1851.58 1 0 +make-backend/internal/gql/generated.go:1852.27,1853.63 1 0 +make-backend/internal/gql/generated.go:1855.2,1855.86 1 0 +make-backend/internal/gql/generated.go:1858.136,1859.20 1 0 +make-backend/internal/gql/generated.go:1860.14,1861.55 1 0 +make-backend/internal/gql/generated.go:1862.21,1863.62 1 0 +make-backend/internal/gql/generated.go:1864.14,1865.55 1 0 +make-backend/internal/gql/generated.go:1866.22,1867.63 1 0 +make-backend/internal/gql/generated.go:1868.22,1869.63 1 0 +make-backend/internal/gql/generated.go:1870.27,1871.68 1 0 +make-backend/internal/gql/generated.go:1873.2,1873.91 1 0 +make-backend/internal/gql/generated.go:1876.132,1877.20 1 0 +make-backend/internal/gql/generated.go:1878.21,1879.58 1 0 +make-backend/internal/gql/generated.go:1880.15,1881.52 1 0 +make-backend/internal/gql/generated.go:1882.19,1883.56 1 0 +make-backend/internal/gql/generated.go:1884.22,1885.59 1 0 +make-backend/internal/gql/generated.go:1886.26,1887.63 1 0 +make-backend/internal/gql/generated.go:1888.20,1889.57 1 0 +make-backend/internal/gql/generated.go:1891.2,1891.87 1 0 +make-backend/internal/gql/generated.go:1894.130,1895.20 1 0 +make-backend/internal/gql/generated.go:1896.14,1897.49 1 0 +make-backend/internal/gql/generated.go:1898.14,1899.49 1 0 +make-backend/internal/gql/generated.go:1900.21,1901.56 1 0 +make-backend/internal/gql/generated.go:1902.24,1903.59 1 0 +make-backend/internal/gql/generated.go:1904.16,1905.51 1 0 +make-backend/internal/gql/generated.go:1906.20,1907.55 1 0 +make-backend/internal/gql/generated.go:1908.23,1909.58 1 0 +make-backend/internal/gql/generated.go:1910.20,1911.55 1 0 +make-backend/internal/gql/generated.go:1912.21,1913.56 1 0 +make-backend/internal/gql/generated.go:1914.16,1915.51 1 0 +make-backend/internal/gql/generated.go:1916.17,1917.52 1 0 +make-backend/internal/gql/generated.go:1919.2,1919.85 1 0 +make-backend/internal/gql/generated.go:1926.135,1930.52 3 0 +make-backend/internal/gql/generated.go:1930.52,1932.4 1 0 +make-backend/internal/gql/generated.go:1933.2,1933.16 1 0 +make-backend/internal/gql/generated.go:1933.16,1935.3 1 0 +make-backend/internal/gql/generated.go:1936.2,1938.50 2 0 +make-backend/internal/gql/generated.go:1938.50,1940.4 1 0 +make-backend/internal/gql/generated.go:1941.2,1941.16 1 0 +make-backend/internal/gql/generated.go:1941.16,1943.3 1 0 +make-backend/internal/gql/generated.go:1944.2,1945.18 2 0 +make-backend/internal/gql/generated.go:1948.135,1952.49 3 0 +make-backend/internal/gql/generated.go:1952.49,1954.4 1 0 +make-backend/internal/gql/generated.go:1955.2,1955.16 1 0 +make-backend/internal/gql/generated.go:1955.16,1957.3 1 0 +make-backend/internal/gql/generated.go:1958.2,1959.18 2 0 +make-backend/internal/gql/generated.go:1962.122,1966.52 3 0 +make-backend/internal/gql/generated.go:1966.52,1968.4 1 0 +make-backend/internal/gql/generated.go:1969.2,1969.16 1 0 +make-backend/internal/gql/generated.go:1969.16,1971.3 1 0 +make-backend/internal/gql/generated.go:1972.2,1973.18 2 0 +make-backend/internal/gql/generated.go:1976.128,1980.49 3 0 +make-backend/internal/gql/generated.go:1980.49,1982.4 1 0 +make-backend/internal/gql/generated.go:1983.2,1983.16 1 0 +make-backend/internal/gql/generated.go:1983.16,1985.3 1 0 +make-backend/internal/gql/generated.go:1986.2,1987.18 2 0 +make-backend/internal/gql/generated.go:1990.135,1994.49 3 0 +make-backend/internal/gql/generated.go:1994.49,1996.4 1 0 +make-backend/internal/gql/generated.go:1997.2,1997.16 1 0 +make-backend/internal/gql/generated.go:1997.16,1999.3 1 0 +make-backend/internal/gql/generated.go:2000.2,2002.49 2 0 +make-backend/internal/gql/generated.go:2002.49,2004.4 1 0 +make-backend/internal/gql/generated.go:2005.2,2005.16 1 0 +make-backend/internal/gql/generated.go:2005.16,2007.3 1 0 +make-backend/internal/gql/generated.go:2008.2,2009.18 2 0 +make-backend/internal/gql/generated.go:2012.134,2016.49 3 0 +make-backend/internal/gql/generated.go:2016.49,2018.4 1 0 +make-backend/internal/gql/generated.go:2019.2,2019.16 1 0 +make-backend/internal/gql/generated.go:2019.16,2021.3 1 0 +make-backend/internal/gql/generated.go:2022.2,2024.49 2 0 +make-backend/internal/gql/generated.go:2024.49,2026.4 1 0 +make-backend/internal/gql/generated.go:2027.2,2027.16 1 0 +make-backend/internal/gql/generated.go:2027.16,2029.3 1 0 +make-backend/internal/gql/generated.go:2030.2,2031.18 2 0 +make-backend/internal/gql/generated.go:2034.122,2038.49 3 0 +make-backend/internal/gql/generated.go:2038.49,2040.4 1 0 +make-backend/internal/gql/generated.go:2041.2,2041.16 1 0 +make-backend/internal/gql/generated.go:2041.16,2043.3 1 0 +make-backend/internal/gql/generated.go:2044.2,2045.18 2 0 +make-backend/internal/gql/generated.go:2048.125,2052.49 3 0 +make-backend/internal/gql/generated.go:2052.49,2054.4 1 0 +make-backend/internal/gql/generated.go:2055.2,2055.16 1 0 +make-backend/internal/gql/generated.go:2055.16,2057.3 1 0 +make-backend/internal/gql/generated.go:2058.2,2059.18 2 0 +make-backend/internal/gql/generated.go:2062.137,2066.49 3 0 +make-backend/internal/gql/generated.go:2066.49,2068.4 1 0 +make-backend/internal/gql/generated.go:2069.2,2069.16 1 0 +make-backend/internal/gql/generated.go:2069.16,2071.3 1 0 +make-backend/internal/gql/generated.go:2072.2,2074.49 2 0 +make-backend/internal/gql/generated.go:2074.49,2076.4 1 0 +make-backend/internal/gql/generated.go:2077.2,2077.16 1 0 +make-backend/internal/gql/generated.go:2077.16,2079.3 1 0 +make-backend/internal/gql/generated.go:2080.2,2081.18 2 0 +make-backend/internal/gql/generated.go:2084.129,2088.49 3 0 +make-backend/internal/gql/generated.go:2088.49,2090.4 1 0 +make-backend/internal/gql/generated.go:2091.2,2091.16 1 0 +make-backend/internal/gql/generated.go:2091.16,2093.3 1 0 +make-backend/internal/gql/generated.go:2094.2,2096.49 2 0 +make-backend/internal/gql/generated.go:2096.49,2098.4 1 0 +make-backend/internal/gql/generated.go:2099.2,2099.16 1 0 +make-backend/internal/gql/generated.go:2099.16,2101.3 1 0 +make-backend/internal/gql/generated.go:2102.2,2103.18 2 0 +make-backend/internal/gql/generated.go:2106.126,2110.49 3 0 +make-backend/internal/gql/generated.go:2110.49,2112.4 1 0 +make-backend/internal/gql/generated.go:2113.2,2113.16 1 0 +make-backend/internal/gql/generated.go:2113.16,2115.3 1 0 +make-backend/internal/gql/generated.go:2116.2,2117.18 2 0 +make-backend/internal/gql/generated.go:2120.130,2124.49 3 0 +make-backend/internal/gql/generated.go:2124.49,2126.4 1 0 +make-backend/internal/gql/generated.go:2127.2,2127.16 1 0 +make-backend/internal/gql/generated.go:2127.16,2129.3 1 0 +make-backend/internal/gql/generated.go:2130.2,2131.18 2 0 +make-backend/internal/gql/generated.go:2134.120,2138.49 3 0 +make-backend/internal/gql/generated.go:2138.49,2140.4 1 0 +make-backend/internal/gql/generated.go:2141.2,2141.16 1 0 +make-backend/internal/gql/generated.go:2141.16,2143.3 1 0 +make-backend/internal/gql/generated.go:2144.2,2145.18 2 0 +make-backend/internal/gql/generated.go:2148.120,2152.49 3 0 +make-backend/internal/gql/generated.go:2152.49,2154.4 1 0 +make-backend/internal/gql/generated.go:2155.2,2155.16 1 0 +make-backend/internal/gql/generated.go:2155.16,2157.3 1 0 +make-backend/internal/gql/generated.go:2158.2,2159.18 2 0 +make-backend/internal/gql/generated.go:2162.135,2166.49 3 0 +make-backend/internal/gql/generated.go:2166.49,2168.4 1 0 +make-backend/internal/gql/generated.go:2169.2,2169.16 1 0 +make-backend/internal/gql/generated.go:2169.16,2171.3 1 0 +make-backend/internal/gql/generated.go:2172.2,2173.18 2 0 +make-backend/internal/gql/generated.go:2176.126,2180.51 3 0 +make-backend/internal/gql/generated.go:2180.51,2182.4 1 0 +make-backend/internal/gql/generated.go:2183.2,2183.16 1 0 +make-backend/internal/gql/generated.go:2183.16,2185.3 1 0 +make-backend/internal/gql/generated.go:2186.2,2187.18 2 0 +make-backend/internal/gql/generated.go:2190.122,2194.51 3 0 +make-backend/internal/gql/generated.go:2194.51,2196.4 1 0 +make-backend/internal/gql/generated.go:2197.2,2197.16 1 0 +make-backend/internal/gql/generated.go:2197.16,2199.3 1 0 +make-backend/internal/gql/generated.go:2200.2,2201.18 2 0 +make-backend/internal/gql/generated.go:2204.127,2208.50 3 0 +make-backend/internal/gql/generated.go:2208.50,2210.4 1 0 +make-backend/internal/gql/generated.go:2211.2,2211.16 1 0 +make-backend/internal/gql/generated.go:2211.16,2213.3 1 0 +make-backend/internal/gql/generated.go:2214.2,2215.18 2 0 +make-backend/internal/gql/generated.go:2218.123,2222.50 3 0 +make-backend/internal/gql/generated.go:2222.50,2224.4 1 0 +make-backend/internal/gql/generated.go:2225.2,2225.16 1 0 +make-backend/internal/gql/generated.go:2225.16,2227.3 1 0 +make-backend/internal/gql/generated.go:2228.2,2229.18 2 0 +make-backend/internal/gql/generated.go:2236.149,2241.90 1 0 +make-backend/internal/gql/generated.go:2241.90,2243.4 1 0 +make-backend/internal/gql/generated.go:2244.42,2246.4 1 0 +make-backend/internal/gql/generated.go:2248.83,2250.4 1 0 +make-backend/internal/gql/generated.go:2255.146,2257.2 1 0 +make-backend/internal/gql/generated.go:2259.156,2264.90 1 0 +make-backend/internal/gql/generated.go:2264.90,2266.4 1 0 +make-backend/internal/gql/generated.go:2267.42,2269.4 1 0 +make-backend/internal/gql/generated.go:2271.83,2273.4 1 0 +make-backend/internal/gql/generated.go:2278.153,2280.2 1 0 +make-backend/internal/gql/generated.go:2282.157,2287.90 1 0 +make-backend/internal/gql/generated.go:2287.90,2289.4 1 0 +make-backend/internal/gql/generated.go:2290.42,2292.4 1 0 +make-backend/internal/gql/generated.go:2294.83,2296.4 1 0 +make-backend/internal/gql/generated.go:2301.154,2303.2 1 0 +make-backend/internal/gql/generated.go:2305.152,2310.90 1 0 +make-backend/internal/gql/generated.go:2310.90,2312.4 1 0 +make-backend/internal/gql/generated.go:2313.42,2315.4 1 0 +make-backend/internal/gql/generated.go:2317.106,2319.4 1 0 +make-backend/internal/gql/generated.go:2324.149,2326.2 1 0 +make-backend/internal/gql/generated.go:2328.160,2333.90 1 0 +make-backend/internal/gql/generated.go:2333.90,2335.4 1 0 +make-backend/internal/gql/generated.go:2336.42,2338.4 1 0 +make-backend/internal/gql/generated.go:2340.83,2342.4 1 0 +make-backend/internal/gql/generated.go:2347.157,2349.2 1 0 +make-backend/internal/gql/generated.go:2351.153,2356.90 1 0 +make-backend/internal/gql/generated.go:2356.90,2358.4 1 0 +make-backend/internal/gql/generated.go:2359.42,2361.4 1 0 +make-backend/internal/gql/generated.go:2363.86,2365.4 1 0 +make-backend/internal/gql/generated.go:2370.148,2372.2 1 0 +make-backend/internal/gql/generated.go:2374.155,2379.90 1 0 +make-backend/internal/gql/generated.go:2379.90,2381.4 1 0 +make-backend/internal/gql/generated.go:2382.42,2384.4 1 0 +make-backend/internal/gql/generated.go:2386.83,2388.4 1 0 +make-backend/internal/gql/generated.go:2393.150,2395.2 1 0 +make-backend/internal/gql/generated.go:2397.159,2402.90 1 0 +make-backend/internal/gql/generated.go:2402.90,2404.4 1 0 +make-backend/internal/gql/generated.go:2405.42,2407.4 1 0 +make-backend/internal/gql/generated.go:2409.104,2411.4 1 0 +make-backend/internal/gql/generated.go:2416.154,2422.97 1 0 +make-backend/internal/gql/generated.go:2422.97,2424.4 1 0 +make-backend/internal/gql/generated.go:2426.2,2426.16 1 0 +make-backend/internal/gql/generated.go:2429.155,2434.90 1 0 +make-backend/internal/gql/generated.go:2434.90,2436.4 1 0 +make-backend/internal/gql/generated.go:2437.42,2439.4 1 0 +make-backend/internal/gql/generated.go:2441.86,2443.4 1 0 +make-backend/internal/gql/generated.go:2448.149,2450.2 1 0 +make-backend/internal/gql/generated.go:2452.163,2457.90 1 0 +make-backend/internal/gql/generated.go:2457.90,2459.4 1 0 +make-backend/internal/gql/generated.go:2460.42,2462.4 1 0 +make-backend/internal/gql/generated.go:2464.104,2466.4 1 0 +make-backend/internal/gql/generated.go:2471.157,2477.97 1 0 +make-backend/internal/gql/generated.go:2477.97,2479.4 1 0 +make-backend/internal/gql/generated.go:2481.2,2481.16 1 0 +make-backend/internal/gql/generated.go:2484.151,2489.90 1 0 +make-backend/internal/gql/generated.go:2489.90,2491.4 1 0 +make-backend/internal/gql/generated.go:2492.42,2494.4 1 0 +make-backend/internal/gql/generated.go:2496.93,2498.4 1 0 +make-backend/internal/gql/generated.go:2503.149,2509.97 1 0 +make-backend/internal/gql/generated.go:2509.97,2511.4 1 0 +make-backend/internal/gql/generated.go:2513.2,2513.16 1 0 +make-backend/internal/gql/generated.go:2516.153,2521.90 1 0 +make-backend/internal/gql/generated.go:2521.90,2523.4 1 0 +make-backend/internal/gql/generated.go:2524.42,2526.4 1 0 +make-backend/internal/gql/generated.go:2528.83,2530.4 1 0 +make-backend/internal/gql/generated.go:2535.151,2537.2 1 0 +make-backend/internal/gql/generated.go:2539.158,2544.90 1 0 +make-backend/internal/gql/generated.go:2544.90,2546.4 1 0 +make-backend/internal/gql/generated.go:2547.42,2549.4 1 0 +make-backend/internal/gql/generated.go:2551.83,2553.4 1 0 +make-backend/internal/gql/generated.go:2558.156,2560.2 1 0 +make-backend/internal/gql/generated.go:2562.161,2567.90 1 0 +make-backend/internal/gql/generated.go:2567.90,2569.4 1 0 +make-backend/internal/gql/generated.go:2570.42,2572.4 1 0 +make-backend/internal/gql/generated.go:2574.86,2576.4 1 0 +make-backend/internal/gql/generated.go:2581.159,2583.2 1 0 +make-backend/internal/gql/generated.go:2585.156,2590.90 1 0 +make-backend/internal/gql/generated.go:2590.90,2592.4 1 0 +make-backend/internal/gql/generated.go:2593.42,2595.4 1 0 +make-backend/internal/gql/generated.go:2597.90,2599.4 1 0 +make-backend/internal/gql/generated.go:2604.154,2606.2 1 0 +make-backend/internal/gql/generated.go:2608.158,2613.90 1 0 +make-backend/internal/gql/generated.go:2613.90,2615.4 1 0 +make-backend/internal/gql/generated.go:2616.42,2618.4 1 0 +make-backend/internal/gql/generated.go:2620.90,2622.4 1 0 +make-backend/internal/gql/generated.go:2627.156,2629.2 1 0 +make-backend/internal/gql/generated.go:2631.150,2636.90 1 0 +make-backend/internal/gql/generated.go:2636.90,2638.4 1 0 +make-backend/internal/gql/generated.go:2639.42,2641.4 1 0 +make-backend/internal/gql/generated.go:2643.104,2645.4 1 0 +make-backend/internal/gql/generated.go:2650.148,2656.97 1 0 +make-backend/internal/gql/generated.go:2656.97,2658.4 1 0 +make-backend/internal/gql/generated.go:2660.2,2660.16 1 0 +make-backend/internal/gql/generated.go:2663.162,2668.90 1 0 +make-backend/internal/gql/generated.go:2668.90,2670.4 1 0 +make-backend/internal/gql/generated.go:2671.42,2673.4 1 0 +make-backend/internal/gql/generated.go:2675.104,2677.4 1 0 +make-backend/internal/gql/generated.go:2682.160,2688.97 1 0 +make-backend/internal/gql/generated.go:2688.97,2690.4 1 0 +make-backend/internal/gql/generated.go:2692.2,2692.16 1 0 +make-backend/internal/gql/generated.go:2695.164,2700.90 1 0 +make-backend/internal/gql/generated.go:2700.90,2702.4 1 0 +make-backend/internal/gql/generated.go:2703.42,2705.4 1 0 +make-backend/internal/gql/generated.go:2707.104,2709.4 1 0 +make-backend/internal/gql/generated.go:2714.162,2720.97 1 0 +make-backend/internal/gql/generated.go:2720.97,2722.4 1 0 +make-backend/internal/gql/generated.go:2724.2,2724.16 1 0 +make-backend/internal/gql/generated.go:2727.169,2732.90 1 0 +make-backend/internal/gql/generated.go:2732.90,2734.4 1 0 +make-backend/internal/gql/generated.go:2735.42,2737.4 1 0 +make-backend/internal/gql/generated.go:2739.84,2741.4 1 0 +make-backend/internal/gql/generated.go:2746.162,2748.2 1 0 +make-backend/internal/gql/generated.go:2750.174,2755.90 1 0 +make-backend/internal/gql/generated.go:2755.90,2757.4 1 0 +make-backend/internal/gql/generated.go:2758.42,2760.4 1 0 +make-backend/internal/gql/generated.go:2762.84,2764.4 1 0 +make-backend/internal/gql/generated.go:2769.167,2771.2 1 0 +make-backend/internal/gql/generated.go:2773.164,2778.90 1 0 +make-backend/internal/gql/generated.go:2778.90,2780.4 1 0 +make-backend/internal/gql/generated.go:2781.42,2783.4 1 0 +make-backend/internal/gql/generated.go:2785.84,2787.4 1 0 +make-backend/internal/gql/generated.go:2792.157,2794.2 1 0 +make-backend/internal/gql/generated.go:2796.147,2801.90 1 0 +make-backend/internal/gql/generated.go:2801.90,2803.4 1 0 +make-backend/internal/gql/generated.go:2804.42,2806.4 1 0 +make-backend/internal/gql/generated.go:2808.83,2810.4 1 0 +make-backend/internal/gql/generated.go:2815.145,2817.2 1 0 +make-backend/internal/gql/generated.go:2819.150,2824.90 1 0 +make-backend/internal/gql/generated.go:2824.90,2826.4 1 0 +make-backend/internal/gql/generated.go:2827.42,2829.4 1 0 +make-backend/internal/gql/generated.go:2831.86,2833.4 1 0 +make-backend/internal/gql/generated.go:2838.148,2840.2 1 0 +make-backend/internal/gql/generated.go:2842.149,2847.90 1 0 +make-backend/internal/gql/generated.go:2847.90,2849.4 1 0 +make-backend/internal/gql/generated.go:2850.42,2852.4 1 0 +make-backend/internal/gql/generated.go:2854.86,2856.4 1 0 +make-backend/internal/gql/generated.go:2861.147,2863.2 1 0 +make-backend/internal/gql/generated.go:2865.158,2870.90 1 0 +make-backend/internal/gql/generated.go:2870.90,2872.4 1 0 +make-backend/internal/gql/generated.go:2873.42,2875.4 1 0 +make-backend/internal/gql/generated.go:2877.84,2879.4 1 0 +make-backend/internal/gql/generated.go:2884.156,2886.2 1 0 +make-backend/internal/gql/generated.go:2888.150,2893.90 1 0 +make-backend/internal/gql/generated.go:2893.90,2895.4 1 0 +make-backend/internal/gql/generated.go:2896.42,2898.4 1 0 +make-backend/internal/gql/generated.go:2900.86,2902.4 1 0 +make-backend/internal/gql/generated.go:2907.150,2909.2 1 0 +make-backend/internal/gql/generated.go:2911.149,2916.90 1 0 +make-backend/internal/gql/generated.go:2916.90,2918.4 1 0 +make-backend/internal/gql/generated.go:2919.42,2921.4 1 0 +make-backend/internal/gql/generated.go:2923.86,2925.4 1 0 +make-backend/internal/gql/generated.go:2930.149,2932.2 1 0 +make-backend/internal/gql/generated.go:2934.158,2939.90 1 0 +make-backend/internal/gql/generated.go:2939.90,2941.4 1 0 +make-backend/internal/gql/generated.go:2942.42,2944.4 1 0 +make-backend/internal/gql/generated.go:2946.83,2948.4 1 0 +make-backend/internal/gql/generated.go:2953.156,2955.2 1 0 +make-backend/internal/gql/generated.go:2957.156,2962.90 1 0 +make-backend/internal/gql/generated.go:2962.90,2964.4 1 0 +make-backend/internal/gql/generated.go:2965.42,2967.4 1 0 +make-backend/internal/gql/generated.go:2969.83,2971.4 1 0 +make-backend/internal/gql/generated.go:2976.154,2978.2 1 0 +make-backend/internal/gql/generated.go:2980.154,2985.90 1 0 +make-backend/internal/gql/generated.go:2985.90,2987.4 1 0 +make-backend/internal/gql/generated.go:2988.42,2990.4 1 0 +make-backend/internal/gql/generated.go:2992.90,2994.4 1 0 +make-backend/internal/gql/generated.go:2999.152,3001.2 1 0 +make-backend/internal/gql/generated.go:3003.155,3008.90 1 0 +make-backend/internal/gql/generated.go:3008.90,3010.4 1 0 +make-backend/internal/gql/generated.go:3011.42,3013.4 1 0 +make-backend/internal/gql/generated.go:3015.90,3017.4 1 0 +make-backend/internal/gql/generated.go:3022.153,3024.2 1 0 +make-backend/internal/gql/generated.go:3026.151,3031.90 1 0 +make-backend/internal/gql/generated.go:3031.90,3033.4 1 0 +make-backend/internal/gql/generated.go:3034.42,3036.4 1 0 +make-backend/internal/gql/generated.go:3038.84,3040.4 1 0 +make-backend/internal/gql/generated.go:3045.149,3047.2 1 0 +make-backend/internal/gql/generated.go:3049.135,3054.90 1 0 +make-backend/internal/gql/generated.go:3054.90,3056.4 1 0 +make-backend/internal/gql/generated.go:3057.42,3059.4 1 0 +make-backend/internal/gql/generated.go:3061.83,3063.4 1 0 +make-backend/internal/gql/generated.go:3068.139,3070.2 1 0 +make-backend/internal/gql/generated.go:3072.137,3077.90 1 0 +make-backend/internal/gql/generated.go:3077.90,3079.4 1 0 +make-backend/internal/gql/generated.go:3080.42,3082.4 1 0 +make-backend/internal/gql/generated.go:3084.86,3086.4 1 0 +make-backend/internal/gql/generated.go:3091.141,3093.2 1 0 +make-backend/internal/gql/generated.go:3095.135,3100.90 1 0 +make-backend/internal/gql/generated.go:3100.90,3102.4 1 0 +make-backend/internal/gql/generated.go:3103.42,3105.4 1 0 +make-backend/internal/gql/generated.go:3107.86,3109.4 1 0 +make-backend/internal/gql/generated.go:3114.139,3116.2 1 0 +make-backend/internal/gql/generated.go:3118.139,3123.90 1 0 +make-backend/internal/gql/generated.go:3123.90,3125.4 1 0 +make-backend/internal/gql/generated.go:3126.42,3128.4 1 0 +make-backend/internal/gql/generated.go:3130.89,3132.4 1 0 +make-backend/internal/gql/generated.go:3137.143,3139.2 1 0 +make-backend/internal/gql/generated.go:3141.141,3146.90 1 0 +make-backend/internal/gql/generated.go:3146.90,3148.4 1 0 +make-backend/internal/gql/generated.go:3149.42,3151.4 1 0 +make-backend/internal/gql/generated.go:3153.87,3155.4 1 0 +make-backend/internal/gql/generated.go:3160.145,3162.2 1 0 +make-backend/internal/gql/generated.go:3164.141,3169.90 1 0 +make-backend/internal/gql/generated.go:3169.90,3171.4 1 0 +make-backend/internal/gql/generated.go:3172.42,3174.4 1 0 +make-backend/internal/gql/generated.go:3176.87,3178.4 1 0 +make-backend/internal/gql/generated.go:3183.145,3185.2 1 0 +make-backend/internal/gql/generated.go:3187.148,3192.90 1 0 +make-backend/internal/gql/generated.go:3192.90,3194.4 1 0 +make-backend/internal/gql/generated.go:3195.42,3197.4 1 0 +make-backend/internal/gql/generated.go:3199.87,3201.4 1 0 +make-backend/internal/gql/generated.go:3206.152,3208.2 1 0 +make-backend/internal/gql/generated.go:3210.142,3215.90 1 0 +make-backend/internal/gql/generated.go:3215.90,3217.4 1 0 +make-backend/internal/gql/generated.go:3218.42,3220.4 1 0 +make-backend/internal/gql/generated.go:3221.69,3224.57 2 0 +make-backend/internal/gql/generated.go:3224.57,3225.37 1 0 +make-backend/internal/gql/generated.go:3225.37,3228.6 2 0 +make-backend/internal/gql/generated.go:3229.5,3229.55 1 0 +make-backend/internal/gql/generated.go:3232.4,3233.15 2 0 +make-backend/internal/gql/generated.go:3235.83,3237.4 1 0 +make-backend/internal/gql/generated.go:3242.146,3244.2 1 0 +make-backend/internal/gql/generated.go:3246.146,3251.90 1 0 +make-backend/internal/gql/generated.go:3251.90,3253.4 1 0 +make-backend/internal/gql/generated.go:3254.42,3256.4 1 0 +make-backend/internal/gql/generated.go:3258.83,3260.4 1 0 +make-backend/internal/gql/generated.go:3265.150,3267.2 1 0 +make-backend/internal/gql/generated.go:3269.148,3274.90 1 0 +make-backend/internal/gql/generated.go:3274.90,3276.4 1 0 +make-backend/internal/gql/generated.go:3277.42,3279.4 1 0 +make-backend/internal/gql/generated.go:3281.83,3283.4 1 0 +make-backend/internal/gql/generated.go:3288.149,3290.2 1 0 +make-backend/internal/gql/generated.go:3292.149,3297.90 1 0 +make-backend/internal/gql/generated.go:3297.90,3299.4 1 0 +make-backend/internal/gql/generated.go:3300.42,3302.4 1 0 +make-backend/internal/gql/generated.go:3304.83,3306.4 1 0 +make-backend/internal/gql/generated.go:3311.150,3313.2 1 0 +make-backend/internal/gql/generated.go:3315.144,3320.90 1 0 +make-backend/internal/gql/generated.go:3320.90,3322.4 1 0 +make-backend/internal/gql/generated.go:3323.42,3325.4 1 0 +make-backend/internal/gql/generated.go:3327.102,3329.4 1 0 +make-backend/internal/gql/generated.go:3334.145,3336.2 1 0 +make-backend/internal/gql/generated.go:3338.141,3343.90 1 0 +make-backend/internal/gql/generated.go:3343.90,3345.4 1 0 +make-backend/internal/gql/generated.go:3346.42,3348.4 1 0 +make-backend/internal/gql/generated.go:3350.83,3352.4 1 0 +make-backend/internal/gql/generated.go:3357.142,3359.2 1 0 +make-backend/internal/gql/generated.go:3361.143,3366.90 1 0 +make-backend/internal/gql/generated.go:3366.90,3368.4 1 0 +make-backend/internal/gql/generated.go:3369.42,3371.4 1 0 +make-backend/internal/gql/generated.go:3373.86,3375.4 1 0 +make-backend/internal/gql/generated.go:3380.144,3382.2 1 0 +make-backend/internal/gql/generated.go:3384.147,3389.90 1 0 +make-backend/internal/gql/generated.go:3389.90,3391.4 1 0 +make-backend/internal/gql/generated.go:3392.42,3394.4 1 0 +make-backend/internal/gql/generated.go:3396.86,3398.4 1 0 +make-backend/internal/gql/generated.go:3403.148,3405.2 1 0 +make-backend/internal/gql/generated.go:3407.146,3412.90 1 0 +make-backend/internal/gql/generated.go:3412.90,3414.4 1 0 +make-backend/internal/gql/generated.go:3415.42,3417.4 1 0 +make-backend/internal/gql/generated.go:3419.83,3421.4 1 0 +make-backend/internal/gql/generated.go:3426.147,3428.2 1 0 +make-backend/internal/gql/generated.go:3430.145,3435.90 1 0 +make-backend/internal/gql/generated.go:3435.90,3437.4 1 0 +make-backend/internal/gql/generated.go:3438.42,3440.4 1 0 +make-backend/internal/gql/generated.go:3442.84,3444.4 1 0 +make-backend/internal/gql/generated.go:3449.146,3451.2 1 0 +make-backend/internal/gql/generated.go:3453.147,3458.90 1 0 +make-backend/internal/gql/generated.go:3458.90,3460.4 1 0 +make-backend/internal/gql/generated.go:3461.42,3463.4 1 0 +make-backend/internal/gql/generated.go:3465.84,3467.4 1 0 +make-backend/internal/gql/generated.go:3472.148,3474.2 1 0 +make-backend/internal/gql/generated.go:3476.146,3481.90 1 0 +make-backend/internal/gql/generated.go:3481.90,3483.4 1 0 +make-backend/internal/gql/generated.go:3484.42,3486.4 1 0 +make-backend/internal/gql/generated.go:3488.86,3490.4 1 0 +make-backend/internal/gql/generated.go:3495.147,3497.2 1 0 +make-backend/internal/gql/generated.go:3499.151,3504.90 1 0 +make-backend/internal/gql/generated.go:3504.90,3506.4 1 0 +make-backend/internal/gql/generated.go:3507.42,3509.4 1 0 +make-backend/internal/gql/generated.go:3511.86,3513.4 1 0 +make-backend/internal/gql/generated.go:3518.152,3520.2 1 0 +make-backend/internal/gql/generated.go:3522.150,3527.90 1 0 +make-backend/internal/gql/generated.go:3527.90,3529.4 1 0 +make-backend/internal/gql/generated.go:3530.42,3532.4 1 0 +make-backend/internal/gql/generated.go:3534.86,3536.4 1 0 +make-backend/internal/gql/generated.go:3541.151,3543.2 1 0 +make-backend/internal/gql/generated.go:3545.149,3550.90 1 0 +make-backend/internal/gql/generated.go:3550.90,3552.4 1 0 +make-backend/internal/gql/generated.go:3553.42,3555.4 1 0 +make-backend/internal/gql/generated.go:3557.84,3559.4 1 0 +make-backend/internal/gql/generated.go:3564.150,3566.2 1 0 +make-backend/internal/gql/generated.go:3568.155,3573.90 1 0 +make-backend/internal/gql/generated.go:3573.90,3575.4 1 0 +make-backend/internal/gql/generated.go:3576.42,3578.4 1 0 +make-backend/internal/gql/generated.go:3580.84,3582.4 1 0 +make-backend/internal/gql/generated.go:3587.156,3589.2 1 0 +make-backend/internal/gql/generated.go:3591.163,3596.90 1 0 +make-backend/internal/gql/generated.go:3596.90,3598.4 1 0 +make-backend/internal/gql/generated.go:3599.42,3601.4 1 0 +make-backend/internal/gql/generated.go:3603.86,3605.4 1 0 +make-backend/internal/gql/generated.go:3610.164,3612.2 1 0 +make-backend/internal/gql/generated.go:3614.152,3619.90 1 0 +make-backend/internal/gql/generated.go:3619.90,3621.4 1 0 +make-backend/internal/gql/generated.go:3622.42,3624.4 1 0 +make-backend/internal/gql/generated.go:3626.84,3628.4 1 0 +make-backend/internal/gql/generated.go:3633.153,3635.2 1 0 +make-backend/internal/gql/generated.go:3637.157,3642.90 1 0 +make-backend/internal/gql/generated.go:3642.90,3644.4 1 0 +make-backend/internal/gql/generated.go:3645.42,3647.4 1 0 +make-backend/internal/gql/generated.go:3649.84,3651.4 1 0 +make-backend/internal/gql/generated.go:3656.158,3658.2 1 0 +make-backend/internal/gql/generated.go:3660.155,3665.90 1 0 +make-backend/internal/gql/generated.go:3665.90,3667.4 1 0 +make-backend/internal/gql/generated.go:3668.42,3670.4 1 0 +make-backend/internal/gql/generated.go:3672.84,3674.4 1 0 +make-backend/internal/gql/generated.go:3679.156,3681.2 1 0 +make-backend/internal/gql/generated.go:3683.157,3688.90 1 0 +make-backend/internal/gql/generated.go:3688.90,3690.4 1 0 +make-backend/internal/gql/generated.go:3691.42,3693.4 1 0 +make-backend/internal/gql/generated.go:3695.83,3697.4 1 0 +make-backend/internal/gql/generated.go:3702.150,3704.2 1 0 +make-backend/internal/gql/generated.go:3706.167,3711.90 1 0 +make-backend/internal/gql/generated.go:3711.90,3713.4 1 0 +make-backend/internal/gql/generated.go:3714.42,3716.4 1 0 +make-backend/internal/gql/generated.go:3718.83,3720.4 1 0 +make-backend/internal/gql/generated.go:3725.160,3727.2 1 0 +make-backend/internal/gql/generated.go:3729.159,3734.90 1 0 +make-backend/internal/gql/generated.go:3734.90,3736.4 1 0 +make-backend/internal/gql/generated.go:3737.42,3739.4 1 0 +make-backend/internal/gql/generated.go:3741.86,3743.4 1 0 +make-backend/internal/gql/generated.go:3748.152,3750.2 1 0 +make-backend/internal/gql/generated.go:3752.172,3757.90 1 0 +make-backend/internal/gql/generated.go:3757.90,3759.4 1 0 +make-backend/internal/gql/generated.go:3760.42,3762.4 1 0 +make-backend/internal/gql/generated.go:3764.84,3766.4 1 0 +make-backend/internal/gql/generated.go:3771.165,3773.2 1 0 +make-backend/internal/gql/generated.go:3775.133,3780.90 1 0 +make-backend/internal/gql/generated.go:3780.90,3782.4 1 0 +make-backend/internal/gql/generated.go:3783.42,3785.4 1 0 +make-backend/internal/gql/generated.go:3787.83,3789.4 1 0 +make-backend/internal/gql/generated.go:3794.138,3796.2 1 0 +make-backend/internal/gql/generated.go:3798.141,3803.90 1 0 +make-backend/internal/gql/generated.go:3803.90,3805.4 1 0 +make-backend/internal/gql/generated.go:3806.42,3808.4 1 0 +make-backend/internal/gql/generated.go:3810.83,3812.4 1 0 +make-backend/internal/gql/generated.go:3817.146,3819.2 1 0 +make-backend/internal/gql/generated.go:3821.135,3826.90 1 0 +make-backend/internal/gql/generated.go:3826.90,3828.4 1 0 +make-backend/internal/gql/generated.go:3829.42,3831.4 1 0 +make-backend/internal/gql/generated.go:3833.86,3835.4 1 0 +make-backend/internal/gql/generated.go:3840.140,3842.2 1 0 +make-backend/internal/gql/generated.go:3844.142,3849.90 1 0 +make-backend/internal/gql/generated.go:3849.90,3851.4 1 0 +make-backend/internal/gql/generated.go:3852.42,3854.4 1 0 +make-backend/internal/gql/generated.go:3856.86,3858.4 1 0 +make-backend/internal/gql/generated.go:3863.147,3865.2 1 0 +make-backend/internal/gql/generated.go:3867.131,3872.90 1 0 +make-backend/internal/gql/generated.go:3872.90,3874.4 1 0 +make-backend/internal/gql/generated.go:3875.42,3877.4 1 0 +make-backend/internal/gql/generated.go:3879.83,3881.4 1 0 +make-backend/internal/gql/generated.go:3886.137,3888.2 1 0 +make-backend/internal/gql/generated.go:3890.139,3895.90 1 0 +make-backend/internal/gql/generated.go:3895.90,3897.4 1 0 +make-backend/internal/gql/generated.go:3898.42,3900.4 1 0 +make-backend/internal/gql/generated.go:3902.83,3904.4 1 0 +make-backend/internal/gql/generated.go:3909.145,3911.2 1 0 +make-backend/internal/gql/generated.go:3913.139,3918.90 1 0 +make-backend/internal/gql/generated.go:3918.90,3920.4 1 0 +make-backend/internal/gql/generated.go:3921.42,3923.4 1 0 +make-backend/internal/gql/generated.go:3925.84,3927.4 1 0 +make-backend/internal/gql/generated.go:3932.145,3934.2 1 0 +make-backend/internal/gql/generated.go:3936.138,3941.90 1 0 +make-backend/internal/gql/generated.go:3941.90,3943.4 1 0 +make-backend/internal/gql/generated.go:3944.42,3946.4 1 0 +make-backend/internal/gql/generated.go:3948.83,3950.4 1 0 +make-backend/internal/gql/generated.go:3955.144,3957.2 1 0 +make-backend/internal/gql/generated.go:3959.135,3964.90 1 0 +make-backend/internal/gql/generated.go:3964.90,3966.4 1 0 +make-backend/internal/gql/generated.go:3967.42,3969.4 1 0 +make-backend/internal/gql/generated.go:3971.86,3973.4 1 0 +make-backend/internal/gql/generated.go:3978.141,3980.2 1 0 +make-backend/internal/gql/generated.go:3982.140,3987.90 1 0 +make-backend/internal/gql/generated.go:3987.90,3989.4 1 0 +make-backend/internal/gql/generated.go:3990.42,3992.4 1 0 +make-backend/internal/gql/generated.go:3994.89,3996.4 1 0 +make-backend/internal/gql/generated.go:4001.146,4003.2 1 0 +make-backend/internal/gql/generated.go:4005.140,4010.90 1 0 +make-backend/internal/gql/generated.go:4010.90,4012.4 1 0 +make-backend/internal/gql/generated.go:4013.42,4015.4 1 0 +make-backend/internal/gql/generated.go:4017.90,4019.4 1 0 +make-backend/internal/gql/generated.go:4024.146,4026.2 1 0 +make-backend/internal/gql/generated.go:4028.133,4033.90 1 0 +make-backend/internal/gql/generated.go:4033.90,4035.4 1 0 +make-backend/internal/gql/generated.go:4036.42,4038.4 1 0 +make-backend/internal/gql/generated.go:4040.83,4042.4 1 0 +make-backend/internal/gql/generated.go:4047.138,4049.2 1 0 +make-backend/internal/gql/generated.go:4051.141,4056.90 1 0 +make-backend/internal/gql/generated.go:4056.90,4058.4 1 0 +make-backend/internal/gql/generated.go:4059.42,4061.4 1 0 +make-backend/internal/gql/generated.go:4063.86,4065.4 1 0 +make-backend/internal/gql/generated.go:4070.146,4072.2 1 0 +make-backend/internal/gql/generated.go:4074.149,4079.90 1 0 +make-backend/internal/gql/generated.go:4079.90,4081.4 1 0 +make-backend/internal/gql/generated.go:4082.42,4084.4 1 0 +make-backend/internal/gql/generated.go:4086.86,4088.4 1 0 +make-backend/internal/gql/generated.go:4093.149,4095.2 1 0 +make-backend/internal/gql/generated.go:4097.145,4102.90 1 0 +make-backend/internal/gql/generated.go:4102.90,4104.4 1 0 +make-backend/internal/gql/generated.go:4105.42,4107.4 1 0 +make-backend/internal/gql/generated.go:4109.86,4111.4 1 0 +make-backend/internal/gql/generated.go:4116.145,4118.2 1 0 +make-backend/internal/gql/generated.go:4120.148,4125.90 1 0 +make-backend/internal/gql/generated.go:4125.90,4127.4 1 0 +make-backend/internal/gql/generated.go:4128.42,4130.4 1 0 +make-backend/internal/gql/generated.go:4132.86,4134.4 1 0 +make-backend/internal/gql/generated.go:4139.148,4141.2 1 0 +make-backend/internal/gql/generated.go:4143.143,4148.90 1 0 +make-backend/internal/gql/generated.go:4148.90,4150.4 1 0 +make-backend/internal/gql/generated.go:4151.42,4153.4 1 0 +make-backend/internal/gql/generated.go:4155.83,4157.4 1 0 +make-backend/internal/gql/generated.go:4162.143,4164.2 1 0 +make-backend/internal/gql/generated.go:4166.145,4171.90 1 0 +make-backend/internal/gql/generated.go:4171.90,4173.4 1 0 +make-backend/internal/gql/generated.go:4174.42,4176.4 1 0 +make-backend/internal/gql/generated.go:4178.86,4180.4 1 0 +make-backend/internal/gql/generated.go:4185.145,4187.2 1 0 +make-backend/internal/gql/generated.go:4189.149,4194.90 1 0 +make-backend/internal/gql/generated.go:4194.90,4196.4 1 0 +make-backend/internal/gql/generated.go:4197.42,4199.4 1 0 +make-backend/internal/gql/generated.go:4201.86,4203.4 1 0 +make-backend/internal/gql/generated.go:4208.149,4210.2 1 0 +make-backend/internal/gql/generated.go:4212.152,4217.90 1 0 +make-backend/internal/gql/generated.go:4217.90,4219.4 1 0 +make-backend/internal/gql/generated.go:4220.42,4222.4 1 0 +make-backend/internal/gql/generated.go:4224.86,4226.4 1 0 +make-backend/internal/gql/generated.go:4231.152,4233.2 1 0 +make-backend/internal/gql/generated.go:4235.149,4240.90 1 0 +make-backend/internal/gql/generated.go:4240.90,4242.4 1 0 +make-backend/internal/gql/generated.go:4243.42,4245.4 1 0 +make-backend/internal/gql/generated.go:4247.86,4249.4 1 0 +make-backend/internal/gql/generated.go:4254.149,4256.2 1 0 +make-backend/internal/gql/generated.go:4258.149,4263.90 1 0 +make-backend/internal/gql/generated.go:4263.90,4265.4 1 0 +make-backend/internal/gql/generated.go:4266.42,4268.4 1 0 +make-backend/internal/gql/generated.go:4270.86,4272.4 1 0 +make-backend/internal/gql/generated.go:4277.149,4279.2 1 0 +make-backend/internal/gql/generated.go:4281.147,4286.90 1 0 +make-backend/internal/gql/generated.go:4286.90,4288.4 1 0 +make-backend/internal/gql/generated.go:4289.42,4291.4 1 0 +make-backend/internal/gql/generated.go:4293.84,4295.4 1 0 +make-backend/internal/gql/generated.go:4300.147,4302.2 1 0 +make-backend/internal/gql/generated.go:4304.149,4309.90 1 0 +make-backend/internal/gql/generated.go:4309.90,4311.4 1 0 +make-backend/internal/gql/generated.go:4312.42,4314.4 1 0 +make-backend/internal/gql/generated.go:4316.86,4318.4 1 0 +make-backend/internal/gql/generated.go:4323.149,4325.2 1 0 +make-backend/internal/gql/generated.go:4327.146,4332.90 1 0 +make-backend/internal/gql/generated.go:4332.90,4334.4 1 0 +make-backend/internal/gql/generated.go:4335.42,4337.4 1 0 +make-backend/internal/gql/generated.go:4339.94,4341.4 1 0 +make-backend/internal/gql/generated.go:4346.146,4352.97 1 0 +make-backend/internal/gql/generated.go:4352.97,4354.4 1 0 +make-backend/internal/gql/generated.go:4356.2,4356.16 1 0 +make-backend/internal/gql/generated.go:4359.146,4364.90 1 0 +make-backend/internal/gql/generated.go:4364.90,4366.4 1 0 +make-backend/internal/gql/generated.go:4367.42,4369.4 1 0 +make-backend/internal/gql/generated.go:4371.104,4373.4 1 0 +make-backend/internal/gql/generated.go:4378.146,4380.2 1 0 +make-backend/internal/gql/generated.go:4382.161,4387.90 1 0 +make-backend/internal/gql/generated.go:4387.90,4389.4 1 0 +make-backend/internal/gql/generated.go:4390.42,4392.4 1 0 +make-backend/internal/gql/generated.go:4394.83,4396.4 1 0 +make-backend/internal/gql/generated.go:4401.154,4403.2 1 0 +make-backend/internal/gql/generated.go:4405.169,4410.90 1 0 +make-backend/internal/gql/generated.go:4410.90,4412.4 1 0 +make-backend/internal/gql/generated.go:4413.42,4415.4 1 0 +make-backend/internal/gql/generated.go:4417.106,4419.4 1 0 +make-backend/internal/gql/generated.go:4424.162,4426.2 1 0 +make-backend/internal/gql/generated.go:4428.131,4433.90 1 0 +make-backend/internal/gql/generated.go:4433.90,4435.4 1 0 +make-backend/internal/gql/generated.go:4436.42,4439.4 2 0 +make-backend/internal/gql/generated.go:4441.83,4443.4 1 0 +make-backend/internal/gql/generated.go:4448.157,4454.97 1 0 +make-backend/internal/gql/generated.go:4454.97,4456.4 1 0 +make-backend/internal/gql/generated.go:4458.2,4458.15 1 0 +make-backend/internal/gql/generated.go:4458.15,4459.31 1 0 +make-backend/internal/gql/generated.go:4459.31,4462.4 2 0 +make-backend/internal/gql/generated.go:4464.2,4465.110 2 0 +make-backend/internal/gql/generated.go:4465.110,4468.3 2 0 +make-backend/internal/gql/generated.go:4469.2,4469.16 1 0 +make-backend/internal/gql/generated.go:4472.131,4477.90 1 0 +make-backend/internal/gql/generated.go:4477.90,4479.4 1 0 +make-backend/internal/gql/generated.go:4480.42,4483.4 2 0 +make-backend/internal/gql/generated.go:4485.84,4487.4 1 0 +make-backend/internal/gql/generated.go:4492.157,4498.97 1 0 +make-backend/internal/gql/generated.go:4498.97,4500.4 1 0 +make-backend/internal/gql/generated.go:4502.2,4502.15 1 0 +make-backend/internal/gql/generated.go:4502.15,4503.31 1 0 +make-backend/internal/gql/generated.go:4503.31,4506.4 2 0 +make-backend/internal/gql/generated.go:4508.2,4509.110 2 0 +make-backend/internal/gql/generated.go:4509.110,4512.3 2 0 +make-backend/internal/gql/generated.go:4513.2,4513.16 1 0 +make-backend/internal/gql/generated.go:4516.151,4521.90 1 0 +make-backend/internal/gql/generated.go:4521.90,4523.4 1 0 +make-backend/internal/gql/generated.go:4524.42,4526.4 1 0 +make-backend/internal/gql/generated.go:4528.86,4530.4 1 0 +make-backend/internal/gql/generated.go:4535.150,4537.2 1 0 +make-backend/internal/gql/generated.go:4539.147,4544.90 1 0 +make-backend/internal/gql/generated.go:4544.90,4546.4 1 0 +make-backend/internal/gql/generated.go:4547.42,4549.4 1 0 +make-backend/internal/gql/generated.go:4551.86,4553.4 1 0 +make-backend/internal/gql/generated.go:4558.146,4560.2 1 0 +make-backend/internal/gql/generated.go:4562.150,4567.90 1 0 +make-backend/internal/gql/generated.go:4567.90,4569.4 1 0 +make-backend/internal/gql/generated.go:4570.42,4572.4 1 0 +make-backend/internal/gql/generated.go:4574.86,4576.4 1 0 +make-backend/internal/gql/generated.go:4581.149,4583.2 1 0 +make-backend/internal/gql/generated.go:4585.150,4590.90 1 0 +make-backend/internal/gql/generated.go:4590.90,4592.4 1 0 +make-backend/internal/gql/generated.go:4593.42,4595.4 1 0 +make-backend/internal/gql/generated.go:4597.106,4599.4 1 0 +make-backend/internal/gql/generated.go:4604.149,4610.97 1 0 +make-backend/internal/gql/generated.go:4610.97,4612.4 1 0 +make-backend/internal/gql/generated.go:4614.2,4614.16 1 0 +make-backend/internal/gql/generated.go:4617.147,4622.90 1 0 +make-backend/internal/gql/generated.go:4622.90,4624.4 1 0 +make-backend/internal/gql/generated.go:4625.42,4627.4 1 0 +make-backend/internal/gql/generated.go:4629.86,4631.4 1 0 +make-backend/internal/gql/generated.go:4636.146,4638.2 1 0 +make-backend/internal/gql/generated.go:4640.154,4645.90 1 0 +make-backend/internal/gql/generated.go:4645.90,4647.4 1 0 +make-backend/internal/gql/generated.go:4648.42,4650.4 1 0 +make-backend/internal/gql/generated.go:4652.86,4654.4 1 0 +make-backend/internal/gql/generated.go:4659.153,4661.2 1 0 +make-backend/internal/gql/generated.go:4663.159,4668.90 1 0 +make-backend/internal/gql/generated.go:4668.90,4670.4 1 0 +make-backend/internal/gql/generated.go:4671.42,4673.4 1 0 +make-backend/internal/gql/generated.go:4675.86,4677.4 1 0 +make-backend/internal/gql/generated.go:4682.152,4684.2 1 0 +make-backend/internal/gql/generated.go:4686.162,4691.90 1 0 +make-backend/internal/gql/generated.go:4691.90,4693.4 1 0 +make-backend/internal/gql/generated.go:4694.42,4696.4 1 0 +make-backend/internal/gql/generated.go:4698.85,4700.4 1 0 +make-backend/internal/gql/generated.go:4705.155,4707.2 1 0 +make-backend/internal/gql/generated.go:4709.147,4714.90 1 0 +make-backend/internal/gql/generated.go:4714.90,4716.4 1 0 +make-backend/internal/gql/generated.go:4717.42,4719.4 1 0 +make-backend/internal/gql/generated.go:4721.83,4723.4 1 0 +make-backend/internal/gql/generated.go:4728.145,4730.2 1 0 +make-backend/internal/gql/generated.go:4732.157,4737.90 1 0 +make-backend/internal/gql/generated.go:4737.90,4739.4 1 0 +make-backend/internal/gql/generated.go:4740.42,4742.4 1 0 +make-backend/internal/gql/generated.go:4744.86,4746.4 1 0 +make-backend/internal/gql/generated.go:4751.155,4753.2 1 0 +make-backend/internal/gql/generated.go:4755.150,4760.90 1 0 +make-backend/internal/gql/generated.go:4760.90,4762.4 1 0 +make-backend/internal/gql/generated.go:4763.42,4765.4 1 0 +make-backend/internal/gql/generated.go:4767.86,4769.4 1 0 +make-backend/internal/gql/generated.go:4774.148,4776.2 1 0 +make-backend/internal/gql/generated.go:4778.150,4783.90 1 0 +make-backend/internal/gql/generated.go:4783.90,4785.4 1 0 +make-backend/internal/gql/generated.go:4786.42,4788.4 1 0 +make-backend/internal/gql/generated.go:4790.86,4792.4 1 0 +make-backend/internal/gql/generated.go:4797.148,4799.2 1 0 +make-backend/internal/gql/generated.go:4801.122,4806.90 1 0 +make-backend/internal/gql/generated.go:4806.90,4808.4 1 0 +make-backend/internal/gql/generated.go:4809.42,4812.4 2 0 +make-backend/internal/gql/generated.go:4814.98,4816.4 1 0 +make-backend/internal/gql/generated.go:4821.148,4827.97 1 0 +make-backend/internal/gql/generated.go:4827.97,4829.4 1 0 +make-backend/internal/gql/generated.go:4831.2,4831.15 1 0 +make-backend/internal/gql/generated.go:4831.15,4832.31 1 0 +make-backend/internal/gql/generated.go:4832.31,4835.4 2 0 +make-backend/internal/gql/generated.go:4837.2,4838.101 2 0 +make-backend/internal/gql/generated.go:4838.101,4841.3 2 0 +make-backend/internal/gql/generated.go:4842.2,4842.16 1 0 +make-backend/internal/gql/generated.go:4845.118,4850.90 1 0 +make-backend/internal/gql/generated.go:4850.90,4852.4 1 0 +make-backend/internal/gql/generated.go:4853.42,4856.4 2 0 +make-backend/internal/gql/generated.go:4858.94,4860.4 1 0 +make-backend/internal/gql/generated.go:4865.144,4871.97 1 0 +make-backend/internal/gql/generated.go:4871.97,4873.4 1 0 +make-backend/internal/gql/generated.go:4875.2,4875.15 1 0 +make-backend/internal/gql/generated.go:4875.15,4876.31 1 0 +make-backend/internal/gql/generated.go:4876.31,4879.4 2 0 +make-backend/internal/gql/generated.go:4881.2,4882.97 2 0 +make-backend/internal/gql/generated.go:4882.97,4885.3 2 0 +make-backend/internal/gql/generated.go:4886.2,4886.16 1 0 +make-backend/internal/gql/generated.go:4889.124,4894.90 1 0 +make-backend/internal/gql/generated.go:4894.90,4896.4 1 0 +make-backend/internal/gql/generated.go:4897.42,4900.4 2 0 +make-backend/internal/gql/generated.go:4902.100,4904.4 1 0 +make-backend/internal/gql/generated.go:4909.150,4915.97 1 0 +make-backend/internal/gql/generated.go:4915.97,4917.4 1 0 +make-backend/internal/gql/generated.go:4919.2,4919.15 1 0 +make-backend/internal/gql/generated.go:4919.15,4920.31 1 0 +make-backend/internal/gql/generated.go:4920.31,4923.4 2 0 +make-backend/internal/gql/generated.go:4925.2,4926.103 2 0 +make-backend/internal/gql/generated.go:4926.103,4929.3 2 0 +make-backend/internal/gql/generated.go:4930.2,4930.16 1 0 +make-backend/internal/gql/generated.go:4933.121,4938.90 1 0 +make-backend/internal/gql/generated.go:4938.90,4940.4 1 0 +make-backend/internal/gql/generated.go:4941.42,4944.4 2 0 +make-backend/internal/gql/generated.go:4946.93,4948.4 1 0 +make-backend/internal/gql/generated.go:4953.147,4959.97 1 0 +make-backend/internal/gql/generated.go:4959.97,4961.4 1 0 +make-backend/internal/gql/generated.go:4963.2,4963.15 1 0 +make-backend/internal/gql/generated.go:4963.15,4964.31 1 0 +make-backend/internal/gql/generated.go:4964.31,4967.4 2 0 +make-backend/internal/gql/generated.go:4969.2,4970.100 2 0 +make-backend/internal/gql/generated.go:4970.100,4973.3 2 0 +make-backend/internal/gql/generated.go:4974.2,4974.16 1 0 +make-backend/internal/gql/generated.go:4977.126,4982.90 1 0 +make-backend/internal/gql/generated.go:4982.90,4984.4 1 0 +make-backend/internal/gql/generated.go:4985.42,4988.4 2 0 +make-backend/internal/gql/generated.go:4990.107,4992.4 1 0 +make-backend/internal/gql/generated.go:4997.152,5003.97 1 0 +make-backend/internal/gql/generated.go:5003.97,5005.4 1 0 +make-backend/internal/gql/generated.go:5007.2,5007.15 1 0 +make-backend/internal/gql/generated.go:5007.15,5008.31 1 0 +make-backend/internal/gql/generated.go:5008.31,5011.4 2 0 +make-backend/internal/gql/generated.go:5013.2,5014.105 2 0 +make-backend/internal/gql/generated.go:5014.105,5017.3 2 0 +make-backend/internal/gql/generated.go:5018.2,5018.16 1 0 +make-backend/internal/gql/generated.go:5021.125,5026.90 1 0 +make-backend/internal/gql/generated.go:5026.90,5028.4 1 0 +make-backend/internal/gql/generated.go:5029.42,5032.4 2 0 +make-backend/internal/gql/generated.go:5034.84,5036.4 1 0 +make-backend/internal/gql/generated.go:5041.151,5047.97 1 0 +make-backend/internal/gql/generated.go:5047.97,5049.4 1 0 +make-backend/internal/gql/generated.go:5051.2,5051.15 1 0 +make-backend/internal/gql/generated.go:5051.15,5052.31 1 0 +make-backend/internal/gql/generated.go:5052.31,5055.4 2 0 +make-backend/internal/gql/generated.go:5057.2,5058.104 2 0 +make-backend/internal/gql/generated.go:5058.104,5061.3 2 0 +make-backend/internal/gql/generated.go:5062.2,5062.16 1 0 +make-backend/internal/gql/generated.go:5065.133,5070.90 1 0 +make-backend/internal/gql/generated.go:5070.90,5072.4 1 0 +make-backend/internal/gql/generated.go:5073.42,5076.4 2 0 +make-backend/internal/gql/generated.go:5078.84,5080.4 1 0 +make-backend/internal/gql/generated.go:5085.159,5091.97 1 0 +make-backend/internal/gql/generated.go:5091.97,5093.4 1 0 +make-backend/internal/gql/generated.go:5095.2,5095.15 1 0 +make-backend/internal/gql/generated.go:5095.15,5096.31 1 0 +make-backend/internal/gql/generated.go:5096.31,5099.4 2 0 +make-backend/internal/gql/generated.go:5101.2,5102.112 2 0 +make-backend/internal/gql/generated.go:5102.112,5105.3 2 0 +make-backend/internal/gql/generated.go:5106.2,5106.16 1 0 +make-backend/internal/gql/generated.go:5109.131,5114.90 1 0 +make-backend/internal/gql/generated.go:5114.90,5116.4 1 0 +make-backend/internal/gql/generated.go:5117.42,5120.4 2 0 +make-backend/internal/gql/generated.go:5122.84,5124.4 1 0 +make-backend/internal/gql/generated.go:5129.157,5135.97 1 0 +make-backend/internal/gql/generated.go:5135.97,5137.4 1 0 +make-backend/internal/gql/generated.go:5139.2,5139.15 1 0 +make-backend/internal/gql/generated.go:5139.15,5140.31 1 0 +make-backend/internal/gql/generated.go:5140.31,5143.4 2 0 +make-backend/internal/gql/generated.go:5145.2,5146.110 2 0 +make-backend/internal/gql/generated.go:5146.110,5149.3 2 0 +make-backend/internal/gql/generated.go:5150.2,5150.16 1 0 +make-backend/internal/gql/generated.go:5153.130,5158.90 1 0 +make-backend/internal/gql/generated.go:5158.90,5160.4 1 0 +make-backend/internal/gql/generated.go:5161.42,5164.4 2 0 +make-backend/internal/gql/generated.go:5166.84,5168.4 1 0 +make-backend/internal/gql/generated.go:5173.156,5179.97 1 0 +make-backend/internal/gql/generated.go:5179.97,5181.4 1 0 +make-backend/internal/gql/generated.go:5183.2,5183.15 1 0 +make-backend/internal/gql/generated.go:5183.15,5184.31 1 0 +make-backend/internal/gql/generated.go:5184.31,5187.4 2 0 +make-backend/internal/gql/generated.go:5189.2,5190.109 2 0 +make-backend/internal/gql/generated.go:5190.109,5193.3 2 0 +make-backend/internal/gql/generated.go:5194.2,5194.16 1 0 +make-backend/internal/gql/generated.go:5197.116,5202.90 1 0 +make-backend/internal/gql/generated.go:5202.90,5204.4 1 0 +make-backend/internal/gql/generated.go:5205.42,5208.4 2 0 +make-backend/internal/gql/generated.go:5210.92,5212.4 1 0 +make-backend/internal/gql/generated.go:5217.142,5223.97 1 0 +make-backend/internal/gql/generated.go:5223.97,5225.4 1 0 +make-backend/internal/gql/generated.go:5227.2,5227.15 1 0 +make-backend/internal/gql/generated.go:5227.15,5228.31 1 0 +make-backend/internal/gql/generated.go:5228.31,5231.4 2 0 +make-backend/internal/gql/generated.go:5233.2,5234.95 2 0 +make-backend/internal/gql/generated.go:5234.95,5237.3 2 0 +make-backend/internal/gql/generated.go:5238.2,5238.16 1 0 +make-backend/internal/gql/generated.go:5241.123,5246.90 1 0 +make-backend/internal/gql/generated.go:5246.90,5248.4 1 0 +make-backend/internal/gql/generated.go:5249.42,5251.4 1 0 +make-backend/internal/gql/generated.go:5253.92,5255.4 1 0 +make-backend/internal/gql/generated.go:5260.147,5266.97 1 0 +make-backend/internal/gql/generated.go:5266.97,5268.4 1 0 +make-backend/internal/gql/generated.go:5270.2,5270.16 1 0 +make-backend/internal/gql/generated.go:5273.116,5278.90 1 0 +make-backend/internal/gql/generated.go:5278.90,5280.4 1 0 +make-backend/internal/gql/generated.go:5281.42,5284.4 2 0 +make-backend/internal/gql/generated.go:5286.92,5288.4 1 0 +make-backend/internal/gql/generated.go:5293.142,5299.97 1 0 +make-backend/internal/gql/generated.go:5299.97,5301.4 1 0 +make-backend/internal/gql/generated.go:5303.2,5303.15 1 0 +make-backend/internal/gql/generated.go:5303.15,5304.31 1 0 +make-backend/internal/gql/generated.go:5304.31,5307.4 2 0 +make-backend/internal/gql/generated.go:5309.2,5310.95 2 0 +make-backend/internal/gql/generated.go:5310.95,5313.3 2 0 +make-backend/internal/gql/generated.go:5314.2,5314.16 1 0 +make-backend/internal/gql/generated.go:5317.131,5322.90 1 0 +make-backend/internal/gql/generated.go:5322.90,5324.4 1 0 +make-backend/internal/gql/generated.go:5325.42,5328.4 2 0 +make-backend/internal/gql/generated.go:5330.94,5332.4 1 0 +make-backend/internal/gql/generated.go:5337.157,5343.97 1 0 +make-backend/internal/gql/generated.go:5343.97,5345.4 1 0 +make-backend/internal/gql/generated.go:5347.2,5347.15 1 0 +make-backend/internal/gql/generated.go:5347.15,5348.31 1 0 +make-backend/internal/gql/generated.go:5348.31,5351.4 2 0 +make-backend/internal/gql/generated.go:5353.2,5354.110 2 0 +make-backend/internal/gql/generated.go:5354.110,5357.3 2 0 +make-backend/internal/gql/generated.go:5358.2,5358.16 1 0 +make-backend/internal/gql/generated.go:5361.118,5366.90 1 0 +make-backend/internal/gql/generated.go:5366.90,5368.4 1 0 +make-backend/internal/gql/generated.go:5369.42,5372.4 2 0 +make-backend/internal/gql/generated.go:5374.99,5376.4 1 0 +make-backend/internal/gql/generated.go:5381.144,5387.97 1 0 +make-backend/internal/gql/generated.go:5387.97,5389.4 1 0 +make-backend/internal/gql/generated.go:5391.2,5391.15 1 0 +make-backend/internal/gql/generated.go:5391.15,5392.31 1 0 +make-backend/internal/gql/generated.go:5392.31,5395.4 2 0 +make-backend/internal/gql/generated.go:5397.2,5398.97 2 0 +make-backend/internal/gql/generated.go:5398.97,5401.3 2 0 +make-backend/internal/gql/generated.go:5402.2,5402.16 1 0 +make-backend/internal/gql/generated.go:5405.120,5410.90 1 0 +make-backend/internal/gql/generated.go:5410.90,5412.4 1 0 +make-backend/internal/gql/generated.go:5413.42,5415.4 1 0 +make-backend/internal/gql/generated.go:5417.101,5419.4 1 0 +make-backend/internal/gql/generated.go:5424.144,5430.97 1 0 +make-backend/internal/gql/generated.go:5430.97,5432.4 1 0 +make-backend/internal/gql/generated.go:5434.2,5434.16 1 0 +make-backend/internal/gql/generated.go:5437.145,5442.90 1 0 +make-backend/internal/gql/generated.go:5442.90,5444.4 1 0 +make-backend/internal/gql/generated.go:5445.42,5447.4 1 0 +make-backend/internal/gql/generated.go:5449.83,5451.4 1 0 +make-backend/internal/gql/generated.go:5456.144,5458.2 1 0 +make-backend/internal/gql/generated.go:5460.150,5465.90 1 0 +make-backend/internal/gql/generated.go:5465.90,5467.4 1 0 +make-backend/internal/gql/generated.go:5468.42,5470.4 1 0 +make-backend/internal/gql/generated.go:5472.84,5474.4 1 0 +make-backend/internal/gql/generated.go:5479.149,5481.2 1 0 +make-backend/internal/gql/generated.go:5483.158,5488.90 1 0 +make-backend/internal/gql/generated.go:5488.90,5490.4 1 0 +make-backend/internal/gql/generated.go:5491.42,5493.4 1 0 +make-backend/internal/gql/generated.go:5495.84,5497.4 1 0 +make-backend/internal/gql/generated.go:5502.157,5504.2 1 0 +make-backend/internal/gql/generated.go:5506.155,5511.90 1 0 +make-backend/internal/gql/generated.go:5511.90,5513.4 1 0 +make-backend/internal/gql/generated.go:5514.42,5516.4 1 0 +make-backend/internal/gql/generated.go:5518.83,5520.4 1 0 +make-backend/internal/gql/generated.go:5525.154,5527.2 1 0 +make-backend/internal/gql/generated.go:5529.154,5534.90 1 0 +make-backend/internal/gql/generated.go:5534.90,5536.4 1 0 +make-backend/internal/gql/generated.go:5537.42,5539.4 1 0 +make-backend/internal/gql/generated.go:5541.86,5543.4 1 0 +make-backend/internal/gql/generated.go:5548.153,5550.2 1 0 +make-backend/internal/gql/generated.go:5552.153,5557.90 1 0 +make-backend/internal/gql/generated.go:5557.90,5559.4 1 0 +make-backend/internal/gql/generated.go:5560.42,5562.4 1 0 +make-backend/internal/gql/generated.go:5564.89,5566.4 1 0 +make-backend/internal/gql/generated.go:5571.152,5573.2 1 0 +make-backend/internal/gql/generated.go:5575.151,5580.90 1 0 +make-backend/internal/gql/generated.go:5580.90,5582.4 1 0 +make-backend/internal/gql/generated.go:5583.42,5585.4 1 0 +make-backend/internal/gql/generated.go:5587.89,5589.4 1 0 +make-backend/internal/gql/generated.go:5594.150,5596.2 1 0 +make-backend/internal/gql/generated.go:5598.151,5603.90 1 0 +make-backend/internal/gql/generated.go:5603.90,5605.4 1 0 +make-backend/internal/gql/generated.go:5606.42,5608.4 1 0 +make-backend/internal/gql/generated.go:5610.84,5612.4 1 0 +make-backend/internal/gql/generated.go:5617.150,5619.2 1 0 +make-backend/internal/gql/generated.go:5621.145,5626.90 1 0 +make-backend/internal/gql/generated.go:5626.90,5628.4 1 0 +make-backend/internal/gql/generated.go:5629.42,5631.4 1 0 +make-backend/internal/gql/generated.go:5633.83,5635.4 1 0 +make-backend/internal/gql/generated.go:5640.144,5642.2 1 0 +make-backend/internal/gql/generated.go:5644.156,5649.90 1 0 +make-backend/internal/gql/generated.go:5649.90,5651.4 1 0 +make-backend/internal/gql/generated.go:5652.42,5654.4 1 0 +make-backend/internal/gql/generated.go:5656.83,5658.4 1 0 +make-backend/internal/gql/generated.go:5663.155,5665.2 1 0 +make-backend/internal/gql/generated.go:5667.153,5672.90 1 0 +make-backend/internal/gql/generated.go:5672.90,5674.4 1 0 +make-backend/internal/gql/generated.go:5675.42,5677.4 1 0 +make-backend/internal/gql/generated.go:5679.83,5681.4 1 0 +make-backend/internal/gql/generated.go:5686.152,5688.2 1 0 +make-backend/internal/gql/generated.go:5690.152,5695.90 1 0 +make-backend/internal/gql/generated.go:5695.90,5697.4 1 0 +make-backend/internal/gql/generated.go:5698.42,5700.4 1 0 +make-backend/internal/gql/generated.go:5702.83,5704.4 1 0 +make-backend/internal/gql/generated.go:5709.151,5711.2 1 0 +make-backend/internal/gql/generated.go:5713.154,5718.90 1 0 +make-backend/internal/gql/generated.go:5718.90,5720.4 1 0 +make-backend/internal/gql/generated.go:5721.42,5723.4 1 0 +make-backend/internal/gql/generated.go:5725.89,5727.4 1 0 +make-backend/internal/gql/generated.go:5732.153,5734.2 1 0 +make-backend/internal/gql/generated.go:5736.149,5741.90 1 0 +make-backend/internal/gql/generated.go:5741.90,5743.4 1 0 +make-backend/internal/gql/generated.go:5744.42,5746.4 1 0 +make-backend/internal/gql/generated.go:5748.86,5750.4 1 0 +make-backend/internal/gql/generated.go:5755.148,5757.2 1 0 +make-backend/internal/gql/generated.go:5759.161,5764.90 1 0 +make-backend/internal/gql/generated.go:5764.90,5766.4 1 0 +make-backend/internal/gql/generated.go:5767.42,5769.4 1 0 +make-backend/internal/gql/generated.go:5771.86,5773.4 1 0 +make-backend/internal/gql/generated.go:5778.155,5780.2 1 0 +make-backend/internal/gql/generated.go:5782.157,5787.90 1 0 +make-backend/internal/gql/generated.go:5787.90,5789.4 1 0 +make-backend/internal/gql/generated.go:5790.42,5792.4 1 0 +make-backend/internal/gql/generated.go:5794.86,5796.4 1 0 +make-backend/internal/gql/generated.go:5801.151,5803.2 1 0 +make-backend/internal/gql/generated.go:5805.160,5810.90 1 0 +make-backend/internal/gql/generated.go:5810.90,5812.4 1 0 +make-backend/internal/gql/generated.go:5813.42,5815.4 1 0 +make-backend/internal/gql/generated.go:5817.86,5819.4 1 0 +make-backend/internal/gql/generated.go:5824.154,5826.2 1 0 +make-backend/internal/gql/generated.go:5828.159,5833.90 1 0 +make-backend/internal/gql/generated.go:5833.90,5835.4 1 0 +make-backend/internal/gql/generated.go:5836.42,5838.4 1 0 +make-backend/internal/gql/generated.go:5840.87,5842.4 1 0 +make-backend/internal/gql/generated.go:5847.153,5849.2 1 0 +make-backend/internal/gql/generated.go:5851.157,5856.90 1 0 +make-backend/internal/gql/generated.go:5856.90,5858.4 1 0 +make-backend/internal/gql/generated.go:5859.42,5861.4 1 0 +make-backend/internal/gql/generated.go:5863.86,5865.4 1 0 +make-backend/internal/gql/generated.go:5870.151,5872.2 1 0 +make-backend/internal/gql/generated.go:5874.164,5879.90 1 0 +make-backend/internal/gql/generated.go:5879.90,5881.4 1 0 +make-backend/internal/gql/generated.go:5882.42,5884.4 1 0 +make-backend/internal/gql/generated.go:5886.86,5888.4 1 0 +make-backend/internal/gql/generated.go:5893.158,5895.2 1 0 +make-backend/internal/gql/generated.go:5897.158,5902.90 1 0 +make-backend/internal/gql/generated.go:5902.90,5904.4 1 0 +make-backend/internal/gql/generated.go:5905.42,5907.4 1 0 +make-backend/internal/gql/generated.go:5909.83,5911.4 1 0 +make-backend/internal/gql/generated.go:5916.156,5918.2 1 0 +make-backend/internal/gql/generated.go:5920.157,5925.90 1 0 +make-backend/internal/gql/generated.go:5925.90,5927.4 1 0 +make-backend/internal/gql/generated.go:5928.42,5930.4 1 0 +make-backend/internal/gql/generated.go:5932.89,5934.4 1 0 +make-backend/internal/gql/generated.go:5939.155,5941.2 1 0 +make-backend/internal/gql/generated.go:5943.154,5948.90 1 0 +make-backend/internal/gql/generated.go:5948.90,5950.4 1 0 +make-backend/internal/gql/generated.go:5951.42,5953.4 1 0 +make-backend/internal/gql/generated.go:5955.90,5957.4 1 0 +make-backend/internal/gql/generated.go:5962.152,5964.2 1 0 +make-backend/internal/gql/generated.go:5966.155,5971.90 1 0 +make-backend/internal/gql/generated.go:5971.90,5973.4 1 0 +make-backend/internal/gql/generated.go:5974.42,5976.4 1 0 +make-backend/internal/gql/generated.go:5978.90,5980.4 1 0 +make-backend/internal/gql/generated.go:5985.153,5987.2 1 0 +make-backend/internal/gql/generated.go:5989.151,5994.90 1 0 +make-backend/internal/gql/generated.go:5994.90,5996.4 1 0 +make-backend/internal/gql/generated.go:5997.42,5999.4 1 0 +make-backend/internal/gql/generated.go:6001.84,6003.4 1 0 +make-backend/internal/gql/generated.go:6008.149,6010.2 1 0 +make-backend/internal/gql/generated.go:6012.139,6017.90 1 0 +make-backend/internal/gql/generated.go:6017.90,6019.4 1 0 +make-backend/internal/gql/generated.go:6020.42,6022.4 1 0 +make-backend/internal/gql/generated.go:6024.83,6026.4 1 0 +make-backend/internal/gql/generated.go:6031.141,6033.2 1 0 +make-backend/internal/gql/generated.go:6035.144,6040.90 1 0 +make-backend/internal/gql/generated.go:6040.90,6042.4 1 0 +make-backend/internal/gql/generated.go:6043.42,6045.4 1 0 +make-backend/internal/gql/generated.go:6047.83,6049.4 1 0 +make-backend/internal/gql/generated.go:6054.146,6056.2 1 0 +make-backend/internal/gql/generated.go:6058.145,6063.90 1 0 +make-backend/internal/gql/generated.go:6063.90,6065.4 1 0 +make-backend/internal/gql/generated.go:6066.42,6068.4 1 0 +make-backend/internal/gql/generated.go:6070.86,6072.4 1 0 +make-backend/internal/gql/generated.go:6077.147,6079.2 1 0 +make-backend/internal/gql/generated.go:6081.143,6086.90 1 0 +make-backend/internal/gql/generated.go:6086.90,6088.4 1 0 +make-backend/internal/gql/generated.go:6089.42,6091.4 1 0 +make-backend/internal/gql/generated.go:6093.89,6095.4 1 0 +make-backend/internal/gql/generated.go:6100.145,6102.2 1 0 +make-backend/internal/gql/generated.go:6104.147,6109.90 1 0 +make-backend/internal/gql/generated.go:6109.90,6111.4 1 0 +make-backend/internal/gql/generated.go:6112.42,6114.4 1 0 +make-backend/internal/gql/generated.go:6116.86,6118.4 1 0 +make-backend/internal/gql/generated.go:6123.148,6125.2 1 0 +make-backend/internal/gql/generated.go:6127.143,6132.90 1 0 +make-backend/internal/gql/generated.go:6132.90,6134.4 1 0 +make-backend/internal/gql/generated.go:6135.42,6137.4 1 0 +make-backend/internal/gql/generated.go:6139.86,6141.4 1 0 +make-backend/internal/gql/generated.go:6146.144,6148.2 1 0 +make-backend/internal/gql/generated.go:6150.146,6155.90 1 0 +make-backend/internal/gql/generated.go:6155.90,6157.4 1 0 +make-backend/internal/gql/generated.go:6158.42,6160.4 1 0 +make-backend/internal/gql/generated.go:6162.86,6164.4 1 0 +make-backend/internal/gql/generated.go:6169.147,6171.2 1 0 +make-backend/internal/gql/generated.go:6173.139,6178.90 1 0 +make-backend/internal/gql/generated.go:6178.90,6180.4 1 0 +make-backend/internal/gql/generated.go:6181.42,6183.4 1 0 +make-backend/internal/gql/generated.go:6185.83,6187.4 1 0 +make-backend/internal/gql/generated.go:6192.141,6194.2 1 0 +make-backend/internal/gql/generated.go:6196.141,6201.90 1 0 +make-backend/internal/gql/generated.go:6201.90,6203.4 1 0 +make-backend/internal/gql/generated.go:6204.42,6206.4 1 0 +make-backend/internal/gql/generated.go:6208.86,6210.4 1 0 +make-backend/internal/gql/generated.go:6215.143,6217.2 1 0 +make-backend/internal/gql/generated.go:6219.150,6224.90 1 0 +make-backend/internal/gql/generated.go:6224.90,6226.4 1 0 +make-backend/internal/gql/generated.go:6227.42,6229.4 1 0 +make-backend/internal/gql/generated.go:6231.84,6233.4 1 0 +make-backend/internal/gql/generated.go:6238.152,6240.2 1 0 +make-backend/internal/gql/generated.go:6242.143,6247.90 1 0 +make-backend/internal/gql/generated.go:6247.90,6249.4 1 0 +make-backend/internal/gql/generated.go:6250.42,6252.4 1 0 +make-backend/internal/gql/generated.go:6254.102,6256.4 1 0 +make-backend/internal/gql/generated.go:6261.145,6263.2 1 0 +make-backend/internal/gql/generated.go:6265.131,6270.90 1 0 +make-backend/internal/gql/generated.go:6270.90,6272.4 1 0 +make-backend/internal/gql/generated.go:6273.42,6275.4 1 0 +make-backend/internal/gql/generated.go:6277.83,6279.4 1 0 +make-backend/internal/gql/generated.go:6284.137,6286.2 1 0 +make-backend/internal/gql/generated.go:6288.134,6293.90 1 0 +make-backend/internal/gql/generated.go:6293.90,6295.4 1 0 +make-backend/internal/gql/generated.go:6296.42,6298.4 1 0 +make-backend/internal/gql/generated.go:6300.86,6302.4 1 0 +make-backend/internal/gql/generated.go:6307.140,6309.2 1 0 +make-backend/internal/gql/generated.go:6311.138,6316.90 1 0 +make-backend/internal/gql/generated.go:6316.90,6318.4 1 0 +make-backend/internal/gql/generated.go:6319.42,6321.4 1 0 +make-backend/internal/gql/generated.go:6323.86,6325.4 1 0 +make-backend/internal/gql/generated.go:6330.144,6332.2 1 0 +make-backend/internal/gql/generated.go:6334.137,6339.90 1 0 +make-backend/internal/gql/generated.go:6339.90,6341.4 1 0 +make-backend/internal/gql/generated.go:6342.42,6344.4 1 0 +make-backend/internal/gql/generated.go:6346.86,6348.4 1 0 +make-backend/internal/gql/generated.go:6353.143,6355.2 1 0 +make-backend/internal/gql/generated.go:6357.137,6362.90 1 0 +make-backend/internal/gql/generated.go:6362.90,6364.4 1 0 +make-backend/internal/gql/generated.go:6365.42,6367.4 1 0 +make-backend/internal/gql/generated.go:6369.86,6371.4 1 0 +make-backend/internal/gql/generated.go:6376.143,6378.2 1 0 +make-backend/internal/gql/generated.go:6380.138,6385.90 1 0 +make-backend/internal/gql/generated.go:6385.90,6387.4 1 0 +make-backend/internal/gql/generated.go:6388.42,6390.4 1 0 +make-backend/internal/gql/generated.go:6392.89,6394.4 1 0 +make-backend/internal/gql/generated.go:6399.144,6401.2 1 0 +make-backend/internal/gql/generated.go:6403.143,6408.90 1 0 +make-backend/internal/gql/generated.go:6408.90,6410.4 1 0 +make-backend/internal/gql/generated.go:6411.42,6413.4 1 0 +make-backend/internal/gql/generated.go:6415.84,6417.4 1 0 +make-backend/internal/gql/generated.go:6422.149,6424.2 1 0 +make-backend/internal/gql/generated.go:6426.137,6431.90 1 0 +make-backend/internal/gql/generated.go:6431.90,6433.4 1 0 +make-backend/internal/gql/generated.go:6434.42,6436.4 1 0 +make-backend/internal/gql/generated.go:6438.84,6440.4 1 0 +make-backend/internal/gql/generated.go:6445.143,6447.2 1 0 +make-backend/internal/gql/generated.go:6449.134,6454.90 1 0 +make-backend/internal/gql/generated.go:6454.90,6456.4 1 0 +make-backend/internal/gql/generated.go:6457.42,6459.4 1 0 +make-backend/internal/gql/generated.go:6461.86,6463.4 1 0 +make-backend/internal/gql/generated.go:6468.140,6470.2 1 0 +make-backend/internal/gql/generated.go:6472.134,6477.90 1 0 +make-backend/internal/gql/generated.go:6477.90,6479.4 1 0 +make-backend/internal/gql/generated.go:6480.42,6482.4 1 0 +make-backend/internal/gql/generated.go:6484.84,6486.4 1 0 +make-backend/internal/gql/generated.go:6491.140,6493.2 1 0 +make-backend/internal/gql/generated.go:6495.142,6500.90 1 0 +make-backend/internal/gql/generated.go:6500.90,6502.4 1 0 +make-backend/internal/gql/generated.go:6503.42,6505.4 1 0 +make-backend/internal/gql/generated.go:6507.85,6509.4 1 0 +make-backend/internal/gql/generated.go:6514.148,6516.2 1 0 +make-backend/internal/gql/generated.go:6518.137,6523.90 1 0 +make-backend/internal/gql/generated.go:6523.90,6525.4 1 0 +make-backend/internal/gql/generated.go:6526.42,6528.4 1 0 +make-backend/internal/gql/generated.go:6529.69,6532.57 2 0 +make-backend/internal/gql/generated.go:6532.57,6533.37 1 0 +make-backend/internal/gql/generated.go:6533.37,6536.6 2 0 +make-backend/internal/gql/generated.go:6537.5,6537.55 1 0 +make-backend/internal/gql/generated.go:6540.4,6541.15 2 0 +make-backend/internal/gql/generated.go:6543.86,6545.4 1 0 +make-backend/internal/gql/generated.go:6550.143,6552.2 1 0 +make-backend/internal/gql/generated.go:6554.131,6559.90 1 0 +make-backend/internal/gql/generated.go:6559.90,6561.4 1 0 +make-backend/internal/gql/generated.go:6562.42,6564.4 1 0 +make-backend/internal/gql/generated.go:6566.83,6568.4 1 0 +make-backend/internal/gql/generated.go:6573.137,6575.2 1 0 +make-backend/internal/gql/generated.go:6577.142,6582.90 1 0 +make-backend/internal/gql/generated.go:6582.90,6584.4 1 0 +make-backend/internal/gql/generated.go:6585.42,6587.4 1 0 +make-backend/internal/gql/generated.go:6589.83,6591.4 1 0 +make-backend/internal/gql/generated.go:6596.148,6598.2 1 0 +make-backend/internal/gql/generated.go:6600.133,6605.90 1 0 +make-backend/internal/gql/generated.go:6605.90,6607.4 1 0 +make-backend/internal/gql/generated.go:6608.42,6610.4 1 0 +make-backend/internal/gql/generated.go:6612.86,6614.4 1 0 +make-backend/internal/gql/generated.go:6619.139,6621.2 1 0 +make-backend/internal/gql/generated.go:6623.135,6628.90 1 0 +make-backend/internal/gql/generated.go:6628.90,6630.4 1 0 +make-backend/internal/gql/generated.go:6631.42,6633.4 1 0 +make-backend/internal/gql/generated.go:6635.84,6637.4 1 0 +make-backend/internal/gql/generated.go:6642.141,6644.2 1 0 +make-backend/internal/gql/generated.go:6646.152,6651.90 1 0 +make-backend/internal/gql/generated.go:6651.90,6653.4 1 0 +make-backend/internal/gql/generated.go:6654.42,6656.4 1 0 +make-backend/internal/gql/generated.go:6658.86,6660.4 1 0 +make-backend/internal/gql/generated.go:6665.146,6667.2 1 0 +make-backend/internal/gql/generated.go:6669.159,6674.90 1 0 +make-backend/internal/gql/generated.go:6674.90,6676.4 1 0 +make-backend/internal/gql/generated.go:6677.42,6679.4 1 0 +make-backend/internal/gql/generated.go:6681.87,6683.4 1 0 +make-backend/internal/gql/generated.go:6688.153,6690.2 1 0 +make-backend/internal/gql/generated.go:6692.160,6697.90 1 0 +make-backend/internal/gql/generated.go:6697.90,6699.4 1 0 +make-backend/internal/gql/generated.go:6700.42,6702.4 1 0 +make-backend/internal/gql/generated.go:6704.84,6706.4 1 0 +make-backend/internal/gql/generated.go:6711.154,6713.2 1 0 +make-backend/internal/gql/generated.go:6715.157,6720.90 1 0 +make-backend/internal/gql/generated.go:6720.90,6722.4 1 0 +make-backend/internal/gql/generated.go:6723.42,6725.4 1 0 +make-backend/internal/gql/generated.go:6727.88,6729.4 1 0 +make-backend/internal/gql/generated.go:6734.151,6736.2 1 0 +make-backend/internal/gql/generated.go:6738.152,6743.90 1 0 +make-backend/internal/gql/generated.go:6743.90,6745.4 1 0 +make-backend/internal/gql/generated.go:6746.42,6748.4 1 0 +make-backend/internal/gql/generated.go:6750.106,6752.4 1 0 +make-backend/internal/gql/generated.go:6757.148,6763.97 1 0 +make-backend/internal/gql/generated.go:6763.97,6765.4 1 0 +make-backend/internal/gql/generated.go:6767.2,6767.15 1 0 +make-backend/internal/gql/generated.go:6767.15,6768.31 1 0 +make-backend/internal/gql/generated.go:6768.31,6771.4 2 0 +make-backend/internal/gql/generated.go:6773.2,6774.101 2 0 +make-backend/internal/gql/generated.go:6774.101,6777.3 2 0 +make-backend/internal/gql/generated.go:6778.2,6778.16 1 0 +make-backend/internal/gql/generated.go:6781.152,6786.90 1 0 +make-backend/internal/gql/generated.go:6786.90,6788.4 1 0 +make-backend/internal/gql/generated.go:6789.42,6791.4 1 0 +make-backend/internal/gql/generated.go:6793.86,6795.4 1 0 +make-backend/internal/gql/generated.go:6800.146,6802.2 1 0 +make-backend/internal/gql/generated.go:6804.159,6809.90 1 0 +make-backend/internal/gql/generated.go:6809.90,6811.4 1 0 +make-backend/internal/gql/generated.go:6812.42,6814.4 1 0 +make-backend/internal/gql/generated.go:6816.87,6818.4 1 0 +make-backend/internal/gql/generated.go:6823.153,6825.2 1 0 +make-backend/internal/gql/generated.go:6827.160,6832.90 1 0 +make-backend/internal/gql/generated.go:6832.90,6834.4 1 0 +make-backend/internal/gql/generated.go:6835.42,6837.4 1 0 +make-backend/internal/gql/generated.go:6839.84,6841.4 1 0 +make-backend/internal/gql/generated.go:6846.154,6848.2 1 0 +make-backend/internal/gql/generated.go:6850.165,6855.90 1 0 +make-backend/internal/gql/generated.go:6855.90,6857.4 1 0 +make-backend/internal/gql/generated.go:6858.42,6860.4 1 0 +make-backend/internal/gql/generated.go:6862.87,6864.4 1 0 +make-backend/internal/gql/generated.go:6869.159,6871.2 1 0 +make-backend/internal/gql/generated.go:6873.144,6878.90 1 0 +make-backend/internal/gql/generated.go:6878.90,6880.4 1 0 +make-backend/internal/gql/generated.go:6881.42,6883.4 1 0 +make-backend/internal/gql/generated.go:6885.86,6887.4 1 0 +make-backend/internal/gql/generated.go:6892.142,6894.2 1 0 +make-backend/internal/gql/generated.go:6896.151,6901.90 1 0 +make-backend/internal/gql/generated.go:6901.90,6903.4 1 0 +make-backend/internal/gql/generated.go:6904.42,6906.4 1 0 +make-backend/internal/gql/generated.go:6908.87,6910.4 1 0 +make-backend/internal/gql/generated.go:6915.149,6917.2 1 0 +make-backend/internal/gql/generated.go:6919.144,6924.90 1 0 +make-backend/internal/gql/generated.go:6924.90,6926.4 1 0 +make-backend/internal/gql/generated.go:6927.42,6929.4 1 0 +make-backend/internal/gql/generated.go:6931.106,6933.4 1 0 +make-backend/internal/gql/generated.go:6938.144,6944.97 1 0 +make-backend/internal/gql/generated.go:6944.97,6946.4 1 0 +make-backend/internal/gql/generated.go:6948.2,6948.15 1 0 +make-backend/internal/gql/generated.go:6948.15,6949.31 1 0 +make-backend/internal/gql/generated.go:6949.31,6952.4 2 0 +make-backend/internal/gql/generated.go:6954.2,6955.97 2 0 +make-backend/internal/gql/generated.go:6955.97,6958.3 2 0 +make-backend/internal/gql/generated.go:6959.2,6959.16 1 0 +make-backend/internal/gql/generated.go:6962.144,6967.90 1 0 +make-backend/internal/gql/generated.go:6967.90,6969.4 1 0 +make-backend/internal/gql/generated.go:6970.42,6972.4 1 0 +make-backend/internal/gql/generated.go:6974.99,6976.4 1 0 +make-backend/internal/gql/generated.go:6981.142,6987.97 1 0 +make-backend/internal/gql/generated.go:6987.97,6989.4 1 0 +make-backend/internal/gql/generated.go:6991.2,6991.16 1 0 +make-backend/internal/gql/generated.go:6994.152,6999.90 1 0 +make-backend/internal/gql/generated.go:6999.90,7001.4 1 0 +make-backend/internal/gql/generated.go:7002.42,7004.4 1 0 +make-backend/internal/gql/generated.go:7006.84,7008.4 1 0 +make-backend/internal/gql/generated.go:7013.150,7015.2 1 0 +make-backend/internal/gql/generated.go:7017.157,7022.90 1 0 +make-backend/internal/gql/generated.go:7022.90,7024.4 1 0 +make-backend/internal/gql/generated.go:7025.42,7027.4 1 0 +make-backend/internal/gql/generated.go:7029.87,7031.4 1 0 +make-backend/internal/gql/generated.go:7036.155,7038.2 1 0 +make-backend/internal/gql/generated.go:7040.154,7045.90 1 0 +make-backend/internal/gql/generated.go:7045.90,7047.4 1 0 +make-backend/internal/gql/generated.go:7048.42,7050.4 1 0 +make-backend/internal/gql/generated.go:7052.86,7054.4 1 0 +make-backend/internal/gql/generated.go:7059.147,7061.2 1 0 +make-backend/internal/gql/generated.go:7063.161,7068.90 1 0 +make-backend/internal/gql/generated.go:7068.90,7070.4 1 0 +make-backend/internal/gql/generated.go:7071.42,7073.4 1 0 +make-backend/internal/gql/generated.go:7075.87,7077.4 1 0 +make-backend/internal/gql/generated.go:7082.154,7084.2 1 0 +make-backend/internal/gql/generated.go:7086.154,7091.90 1 0 +make-backend/internal/gql/generated.go:7091.90,7093.4 1 0 +make-backend/internal/gql/generated.go:7094.42,7096.4 1 0 +make-backend/internal/gql/generated.go:7098.99,7100.4 1 0 +make-backend/internal/gql/generated.go:7105.147,7111.97 1 0 +make-backend/internal/gql/generated.go:7111.97,7113.4 1 0 +make-backend/internal/gql/generated.go:7115.2,7115.16 1 0 +make-backend/internal/gql/generated.go:7118.162,7123.90 1 0 +make-backend/internal/gql/generated.go:7123.90,7125.4 1 0 +make-backend/internal/gql/generated.go:7126.42,7128.4 1 0 +make-backend/internal/gql/generated.go:7130.87,7132.4 1 0 +make-backend/internal/gql/generated.go:7137.155,7139.2 1 0 +make-backend/internal/gql/generated.go:7141.162,7146.90 1 0 +make-backend/internal/gql/generated.go:7146.90,7148.4 1 0 +make-backend/internal/gql/generated.go:7149.42,7151.4 1 0 +make-backend/internal/gql/generated.go:7153.84,7155.4 1 0 +make-backend/internal/gql/generated.go:7160.155,7162.2 1 0 +make-backend/internal/gql/generated.go:7164.167,7169.90 1 0 +make-backend/internal/gql/generated.go:7169.90,7171.4 1 0 +make-backend/internal/gql/generated.go:7172.42,7174.4 1 0 +make-backend/internal/gql/generated.go:7176.87,7178.4 1 0 +make-backend/internal/gql/generated.go:7183.160,7185.2 1 0 +make-backend/internal/gql/generated.go:7187.153,7192.90 1 0 +make-backend/internal/gql/generated.go:7192.90,7194.4 1 0 +make-backend/internal/gql/generated.go:7195.42,7197.4 1 0 +make-backend/internal/gql/generated.go:7199.87,7201.4 1 0 +make-backend/internal/gql/generated.go:7206.150,7208.2 1 0 +make-backend/internal/gql/generated.go:7210.147,7215.90 1 0 +make-backend/internal/gql/generated.go:7215.90,7217.4 1 0 +make-backend/internal/gql/generated.go:7218.42,7220.4 1 0 +make-backend/internal/gql/generated.go:7222.100,7224.4 1 0 +make-backend/internal/gql/generated.go:7229.144,7235.97 1 0 +make-backend/internal/gql/generated.go:7235.97,7237.4 1 0 +make-backend/internal/gql/generated.go:7239.2,7239.16 1 0 +make-backend/internal/gql/generated.go:7242.151,7247.90 1 0 +make-backend/internal/gql/generated.go:7247.90,7249.4 1 0 +make-backend/internal/gql/generated.go:7250.42,7252.4 1 0 +make-backend/internal/gql/generated.go:7254.99,7256.4 1 0 +make-backend/internal/gql/generated.go:7261.148,7267.97 1 0 +make-backend/internal/gql/generated.go:7267.97,7269.4 1 0 +make-backend/internal/gql/generated.go:7271.2,7271.16 1 0 +make-backend/internal/gql/generated.go:7274.154,7279.90 1 0 +make-backend/internal/gql/generated.go:7279.90,7281.4 1 0 +make-backend/internal/gql/generated.go:7282.42,7284.4 1 0 +make-backend/internal/gql/generated.go:7286.99,7288.4 1 0 +make-backend/internal/gql/generated.go:7293.151,7299.97 1 0 +make-backend/internal/gql/generated.go:7299.97,7301.4 1 0 +make-backend/internal/gql/generated.go:7303.2,7303.16 1 0 +make-backend/internal/gql/generated.go:7306.158,7311.90 1 0 +make-backend/internal/gql/generated.go:7311.90,7313.4 1 0 +make-backend/internal/gql/generated.go:7314.42,7316.4 1 0 +make-backend/internal/gql/generated.go:7318.99,7320.4 1 0 +make-backend/internal/gql/generated.go:7325.155,7331.97 1 0 +make-backend/internal/gql/generated.go:7331.97,7333.4 1 0 +make-backend/internal/gql/generated.go:7335.2,7335.16 1 0 +make-backend/internal/gql/generated.go:7338.152,7343.90 1 0 +make-backend/internal/gql/generated.go:7343.90,7345.4 1 0 +make-backend/internal/gql/generated.go:7346.42,7348.4 1 0 +make-backend/internal/gql/generated.go:7350.105,7352.4 1 0 +make-backend/internal/gql/generated.go:7357.149,7363.97 1 0 +make-backend/internal/gql/generated.go:7363.97,7365.4 1 0 +make-backend/internal/gql/generated.go:7367.2,7367.16 1 0 +make-backend/internal/gql/generated.go:7370.142,7375.90 1 0 +make-backend/internal/gql/generated.go:7375.90,7377.4 1 0 +make-backend/internal/gql/generated.go:7378.42,7380.4 1 0 +make-backend/internal/gql/generated.go:7382.86,7384.4 1 0 +make-backend/internal/gql/generated.go:7389.141,7391.2 1 0 +make-backend/internal/gql/generated.go:7393.142,7398.90 1 0 +make-backend/internal/gql/generated.go:7398.90,7400.4 1 0 +make-backend/internal/gql/generated.go:7401.42,7403.4 1 0 +make-backend/internal/gql/generated.go:7405.87,7407.4 1 0 +make-backend/internal/gql/generated.go:7412.141,7414.2 1 0 +make-backend/internal/gql/generated.go:7416.149,7421.90 1 0 +make-backend/internal/gql/generated.go:7421.90,7423.4 1 0 +make-backend/internal/gql/generated.go:7424.42,7426.4 1 0 +make-backend/internal/gql/generated.go:7428.87,7430.4 1 0 +make-backend/internal/gql/generated.go:7435.148,7437.2 1 0 +make-backend/internal/gql/generated.go:7439.152,7444.90 1 0 +make-backend/internal/gql/generated.go:7444.90,7446.4 1 0 +make-backend/internal/gql/generated.go:7447.42,7449.4 1 0 +make-backend/internal/gql/generated.go:7451.87,7453.4 1 0 +make-backend/internal/gql/generated.go:7458.151,7460.2 1 0 +make-backend/internal/gql/generated.go:7462.144,7467.90 1 0 +make-backend/internal/gql/generated.go:7467.90,7469.4 1 0 +make-backend/internal/gql/generated.go:7470.42,7473.4 2 0 +make-backend/internal/gql/generated.go:7475.101,7477.4 1 0 +make-backend/internal/gql/generated.go:7482.145,7488.97 1 0 +make-backend/internal/gql/generated.go:7488.97,7490.4 1 0 +make-backend/internal/gql/generated.go:7492.2,7492.15 1 0 +make-backend/internal/gql/generated.go:7492.15,7493.31 1 0 +make-backend/internal/gql/generated.go:7493.31,7496.4 2 0 +make-backend/internal/gql/generated.go:7498.2,7499.98 2 0 +make-backend/internal/gql/generated.go:7499.98,7502.3 2 0 +make-backend/internal/gql/generated.go:7503.2,7503.16 1 0 +make-backend/internal/gql/generated.go:7506.148,7511.90 1 0 +make-backend/internal/gql/generated.go:7511.90,7513.4 1 0 +make-backend/internal/gql/generated.go:7514.42,7516.4 1 0 +make-backend/internal/gql/generated.go:7518.100,7520.4 1 0 +make-backend/internal/gql/generated.go:7525.147,7531.97 1 0 +make-backend/internal/gql/generated.go:7531.97,7533.4 1 0 +make-backend/internal/gql/generated.go:7535.2,7535.16 1 0 +make-backend/internal/gql/generated.go:7538.151,7543.90 1 0 +make-backend/internal/gql/generated.go:7543.90,7545.4 1 0 +make-backend/internal/gql/generated.go:7546.42,7548.4 1 0 +make-backend/internal/gql/generated.go:7550.100,7552.4 1 0 +make-backend/internal/gql/generated.go:7557.150,7563.97 1 0 +make-backend/internal/gql/generated.go:7563.97,7565.4 1 0 +make-backend/internal/gql/generated.go:7567.2,7567.16 1 0 +make-backend/internal/gql/generated.go:7570.148,7575.90 1 0 +make-backend/internal/gql/generated.go:7575.90,7577.4 1 0 +make-backend/internal/gql/generated.go:7578.42,7581.4 2 0 +make-backend/internal/gql/generated.go:7583.105,7585.4 1 0 +make-backend/internal/gql/generated.go:7590.149,7596.97 1 0 +make-backend/internal/gql/generated.go:7596.97,7598.4 1 0 +make-backend/internal/gql/generated.go:7600.2,7600.15 1 0 +make-backend/internal/gql/generated.go:7600.15,7601.31 1 0 +make-backend/internal/gql/generated.go:7601.31,7604.4 2 0 +make-backend/internal/gql/generated.go:7606.2,7607.102 2 0 +make-backend/internal/gql/generated.go:7607.102,7610.3 2 0 +make-backend/internal/gql/generated.go:7611.2,7611.16 1 0 +make-backend/internal/gql/generated.go:7614.149,7619.90 1 0 +make-backend/internal/gql/generated.go:7619.90,7621.4 1 0 +make-backend/internal/gql/generated.go:7622.42,7624.4 1 0 +make-backend/internal/gql/generated.go:7626.106,7628.4 1 0 +make-backend/internal/gql/generated.go:7633.148,7639.97 1 0 +make-backend/internal/gql/generated.go:7639.97,7641.4 1 0 +make-backend/internal/gql/generated.go:7643.2,7643.16 1 0 +make-backend/internal/gql/generated.go:7646.144,7651.90 1 0 +make-backend/internal/gql/generated.go:7651.90,7653.4 1 0 +make-backend/internal/gql/generated.go:7654.42,7656.4 1 0 +make-backend/internal/gql/generated.go:7658.99,7660.4 1 0 +make-backend/internal/gql/generated.go:7665.143,7671.97 1 0 +make-backend/internal/gql/generated.go:7671.97,7673.4 1 0 +make-backend/internal/gql/generated.go:7675.2,7675.16 1 0 +make-backend/internal/gql/generated.go:7678.145,7683.90 1 0 +make-backend/internal/gql/generated.go:7683.90,7685.4 1 0 +make-backend/internal/gql/generated.go:7686.42,7688.4 1 0 +make-backend/internal/gql/generated.go:7690.84,7692.4 1 0 +make-backend/internal/gql/generated.go:7697.144,7699.2 1 0 +make-backend/internal/gql/generated.go:7709.135,7710.29 1 0 +make-backend/internal/gql/generated.go:7711.11,7712.22 1 0 +make-backend/internal/gql/generated.go:7713.27,7714.42 1 0 +make-backend/internal/gql/generated.go:7715.28,7716.17 1 0 +make-backend/internal/gql/generated.go:7716.17,7718.4 1 0 +make-backend/internal/gql/generated.go:7719.3,7719.41 1 0 +make-backend/internal/gql/generated.go:7720.27,7721.42 1 0 +make-backend/internal/gql/generated.go:7722.28,7723.17 1 0 +make-backend/internal/gql/generated.go:7723.17,7725.4 1 0 +make-backend/internal/gql/generated.go:7726.3,7726.41 1 0 +make-backend/internal/gql/generated.go:7727.10,7728.50 1 0 +make-backend/internal/gql/generated.go:7728.50,7730.4 1 0 +make-backend/internal/gql/generated.go:7730.9,7731.124 1 0 +make-backend/internal/gql/generated.go:7736.131,7737.29 1 0 +make-backend/internal/gql/generated.go:7738.11,7739.22 1 0 +make-backend/internal/gql/generated.go:7740.25,7741.17 1 0 +make-backend/internal/gql/generated.go:7741.17,7743.4 1 0 +make-backend/internal/gql/generated.go:7744.3,7744.38 1 0 +make-backend/internal/gql/generated.go:7745.32,7746.17 1 0 +make-backend/internal/gql/generated.go:7746.17,7748.4 1 0 +make-backend/internal/gql/generated.go:7749.3,7749.45 1 0 +make-backend/internal/gql/generated.go:7750.27,7751.17 1 0 +make-backend/internal/gql/generated.go:7751.17,7753.4 1 0 +make-backend/internal/gql/generated.go:7754.3,7754.40 1 0 +make-backend/internal/gql/generated.go:7755.26,7756.17 1 0 +make-backend/internal/gql/generated.go:7756.17,7758.4 1 0 +make-backend/internal/gql/generated.go:7759.3,7759.39 1 0 +make-backend/internal/gql/generated.go:7760.10,7761.50 1 0 +make-backend/internal/gql/generated.go:7761.50,7763.4 1 0 +make-backend/internal/gql/generated.go:7763.9,7764.122 1 0 +make-backend/internal/gql/generated.go:7775.132,7781.31 5 0 +make-backend/internal/gql/generated.go:7781.31,7782.21 1 0 +make-backend/internal/gql/generated.go:7783.21,7784.58 1 0 +make-backend/internal/gql/generated.go:7785.13,7787.37 2 0 +make-backend/internal/gql/generated.go:7787.37,7789.5 1 0 +make-backend/internal/gql/generated.go:7790.20,7792.37 2 0 +make-backend/internal/gql/generated.go:7792.37,7794.5 1 0 +make-backend/internal/gql/generated.go:7795.21,7797.37 2 0 +make-backend/internal/gql/generated.go:7797.37,7799.5 1 0 +make-backend/internal/gql/generated.go:7800.16,7802.45 2 0 +make-backend/internal/gql/generated.go:7802.45,7804.5 1 0 +make-backend/internal/gql/generated.go:7805.24,7807.37 2 0 +make-backend/internal/gql/generated.go:7807.37,7809.5 1 0 +make-backend/internal/gql/generated.go:7810.11,7811.55 1 0 +make-backend/internal/gql/generated.go:7814.2,7815.22 2 0 +make-backend/internal/gql/generated.go:7815.22,7817.3 1 0 +make-backend/internal/gql/generated.go:7819.2,7828.12 3 0 +make-backend/internal/gql/generated.go:7833.136,7839.31 5 0 +make-backend/internal/gql/generated.go:7839.31,7840.21 1 0 +make-backend/internal/gql/generated.go:7841.21,7842.60 1 0 +make-backend/internal/gql/generated.go:7843.13,7845.37 2 0 +make-backend/internal/gql/generated.go:7845.37,7847.5 1 0 +make-backend/internal/gql/generated.go:7848.15,7851.89 2 0 +make-backend/internal/gql/generated.go:7851.89,7852.18 1 0 +make-backend/internal/gql/generated.go:7852.18,7853.34 1 0 +make-backend/internal/gql/generated.go:7853.34,7855.7 1 0 +make-backend/internal/gql/generated.go:7857.5,7858.28 2 0 +make-backend/internal/gql/generated.go:7858.28,7860.6 1 0 +make-backend/internal/gql/generated.go:7861.5,7861.15 1 0 +make-backend/internal/gql/generated.go:7864.4,7864.26 1 0 +make-backend/internal/gql/generated.go:7864.26,7867.91 3 0 +make-backend/internal/gql/generated.go:7867.91,7869.6 1 0 +make-backend/internal/gql/generated.go:7871.5,7871.50 1 0 +make-backend/internal/gql/generated.go:7871.50,7873.13 2 0 +make-backend/internal/gql/generated.go:7873.13,7876.7 2 0 +make-backend/internal/gql/generated.go:7877.6,7877.33 1 0 +make-backend/internal/gql/generated.go:7881.5,7882.13 2 0 +make-backend/internal/gql/generated.go:7885.4,7885.68 1 0 +make-backend/internal/gql/generated.go:7885.68,7885.98 1 0 +make-backend/internal/gql/generated.go:7886.19,7888.37 2 0 +make-backend/internal/gql/generated.go:7888.37,7890.5 1 0 +make-backend/internal/gql/generated.go:7891.11,7892.55 1 0 +make-backend/internal/gql/generated.go:7895.2,7896.22 2 0 +make-backend/internal/gql/generated.go:7896.22,7898.3 1 0 +make-backend/internal/gql/generated.go:7900.2,7909.12 3 0 +make-backend/internal/gql/generated.go:7914.138,7920.31 5 0 +make-backend/internal/gql/generated.go:7920.31,7921.21 1 0 +make-backend/internal/gql/generated.go:7922.21,7923.61 1 0 +make-backend/internal/gql/generated.go:7924.13,7926.37 2 0 +make-backend/internal/gql/generated.go:7926.37,7928.5 1 0 +make-backend/internal/gql/generated.go:7929.21,7931.37 2 0 +make-backend/internal/gql/generated.go:7931.37,7933.5 1 0 +make-backend/internal/gql/generated.go:7934.11,7935.55 1 0 +make-backend/internal/gql/generated.go:7938.2,7939.22 2 0 +make-backend/internal/gql/generated.go:7939.22,7941.3 1 0 +make-backend/internal/gql/generated.go:7943.2,7952.12 3 0 +make-backend/internal/gql/generated.go:7957.130,7963.31 5 0 +make-backend/internal/gql/generated.go:7963.31,7964.21 1 0 +make-backend/internal/gql/generated.go:7965.21,7966.57 1 0 +make-backend/internal/gql/generated.go:7967.17,7969.37 2 0 +make-backend/internal/gql/generated.go:7969.37,7971.5 1 0 +make-backend/internal/gql/generated.go:7972.19,7974.37 2 0 +make-backend/internal/gql/generated.go:7974.37,7976.5 1 0 +make-backend/internal/gql/generated.go:7977.24,7979.37 2 0 +make-backend/internal/gql/generated.go:7979.37,7981.5 1 0 +make-backend/internal/gql/generated.go:7982.27,7984.37 2 0 +make-backend/internal/gql/generated.go:7984.37,7986.5 1 0 +make-backend/internal/gql/generated.go:7987.22,7989.45 2 0 +make-backend/internal/gql/generated.go:7989.45,7991.5 1 0 +make-backend/internal/gql/generated.go:7992.24,7994.45 2 0 +make-backend/internal/gql/generated.go:7994.45,7996.5 1 0 +make-backend/internal/gql/generated.go:7997.16,7999.37 2 0 +make-backend/internal/gql/generated.go:7999.37,8001.5 1 0 +make-backend/internal/gql/generated.go:8002.28,8004.45 2 0 +make-backend/internal/gql/generated.go:8004.45,8006.5 1 0 +make-backend/internal/gql/generated.go:8007.30,8009.45 2 0 +make-backend/internal/gql/generated.go:8009.45,8011.5 1 0 +make-backend/internal/gql/generated.go:8012.11,8013.55 1 0 +make-backend/internal/gql/generated.go:8016.2,8017.22 2 0 +make-backend/internal/gql/generated.go:8017.22,8019.3 1 0 +make-backend/internal/gql/generated.go:8021.2,8030.12 3 0 +make-backend/internal/gql/generated.go:8035.140,8041.31 5 0 +make-backend/internal/gql/generated.go:8041.31,8042.21 1 0 +make-backend/internal/gql/generated.go:8043.21,8044.62 1 0 +make-backend/internal/gql/generated.go:8045.25,8047.37 2 0 +make-backend/internal/gql/generated.go:8047.37,8049.5 1 0 +make-backend/internal/gql/generated.go:8050.30,8052.37 2 0 +make-backend/internal/gql/generated.go:8052.37,8054.5 1 0 +make-backend/internal/gql/generated.go:8055.20,8057.37 2 0 +make-backend/internal/gql/generated.go:8057.37,8059.5 1 0 +make-backend/internal/gql/generated.go:8060.11,8061.55 1 0 +make-backend/internal/gql/generated.go:8064.2,8065.22 2 0 +make-backend/internal/gql/generated.go:8065.22,8067.3 1 0 +make-backend/internal/gql/generated.go:8069.2,8078.12 3 0 +make-backend/internal/gql/generated.go:8083.130,8089.31 5 0 +make-backend/internal/gql/generated.go:8089.31,8090.21 1 0 +make-backend/internal/gql/generated.go:8091.21,8092.57 1 0 +make-backend/internal/gql/generated.go:8093.13,8095.37 2 0 +make-backend/internal/gql/generated.go:8095.37,8097.5 1 0 +make-backend/internal/gql/generated.go:8098.16,8100.37 2 0 +make-backend/internal/gql/generated.go:8100.37,8102.5 1 0 +make-backend/internal/gql/generated.go:8103.15,8105.37 2 0 +make-backend/internal/gql/generated.go:8105.37,8107.5 1 0 +make-backend/internal/gql/generated.go:8108.24,8110.45 2 0 +make-backend/internal/gql/generated.go:8110.45,8112.5 1 0 +make-backend/internal/gql/generated.go:8113.11,8114.55 1 0 +make-backend/internal/gql/generated.go:8117.2,8118.22 2 0 +make-backend/internal/gql/generated.go:8118.22,8120.3 1 0 +make-backend/internal/gql/generated.go:8122.2,8131.12 3 0 +make-backend/internal/gql/generated.go:8136.126,8142.31 5 0 +make-backend/internal/gql/generated.go:8142.31,8143.21 1 0 +make-backend/internal/gql/generated.go:8144.21,8145.55 1 0 +make-backend/internal/gql/generated.go:8146.20,8148.37 2 0 +make-backend/internal/gql/generated.go:8148.37,8150.5 1 0 +make-backend/internal/gql/generated.go:8151.19,8153.37 2 0 +make-backend/internal/gql/generated.go:8153.37,8155.5 1 0 +make-backend/internal/gql/generated.go:8156.11,8157.55 1 0 +make-backend/internal/gql/generated.go:8160.2,8161.22 2 0 +make-backend/internal/gql/generated.go:8161.22,8163.3 1 0 +make-backend/internal/gql/generated.go:8165.2,8174.12 3 0 +make-backend/internal/gql/generated.go:8179.130,8185.31 5 0 +make-backend/internal/gql/generated.go:8185.31,8186.21 1 0 +make-backend/internal/gql/generated.go:8187.21,8188.57 1 0 +make-backend/internal/gql/generated.go:8189.24,8191.37 2 0 +make-backend/internal/gql/generated.go:8191.37,8193.5 1 0 +make-backend/internal/gql/generated.go:8194.22,8196.37 2 0 +make-backend/internal/gql/generated.go:8196.37,8198.5 1 0 +make-backend/internal/gql/generated.go:8199.20,8201.45 2 0 +make-backend/internal/gql/generated.go:8201.45,8203.5 1 0 +make-backend/internal/gql/generated.go:8204.21,8206.45 2 0 +make-backend/internal/gql/generated.go:8206.45,8208.5 1 0 +make-backend/internal/gql/generated.go:8209.17,8211.37 2 0 +make-backend/internal/gql/generated.go:8211.37,8213.5 1 0 +make-backend/internal/gql/generated.go:8214.11,8215.55 1 0 +make-backend/internal/gql/generated.go:8218.2,8219.22 2 0 +make-backend/internal/gql/generated.go:8219.22,8221.3 1 0 +make-backend/internal/gql/generated.go:8223.2,8232.12 3 0 +make-backend/internal/gql/generated.go:8237.118,8243.31 5 0 +make-backend/internal/gql/generated.go:8243.31,8244.21 1 0 +make-backend/internal/gql/generated.go:8245.21,8246.51 1 0 +make-backend/internal/gql/generated.go:8247.13,8249.37 2 0 +make-backend/internal/gql/generated.go:8249.37,8251.5 1 0 +make-backend/internal/gql/generated.go:8252.15,8254.37 2 0 +make-backend/internal/gql/generated.go:8254.37,8256.5 1 0 +make-backend/internal/gql/generated.go:8257.13,8259.37 2 0 +make-backend/internal/gql/generated.go:8259.37,8261.5 1 0 +make-backend/internal/gql/generated.go:8262.17,8264.37 2 0 +make-backend/internal/gql/generated.go:8264.37,8266.5 1 0 +make-backend/internal/gql/generated.go:8267.19,8269.45 2 0 +make-backend/internal/gql/generated.go:8269.45,8271.5 1 0 +make-backend/internal/gql/generated.go:8272.19,8274.45 2 0 +make-backend/internal/gql/generated.go:8274.45,8276.5 1 0 +make-backend/internal/gql/generated.go:8277.26,8279.45 2 0 +make-backend/internal/gql/generated.go:8279.45,8281.5 1 0 +make-backend/internal/gql/generated.go:8282.20,8284.37 2 0 +make-backend/internal/gql/generated.go:8284.37,8286.5 1 0 +make-backend/internal/gql/generated.go:8287.24,8289.37 2 0 +make-backend/internal/gql/generated.go:8289.37,8291.5 1 0 +make-backend/internal/gql/generated.go:8292.11,8293.55 1 0 +make-backend/internal/gql/generated.go:8296.2,8297.22 2 0 +make-backend/internal/gql/generated.go:8297.22,8299.3 1 0 +make-backend/internal/gql/generated.go:8301.2,8310.12 3 0 +make-backend/internal/gql/generated.go:8315.124,8321.31 5 0 +make-backend/internal/gql/generated.go:8321.31,8322.21 1 0 +make-backend/internal/gql/generated.go:8323.21,8324.54 1 0 +make-backend/internal/gql/generated.go:8325.20,8327.37 2 0 +make-backend/internal/gql/generated.go:8327.37,8329.5 1 0 +make-backend/internal/gql/generated.go:8330.21,8332.37 2 0 +make-backend/internal/gql/generated.go:8332.37,8334.5 1 0 +make-backend/internal/gql/generated.go:8335.16,8337.45 2 0 +make-backend/internal/gql/generated.go:8337.45,8339.5 1 0 +make-backend/internal/gql/generated.go:8340.11,8341.55 1 0 +make-backend/internal/gql/generated.go:8344.2,8345.22 2 0 +make-backend/internal/gql/generated.go:8345.22,8347.3 1 0 +make-backend/internal/gql/generated.go:8349.2,8358.12 3 0 +make-backend/internal/gql/generated.go:8363.124,8369.31 5 0 +make-backend/internal/gql/generated.go:8369.31,8370.21 1 0 +make-backend/internal/gql/generated.go:8371.21,8372.54 1 0 +make-backend/internal/gql/generated.go:8373.13,8375.37 2 0 +make-backend/internal/gql/generated.go:8375.37,8377.5 1 0 +make-backend/internal/gql/generated.go:8378.15,8380.37 2 0 +make-backend/internal/gql/generated.go:8380.37,8382.5 1 0 +make-backend/internal/gql/generated.go:8383.19,8385.37 2 0 +make-backend/internal/gql/generated.go:8385.37,8387.5 1 0 +make-backend/internal/gql/generated.go:8388.18,8390.37 2 0 +make-backend/internal/gql/generated.go:8390.37,8392.5 1 0 +make-backend/internal/gql/generated.go:8393.17,8395.37 2 0 +make-backend/internal/gql/generated.go:8395.37,8397.5 1 0 +make-backend/internal/gql/generated.go:8398.19,8400.45 2 0 +make-backend/internal/gql/generated.go:8400.45,8402.5 1 0 +make-backend/internal/gql/generated.go:8403.18,8405.37 2 0 +make-backend/internal/gql/generated.go:8405.37,8407.5 1 0 +make-backend/internal/gql/generated.go:8408.23,8410.37 2 0 +make-backend/internal/gql/generated.go:8410.37,8412.5 1 0 +make-backend/internal/gql/generated.go:8413.22,8415.37 2 0 +make-backend/internal/gql/generated.go:8415.37,8417.5 1 0 +make-backend/internal/gql/generated.go:8418.21,8420.37 2 0 +make-backend/internal/gql/generated.go:8420.37,8422.5 1 0 +make-backend/internal/gql/generated.go:8423.27,8425.37 2 0 +make-backend/internal/gql/generated.go:8425.37,8427.5 1 0 +make-backend/internal/gql/generated.go:8428.35,8430.37 2 0 +make-backend/internal/gql/generated.go:8430.37,8432.5 1 0 +make-backend/internal/gql/generated.go:8433.24,8435.37 2 0 +make-backend/internal/gql/generated.go:8435.37,8437.5 1 0 +make-backend/internal/gql/generated.go:8438.29,8440.37 2 0 +make-backend/internal/gql/generated.go:8440.37,8442.5 1 0 +make-backend/internal/gql/generated.go:8443.27,8445.37 2 0 +make-backend/internal/gql/generated.go:8445.37,8447.5 1 0 +make-backend/internal/gql/generated.go:8448.11,8449.55 1 0 +make-backend/internal/gql/generated.go:8452.2,8453.22 2 0 +make-backend/internal/gql/generated.go:8453.22,8455.3 1 0 +make-backend/internal/gql/generated.go:8457.2,8466.12 3 0 +make-backend/internal/gql/generated.go:8471.140,8477.31 5 0 +make-backend/internal/gql/generated.go:8477.31,8478.21 1 0 +make-backend/internal/gql/generated.go:8479.21,8480.62 1 0 +make-backend/internal/gql/generated.go:8481.13,8483.37 2 0 +make-backend/internal/gql/generated.go:8483.37,8485.5 1 0 +make-backend/internal/gql/generated.go:8486.23,8488.37 2 0 +make-backend/internal/gql/generated.go:8488.37,8490.5 1 0 +make-backend/internal/gql/generated.go:8491.15,8493.37 2 0 +make-backend/internal/gql/generated.go:8493.37,8495.5 1 0 +make-backend/internal/gql/generated.go:8496.28,8498.45 2 0 +make-backend/internal/gql/generated.go:8498.45,8500.5 1 0 +make-backend/internal/gql/generated.go:8501.11,8502.55 1 0 +make-backend/internal/gql/generated.go:8505.2,8506.22 2 0 +make-backend/internal/gql/generated.go:8506.22,8508.3 1 0 +make-backend/internal/gql/generated.go:8510.2,8519.12 3 0 +make-backend/internal/gql/generated.go:8524.116,8530.31 5 0 +make-backend/internal/gql/generated.go:8530.31,8531.21 1 0 +make-backend/internal/gql/generated.go:8532.21,8533.50 1 0 +make-backend/internal/gql/generated.go:8534.13,8536.37 2 0 +make-backend/internal/gql/generated.go:8536.37,8538.5 1 0 +make-backend/internal/gql/generated.go:8539.21,8541.37 2 0 +make-backend/internal/gql/generated.go:8541.37,8543.5 1 0 +make-backend/internal/gql/generated.go:8544.15,8546.37 2 0 +make-backend/internal/gql/generated.go:8546.37,8548.5 1 0 +make-backend/internal/gql/generated.go:8549.22,8551.37 2 0 +make-backend/internal/gql/generated.go:8551.37,8553.5 1 0 +make-backend/internal/gql/generated.go:8554.11,8555.55 1 0 +make-backend/internal/gql/generated.go:8558.2,8559.22 2 0 +make-backend/internal/gql/generated.go:8559.22,8561.3 1 0 +make-backend/internal/gql/generated.go:8563.2,8572.12 3 0 +make-backend/internal/gql/generated.go:8577.114,8583.31 5 0 +make-backend/internal/gql/generated.go:8583.31,8584.21 1 0 +make-backend/internal/gql/generated.go:8585.21,8586.49 1 0 +make-backend/internal/gql/generated.go:8587.13,8589.37 2 0 +make-backend/internal/gql/generated.go:8589.37,8591.5 1 0 +make-backend/internal/gql/generated.go:8592.21,8594.37 2 0 +make-backend/internal/gql/generated.go:8594.37,8596.5 1 0 +make-backend/internal/gql/generated.go:8597.21,8599.45 2 0 +make-backend/internal/gql/generated.go:8599.45,8601.5 1 0 +make-backend/internal/gql/generated.go:8602.20,8604.37 2 0 +make-backend/internal/gql/generated.go:8604.37,8606.5 1 0 +make-backend/internal/gql/generated.go:8607.17,8609.37 2 0 +make-backend/internal/gql/generated.go:8609.37,8611.5 1 0 +make-backend/internal/gql/generated.go:8612.22,8614.37 2 0 +make-backend/internal/gql/generated.go:8614.37,8616.5 1 0 +make-backend/internal/gql/generated.go:8617.22,8619.45 2 0 +make-backend/internal/gql/generated.go:8619.45,8621.5 1 0 +make-backend/internal/gql/generated.go:8622.11,8623.55 1 0 +make-backend/internal/gql/generated.go:8626.2,8627.22 2 0 +make-backend/internal/gql/generated.go:8627.22,8629.3 1 0 +make-backend/internal/gql/generated.go:8631.2,8640.12 3 0 +make-backend/internal/gql/generated.go:8645.116,8651.31 5 0 +make-backend/internal/gql/generated.go:8651.31,8652.21 1 0 +make-backend/internal/gql/generated.go:8653.21,8654.50 1 0 +make-backend/internal/gql/generated.go:8655.13,8657.37 2 0 +make-backend/internal/gql/generated.go:8657.37,8659.5 1 0 +make-backend/internal/gql/generated.go:8660.21,8662.37 2 0 +make-backend/internal/gql/generated.go:8662.37,8664.5 1 0 +make-backend/internal/gql/generated.go:8665.11,8666.55 1 0 +make-backend/internal/gql/generated.go:8669.2,8670.22 2 0 +make-backend/internal/gql/generated.go:8670.22,8672.3 1 0 +make-backend/internal/gql/generated.go:8674.2,8683.12 3 0 +make-backend/internal/gql/generated.go:8688.126,8694.31 5 0 +make-backend/internal/gql/generated.go:8694.31,8695.21 1 0 +make-backend/internal/gql/generated.go:8696.21,8697.55 1 0 +make-backend/internal/gql/generated.go:8698.19,8700.37 2 0 +make-backend/internal/gql/generated.go:8700.37,8702.5 1 0 +make-backend/internal/gql/generated.go:8703.15,8705.37 2 0 +make-backend/internal/gql/generated.go:8705.37,8707.5 1 0 +make-backend/internal/gql/generated.go:8708.18,8710.37 2 0 +make-backend/internal/gql/generated.go:8710.37,8712.5 1 0 +make-backend/internal/gql/generated.go:8713.11,8714.55 1 0 +make-backend/internal/gql/generated.go:8717.2,8718.22 2 0 +make-backend/internal/gql/generated.go:8718.22,8720.3 1 0 +make-backend/internal/gql/generated.go:8722.2,8731.12 3 0 +make-backend/internal/gql/generated.go:8736.126,8742.31 5 0 +make-backend/internal/gql/generated.go:8742.31,8743.21 1 0 +make-backend/internal/gql/generated.go:8744.21,8745.55 1 0 +make-backend/internal/gql/generated.go:8746.13,8748.37 2 0 +make-backend/internal/gql/generated.go:8748.37,8750.5 1 0 +make-backend/internal/gql/generated.go:8751.15,8753.37 2 0 +make-backend/internal/gql/generated.go:8753.37,8755.5 1 0 +make-backend/internal/gql/generated.go:8756.19,8758.37 2 0 +make-backend/internal/gql/generated.go:8758.37,8760.5 1 0 +make-backend/internal/gql/generated.go:8761.22,8763.37 2 0 +make-backend/internal/gql/generated.go:8763.37,8765.5 1 0 +make-backend/internal/gql/generated.go:8766.19,8768.37 2 0 +make-backend/internal/gql/generated.go:8768.37,8770.5 1 0 +make-backend/internal/gql/generated.go:8771.19,8773.45 2 0 +make-backend/internal/gql/generated.go:8773.45,8775.5 1 0 +make-backend/internal/gql/generated.go:8776.17,8778.37 2 0 +make-backend/internal/gql/generated.go:8778.37,8780.5 1 0 +make-backend/internal/gql/generated.go:8781.19,8783.37 2 0 +make-backend/internal/gql/generated.go:8783.37,8785.5 1 0 +make-backend/internal/gql/generated.go:8786.16,8789.89 2 0 +make-backend/internal/gql/generated.go:8789.89,8790.18 1 0 +make-backend/internal/gql/generated.go:8790.18,8791.34 1 0 +make-backend/internal/gql/generated.go:8791.34,8793.7 1 0 +make-backend/internal/gql/generated.go:8795.5,8796.28 2 0 +make-backend/internal/gql/generated.go:8796.28,8798.6 1 0 +make-backend/internal/gql/generated.go:8799.5,8799.15 1 0 +make-backend/internal/gql/generated.go:8802.4,8802.26 1 0 +make-backend/internal/gql/generated.go:8802.26,8805.91 3 0 +make-backend/internal/gql/generated.go:8805.91,8807.6 1 0 +make-backend/internal/gql/generated.go:8809.5,8809.50 1 0 +make-backend/internal/gql/generated.go:8809.50,8811.13 2 0 +make-backend/internal/gql/generated.go:8811.13,8814.7 2 0 +make-backend/internal/gql/generated.go:8815.6,8815.33 1 0 +make-backend/internal/gql/generated.go:8819.5,8820.13 2 0 +make-backend/internal/gql/generated.go:8823.4,8823.68 1 0 +make-backend/internal/gql/generated.go:8823.68,8823.98 1 0 +make-backend/internal/gql/generated.go:8824.16,8827.89 2 0 +make-backend/internal/gql/generated.go:8827.89,8828.18 1 0 +make-backend/internal/gql/generated.go:8828.18,8829.34 1 0 +make-backend/internal/gql/generated.go:8829.34,8831.7 1 0 +make-backend/internal/gql/generated.go:8833.5,8834.28 2 0 +make-backend/internal/gql/generated.go:8834.28,8836.6 1 0 +make-backend/internal/gql/generated.go:8837.5,8837.15 1 0 +make-backend/internal/gql/generated.go:8840.4,8840.26 1 0 +make-backend/internal/gql/generated.go:8840.26,8843.91 3 0 +make-backend/internal/gql/generated.go:8843.91,8845.6 1 0 +make-backend/internal/gql/generated.go:8847.5,8847.50 1 0 +make-backend/internal/gql/generated.go:8847.50,8849.13 2 0 +make-backend/internal/gql/generated.go:8849.13,8852.7 2 0 +make-backend/internal/gql/generated.go:8853.6,8853.33 1 0 +make-backend/internal/gql/generated.go:8857.5,8858.13 2 0 +make-backend/internal/gql/generated.go:8861.4,8861.68 1 0 +make-backend/internal/gql/generated.go:8861.68,8861.98 1 0 +make-backend/internal/gql/generated.go:8862.11,8863.55 1 0 +make-backend/internal/gql/generated.go:8866.2,8867.22 2 0 +make-backend/internal/gql/generated.go:8867.22,8869.3 1 0 +make-backend/internal/gql/generated.go:8871.2,8880.12 3 0 +make-backend/internal/gql/generated.go:8885.140,8891.31 5 0 +make-backend/internal/gql/generated.go:8891.31,8892.21 1 0 +make-backend/internal/gql/generated.go:8893.21,8894.62 1 0 +make-backend/internal/gql/generated.go:8895.17,8897.37 2 0 +make-backend/internal/gql/generated.go:8897.37,8899.5 1 0 +make-backend/internal/gql/generated.go:8900.25,8902.37 2 0 +make-backend/internal/gql/generated.go:8902.37,8904.5 1 0 +make-backend/internal/gql/generated.go:8905.11,8906.55 1 0 +make-backend/internal/gql/generated.go:8909.2,8910.22 2 0 +make-backend/internal/gql/generated.go:8910.22,8912.3 1 0 +make-backend/internal/gql/generated.go:8914.2,8923.12 3 0 +make-backend/internal/gql/generated.go:8928.100,8937.31 6 0 +make-backend/internal/gql/generated.go:8937.31,8943.21 2 0 +make-backend/internal/gql/generated.go:8944.21,8945.53 1 0 +make-backend/internal/gql/generated.go:8946.27,8947.123 1 0 +make-backend/internal/gql/generated.go:8947.123,8949.5 1 0 +make-backend/internal/gql/generated.go:8950.4,8950.37 1 0 +make-backend/internal/gql/generated.go:8950.37,8952.5 1 0 +make-backend/internal/gql/generated.go:8953.27,8954.123 1 0 +make-backend/internal/gql/generated.go:8954.123,8956.5 1 0 +make-backend/internal/gql/generated.go:8957.4,8957.37 1 0 +make-backend/internal/gql/generated.go:8957.37,8959.5 1 0 +make-backend/internal/gql/generated.go:8960.11,8961.55 1 0 +make-backend/internal/gql/generated.go:8964.2,8965.22 2 0 +make-backend/internal/gql/generated.go:8965.22,8967.3 1 0 +make-backend/internal/gql/generated.go:8969.2,8978.12 3 0 +make-backend/internal/gql/generated.go:8983.128,8989.31 5 0 +make-backend/internal/gql/generated.go:8989.31,8990.21 1 0 +make-backend/internal/gql/generated.go:8991.21,8992.56 1 0 +make-backend/internal/gql/generated.go:8993.19,8995.37 2 0 +make-backend/internal/gql/generated.go:8995.37,8997.5 1 0 +make-backend/internal/gql/generated.go:8998.15,9000.37 2 0 +make-backend/internal/gql/generated.go:9000.37,9002.5 1 0 +make-backend/internal/gql/generated.go:9003.18,9005.37 2 0 +make-backend/internal/gql/generated.go:9005.37,9007.5 1 0 +make-backend/internal/gql/generated.go:9008.18,9010.37 2 0 +make-backend/internal/gql/generated.go:9010.37,9012.5 1 0 +make-backend/internal/gql/generated.go:9013.15,9015.37 2 0 +make-backend/internal/gql/generated.go:9015.37,9017.5 1 0 +make-backend/internal/gql/generated.go:9018.22,9020.37 2 0 +make-backend/internal/gql/generated.go:9020.37,9022.5 1 0 +make-backend/internal/gql/generated.go:9023.11,9024.55 1 0 +make-backend/internal/gql/generated.go:9027.2,9028.22 2 0 +make-backend/internal/gql/generated.go:9028.22,9030.3 1 0 +make-backend/internal/gql/generated.go:9032.2,9041.12 3 0 +make-backend/internal/gql/generated.go:9046.140,9052.31 5 0 +make-backend/internal/gql/generated.go:9052.31,9053.21 1 0 +make-backend/internal/gql/generated.go:9054.21,9055.62 1 0 +make-backend/internal/gql/generated.go:9056.15,9058.37 2 0 +make-backend/internal/gql/generated.go:9058.37,9060.5 1 0 +make-backend/internal/gql/generated.go:9061.18,9064.89 2 0 +make-backend/internal/gql/generated.go:9064.89,9065.18 1 0 +make-backend/internal/gql/generated.go:9065.18,9066.34 1 0 +make-backend/internal/gql/generated.go:9066.34,9068.7 1 0 +make-backend/internal/gql/generated.go:9070.5,9071.36 2 0 +make-backend/internal/gql/generated.go:9071.36,9073.6 1 0 +make-backend/internal/gql/generated.go:9074.5,9074.15 1 0 +make-backend/internal/gql/generated.go:9077.4,9077.26 1 0 +make-backend/internal/gql/generated.go:9077.26,9080.91 3 0 +make-backend/internal/gql/generated.go:9080.91,9082.6 1 0 +make-backend/internal/gql/generated.go:9084.5,9084.50 1 0 +make-backend/internal/gql/generated.go:9084.50,9086.13 2 0 +make-backend/internal/gql/generated.go:9086.13,9089.7 2 0 +make-backend/internal/gql/generated.go:9090.6,9090.33 1 0 +make-backend/internal/gql/generated.go:9094.5,9095.13 2 0 +make-backend/internal/gql/generated.go:9098.4,9098.68 1 0 +make-backend/internal/gql/generated.go:9098.68,9098.98 1 0 +make-backend/internal/gql/generated.go:9099.11,9100.55 1 0 +make-backend/internal/gql/generated.go:9103.2,9104.22 2 0 +make-backend/internal/gql/generated.go:9104.22,9106.3 1 0 +make-backend/internal/gql/generated.go:9108.2,9117.12 3 0 +make-backend/internal/gql/generated.go:9122.130,9128.31 5 0 +make-backend/internal/gql/generated.go:9128.31,9129.21 1 0 +make-backend/internal/gql/generated.go:9130.21,9131.57 1 0 +make-backend/internal/gql/generated.go:9132.13,9134.37 2 0 +make-backend/internal/gql/generated.go:9134.37,9136.5 1 0 +make-backend/internal/gql/generated.go:9137.23,9139.37 2 0 +make-backend/internal/gql/generated.go:9139.37,9141.5 1 0 +make-backend/internal/gql/generated.go:9142.16,9144.37 2 0 +make-backend/internal/gql/generated.go:9144.37,9146.5 1 0 +make-backend/internal/gql/generated.go:9147.16,9149.37 2 0 +make-backend/internal/gql/generated.go:9149.37,9151.5 1 0 +make-backend/internal/gql/generated.go:9152.11,9153.55 1 0 +make-backend/internal/gql/generated.go:9156.2,9157.22 2 0 +make-backend/internal/gql/generated.go:9157.22,9159.3 1 0 +make-backend/internal/gql/generated.go:9161.2,9170.12 3 0 +make-backend/internal/gql/generated.go:9175.97,9184.31 6 0 +make-backend/internal/gql/generated.go:9184.31,9190.21 2 0 +make-backend/internal/gql/generated.go:9191.21,9192.50 1 0 +make-backend/internal/gql/generated.go:9193.21,9196.89 2 0 +make-backend/internal/gql/generated.go:9196.89,9197.18 1 0 +make-backend/internal/gql/generated.go:9197.18,9198.34 1 0 +make-backend/internal/gql/generated.go:9198.34,9200.7 1 0 +make-backend/internal/gql/generated.go:9202.5,9203.36 2 0 +make-backend/internal/gql/generated.go:9203.36,9205.6 1 0 +make-backend/internal/gql/generated.go:9206.5,9206.15 1 0 +make-backend/internal/gql/generated.go:9209.4,9209.55 1 0 +make-backend/internal/gql/generated.go:9209.55,9211.50 1 0 +make-backend/internal/gql/generated.go:9211.50,9211.80 1 0 +make-backend/internal/gql/generated.go:9214.4,9214.68 1 0 +make-backend/internal/gql/generated.go:9214.68,9214.92 1 0 +make-backend/internal/gql/generated.go:9215.17,9218.89 2 0 +make-backend/internal/gql/generated.go:9218.89,9219.18 1 0 +make-backend/internal/gql/generated.go:9219.18,9220.34 1 0 +make-backend/internal/gql/generated.go:9220.34,9222.7 1 0 +make-backend/internal/gql/generated.go:9224.5,9225.36 2 0 +make-backend/internal/gql/generated.go:9225.36,9227.6 1 0 +make-backend/internal/gql/generated.go:9228.5,9228.15 1 0 +make-backend/internal/gql/generated.go:9231.4,9231.55 1 0 +make-backend/internal/gql/generated.go:9231.55,9233.50 1 0 +make-backend/internal/gql/generated.go:9233.50,9233.80 1 0 +make-backend/internal/gql/generated.go:9236.4,9236.68 1 0 +make-backend/internal/gql/generated.go:9236.68,9236.92 1 0 +make-backend/internal/gql/generated.go:9237.23,9240.89 2 0 +make-backend/internal/gql/generated.go:9240.89,9241.18 1 0 +make-backend/internal/gql/generated.go:9241.18,9242.34 1 0 +make-backend/internal/gql/generated.go:9242.34,9244.7 1 0 +make-backend/internal/gql/generated.go:9246.5,9247.36 2 0 +make-backend/internal/gql/generated.go:9247.36,9249.6 1 0 +make-backend/internal/gql/generated.go:9250.5,9250.15 1 0 +make-backend/internal/gql/generated.go:9253.4,9253.55 1 0 +make-backend/internal/gql/generated.go:9253.55,9255.50 1 0 +make-backend/internal/gql/generated.go:9255.50,9255.80 1 0 +make-backend/internal/gql/generated.go:9258.4,9258.68 1 0 +make-backend/internal/gql/generated.go:9258.68,9258.92 1 0 +make-backend/internal/gql/generated.go:9259.20,9262.89 2 0 +make-backend/internal/gql/generated.go:9262.89,9263.18 1 0 +make-backend/internal/gql/generated.go:9263.18,9264.34 1 0 +make-backend/internal/gql/generated.go:9264.34,9266.7 1 0 +make-backend/internal/gql/generated.go:9268.5,9269.28 2 0 +make-backend/internal/gql/generated.go:9269.28,9271.6 1 0 +make-backend/internal/gql/generated.go:9272.5,9272.15 1 0 +make-backend/internal/gql/generated.go:9275.4,9275.55 1 0 +make-backend/internal/gql/generated.go:9275.55,9277.50 1 0 +make-backend/internal/gql/generated.go:9277.50,9277.80 1 0 +make-backend/internal/gql/generated.go:9280.4,9280.68 1 0 +make-backend/internal/gql/generated.go:9280.68,9280.92 1 0 +make-backend/internal/gql/generated.go:9281.25,9284.89 2 0 +make-backend/internal/gql/generated.go:9284.89,9285.18 1 0 +make-backend/internal/gql/generated.go:9285.18,9286.34 1 0 +make-backend/internal/gql/generated.go:9286.34,9288.7 1 0 +make-backend/internal/gql/generated.go:9290.5,9291.28 2 0 +make-backend/internal/gql/generated.go:9291.28,9293.6 1 0 +make-backend/internal/gql/generated.go:9294.5,9294.15 1 0 +make-backend/internal/gql/generated.go:9297.4,9297.55 1 0 +make-backend/internal/gql/generated.go:9297.55,9299.50 1 0 +make-backend/internal/gql/generated.go:9299.50,9299.80 1 0 +make-backend/internal/gql/generated.go:9302.4,9302.68 1 0 +make-backend/internal/gql/generated.go:9302.68,9302.92 1 0 +make-backend/internal/gql/generated.go:9303.24,9306.89 2 0 +make-backend/internal/gql/generated.go:9306.89,9307.18 1 0 +make-backend/internal/gql/generated.go:9307.18,9308.34 1 0 +make-backend/internal/gql/generated.go:9308.34,9310.7 1 0 +make-backend/internal/gql/generated.go:9312.5,9313.28 2 0 +make-backend/internal/gql/generated.go:9313.28,9315.6 1 0 +make-backend/internal/gql/generated.go:9316.5,9316.15 1 0 +make-backend/internal/gql/generated.go:9319.4,9319.55 1 0 +make-backend/internal/gql/generated.go:9319.55,9321.50 1 0 +make-backend/internal/gql/generated.go:9321.50,9321.80 1 0 +make-backend/internal/gql/generated.go:9324.4,9324.68 1 0 +make-backend/internal/gql/generated.go:9324.68,9324.92 1 0 +make-backend/internal/gql/generated.go:9325.32,9328.89 2 0 +make-backend/internal/gql/generated.go:9328.89,9329.18 1 0 +make-backend/internal/gql/generated.go:9329.18,9330.34 1 0 +make-backend/internal/gql/generated.go:9330.34,9332.7 1 0 +make-backend/internal/gql/generated.go:9334.5,9335.28 2 0 +make-backend/internal/gql/generated.go:9335.28,9337.6 1 0 +make-backend/internal/gql/generated.go:9338.5,9338.15 1 0 +make-backend/internal/gql/generated.go:9341.4,9341.55 1 0 +make-backend/internal/gql/generated.go:9341.55,9343.50 1 0 +make-backend/internal/gql/generated.go:9343.50,9343.80 1 0 +make-backend/internal/gql/generated.go:9346.4,9346.68 1 0 +make-backend/internal/gql/generated.go:9346.68,9346.92 1 0 +make-backend/internal/gql/generated.go:9347.30,9350.89 2 0 +make-backend/internal/gql/generated.go:9350.89,9351.18 1 0 +make-backend/internal/gql/generated.go:9351.18,9352.34 1 0 +make-backend/internal/gql/generated.go:9352.34,9354.7 1 0 +make-backend/internal/gql/generated.go:9356.5,9357.28 2 0 +make-backend/internal/gql/generated.go:9357.28,9359.6 1 0 +make-backend/internal/gql/generated.go:9360.5,9360.15 1 0 +make-backend/internal/gql/generated.go:9363.4,9363.55 1 0 +make-backend/internal/gql/generated.go:9363.55,9365.50 1 0 +make-backend/internal/gql/generated.go:9365.50,9365.80 1 0 +make-backend/internal/gql/generated.go:9368.4,9368.68 1 0 +make-backend/internal/gql/generated.go:9368.68,9368.92 1 0 +make-backend/internal/gql/generated.go:9369.29,9372.89 2 0 +make-backend/internal/gql/generated.go:9372.89,9373.18 1 0 +make-backend/internal/gql/generated.go:9373.18,9374.34 1 0 +make-backend/internal/gql/generated.go:9374.34,9376.7 1 0 +make-backend/internal/gql/generated.go:9378.5,9379.28 2 0 +make-backend/internal/gql/generated.go:9379.28,9381.6 1 0 +make-backend/internal/gql/generated.go:9382.5,9382.15 1 0 +make-backend/internal/gql/generated.go:9385.4,9385.55 1 0 +make-backend/internal/gql/generated.go:9385.55,9387.50 1 0 +make-backend/internal/gql/generated.go:9387.50,9387.80 1 0 +make-backend/internal/gql/generated.go:9390.4,9390.68 1 0 +make-backend/internal/gql/generated.go:9390.68,9390.92 1 0 +make-backend/internal/gql/generated.go:9391.15,9394.89 2 0 +make-backend/internal/gql/generated.go:9394.89,9395.18 1 0 +make-backend/internal/gql/generated.go:9395.18,9396.34 1 0 +make-backend/internal/gql/generated.go:9396.34,9398.7 1 0 +make-backend/internal/gql/generated.go:9400.5,9401.28 2 0 +make-backend/internal/gql/generated.go:9401.28,9403.6 1 0 +make-backend/internal/gql/generated.go:9404.5,9404.15 1 0 +make-backend/internal/gql/generated.go:9407.4,9407.55 1 0 +make-backend/internal/gql/generated.go:9407.55,9409.50 1 0 +make-backend/internal/gql/generated.go:9409.50,9409.80 1 0 +make-backend/internal/gql/generated.go:9412.4,9412.68 1 0 +make-backend/internal/gql/generated.go:9412.68,9412.92 1 0 +make-backend/internal/gql/generated.go:9413.22,9416.89 2 0 +make-backend/internal/gql/generated.go:9416.89,9417.18 1 0 +make-backend/internal/gql/generated.go:9417.18,9418.34 1 0 +make-backend/internal/gql/generated.go:9418.34,9420.7 1 0 +make-backend/internal/gql/generated.go:9422.5,9423.28 2 0 +make-backend/internal/gql/generated.go:9423.28,9425.6 1 0 +make-backend/internal/gql/generated.go:9426.5,9426.15 1 0 +make-backend/internal/gql/generated.go:9429.4,9429.55 1 0 +make-backend/internal/gql/generated.go:9429.55,9431.50 1 0 +make-backend/internal/gql/generated.go:9431.50,9431.80 1 0 +make-backend/internal/gql/generated.go:9434.4,9434.68 1 0 +make-backend/internal/gql/generated.go:9434.68,9434.92 1 0 +make-backend/internal/gql/generated.go:9435.15,9438.89 2 0 +make-backend/internal/gql/generated.go:9438.89,9439.18 1 0 +make-backend/internal/gql/generated.go:9439.18,9440.34 1 0 +make-backend/internal/gql/generated.go:9440.34,9442.7 1 0 +make-backend/internal/gql/generated.go:9444.5,9445.28 2 0 +make-backend/internal/gql/generated.go:9445.28,9447.6 1 0 +make-backend/internal/gql/generated.go:9448.5,9448.15 1 0 +make-backend/internal/gql/generated.go:9451.4,9451.55 1 0 +make-backend/internal/gql/generated.go:9451.55,9453.50 1 0 +make-backend/internal/gql/generated.go:9453.50,9453.80 1 0 +make-backend/internal/gql/generated.go:9456.4,9456.68 1 0 +make-backend/internal/gql/generated.go:9456.68,9456.92 1 0 +make-backend/internal/gql/generated.go:9457.30,9460.89 2 0 +make-backend/internal/gql/generated.go:9460.89,9461.18 1 0 +make-backend/internal/gql/generated.go:9461.18,9462.34 1 0 +make-backend/internal/gql/generated.go:9462.34,9464.7 1 0 +make-backend/internal/gql/generated.go:9466.5,9467.28 2 0 +make-backend/internal/gql/generated.go:9467.28,9469.6 1 0 +make-backend/internal/gql/generated.go:9470.5,9470.15 1 0 +make-backend/internal/gql/generated.go:9473.4,9473.55 1 0 +make-backend/internal/gql/generated.go:9473.55,9475.50 1 0 +make-backend/internal/gql/generated.go:9475.50,9475.80 1 0 +make-backend/internal/gql/generated.go:9478.4,9478.68 1 0 +make-backend/internal/gql/generated.go:9478.68,9478.92 1 0 +make-backend/internal/gql/generated.go:9479.17,9480.123 1 0 +make-backend/internal/gql/generated.go:9480.123,9482.5 1 0 +make-backend/internal/gql/generated.go:9483.4,9483.45 1 0 +make-backend/internal/gql/generated.go:9483.45,9485.5 1 0 +make-backend/internal/gql/generated.go:9486.19,9487.123 1 0 +make-backend/internal/gql/generated.go:9487.123,9489.5 1 0 +make-backend/internal/gql/generated.go:9490.4,9490.45 1 0 +make-backend/internal/gql/generated.go:9490.45,9492.5 1 0 +make-backend/internal/gql/generated.go:9493.11,9494.55 1 0 +make-backend/internal/gql/generated.go:9497.2,9498.22 2 0 +make-backend/internal/gql/generated.go:9498.22,9500.3 1 0 +make-backend/internal/gql/generated.go:9502.2,9511.12 3 0 +make-backend/internal/gql/generated.go:9516.128,9522.31 5 0 +make-backend/internal/gql/generated.go:9522.31,9523.21 1 0 +make-backend/internal/gql/generated.go:9524.21,9525.56 1 0 +make-backend/internal/gql/generated.go:9526.13,9528.37 2 0 +make-backend/internal/gql/generated.go:9528.37,9530.5 1 0 +make-backend/internal/gql/generated.go:9531.18,9533.45 2 0 +make-backend/internal/gql/generated.go:9533.45,9535.5 1 0 +make-backend/internal/gql/generated.go:9536.26,9538.45 2 0 +make-backend/internal/gql/generated.go:9538.45,9540.5 1 0 +make-backend/internal/gql/generated.go:9541.23,9543.37 2 0 +make-backend/internal/gql/generated.go:9543.37,9545.5 1 0 +make-backend/internal/gql/generated.go:9546.22,9548.37 2 0 +make-backend/internal/gql/generated.go:9548.37,9550.5 1 0 +make-backend/internal/gql/generated.go:9551.21,9553.37 2 0 +make-backend/internal/gql/generated.go:9553.37,9555.5 1 0 +make-backend/internal/gql/generated.go:9556.19,9558.37 2 0 +make-backend/internal/gql/generated.go:9558.37,9560.5 1 0 +make-backend/internal/gql/generated.go:9561.19,9563.37 2 0 +make-backend/internal/gql/generated.go:9563.37,9565.5 1 0 +make-backend/internal/gql/generated.go:9566.11,9567.55 1 0 +make-backend/internal/gql/generated.go:9570.2,9571.22 2 0 +make-backend/internal/gql/generated.go:9571.22,9573.3 1 0 +make-backend/internal/gql/generated.go:9575.2,9584.12 3 0 +make-backend/internal/gql/generated.go:9589.128,9595.31 5 0 +make-backend/internal/gql/generated.go:9595.31,9596.21 1 0 +make-backend/internal/gql/generated.go:9597.21,9598.56 1 0 +make-backend/internal/gql/generated.go:9599.13,9601.37 2 0 +make-backend/internal/gql/generated.go:9601.37,9603.5 1 0 +make-backend/internal/gql/generated.go:9604.24,9606.37 2 0 +make-backend/internal/gql/generated.go:9606.37,9608.5 1 0 +make-backend/internal/gql/generated.go:9609.21,9611.37 2 0 +make-backend/internal/gql/generated.go:9611.37,9613.5 1 0 +make-backend/internal/gql/generated.go:9614.20,9616.37 2 0 +make-backend/internal/gql/generated.go:9616.37,9618.5 1 0 +make-backend/internal/gql/generated.go:9619.22,9621.37 2 0 +make-backend/internal/gql/generated.go:9621.37,9623.5 1 0 +make-backend/internal/gql/generated.go:9624.17,9626.37 2 0 +make-backend/internal/gql/generated.go:9626.37,9628.5 1 0 +make-backend/internal/gql/generated.go:9629.11,9630.55 1 0 +make-backend/internal/gql/generated.go:9633.2,9634.22 2 0 +make-backend/internal/gql/generated.go:9634.22,9636.3 1 0 +make-backend/internal/gql/generated.go:9638.2,9647.12 3 0 +make-backend/internal/gql/generated.go:9652.138,9658.31 5 0 +make-backend/internal/gql/generated.go:9658.31,9659.21 1 0 +make-backend/internal/gql/generated.go:9660.21,9661.61 1 0 +make-backend/internal/gql/generated.go:9662.19,9664.37 2 0 +make-backend/internal/gql/generated.go:9664.37,9666.5 1 0 +make-backend/internal/gql/generated.go:9667.15,9669.37 2 0 +make-backend/internal/gql/generated.go:9669.37,9671.5 1 0 +make-backend/internal/gql/generated.go:9672.18,9674.37 2 0 +make-backend/internal/gql/generated.go:9674.37,9676.5 1 0 +make-backend/internal/gql/generated.go:9677.17,9679.45 2 0 +make-backend/internal/gql/generated.go:9679.45,9681.5 1 0 +make-backend/internal/gql/generated.go:9682.15,9684.37 2 0 +make-backend/internal/gql/generated.go:9684.37,9686.5 1 0 +make-backend/internal/gql/generated.go:9687.22,9689.37 2 0 +make-backend/internal/gql/generated.go:9689.37,9691.5 1 0 +make-backend/internal/gql/generated.go:9692.11,9693.55 1 0 +make-backend/internal/gql/generated.go:9696.2,9697.22 2 0 +make-backend/internal/gql/generated.go:9697.22,9699.3 1 0 +make-backend/internal/gql/generated.go:9701.2,9710.12 3 0 +make-backend/internal/gql/generated.go:9715.130,9721.31 5 0 +make-backend/internal/gql/generated.go:9721.31,9722.21 1 0 +make-backend/internal/gql/generated.go:9723.21,9724.57 1 0 +make-backend/internal/gql/generated.go:9725.24,9727.37 2 0 +make-backend/internal/gql/generated.go:9727.37,9729.5 1 0 +make-backend/internal/gql/generated.go:9730.23,9732.37 2 0 +make-backend/internal/gql/generated.go:9732.37,9734.5 1 0 +make-backend/internal/gql/generated.go:9735.20,9737.45 2 0 +make-backend/internal/gql/generated.go:9737.45,9739.5 1 0 +make-backend/internal/gql/generated.go:9740.21,9742.45 2 0 +make-backend/internal/gql/generated.go:9742.45,9744.5 1 0 +make-backend/internal/gql/generated.go:9745.17,9747.37 2 0 +make-backend/internal/gql/generated.go:9747.37,9749.5 1 0 +make-backend/internal/gql/generated.go:9750.11,9751.55 1 0 +make-backend/internal/gql/generated.go:9754.2,9755.22 2 0 +make-backend/internal/gql/generated.go:9755.22,9757.3 1 0 +make-backend/internal/gql/generated.go:9759.2,9768.12 3 0 +make-backend/internal/gql/generated.go:9773.122,9779.31 5 0 +make-backend/internal/gql/generated.go:9779.31,9780.21 1 0 +make-backend/internal/gql/generated.go:9781.21,9782.53 1 0 +make-backend/internal/gql/generated.go:9783.13,9785.37 2 0 +make-backend/internal/gql/generated.go:9785.37,9787.5 1 0 +make-backend/internal/gql/generated.go:9788.18,9790.37 2 0 +make-backend/internal/gql/generated.go:9790.37,9792.5 1 0 +make-backend/internal/gql/generated.go:9793.19,9795.37 2 0 +make-backend/internal/gql/generated.go:9795.37,9797.5 1 0 +make-backend/internal/gql/generated.go:9798.17,9800.37 2 0 +make-backend/internal/gql/generated.go:9800.37,9802.5 1 0 +make-backend/internal/gql/generated.go:9803.11,9804.55 1 0 +make-backend/internal/gql/generated.go:9807.2,9808.22 2 0 +make-backend/internal/gql/generated.go:9808.22,9810.3 1 0 +make-backend/internal/gql/generated.go:9812.2,9821.12 3 0 +make-backend/internal/gql/generated.go:9826.124,9832.31 5 0 +make-backend/internal/gql/generated.go:9832.31,9833.21 1 0 +make-backend/internal/gql/generated.go:9834.21,9835.54 1 0 +make-backend/internal/gql/generated.go:9836.19,9838.37 2 0 +make-backend/internal/gql/generated.go:9838.37,9840.5 1 0 +make-backend/internal/gql/generated.go:9841.15,9843.37 2 0 +make-backend/internal/gql/generated.go:9843.37,9845.5 1 0 +make-backend/internal/gql/generated.go:9846.18,9848.37 2 0 +make-backend/internal/gql/generated.go:9848.37,9850.5 1 0 +make-backend/internal/gql/generated.go:9851.11,9852.55 1 0 +make-backend/internal/gql/generated.go:9855.2,9856.22 2 0 +make-backend/internal/gql/generated.go:9856.22,9858.3 1 0 +make-backend/internal/gql/generated.go:9860.2,9869.12 3 0 +make-backend/internal/gql/generated.go:9874.122,9880.31 5 0 +make-backend/internal/gql/generated.go:9880.31,9881.21 1 0 +make-backend/internal/gql/generated.go:9882.21,9883.53 1 0 +make-backend/internal/gql/generated.go:9884.13,9886.37 2 0 +make-backend/internal/gql/generated.go:9886.37,9888.5 1 0 +make-backend/internal/gql/generated.go:9889.15,9891.37 2 0 +make-backend/internal/gql/generated.go:9891.37,9893.5 1 0 +make-backend/internal/gql/generated.go:9894.24,9896.45 2 0 +make-backend/internal/gql/generated.go:9896.45,9898.5 1 0 +make-backend/internal/gql/generated.go:9899.17,9902.89 2 0 +make-backend/internal/gql/generated.go:9902.89,9903.18 1 0 +make-backend/internal/gql/generated.go:9903.18,9904.34 1 0 +make-backend/internal/gql/generated.go:9904.34,9906.7 1 0 +make-backend/internal/gql/generated.go:9908.5,9909.28 2 0 +make-backend/internal/gql/generated.go:9909.28,9911.6 1 0 +make-backend/internal/gql/generated.go:9912.5,9912.15 1 0 +make-backend/internal/gql/generated.go:9915.4,9915.26 1 0 +make-backend/internal/gql/generated.go:9915.26,9918.91 3 0 +make-backend/internal/gql/generated.go:9918.91,9920.6 1 0 +make-backend/internal/gql/generated.go:9922.5,9922.50 1 0 +make-backend/internal/gql/generated.go:9922.50,9924.13 2 0 +make-backend/internal/gql/generated.go:9924.13,9927.7 2 0 +make-backend/internal/gql/generated.go:9928.6,9928.33 1 0 +make-backend/internal/gql/generated.go:9932.5,9933.13 2 0 +make-backend/internal/gql/generated.go:9936.4,9936.68 1 0 +make-backend/internal/gql/generated.go:9936.68,9936.98 1 0 +make-backend/internal/gql/generated.go:9937.11,9938.55 1 0 +make-backend/internal/gql/generated.go:9941.2,9942.22 2 0 +make-backend/internal/gql/generated.go:9942.22,9944.3 1 0 +make-backend/internal/gql/generated.go:9946.2,9955.12 3 0 +make-backend/internal/gql/generated.go:9960.114,9966.31 5 0 +make-backend/internal/gql/generated.go:9966.31,9967.21 1 0 +make-backend/internal/gql/generated.go:9968.21,9969.49 1 0 +make-backend/internal/gql/generated.go:9970.13,9972.37 2 0 +make-backend/internal/gql/generated.go:9972.37,9974.5 1 0 +make-backend/internal/gql/generated.go:9975.16,9977.37 2 0 +make-backend/internal/gql/generated.go:9977.37,9979.5 1 0 +make-backend/internal/gql/generated.go:9980.20,9982.37 2 0 +make-backend/internal/gql/generated.go:9982.37,9984.5 1 0 +make-backend/internal/gql/generated.go:9985.19,9987.37 2 0 +make-backend/internal/gql/generated.go:9987.37,9989.5 1 0 +make-backend/internal/gql/generated.go:9990.19,9992.37 2 0 +make-backend/internal/gql/generated.go:9992.37,9994.5 1 0 +make-backend/internal/gql/generated.go:9995.20,9997.37 2 0 +make-backend/internal/gql/generated.go:9997.37,9999.5 1 0 +make-backend/internal/gql/generated.go:10000.25,10002.37 2 0 +make-backend/internal/gql/generated.go:10002.37,10004.5 1 0 +make-backend/internal/gql/generated.go:10005.19,10007.37 2 0 +make-backend/internal/gql/generated.go:10007.37,10009.5 1 0 +make-backend/internal/gql/generated.go:10010.16,10012.37 2 0 +make-backend/internal/gql/generated.go:10012.37,10014.5 1 0 +make-backend/internal/gql/generated.go:10015.16,10017.37 2 0 +make-backend/internal/gql/generated.go:10017.37,10019.5 1 0 +make-backend/internal/gql/generated.go:10020.24,10022.45 2 0 +make-backend/internal/gql/generated.go:10022.45,10024.5 1 0 +make-backend/internal/gql/generated.go:10025.19,10027.37 2 0 +make-backend/internal/gql/generated.go:10027.37,10029.5 1 0 +make-backend/internal/gql/generated.go:10030.11,10031.55 1 0 +make-backend/internal/gql/generated.go:10034.2,10035.22 2 0 +make-backend/internal/gql/generated.go:10035.22,10037.3 1 0 +make-backend/internal/gql/generated.go:10039.2,10048.12 3 0 +make-backend/internal/gql/generated.go:10053.114,10059.31 5 0 +make-backend/internal/gql/generated.go:10059.31,10060.21 1 0 +make-backend/internal/gql/generated.go:10061.21,10062.49 1 0 +make-backend/internal/gql/generated.go:10063.13,10065.37 2 0 +make-backend/internal/gql/generated.go:10065.37,10067.5 1 0 +make-backend/internal/gql/generated.go:10068.24,10070.37 2 0 +make-backend/internal/gql/generated.go:10070.37,10072.5 1 0 +make-backend/internal/gql/generated.go:10073.15,10075.37 2 0 +make-backend/internal/gql/generated.go:10075.37,10077.5 1 0 +make-backend/internal/gql/generated.go:10078.17,10080.37 2 0 +make-backend/internal/gql/generated.go:10080.37,10082.5 1 0 +make-backend/internal/gql/generated.go:10083.11,10084.55 1 0 +make-backend/internal/gql/generated.go:10087.2,10088.22 2 0 +make-backend/internal/gql/generated.go:10088.22,10090.3 1 0 +make-backend/internal/gql/generated.go:10092.2,10101.12 3 0 +make-backend/internal/gql/generated.go:10106.133,10112.31 5 0 +make-backend/internal/gql/generated.go:10112.31,10113.21 1 0 +make-backend/internal/gql/generated.go:10114.21,10115.56 1 0 +make-backend/internal/gql/generated.go:10116.15,10118.37 2 0 +make-backend/internal/gql/generated.go:10118.37,10120.5 1 0 +make-backend/internal/gql/generated.go:10121.22,10123.45 2 0 +make-backend/internal/gql/generated.go:10123.45,10125.5 1 0 +make-backend/internal/gql/generated.go:10126.23,10128.37 2 0 +make-backend/internal/gql/generated.go:10128.37,10130.5 1 0 +make-backend/internal/gql/generated.go:10131.20,10133.37 2 0 +make-backend/internal/gql/generated.go:10133.37,10135.5 1 0 +make-backend/internal/gql/generated.go:10136.15,10138.37 2 0 +make-backend/internal/gql/generated.go:10138.37,10140.5 1 0 +make-backend/internal/gql/generated.go:10141.11,10142.55 1 0 +make-backend/internal/gql/generated.go:10145.2,10146.22 2 0 +make-backend/internal/gql/generated.go:10146.22,10148.3 1 0 +make-backend/internal/gql/generated.go:10150.2,10159.12 3 0 +make-backend/internal/gql/generated.go:10164.133,10170.31 5 0 +make-backend/internal/gql/generated.go:10170.31,10171.21 1 0 +make-backend/internal/gql/generated.go:10172.21,10173.56 1 0 +make-backend/internal/gql/generated.go:10174.15,10176.37 2 0 +make-backend/internal/gql/generated.go:10176.37,10178.5 1 0 +make-backend/internal/gql/generated.go:10179.22,10181.45 2 0 +make-backend/internal/gql/generated.go:10181.45,10183.5 1 0 +make-backend/internal/gql/generated.go:10184.23,10186.37 2 0 +make-backend/internal/gql/generated.go:10186.37,10188.5 1 0 +make-backend/internal/gql/generated.go:10189.28,10191.45 2 0 +make-backend/internal/gql/generated.go:10191.45,10193.5 1 0 +make-backend/internal/gql/generated.go:10194.11,10195.55 1 0 +make-backend/internal/gql/generated.go:10198.2,10199.22 2 0 +make-backend/internal/gql/generated.go:10199.22,10201.3 1 0 +make-backend/internal/gql/generated.go:10203.2,10212.12 3 0 +make-backend/internal/gql/generated.go:10217.125,10223.31 5 0 +make-backend/internal/gql/generated.go:10223.31,10224.21 1 0 +make-backend/internal/gql/generated.go:10225.21,10226.52 1 0 +make-backend/internal/gql/generated.go:10227.15,10229.37 2 0 +make-backend/internal/gql/generated.go:10229.37,10231.5 1 0 +make-backend/internal/gql/generated.go:10232.22,10234.45 2 0 +make-backend/internal/gql/generated.go:10234.45,10236.5 1 0 +make-backend/internal/gql/generated.go:10237.15,10239.37 2 0 +make-backend/internal/gql/generated.go:10239.37,10241.5 1 0 +make-backend/internal/gql/generated.go:10242.15,10244.37 2 0 +make-backend/internal/gql/generated.go:10244.37,10246.5 1 0 +make-backend/internal/gql/generated.go:10247.23,10249.37 2 0 +make-backend/internal/gql/generated.go:10249.37,10251.5 1 0 +make-backend/internal/gql/generated.go:10252.28,10254.45 2 0 +make-backend/internal/gql/generated.go:10254.45,10256.5 1 0 +make-backend/internal/gql/generated.go:10257.11,10258.55 1 0 +make-backend/internal/gql/generated.go:10261.2,10262.22 2 0 +make-backend/internal/gql/generated.go:10262.22,10264.3 1 0 +make-backend/internal/gql/generated.go:10266.2,10275.12 3 0 +make-backend/internal/gql/generated.go:10280.135,10286.31 5 0 +make-backend/internal/gql/generated.go:10286.31,10287.21 1 0 +make-backend/internal/gql/generated.go:10288.21,10289.57 1 0 +make-backend/internal/gql/generated.go:10290.15,10292.37 2 0 +make-backend/internal/gql/generated.go:10292.37,10294.5 1 0 +make-backend/internal/gql/generated.go:10295.22,10297.45 2 0 +make-backend/internal/gql/generated.go:10297.45,10299.5 1 0 +make-backend/internal/gql/generated.go:10300.15,10302.37 2 0 +make-backend/internal/gql/generated.go:10302.37,10304.5 1 0 +make-backend/internal/gql/generated.go:10305.23,10307.45 2 0 +make-backend/internal/gql/generated.go:10307.45,10309.5 1 0 +make-backend/internal/gql/generated.go:10310.23,10312.37 2 0 +make-backend/internal/gql/generated.go:10312.37,10314.5 1 0 +make-backend/internal/gql/generated.go:10315.28,10317.45 2 0 +make-backend/internal/gql/generated.go:10317.45,10319.5 1 0 +make-backend/internal/gql/generated.go:10320.11,10321.55 1 0 +make-backend/internal/gql/generated.go:10324.2,10325.22 2 0 +make-backend/internal/gql/generated.go:10325.22,10327.3 1 0 +make-backend/internal/gql/generated.go:10329.2,10338.12 3 0 +make-backend/internal/gql/generated.go:10343.127,10349.31 5 0 +make-backend/internal/gql/generated.go:10349.31,10350.21 1 0 +make-backend/internal/gql/generated.go:10351.21,10352.53 1 0 +make-backend/internal/gql/generated.go:10353.22,10355.45 2 0 +make-backend/internal/gql/generated.go:10355.45,10357.5 1 0 +make-backend/internal/gql/generated.go:10358.16,10360.37 2 0 +make-backend/internal/gql/generated.go:10360.37,10362.5 1 0 +make-backend/internal/gql/generated.go:10363.20,10365.37 2 0 +make-backend/internal/gql/generated.go:10365.37,10367.5 1 0 +make-backend/internal/gql/generated.go:10368.23,10370.45 2 0 +make-backend/internal/gql/generated.go:10370.45,10372.5 1 0 +make-backend/internal/gql/generated.go:10373.27,10375.45 2 0 +make-backend/internal/gql/generated.go:10375.45,10377.5 1 0 +make-backend/internal/gql/generated.go:10378.21,10380.37 2 0 +make-backend/internal/gql/generated.go:10380.37,10382.5 1 0 +make-backend/internal/gql/generated.go:10383.11,10384.55 1 0 +make-backend/internal/gql/generated.go:10387.2,10388.22 2 0 +make-backend/internal/gql/generated.go:10388.22,10390.3 1 0 +make-backend/internal/gql/generated.go:10392.2,10401.12 3 0 +make-backend/internal/gql/generated.go:10406.123,10412.31 5 0 +make-backend/internal/gql/generated.go:10412.31,10413.21 1 0 +make-backend/internal/gql/generated.go:10414.21,10415.51 1 0 +make-backend/internal/gql/generated.go:10416.15,10418.37 2 0 +make-backend/internal/gql/generated.go:10418.37,10420.5 1 0 +make-backend/internal/gql/generated.go:10421.15,10423.45 2 0 +make-backend/internal/gql/generated.go:10423.45,10425.5 1 0 +make-backend/internal/gql/generated.go:10426.22,10428.45 2 0 +make-backend/internal/gql/generated.go:10428.45,10430.5 1 0 +make-backend/internal/gql/generated.go:10431.25,10433.45 2 0 +make-backend/internal/gql/generated.go:10433.45,10435.5 1 0 +make-backend/internal/gql/generated.go:10436.17,10438.45 2 0 +make-backend/internal/gql/generated.go:10438.45,10440.5 1 0 +make-backend/internal/gql/generated.go:10441.21,10443.45 2 0 +make-backend/internal/gql/generated.go:10443.45,10445.5 1 0 +make-backend/internal/gql/generated.go:10446.24,10448.45 2 0 +make-backend/internal/gql/generated.go:10448.45,10450.5 1 0 +make-backend/internal/gql/generated.go:10451.21,10453.45 2 0 +make-backend/internal/gql/generated.go:10453.45,10455.5 1 0 +make-backend/internal/gql/generated.go:10456.22,10458.45 2 0 +make-backend/internal/gql/generated.go:10458.45,10460.5 1 0 +make-backend/internal/gql/generated.go:10461.17,10463.45 2 0 +make-backend/internal/gql/generated.go:10463.45,10465.5 1 0 +make-backend/internal/gql/generated.go:10466.18,10468.45 2 0 +make-backend/internal/gql/generated.go:10468.45,10470.5 1 0 +make-backend/internal/gql/generated.go:10471.11,10472.55 1 0 +make-backend/internal/gql/generated.go:10475.2,10476.22 2 0 +make-backend/internal/gql/generated.go:10476.22,10478.3 1 0 +make-backend/internal/gql/generated.go:10480.2,10489.12 3 0 +make-backend/internal/gql/generated.go:10496.204,10498.2 1 0 +make-backend/internal/gql/generated.go:10500.212,10501.116 1 0 +make-backend/internal/gql/generated.go:10501.116,10505.3 3 0 +make-backend/internal/gql/generated.go:10507.2,10507.24 1 0 +make-backend/internal/gql/generated.go:10507.24,10508.24 1 0 +make-backend/internal/gql/generated.go:10508.24,10510.4 1 0 +make-backend/internal/gql/generated.go:10513.2,10513.12 1 0 +make-backend/internal/gql/generated.go:10516.210,10518.2 1 0 +make-backend/internal/gql/generated.go:10520.94,10523.2 2 0 +make-backend/internal/gql/generated.go:10525.119,10528.25 3 0 +make-backend/internal/gql/generated.go:10528.25,10529.64 1 0 +make-backend/internal/gql/generated.go:10529.64,10531.4 1 0 +make-backend/internal/gql/generated.go:10533.2,10533.12 1 0 +make-backend/internal/gql/generated.go:10536.103,10539.2 2 0 +make-backend/internal/gql/generated.go:10541.128,10544.25 3 0 +make-backend/internal/gql/generated.go:10544.25,10545.64 1 0 +make-backend/internal/gql/generated.go:10545.64,10547.4 1 0 +make-backend/internal/gql/generated.go:10549.2,10549.12 1 0 +make-backend/internal/gql/generated.go:10552.177,10554.2 1 0 +make-backend/internal/gql/generated.go:10556.174,10558.2 1 0 +make-backend/internal/gql/generated.go:10560.178,10561.14 1 0 +make-backend/internal/gql/generated.go:10561.14,10562.64 1 0 +make-backend/internal/gql/generated.go:10562.64,10564.4 1 0 +make-backend/internal/gql/generated.go:10565.3,10565.22 1 0 +make-backend/internal/gql/generated.go:10567.2,10567.31 1 0 +make-backend/internal/gql/generated.go:10570.191,10574.2 3 0 +make-backend/internal/gql/generated.go:10576.216,10578.2 1 0 +make-backend/internal/gql/generated.go:10580.87,10583.2 2 0 +make-backend/internal/gql/generated.go:10585.112,10588.25 3 0 +make-backend/internal/gql/generated.go:10588.25,10589.64 1 0 +make-backend/internal/gql/generated.go:10589.64,10591.4 1 0 +make-backend/internal/gql/generated.go:10593.2,10593.12 1 0 +make-backend/internal/gql/generated.go:10596.88,10599.2 2 0 +make-backend/internal/gql/generated.go:10601.113,10604.25 3 0 +make-backend/internal/gql/generated.go:10604.25,10605.64 1 0 +make-backend/internal/gql/generated.go:10605.64,10607.4 1 0 +make-backend/internal/gql/generated.go:10609.2,10609.12 1 0 +make-backend/internal/gql/generated.go:10612.204,10613.14 1 0 +make-backend/internal/gql/generated.go:10613.14,10614.64 1 0 +make-backend/internal/gql/generated.go:10614.64,10616.4 1 0 +make-backend/internal/gql/generated.go:10617.3,10617.22 1 0 +make-backend/internal/gql/generated.go:10619.2,10619.41 1 0 +make-backend/internal/gql/generated.go:10622.212,10623.116 1 0 +make-backend/internal/gql/generated.go:10623.116,10627.3 3 0 +make-backend/internal/gql/generated.go:10629.2,10629.24 1 0 +make-backend/internal/gql/generated.go:10629.24,10630.24 1 0 +make-backend/internal/gql/generated.go:10630.24,10632.4 1 0 +make-backend/internal/gql/generated.go:10635.2,10635.12 1 0 +make-backend/internal/gql/generated.go:10638.222,10639.116 1 0 +make-backend/internal/gql/generated.go:10639.116,10643.3 3 0 +make-backend/internal/gql/generated.go:10645.2,10645.24 1 0 +make-backend/internal/gql/generated.go:10645.24,10646.24 1 0 +make-backend/internal/gql/generated.go:10646.24,10648.4 1 0 +make-backend/internal/gql/generated.go:10651.2,10651.12 1 0 +make-backend/internal/gql/generated.go:10654.214,10655.14 1 0 +make-backend/internal/gql/generated.go:10655.14,10656.64 1 0 +make-backend/internal/gql/generated.go:10656.64,10658.4 1 0 +make-backend/internal/gql/generated.go:10659.3,10659.22 1 0 +make-backend/internal/gql/generated.go:10661.2,10661.43 1 0 +make-backend/internal/gql/generated.go:10664.210,10666.2 1 0 +make-backend/internal/gql/generated.go:10668.218,10669.116 1 0 +make-backend/internal/gql/generated.go:10669.116,10673.3 3 0 +make-backend/internal/gql/generated.go:10675.2,10675.24 1 0 +make-backend/internal/gql/generated.go:10675.24,10676.24 1 0 +make-backend/internal/gql/generated.go:10676.24,10678.4 1 0 +make-backend/internal/gql/generated.go:10681.2,10681.12 1 0 +make-backend/internal/gql/generated.go:10684.97,10687.2 2 0 +make-backend/internal/gql/generated.go:10689.122,10692.25 3 0 +make-backend/internal/gql/generated.go:10692.25,10693.64 1 0 +make-backend/internal/gql/generated.go:10693.64,10695.4 1 0 +make-backend/internal/gql/generated.go:10697.2,10697.12 1 0 +make-backend/internal/gql/generated.go:10700.103,10703.2 2 0 +make-backend/internal/gql/generated.go:10705.128,10708.25 3 0 +make-backend/internal/gql/generated.go:10708.25,10709.64 1 0 +make-backend/internal/gql/generated.go:10709.64,10711.4 1 0 +make-backend/internal/gql/generated.go:10713.2,10713.12 1 0 +make-backend/internal/gql/generated.go:10716.198,10717.14 1 0 +make-backend/internal/gql/generated.go:10717.14,10718.64 1 0 +make-backend/internal/gql/generated.go:10718.64,10720.4 1 0 +make-backend/internal/gql/generated.go:10721.3,10721.22 1 0 +make-backend/internal/gql/generated.go:10723.2,10723.39 1 0 +make-backend/internal/gql/generated.go:10726.206,10727.116 1 0 +make-backend/internal/gql/generated.go:10727.116,10731.3 3 0 +make-backend/internal/gql/generated.go:10733.2,10733.24 1 0 +make-backend/internal/gql/generated.go:10733.24,10734.24 1 0 +make-backend/internal/gql/generated.go:10734.24,10736.4 1 0 +make-backend/internal/gql/generated.go:10739.2,10739.12 1 0 +make-backend/internal/gql/generated.go:10742.171,10744.2 1 0 +make-backend/internal/gql/generated.go:10746.175,10747.14 1 0 +make-backend/internal/gql/generated.go:10747.14,10748.64 1 0 +make-backend/internal/gql/generated.go:10748.64,10750.4 1 0 +make-backend/internal/gql/generated.go:10751.3,10751.22 1 0 +make-backend/internal/gql/generated.go:10753.2,10753.30 1 0 +make-backend/internal/gql/generated.go:10756.171,10758.2 1 0 +make-backend/internal/gql/generated.go:10760.183,10761.116 1 0 +make-backend/internal/gql/generated.go:10761.116,10765.3 3 0 +make-backend/internal/gql/generated.go:10767.2,10767.24 1 0 +make-backend/internal/gql/generated.go:10767.24,10768.24 1 0 +make-backend/internal/gql/generated.go:10768.24,10770.4 1 0 +make-backend/internal/gql/generated.go:10773.2,10773.12 1 0 +make-backend/internal/gql/generated.go:10776.175,10777.14 1 0 +make-backend/internal/gql/generated.go:10777.14,10778.64 1 0 +make-backend/internal/gql/generated.go:10778.64,10780.4 1 0 +make-backend/internal/gql/generated.go:10781.3,10781.22 1 0 +make-backend/internal/gql/generated.go:10783.2,10783.30 1 0 +make-backend/internal/gql/generated.go:10786.209,10788.2 1 0 +make-backend/internal/gql/generated.go:10790.217,10791.116 1 0 +make-backend/internal/gql/generated.go:10791.116,10795.3 3 0 +make-backend/internal/gql/generated.go:10797.2,10797.24 1 0 +make-backend/internal/gql/generated.go:10797.24,10798.24 1 0 +make-backend/internal/gql/generated.go:10798.24,10800.4 1 0 +make-backend/internal/gql/generated.go:10803.2,10803.12 1 0 +make-backend/internal/gql/generated.go:10806.110,10809.2 2 0 +make-backend/internal/gql/generated.go:10811.135,10814.25 3 0 +make-backend/internal/gql/generated.go:10814.25,10815.64 1 0 +make-backend/internal/gql/generated.go:10815.64,10817.4 1 0 +make-backend/internal/gql/generated.go:10819.2,10819.12 1 0 +make-backend/internal/gql/generated.go:10822.118,10827.24 5 0 +make-backend/internal/gql/generated.go:10827.24,10830.17 3 0 +make-backend/internal/gql/generated.go:10830.17,10832.4 1 0 +make-backend/internal/gql/generated.go:10834.2,10834.17 1 0 +make-backend/internal/gql/generated.go:10837.143,10838.116 1 0 +make-backend/internal/gql/generated.go:10838.116,10842.3 3 0 +make-backend/internal/gql/generated.go:10844.2,10844.24 1 0 +make-backend/internal/gql/generated.go:10844.24,10845.24 1 0 +make-backend/internal/gql/generated.go:10845.24,10847.4 1 0 +make-backend/internal/gql/generated.go:10850.2,10850.12 1 0 +make-backend/internal/gql/generated.go:10853.209,10855.2 1 0 +make-backend/internal/gql/generated.go:10857.197,10859.2 1 0 +make-backend/internal/gql/generated.go:10861.212,10863.2 1 0 +make-backend/internal/gql/generated.go:10865.220,10866.116 1 0 +make-backend/internal/gql/generated.go:10866.116,10870.3 3 0 +make-backend/internal/gql/generated.go:10872.2,10872.24 1 0 +make-backend/internal/gql/generated.go:10872.24,10873.24 1 0 +make-backend/internal/gql/generated.go:10873.24,10875.4 1 0 +make-backend/internal/gql/generated.go:10878.2,10878.12 1 0 +make-backend/internal/gql/generated.go:10881.194,10883.2 1 0 +make-backend/internal/gql/generated.go:10885.202,10886.116 1 0 +make-backend/internal/gql/generated.go:10886.116,10890.3 3 0 +make-backend/internal/gql/generated.go:10892.2,10892.24 1 0 +make-backend/internal/gql/generated.go:10892.24,10893.24 1 0 +make-backend/internal/gql/generated.go:10893.24,10895.4 1 0 +make-backend/internal/gql/generated.go:10898.2,10898.12 1 0 +make-backend/internal/gql/generated.go:10901.198,10902.14 1 0 +make-backend/internal/gql/generated.go:10902.14,10903.64 1 0 +make-backend/internal/gql/generated.go:10903.64,10905.4 1 0 +make-backend/internal/gql/generated.go:10906.3,10906.22 1 0 +make-backend/internal/gql/generated.go:10908.2,10908.32 1 0 +make-backend/internal/gql/generated.go:10911.101,10914.2 2 0 +make-backend/internal/gql/generated.go:10916.126,10919.25 3 0 +make-backend/internal/gql/generated.go:10919.25,10920.64 1 0 +make-backend/internal/gql/generated.go:10920.64,10922.4 1 0 +make-backend/internal/gql/generated.go:10924.2,10924.12 1 0 +make-backend/internal/gql/generated.go:10927.192,10928.14 1 0 +make-backend/internal/gql/generated.go:10928.14,10930.3 1 0 +make-backend/internal/gql/generated.go:10931.2,10933.44 3 0 +make-backend/internal/gql/generated.go:10936.217,10937.14 1 0 +make-backend/internal/gql/generated.go:10937.14,10939.3 1 0 +make-backend/internal/gql/generated.go:10940.2,10943.12 4 0 +make-backend/internal/gql/generated.go:10946.211,10947.14 1 0 +make-backend/internal/gql/generated.go:10947.14,10949.3 1 0 +make-backend/internal/gql/generated.go:10950.2,10950.42 1 0 +make-backend/internal/gql/generated.go:10953.199,10954.14 1 0 +make-backend/internal/gql/generated.go:10954.14,10956.3 1 0 +make-backend/internal/gql/generated.go:10957.2,10957.38 1 0 +make-backend/internal/gql/generated.go:10960.94,10963.2 2 0 +make-backend/internal/gql/generated.go:10965.119,10970.2 4 0 +make-backend/internal/gql/generated.go:10972.98,10973.14 1 0 +make-backend/internal/gql/generated.go:10973.14,10975.3 1 0 +make-backend/internal/gql/generated.go:10976.2,10977.44 2 0 +make-backend/internal/gql/generated.go:10980.123,10981.14 1 0 +make-backend/internal/gql/generated.go:10981.14,10983.3 1 0 +make-backend/internal/gql/generated.go:10984.2,10987.12 4 0 +make-backend/internal/gql/generated.go:10990.112,10991.14 1 0 +make-backend/internal/gql/generated.go:10991.14,10993.3 1 0 +make-backend/internal/gql/generated.go:10994.2,10995.44 2 0 +make-backend/internal/gql/generated.go:10998.137,10999.14 1 0 +make-backend/internal/gql/generated.go:10999.14,11001.3 1 0 +make-backend/internal/gql/generated.go:11002.2,11005.12 4 0 +make-backend/internal/gql/generated.go:11008.181,11009.14 1 0 +make-backend/internal/gql/generated.go:11009.14,11011.3 1 0 +make-backend/internal/gql/generated.go:11012.2,11012.32 1 0 +make-backend/internal/gql/generated.go:11015.180,11016.14 1 0 +make-backend/internal/gql/generated.go:11016.14,11018.3 1 0 +make-backend/internal/gql/generated.go:11019.2,11021.44 3 0 +make-backend/internal/gql/generated.go:11024.205,11025.14 1 0 +make-backend/internal/gql/generated.go:11025.14,11027.3 1 0 +make-backend/internal/gql/generated.go:11028.2,11031.12 4 0 +make-backend/internal/gql/generated.go:11034.91,11035.14 1 0 +make-backend/internal/gql/generated.go:11035.14,11037.3 1 0 +make-backend/internal/gql/generated.go:11038.2,11039.44 2 0 +make-backend/internal/gql/generated.go:11042.116,11043.14 1 0 +make-backend/internal/gql/generated.go:11043.14,11045.3 1 0 +make-backend/internal/gql/generated.go:11046.2,11049.12 4 0 +make-backend/internal/gql/generated.go:11052.96,11053.14 1 0 +make-backend/internal/gql/generated.go:11053.14,11055.3 1 0 +make-backend/internal/gql/generated.go:11056.2,11057.44 2 0 +make-backend/internal/gql/generated.go:11060.121,11061.14 1 0 +make-backend/internal/gql/generated.go:11061.14,11063.3 1 0 +make-backend/internal/gql/generated.go:11064.2,11067.12 4 0 +make-backend/internal/gql/generated.go:11070.193,11071.14 1 0 +make-backend/internal/gql/generated.go:11071.14,11073.3 1 0 +make-backend/internal/gql/generated.go:11074.2,11074.36 1 0 +make-backend/internal/gql/generated.go:11077.101,11078.14 1 0 +make-backend/internal/gql/generated.go:11078.14,11080.3 1 0 +make-backend/internal/gql/generated.go:11081.2,11082.44 2 0 +make-backend/internal/gql/generated.go:11085.126,11086.14 1 0 +make-backend/internal/gql/generated.go:11086.14,11088.3 1 0 +make-backend/internal/gql/generated.go:11089.2,11092.12 4 0 +make-backend/internal/gql/generated.go:11095.107,11096.14 1 0 +make-backend/internal/gql/generated.go:11096.14,11098.3 1 0 +make-backend/internal/gql/generated.go:11099.2,11100.44 2 0 +make-backend/internal/gql/generated.go:11103.132,11104.14 1 0 +make-backend/internal/gql/generated.go:11104.14,11106.3 1 0 +make-backend/internal/gql/generated.go:11107.2,11110.12 4 0 +make-backend/internal/gql/generated.go:11113.217,11114.14 1 0 +make-backend/internal/gql/generated.go:11114.14,11116.3 1 0 +make-backend/internal/gql/generated.go:11117.2,11117.116 1 0 +make-backend/internal/gql/generated.go:11117.116,11121.3 3 0 +make-backend/internal/gql/generated.go:11123.2,11123.24 1 0 +make-backend/internal/gql/generated.go:11123.24,11124.24 1 0 +make-backend/internal/gql/generated.go:11124.24,11126.4 1 0 +make-backend/internal/gql/generated.go:11129.2,11129.12 1 0 +make-backend/internal/gql/generated.go:11132.205,11133.14 1 0 +make-backend/internal/gql/generated.go:11133.14,11135.3 1 0 +make-backend/internal/gql/generated.go:11136.2,11136.116 1 0 +make-backend/internal/gql/generated.go:11136.116,11140.3 3 0 +make-backend/internal/gql/generated.go:11142.2,11142.24 1 0 +make-backend/internal/gql/generated.go:11142.24,11143.24 1 0 +make-backend/internal/gql/generated.go:11143.24,11145.4 1 0 +make-backend/internal/gql/generated.go:11148.2,11148.12 1 0 +make-backend/internal/gql/generated.go:11151.220,11152.14 1 0 +make-backend/internal/gql/generated.go:11152.14,11154.3 1 0 +make-backend/internal/gql/generated.go:11155.2,11155.116 1 0 +make-backend/internal/gql/generated.go:11155.116,11159.3 3 0 +make-backend/internal/gql/generated.go:11161.2,11161.24 1 0 +make-backend/internal/gql/generated.go:11161.24,11162.24 1 0 +make-backend/internal/gql/generated.go:11162.24,11164.4 1 0 +make-backend/internal/gql/generated.go:11167.2,11167.12 1 0 +make-backend/internal/gql/generated.go:11170.204,11171.14 1 0 +make-backend/internal/gql/generated.go:11171.14,11173.3 1 0 +make-backend/internal/gql/generated.go:11174.2,11174.34 1 0 +make-backend/internal/gql/generated.go:11177.202,11178.14 1 0 +make-backend/internal/gql/generated.go:11178.14,11180.3 1 0 +make-backend/internal/gql/generated.go:11181.2,11181.116 1 0 +make-backend/internal/gql/generated.go:11181.116,11185.3 3 0 +make-backend/internal/gql/generated.go:11187.2,11187.24 1 0 +make-backend/internal/gql/generated.go:11187.24,11188.24 1 0 +make-backend/internal/gql/generated.go:11188.24,11190.4 1 0 +make-backend/internal/gql/generated.go:11193.2,11193.12 1 0 +make-backend/internal/gql/generated.go:11196.198,11197.14 1 0 +make-backend/internal/gql/generated.go:11197.14,11199.3 1 0 +make-backend/internal/gql/generated.go:11200.2,11200.32 1 0 +make-backend/internal/gql/resolvers/device.resolvers.go:15.103,17.2 1 0 +make-backend/internal/gql/resolvers/device.resolvers.go:20.85,22.16 2 0 +make-backend/internal/gql/resolvers/device.resolvers.go:22.16,24.3 1 0 +make-backend/internal/gql/resolvers/device.resolvers.go:25.2,25.17 1 0 +make-backend/internal/gql/resolvers/device.resolvers.go:29.97,31.16 2 0 +make-backend/internal/gql/resolvers/device.resolvers.go:31.16,33.3 1 0 +make-backend/internal/gql/resolvers/device.resolvers.go:34.2,34.17 1 0 +make-backend/internal/gql/resolvers/device.resolvers.go:38.66,38.104 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:16.87,20.16 3 0 +make-backend/internal/gql/resolvers/group.resolvers.go:20.16,22.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:23.2,24.16 2 0 +make-backend/internal/gql/resolvers/group.resolvers.go:24.16,26.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:27.2,27.14 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:27.14,29.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:30.2,30.19 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:34.111,37.16 3 0 +make-backend/internal/gql/resolvers/group.resolvers.go:37.16,39.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:40.2,40.14 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:40.14,42.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:44.2,45.47 2 0 +make-backend/internal/gql/resolvers/group.resolvers.go:45.47,47.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:48.2,48.47 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:48.47,50.17 2 0 +make-backend/internal/gql/resolvers/group.resolvers.go:50.17,52.4 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:53.3,56.10 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:58.2,59.59 2 0 +make-backend/internal/gql/resolvers/group.resolvers.go:59.59,61.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:62.2,63.33 2 0 +make-backend/internal/gql/resolvers/group.resolvers.go:63.33,65.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:66.2,66.22 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:70.99,74.16 3 0 +make-backend/internal/gql/resolvers/group.resolvers.go:74.16,76.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:77.2,77.21 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:77.21,79.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:81.2,82.16 2 0 +make-backend/internal/gql/resolvers/group.resolvers.go:86.107,90.16 3 0 +make-backend/internal/gql/resolvers/group.resolvers.go:90.16,92.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:93.2,93.21 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:93.21,95.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:97.2,98.16 2 0 +make-backend/internal/gql/resolvers/group.resolvers.go:103.108,107.16 3 0 +make-backend/internal/gql/resolvers/group.resolvers.go:107.16,109.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:110.2,110.28 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:110.28,112.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:113.2,114.16 2 0 +make-backend/internal/gql/resolvers/group.resolvers.go:114.16,116.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:117.2,117.28 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:117.28,119.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:120.2,120.68 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:124.107,128.16 3 0 +make-backend/internal/gql/resolvers/group.resolvers.go:128.16,130.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:131.2,131.21 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:131.21,133.3 1 0 +make-backend/internal/gql/resolvers/group.resolvers.go:134.2,134.67 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:15.105,17.16 2 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:17.16,19.3 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:21.2,21.19 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:25.115,27.16 2 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:27.16,29.3 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:31.2,32.34 2 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:32.34,34.3 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:36.2,36.19 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:40.105,42.16 2 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:42.16,44.3 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:46.2,46.16 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:50.88,52.16 2 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:52.16,54.3 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:56.2,56.21 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:60.93,62.16 2 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:62.16,64.3 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:66.2,66.24 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:70.56,70.89 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:73.52,73.83 1 0 +make-backend/internal/gql/resolvers/makerspace.resolvers.go:76.46,76.74 1 0 +make-backend/internal/gql/resolvers/training.resolvers.go:16.112,17.57 1 0 +make-backend/internal/gql/resolvers/training.resolvers.go:21.110,23.2 1 0 +make-backend/internal/gql/resolvers/training.resolvers.go:26.70,28.2 1 0 +make-backend/internal/gql/resolvers/training.resolvers.go:31.52,31.83 1 0 +make-backend/internal/gql/resolvers/user.resolvers.go:16.81,17.51 1 0 +make-backend/internal/gql/resolvers/user.resolvers.go:21.80,26.2 3 0 +make-backend/internal/gql/resolvers/zones.resolvers.go:15.81,17.16 2 0 +make-backend/internal/gql/resolvers/zones.resolvers.go:17.16,19.3 1 0 +make-backend/internal/gql/resolvers/zones.resolvers.go:21.2,21.18 1 0 +make-backend/internal/gql/resolvers/zones.resolvers.go:25.108,26.81 1 0 diff --git a/internal/database/group_test.go b/internal/database/group_test.go index 4e2305c2..6b9d370d 100644 --- a/internal/database/group_test.go +++ b/internal/database/group_test.go @@ -243,7 +243,7 @@ func TestGroupMembership(t *testing.T) { if err != nil { t.Fatalf("couldn't find user with email '%s': %v", email, err) } - inGroup, err := store.Groups.IsUserInGroup(t.Context(), user.Id, localContext.beatlesMusicians.Id) + inGroup, _, err := store.Groups.IsUserInGroup(t.Context(), user.Id, localContext.beatlesMusicians.Id) if err != nil { t.Fatalf("couldn't check user in group for email '%s': %v", email, err) } @@ -269,7 +269,7 @@ func TestSubgroupMembership(t *testing.T) { if err != nil { t.Fatalf("couldn't find user with email '%s': %v", email, err) } - inGroup, err := store.Groups.IsUserInGroup(t.Context(), user.Id, localContext.brits.Id) + inGroup, _, err := store.Groups.IsUserInGroup(t.Context(), user.Id, localContext.brits.Id) if err != nil { t.Fatalf("couldn't check user in group for email '%s': %v", email, err) } diff --git a/internal/database/repos/group_repo.go b/internal/database/repos/group_repo.go index 5f910d96..1d4ef470 100644 --- a/internal/database/repos/group_repo.go +++ b/internal/database/repos/group_repo.go @@ -25,10 +25,10 @@ type GroupRepository interface { GetGroupMembers(ctx context.Context, groupId int) ([]models.MembershipToGroup, error) GetDirectGroupMembers(ctx context.Context, groupId int) ([]models.MembershipToGroup, error) - IsUserInGroup(ctx context.Context, userId int, groupId int) (bool, error) + IsUserInGroup(ctx context.Context, userId int, groupId int) (bool, models.GroupViewPermission, error) AllGroupsUserIsMemberOf(ctx context.Context, userId int) ([]models.MembershipToUser, error) - IsUserInGroupDirectly(ctx context.Context, userId int, groupId int) (bool, error) + IsUserInGroupDirectly(ctx context.Context, userId int, groupId int) (bool, models.GroupViewPermission, error) // add a user to a group AddUserToGroup(ctx context.Context, userId int, groupId int, perms models.GroupViewPermission) error // remove user from a group @@ -40,25 +40,44 @@ type GroupRepository interface { AllGroupsGroupCanManage(ctx context.Context, userId int) ([]int, error) AllGroupsVisibleToGroup(ctx context.Context, groupId int) ([]int, error) + IsGroupVisibleToGroup(ctx context.Context, lookingGroupId int, groupId int) (bool, error) AllGroupsUserCanManage(ctx context.Context, userId int) ([]int, error) AllGroupsUserVisibleToUser(ctx context.Context, userId int) ([]int, error) - IsGroupVisibleToUser(ctx context.Context, userId int, groupId int) (bool, models.GroupViewPermission, error) + IsGroupVisibleToUser(ctx context.Context, userId int, groupId int) (bool, error) } type GroupRepo struct { DB *sql.DB } -func (g *GroupRepo) IsGroupVisibleToUser(ctx context.Context, userId int, groupId int) (bool, models.GroupViewPermission, error) { +func (g *GroupRepo) IsGroupVisibleToUser(ctx context.Context, userId int, groupId int) (bool, error) { // if can manage -> see all canManage, err := g.CanUserManageGroup(ctx, userId, groupId) if err != nil { - return false, models.GroupViewPermission_SeeNone, fmt.Errorf("failed to check if group is visible to user: %w", err) - + return false, fmt.Errorf("failed to check if group is visible to user: %w", err) } if canManage { - return true, models.GroupViewPermission_SeeAll, nil + return true, nil + } + // TODO check if group is shared to group that user is in + + isInGroup, how, err := g.IsUserInGroup(ctx, userId, groupId) + if err != nil { + return false, fmt.Errorf("failed to check if group is visible to user: %w", err) + } + + if isInGroup { + switch how { + case models.GroupViewPermission_SeeAll: + return true, nil + case models.GroupViewPermission_SeeNone: + return false, nil + case models.GroupViewPermission_SeeSelf: + return true, nil + default: + return false, fmt.Errorf("invalid view permission: %v", how) + } } // if inside @@ -67,6 +86,22 @@ func (g *GroupRepo) IsGroupVisibleToUser(ctx context.Context, userId int, groupI // if see all -> true, see all panic("unimplemented") +} +func (g *GroupRepo) IsGroupVisibleToGroup(ctx context.Context, lookingGroupId int, groupId int) (bool, error) { + // if can manage -> see all + canManage, err := g.CanGroupManageGroup(ctx, lookingGroupId, groupId) + if err != nil { + return false, fmt.Errorf("failed to check if group is visible to group: %w", err) + } + if canManage { + return true, nil + } + + // if see none -> false, see none + // if see some -> true, see self + // if see all -> true, see all + panic("unimplemented") + } func (g *GroupRepo) AddSubgroupToGroup(ctx context.Context, subgroupID, supergroupID int, permissions models.GroupViewPermission) error { @@ -268,28 +303,29 @@ func (g *GroupRepo) CanUserManageGroup(ctx context.Context, managerUser int, man return exists, nil } -func (g *GroupRepo) IsUserInGroup(ctx context.Context, userId int, groupId int) (bool, error) { - var exists bool +func (g *GroupRepo) IsUserInGroup(ctx context.Context, userId int, groupId int) (bool, models.GroupViewPermission, error) { + var perms models.GroupViewPermission - query := "SELECT EXISTS(SELECT 1 FROM group_membership WHERE user_id = $1 and group_id = $2)" + query := "SELECT view_permission FROM group_membership WHERE user_id = $1 and group_id = $2" - err := g.DB.QueryRow(query, userId, groupId).Scan(&exists) + err := g.DB.QueryRow(query, userId, groupId).Scan(&perms) if err != nil { - return false, err + return false, models.GroupViewPermission_SeeNone, err } - return exists, nil + return true, perms, nil } -func (g *GroupRepo) IsUserInGroupDirectly(ctx context.Context, userId int, groupId int) (bool, error) { - var exists bool +func (g *GroupRepo) IsUserInGroupDirectly(ctx context.Context, userId int, groupId int) (bool, models.GroupViewPermission, error) { + var perms models.GroupViewPermission - query := "SELECT EXISTS(SELECT 1 FROM group_direct_membership WHERE user_id = $1 and group_id = $2)" + query := "SELECT view_permission FROM group_membership WHERE user_id = $1 and group_id = $2" - err := g.DB.QueryRow(query, userId, groupId).Scan(&exists) + err := g.DB.QueryRow(query, userId, groupId).Scan(&perms) if err != nil { - return false, err + return false, models.GroupViewPermission_SeeNone, err } - return exists, nil + return true, perms, nil + } func (g *GroupRepo) GetAdminGroupId(ctx context.Context) (int, error) { diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index 9a20771b..718c3347 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -20,11 +20,11 @@ func (r *queryResolver) GroupByID(ctx context.Context, id int) (*models.Group, e if err != nil { return nil, err } - visible, how, err := r.Store.Groups.IsGroupVisibleToUser(ctx, userID, group.Id) + visible, err := r.Store.Groups.IsGroupVisibleToUser(ctx, userID, group.Id) if err != nil { return nil, err } - if !visible || how != models.GroupViewPermission_SeeAll { + if !visible { return nil, fmt.Errorf("group does not exist or user does not have permission to see it") } return group, nil @@ -32,17 +32,21 @@ func (r *queryResolver) GroupByID(ctx context.Context, id int) (*models.Group, e // MembersOfGroup is the resolver for the membersOfGroup field. func (r *queryResolver) MembersOfGroup(ctx context.Context, groupID int) ([]*models.MembershipToGroup, error) { - userID := ctx.Value(auth.UserContextKey{}).(int) - visible, how, err := r.Store.Groups.IsGroupVisibleToUser(ctx, userID, groupID) + askingUserID := ctx.Value(auth.UserContextKey{}).(int) + visible, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) if err != nil { return nil, err } - if !visible || how == models.GroupViewPermission_SeeNone { + if !visible { return nil, fmt.Errorf("group does not exist or user does not have permission to see it") } + _, how, err := r.Store.Groups.IsUserInGroup(ctx, askingUserID, groupID) + if how == models.GroupViewPermission_SeeNone { + return nil, fmt.Errorf("group does not exist or user does not have permission to see it") + } if how == models.GroupViewPermission_SeeSelf { - user, err := r.Store.Users.GetUserById(ctx, userID) + user, err := r.Store.Users.GetUserById(ctx, askingUserID) if err != nil { return nil, fmt.Errorf("could not find querying user %w", err) } @@ -66,30 +70,32 @@ func (r *queryResolver) MembersOfGroup(ctx context.Context, groupID int) ([]*mod func (r *queryResolver) IsUserInGroup(ctx context.Context, userID int, groupID int) (bool, error) { askingUserID := ctx.Value(auth.UserContextKey{}).(int) - visibleToAsker, howToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) + visibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) if err != nil { return false, err } - if !visibleToAsker || howToAsker == models.GroupViewPermission_SeeNone { + if !visibleToAsker { return false, fmt.Errorf("group does not exist or user has invalid permissions to query it") } - return r.Store.Groups.IsUserInGroup(ctx, userID, groupID) + in, _, err := r.Store.Groups.IsUserInGroup(ctx, userID, groupID) + return in, err } // IsUserInGroupDirectly is the resolver for the isUserInGroupDirectly field. func (r *queryResolver) IsUserInGroupDirectly(ctx context.Context, userID int, groupID int) (bool, error) { askingUserID := ctx.Value(auth.UserContextKey{}).(int) - visibleToAsker, howToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) + visibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) if err != nil { return false, err } - if !visibleToAsker || howToAsker == models.GroupViewPermission_SeeNone { + if !visibleToAsker { return false, fmt.Errorf("group does not exist or user has invalid permissions to query it") } - return r.Store.Groups.IsUserInGroupDirectly(ctx, userID, groupID) + in, _, err := r.Store.Groups.IsUserInGroupDirectly(ctx, userID, groupID) + return in, err } @@ -97,14 +103,14 @@ func (r *queryResolver) IsUserInGroupDirectly(ctx context.Context, userID int, g func (r *queryResolver) CanGroupManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) { askingUserID := ctx.Value(auth.UserContextKey{}).(int) - managerVisibleToAsker, _, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, managerID) + managerVisibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, managerID) if err != nil { return false, err } if !managerVisibleToAsker { return false, fmt.Errorf("manager group does not exist or user has invalid permissions to query it") } - managedVisibleToAsker, _, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) + managedVisibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) if err != nil { return false, err } @@ -118,7 +124,7 @@ func (r *queryResolver) CanGroupManageGroup(ctx context.Context, managerID int, func (r *queryResolver) CanUserManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) { askingUserID := ctx.Value(auth.UserContextKey{}).(int) - visibleToAsker, _, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) + visibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) if err != nil { return false, err } diff --git a/internal/logging/audit_log.go b/internal/logging/audit_log.go index c992dde7..d6af2d4c 100644 --- a/internal/logging/audit_log.go +++ b/internal/logging/audit_log.go @@ -78,7 +78,7 @@ func dataForEntities(fmtString string, entities []models.LogEntity) map[string]a locations := auditLogRegex.FindAllString(fmtString, -1) for i, entityType := range locations { - if i > len(entities) { + if i >= len(entities) { slog.Warn("Invalid audit log format string - too many specifiers without entities", "num_specifiers", len(locations), "num_entities", len(entities)) break } @@ -101,11 +101,8 @@ func dataForEntities(fmtString string, entities []models.LogEntity) map[string]a func CreatePlainString(fmtString string, entities ...models.LogEntity) string { index := 0 replacer := func(s string) string { - if len(s) > 2 { - s = s[1 : len(s)-1] - } var entity models.LogEntity - if index > len(entities) { + if index >= len(entities) { entity = models.LogEntity{Id: -1, Label: "unknown"} } else { entity = entities[index] @@ -124,7 +121,7 @@ func CreateFormatString(fmtString string, entities ...models.LogEntity) string { s = s[1 : len(s)-1] } var entity models.LogEntity - if index > len(entities) { + if index >= len(entities) { entity = models.LogEntity{Id: -1, Label: "unknown"} } else { entity = entities[index] diff --git a/internal/logging/audit_log_test.go b/internal/logging/audit_log_test.go index 34d91e0c..d1122147 100644 --- a/internal/logging/audit_log_test.go +++ b/internal/logging/audit_log_test.go @@ -80,3 +80,26 @@ func TestJsonDataGenerationMultipleSame(t *testing.T) { } } + +func TestMoreSpacesThanEntitiesFormat(t *testing.T) { + // should log a warning but still work and not crash + str := CreateFormatString("{user} elevated {user}", user1.LogEntity()) + ref := "{user:0:John Doe} elevated {user:-1:unknown}" + if str != ref { + t.Errorf("reference and created string don't agree. Wanted `%s` got `%s`", str, ref) + } +} + +func TestMoreSpacesThanEntitiesPlain(t *testing.T) { + // should log a warning but still work and not crash + str := CreatePlainString("{user} elevated {user}", user1.LogEntity()) + ref := "John Doe elevated unknown" + if str != ref { + t.Errorf("reference and created string don't agree. Wanted `%s` got `%s`", str, ref) + } +} + +func TestMoreSpacesThanEntitiesData(t *testing.T) { + // should log a warning but still work and not crash + _ = dataForEntities("{user} elevated {user}", []models.LogEntity{user1.LogEntity()}) +} From 6c5ecffa04f2d4b726d9f4479f4dd7ac156e4e4d Mon Sep 17 00:00:00 2001 From: cowsed Date: Mon, 10 Aug 2026 12:10:14 -0400 Subject: [PATCH 06/22] moved test stuff around --- coverage.out | 3966 ------------------------------- internal/database/group_test.go | 216 +- internal/database/mock_data.go | 225 ++ internal/database/setup.go | 4 + 4 files changed, 232 insertions(+), 4179 deletions(-) delete mode 100644 coverage.out create mode 100644 internal/database/mock_data.go diff --git a/coverage.out b/coverage.out deleted file mode 100644 index af58a88c..00000000 --- a/coverage.out +++ /dev/null @@ -1,3966 +0,0 @@ -mode: set -make-backend/internal/database/setup.go:13.33,15.16 2 0 -make-backend/internal/database/setup.go:15.16,17.3 1 0 -make-backend/internal/database/setup.go:18.2,19.16 2 0 -make-backend/internal/database/setup.go:19.16,21.3 1 0 -make-backend/internal/database/setup.go:22.2,22.16 1 0 -make-backend/internal/database/setup.go:25.34,32.16 4 0 -make-backend/internal/database/setup.go:32.16,34.3 1 0 -make-backend/internal/database/setup.go:36.2,36.34 1 0 -make-backend/internal/database/setup.go:36.34,38.3 1 0 -make-backend/internal/database/setup.go:40.2,40.16 1 0 -make-backend/internal/database/setup.go:43.34,47.53 3 0 -make-backend/internal/database/setup.go:47.53,49.3 1 0 -make-backend/internal/database/setup.go:51.2,51.51 1 0 -make-backend/internal/database/setup.go:51.51,53.3 1 0 -make-backend/internal/database/setup.go:54.2,54.12 1 0 -make-backend/internal/database/store.go:22.34,32.2 1 1 -make-backend/cmd/migrate/down.go:12.13,16.16 3 0 -make-backend/cmd/migrate/down.go:16.16,18.3 1 0 -make-backend/cmd/migrate/down.go:19.2,22.53 3 0 -make-backend/cmd/migrate/down.go:22.53,24.3 1 0 -make-backend/cmd/migrate/down.go:26.2,26.53 1 0 -make-backend/cmd/migrate/down.go:26.53,28.3 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:18.84,20.2 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:22.77,24.9 2 0 -make-backend/internal/api/acs/acs_orchestrator.go:24.9,26.3 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:27.2,27.12 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:30.113,31.24 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:34.85,35.24 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:37.84,38.24 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:41.128,42.24 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:45.107,47.16 2 0 -make-backend/internal/api/acs/acs_orchestrator.go:47.16,50.3 2 0 -make-backend/internal/api/acs/acs_orchestrator.go:51.2,57.25 2 0 -make-backend/internal/api/acs/acs_orchestrator.go:57.25,60.3 2 0 -make-backend/internal/api/acs/acs_orchestrator.go:60.8,61.25 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:66.90,67.24 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:70.116,71.24 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:74.110,75.24 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:78.96,79.24 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:82.100,83.24 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:86.76,87.24 1 0 -make-backend/internal/api/acs/acs_orchestrator.go:90.101,91.24 1 0 -make-backend/cmd/make-backend/main.go:35.13,43.2 5 0 -make-backend/cmd/make-backend/main.go:48.13,52.12 4 0 -make-backend/cmd/make-backend/main.go:52.12,55.3 2 0 -make-backend/cmd/make-backend/main.go:57.2,58.16 2 0 -make-backend/cmd/make-backend/main.go:58.16,60.3 1 0 -make-backend/cmd/make-backend/main.go:63.2,64.16 2 0 -make-backend/cmd/make-backend/main.go:64.16,66.3 1 0 -make-backend/cmd/make-backend/main.go:67.2,84.31 13 0 -make-backend/cmd/make-backend/main.go:88.74,95.58 5 0 -make-backend/cmd/make-backend/main.go:95.58,96.45 1 0 -make-backend/cmd/make-backend/main.go:96.45,99.4 2 0 -make-backend/cmd/make-backend/main.go:99.9,102.4 2 0 -make-backend/cmd/make-backend/main.go:104.2,106.12 2 0 -make-backend/cmd/make-backend/main.go:106.12,108.3 1 0 -make-backend/cmd/make-backend/main.go:110.2,110.15 1 0 -make-backend/cmd/make-backend/main.go:114.98,158.12 23 0 -make-backend/cmd/make-backend/main.go:158.12,160.3 1 0 -make-backend/cmd/make-backend/main.go:162.2,162.15 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:39.32,41.2 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:44.42,49.2 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:52.83,53.91 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:53.91,55.3 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:57.2,59.16 3 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:59.16,62.3 2 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:63.2,64.16 2 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:64.16,67.3 2 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:68.2,68.11 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:72.79,74.69 2 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:74.69,76.12 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:76.12,78.4 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:78.9,80.4 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:84.2,85.11 2 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:85.11,87.3 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:87.8,89.3 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:91.2,91.11 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:99.35,101.2 1 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:105.73,109.21 2 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:109.21,112.3 2 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:113.2,113.45 1 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:113.45,115.3 1 0 -make-backend/internal/api/acs/acs-mqtt/auth.go:116.2,116.38 1 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:116.38,117.27 1 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:117.27,119.12 1 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:121.3,121.28 1 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:121.28,124.4 1 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:126.2,126.46 1 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:129.76,131.31 2 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:131.31,133.15 2 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:133.15,134.12 1 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:136.3,136.20 1 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:136.20,138.4 1 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:138.9,140.4 1 1 -make-backend/internal/api/acs/acs-mqtt/auth.go:144.2,144.14 1 1 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:24.147,33.2 2 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:35.43,37.2 1 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:39.76,41.16 2 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:41.16,43.3 1 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:44.2,45.16 2 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:45.16,47.3 1 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:48.2,48.12 1 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:51.122,54.16 3 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:54.16,57.3 2 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:58.2,58.13 1 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:61.107,65.16 3 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:65.16,68.3 2 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:69.2,69.13 1 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:72.123,75.16 3 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:75.16,78.3 2 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:79.2,79.13 1 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:82.118,85.16 3 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:85.16,88.3 2 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:89.2,89.13 1 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:92.100,96.16 3 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:96.16,99.3 2 0 -make-backend/internal/api/acs/acs-mqtt/mqtt_controller.go:100.2,100.13 1 0 -make-backend/internal/api/acs/acs-mqtt/server.go:24.37,26.2 1 0 -make-backend/internal/api/acs/acs-mqtt/server.go:28.104,39.32 3 0 -make-backend/internal/api/acs/acs-mqtt/server.go:39.32,41.3 1 0 -make-backend/internal/api/acs/acs-mqtt/server.go:41.8,43.3 1 0 -make-backend/internal/api/acs/acs-mqtt/server.go:44.2,44.26 1 0 -make-backend/internal/api/acs/acs-mqtt/server.go:44.26,46.3 1 0 -make-backend/internal/api/acs/acs-mqtt/server.go:48.2,53.16 4 0 -make-backend/internal/api/acs/acs-mqtt/server.go:53.16,55.3 1 0 -make-backend/internal/api/acs/acs-mqtt/server.go:57.2,58.89 2 0 -make-backend/internal/logging/audit_log.go:16.117,22.16 5 0 -make-backend/internal/logging/audit_log.go:22.16,24.3 1 0 -make-backend/internal/logging/audit_log.go:27.111,33.16 5 0 -make-backend/internal/logging/audit_log.go:33.16,35.3 1 0 -make-backend/internal/logging/audit_log.go:38.146,43.16 4 0 -make-backend/internal/logging/audit_log.go:43.16,45.3 1 0 -make-backend/internal/logging/audit_log.go:47.140,52.16 4 0 -make-backend/internal/logging/audit_log.go:52.16,54.3 1 0 -make-backend/internal/logging/audit_log.go:60.96,61.24 1 1 -make-backend/internal/logging/audit_log.go:61.24,65.3 3 1 -make-backend/internal/logging/audit_log.go:66.2,66.34 1 1 -make-backend/internal/logging/audit_log.go:66.34,69.3 2 1 -make-backend/internal/logging/audit_log.go:76.84,80.39 3 1 -make-backend/internal/logging/audit_log.go:80.39,81.25 1 1 -make-backend/internal/logging/audit_log.go:81.25,83.9 2 1 -make-backend/internal/logging/audit_log.go:85.3,85.26 1 1 -make-backend/internal/logging/audit_log.go:85.26,87.4 1 1 -make-backend/internal/logging/audit_log.go:89.3,89.65 1 1 -make-backend/internal/logging/audit_log.go:92.2,93.50 2 1 -make-backend/internal/logging/audit_log.go:93.50,95.3 1 1 -make-backend/internal/logging/audit_log.go:96.2,96.13 1 1 -make-backend/internal/logging/audit_log.go:101.79,103.36 2 1 -make-backend/internal/logging/audit_log.go:103.36,105.29 2 1 -make-backend/internal/logging/audit_log.go:105.29,107.4 1 1 -make-backend/internal/logging/audit_log.go:107.9,109.4 1 1 -make-backend/internal/logging/audit_log.go:110.3,111.22 2 1 -make-backend/internal/logging/audit_log.go:113.2,113.64 1 1 -make-backend/internal/logging/audit_log.go:117.80,119.36 2 1 -make-backend/internal/logging/audit_log.go:119.36,120.17 1 1 -make-backend/internal/logging/audit_log.go:120.17,122.4 1 1 -make-backend/internal/logging/audit_log.go:123.3,124.29 2 1 -make-backend/internal/logging/audit_log.go:124.29,126.4 1 1 -make-backend/internal/logging/audit_log.go:126.9,128.4 1 1 -make-backend/internal/logging/audit_log.go:129.3,130.63 2 1 -make-backend/internal/logging/audit_log.go:132.2,132.64 1 1 -make-backend/internal/logging/logger.go:10.47,15.2 1 0 -make-backend/internal/gql/directives/directives.go:12.72,14.9 2 0 -make-backend/internal/gql/directives/directives.go:14.9,16.3 1 0 -make-backend/internal/gql/directives/directives.go:18.2,19.16 2 0 -make-backend/internal/gql/directives/directives.go:19.16,21.3 1 0 -make-backend/internal/gql/directives/directives.go:23.2,23.24 1 0 -make-backend/internal/gql/directives/directives.go:26.74,28.9 2 0 -make-backend/internal/gql/directives/directives.go:28.9,30.3 1 0 -make-backend/internal/gql/directives/directives.go:32.2,33.16 2 0 -make-backend/internal/gql/directives/directives.go:33.16,35.3 1 0 -make-backend/internal/gql/directives/directives.go:37.2,37.21 1 0 -make-backend/internal/gql/directives/directives.go:40.72,42.9 2 0 -make-backend/internal/gql/directives/directives.go:42.9,44.3 1 0 -make-backend/internal/gql/directives/directives.go:46.2,47.16 2 0 -make-backend/internal/gql/directives/directives.go:47.16,49.3 1 0 -make-backend/internal/gql/directives/directives.go:51.2,51.19 1 0 -make-backend/internal/gql/directives/directives.go:54.74,56.9 2 0 -make-backend/internal/gql/directives/directives.go:56.9,58.3 1 0 -make-backend/internal/gql/directives/directives.go:60.2,61.16 2 0 -make-backend/internal/gql/directives/directives.go:61.16,63.3 1 0 -make-backend/internal/gql/directives/directives.go:65.2,65.21 1 0 -make-backend/internal/gql/directives/directives.go:68.48,70.15 2 0 -make-backend/internal/gql/directives/directives.go:70.15,72.3 1 0 -make-backend/internal/gql/directives/directives.go:74.2,75.9 2 0 -make-backend/internal/gql/directives/directives.go:75.9,77.3 1 0 -make-backend/internal/gql/directives/directives.go:79.2,80.9 2 0 -make-backend/internal/gql/directives/directives.go:80.9,82.3 1 0 -make-backend/internal/gql/directives/directives.go:84.2,84.34 1 0 -make-backend/internal/gql/directives/directives.go:87.77,89.15 2 0 -make-backend/internal/gql/directives/directives.go:89.15,91.3 1 0 -make-backend/internal/gql/directives/directives.go:93.2,94.9 2 0 -make-backend/internal/gql/directives/directives.go:94.9,96.3 1 0 -make-backend/internal/gql/directives/directives.go:98.2,99.9 2 0 -make-backend/internal/gql/directives/directives.go:99.9,101.3 1 0 -make-backend/internal/gql/directives/directives.go:103.2,104.16 2 0 -make-backend/internal/gql/directives/directives.go:104.16,106.3 1 0 -make-backend/internal/gql/directives/directives.go:108.2,108.24 1 0 -make-backend/internal/gql/directives/directives.go:111.75,113.15 2 0 -make-backend/internal/gql/directives/directives.go:113.15,115.3 1 0 -make-backend/internal/gql/directives/directives.go:117.2,118.9 2 0 -make-backend/internal/gql/directives/directives.go:118.9,120.3 1 0 -make-backend/internal/gql/directives/directives.go:122.2,123.9 2 0 -make-backend/internal/gql/directives/directives.go:123.9,125.3 1 0 -make-backend/internal/gql/directives/directives.go:127.2,128.16 2 0 -make-backend/internal/gql/directives/directives.go:128.16,130.3 1 0 -make-backend/internal/gql/directives/directives.go:132.2,132.22 1 0 -make-backend/internal/gql/directives/directives.go:135.77,137.15 2 0 -make-backend/internal/gql/directives/directives.go:137.15,139.3 1 0 -make-backend/internal/gql/directives/directives.go:141.2,142.9 2 0 -make-backend/internal/gql/directives/directives.go:142.9,144.3 1 0 -make-backend/internal/gql/directives/directives.go:146.2,147.9 2 0 -make-backend/internal/gql/directives/directives.go:147.9,149.3 1 0 -make-backend/internal/gql/directives/directives.go:151.2,152.16 2 0 -make-backend/internal/gql/directives/directives.go:152.16,154.3 1 0 -make-backend/internal/gql/directives/directives.go:156.2,156.24 1 0 -make-backend/internal/gql/directives/directives.go:159.65,160.101 1 0 -make-backend/internal/gql/directives/directives.go:160.101,162.17 2 0 -make-backend/internal/gql/directives/directives.go:162.17,164.4 1 0 -make-backend/internal/gql/directives/directives.go:166.3,166.12 1 0 -make-backend/internal/gql/directives/directives.go:166.12,168.4 1 0 -make-backend/internal/gql/directives/directives.go:168.9,170.4 1 0 -make-backend/internal/gql/directives/directives.go:173.2,173.103 1 0 -make-backend/internal/gql/directives/directives.go:173.103,175.17 2 0 -make-backend/internal/gql/directives/directives.go:175.17,177.4 1 0 -make-backend/internal/gql/directives/directives.go:179.3,179.14 1 0 -make-backend/internal/gql/directives/directives.go:179.14,181.4 1 0 -make-backend/internal/gql/directives/directives.go:181.9,183.4 1 0 -make-backend/internal/gql/directives/directives.go:186.2,186.101 1 0 -make-backend/internal/gql/directives/directives.go:186.101,188.17 2 0 -make-backend/internal/gql/directives/directives.go:188.17,190.4 1 0 -make-backend/internal/gql/directives/directives.go:192.3,192.12 1 0 -make-backend/internal/gql/directives/directives.go:192.12,194.4 1 0 -make-backend/internal/gql/directives/directives.go:194.9,196.4 1 0 -make-backend/internal/gql/directives/directives.go:199.2,199.103 1 0 -make-backend/internal/gql/directives/directives.go:199.103,201.17 2 0 -make-backend/internal/gql/directives/directives.go:201.17,203.4 1 0 -make-backend/internal/gql/directives/directives.go:205.3,205.14 1 0 -make-backend/internal/gql/directives/directives.go:205.14,207.4 1 0 -make-backend/internal/gql/directives/directives.go:207.9,209.4 1 0 -make-backend/internal/gql/directives/directives.go:212.2,212.100 1 0 -make-backend/internal/gql/directives/directives.go:212.100,214.17 2 0 -make-backend/internal/gql/directives/directives.go:214.17,216.4 1 0 -make-backend/internal/gql/directives/directives.go:218.3,218.11 1 0 -make-backend/internal/gql/directives/directives.go:218.11,220.4 1 0 -make-backend/internal/gql/directives/directives.go:220.9,222.4 1 0 -make-backend/internal/gql/directives/directives.go:225.2,225.106 1 0 -make-backend/internal/gql/directives/directives.go:225.106,227.17 2 0 -make-backend/internal/gql/directives/directives.go:227.17,229.4 1 0 -make-backend/internal/gql/directives/directives.go:231.3,231.17 1 0 -make-backend/internal/gql/directives/directives.go:231.17,233.4 1 0 -make-backend/internal/gql/directives/directives.go:233.9,235.4 1 0 -make-backend/internal/gql/directives/directives.go:238.2,238.104 1 0 -make-backend/internal/gql/directives/directives.go:238.104,240.17 2 0 -make-backend/internal/gql/directives/directives.go:240.17,242.4 1 0 -make-backend/internal/gql/directives/directives.go:244.3,244.15 1 0 -make-backend/internal/gql/directives/directives.go:244.15,246.4 1 0 -make-backend/internal/gql/directives/directives.go:246.9,248.4 1 0 -make-backend/internal/gql/directives/directives.go:251.2,251.106 1 0 -make-backend/internal/gql/directives/directives.go:251.106,253.17 2 0 -make-backend/internal/gql/directives/directives.go:253.17,255.4 1 0 -make-backend/internal/gql/directives/directives.go:257.3,257.17 1 0 -make-backend/internal/gql/directives/directives.go:257.17,259.4 1 0 -make-backend/internal/gql/directives/directives.go:259.9,261.4 1 0 -make-backend/internal/gql/directives/directives.go:264.2,264.107 1 0 -make-backend/internal/gql/directives/directives.go:264.107,266.17 2 0 -make-backend/internal/gql/directives/directives.go:266.17,268.4 1 0 -make-backend/internal/gql/directives/directives.go:270.3,271.17 2 0 -make-backend/internal/gql/directives/directives.go:271.17,273.4 1 0 -make-backend/internal/gql/directives/directives.go:275.3,275.20 1 0 -make-backend/internal/gql/directives/directives.go:275.20,277.4 1 0 -make-backend/internal/gql/directives/directives.go:277.9,279.4 1 0 -make-backend/internal/api/rest/api.go:5.44,7.2 0 0 -make-backend/internal/auth/middleware.go:12.96,13.71 1 0 -make-backend/internal/auth/middleware.go:13.71,17.17 2 0 -make-backend/internal/auth/middleware.go:17.17,20.4 2 0 -make-backend/internal/auth/middleware.go:22.3,22.23 1 0 -make-backend/internal/auth/saml.go:20.96,23.18 3 0 -make-backend/internal/auth/saml.go:23.18,25.3 1 0 -make-backend/internal/auth/saml.go:26.2,26.17 1 0 -make-backend/internal/auth/saml.go:26.17,28.3 1 0 -make-backend/internal/auth/saml.go:30.2,31.16 2 0 -make-backend/internal/auth/saml.go:31.16,33.3 1 0 -make-backend/internal/auth/saml.go:35.2,36.16 2 0 -make-backend/internal/auth/saml.go:36.16,38.3 1 0 -make-backend/internal/auth/saml.go:40.2,41.16 2 0 -make-backend/internal/auth/saml.go:41.16,43.3 1 0 -make-backend/internal/auth/saml.go:45.2,46.16 2 0 -make-backend/internal/auth/saml.go:46.16,48.3 1 0 -make-backend/internal/auth/saml.go:50.2,51.20 2 0 -make-backend/internal/auth/saml.go:51.20,53.3 1 0 -make-backend/internal/auth/saml.go:55.2,56.16 2 0 -make-backend/internal/auth/saml.go:56.16,58.3 1 0 -make-backend/internal/auth/saml.go:60.2,69.16 3 0 -make-backend/internal/auth/saml.go:69.16,71.3 1 0 -make-backend/internal/auth/saml.go:73.2,78.15 2 0 -make-backend/internal/auth/saml.go:86.116,90.16 3 0 -make-backend/internal/auth/saml.go:90.16,92.3 1 0 -make-backend/internal/auth/saml.go:94.2,96.12 2 0 -make-backend/internal/auth/saml.go:99.89,101.2 1 0 -make-backend/internal/auth/saml.go:105.81,106.53 1 0 -make-backend/internal/auth/saml.go:106.53,108.3 1 0 -make-backend/internal/auth/saml.go:110.2,110.33 1 0 -make-backend/internal/auth/sessions.go:10.52,16.2 3 0 -make-backend/internal/database/models/device.go:31.39,36.2 1 0 -make-backend/internal/database/models/device.go:38.62,40.16 2 0 -make-backend/internal/database/models/device.go:40.16,42.3 1 0 -make-backend/internal/database/models/device.go:43.2,43.31 1 0 -make-backend/internal/database/models/device.go:48.60,52.2 3 0 -make-backend/internal/database/models/device.go:54.49,57.25 2 0 -make-backend/internal/database/models/device.go:57.25,59.3 1 0 -make-backend/internal/database/models/device.go:62.2,64.16 3 0 -make-backend/internal/database/models/device.go:64.16,66.3 1 0 -make-backend/internal/database/models/device.go:69.2,79.16 7 0 -make-backend/internal/database/models/device.go:79.16,81.3 1 0 -make-backend/internal/database/models/device.go:84.2,92.43 5 0 -make-backend/internal/database/models/device.go:101.51,102.18 1 0 -make-backend/internal/database/models/device.go:102.18,105.3 2 0 -make-backend/internal/database/models/device.go:107.2,108.9 2 0 -make-backend/internal/database/models/device.go:108.9,110.3 1 0 -make-backend/internal/database/models/device.go:112.2,112.33 1 0 -make-backend/internal/database/models/device.go:115.58,117.2 1 0 -make-backend/internal/database/models/device.go:143.50,144.18 1 0 -make-backend/internal/database/models/device.go:144.18,146.3 1 0 -make-backend/internal/database/models/device.go:148.2,149.9 2 0 -make-backend/internal/database/models/device.go:149.9,151.3 1 0 -make-backend/internal/database/models/device.go:153.2,153.33 1 0 -make-backend/internal/database/models/device.go:156.57,158.2 1 0 -make-backend/internal/database/models/equipment.go:21.42,26.2 1 0 -make-backend/internal/database/models/equipment.go:35.50,40.2 1 0 -make-backend/internal/database/models/group.go:56.54,58.11 2 0 -make-backend/internal/database/models/group.go:59.34,60.16 1 0 -make-backend/internal/database/models/group.go:61.35,62.17 1 0 -make-backend/internal/database/models/group.go:63.35,64.17 1 0 -make-backend/internal/database/models/group.go:65.10,66.9 1 0 -make-backend/internal/database/models/group.go:68.2,68.35 1 0 -make-backend/internal/database/models/group.go:71.65,73.9 2 0 -make-backend/internal/database/models/group.go:73.9,75.3 1 0 -make-backend/internal/database/models/group.go:76.2,76.13 1 0 -make-backend/internal/database/models/group.go:77.17,78.34 1 0 -make-backend/internal/database/models/group.go:79.18,80.35 1 0 -make-backend/internal/database/models/group.go:81.18,82.35 1 0 -make-backend/internal/database/models/group.go:83.10,84.66 1 0 -make-backend/internal/database/models/group.go:86.2,86.12 1 0 -make-backend/internal/database/models/hours.go:17.42,17.43 0 0 -make-backend/internal/database/models/hours.go:27.42,27.43 0 0 -make-backend/internal/database/models/makerspace.go:14.43,19.2 1 0 -make-backend/internal/database/models/training.go:20.37,20.38 0 0 -make-backend/internal/database/models/training.go:21.37,21.38 0 0 -make-backend/internal/database/models/training.go:29.38,29.39 0 0 -make-backend/internal/database/models/training.go:30.38,30.39 0 0 -make-backend/internal/database/models/training.go:46.39,46.40 0 0 -make-backend/internal/database/models/training.go:47.37,48.27 1 0 -make-backend/internal/database/models/training.go:48.27,50.3 1 0 -make-backend/internal/database/models/training.go:62.44,62.45 0 0 -make-backend/internal/database/models/training.go:63.42,65.2 1 0 -make-backend/internal/database/models/training.go:70.65,72.60 2 0 -make-backend/internal/database/models/training.go:72.60,74.3 1 0 -make-backend/internal/database/models/training.go:76.2,78.35 2 0 -make-backend/internal/database/models/training.go:78.35,82.60 2 0 -make-backend/internal/database/models/training.go:82.60,84.4 1 0 -make-backend/internal/database/models/training.go:86.3,87.28 2 0 -make-backend/internal/database/models/training.go:88.15,90.50 2 0 -make-backend/internal/database/models/training.go:90.50,92.5 1 0 -make-backend/internal/database/models/training.go:93.4,93.14 1 0 -make-backend/internal/database/models/training.go:95.16,97.50 2 0 -make-backend/internal/database/models/training.go:97.50,99.5 1 0 -make-backend/internal/database/models/training.go:100.4,100.14 1 0 -make-backend/internal/database/models/training.go:102.40,104.50 2 0 -make-backend/internal/database/models/training.go:104.50,106.5 1 0 -make-backend/internal/database/models/training.go:107.4,107.14 1 0 -make-backend/internal/database/models/training.go:109.23,111.50 2 0 -make-backend/internal/database/models/training.go:111.50,113.5 1 0 -make-backend/internal/database/models/training.go:114.4,114.14 1 0 -make-backend/internal/database/models/training.go:116.11,117.74 1 0 -make-backend/internal/database/models/training.go:120.3,120.31 1 0 -make-backend/internal/database/models/training.go:123.2,123.12 1 0 -make-backend/internal/database/models/training.go:133.51,135.9 2 0 -make-backend/internal/database/models/training.go:135.9,137.3 1 0 -make-backend/internal/database/models/training.go:139.2,139.33 1 0 -make-backend/internal/database/models/user.go:24.33,26.2 1 0 -make-backend/internal/database/models/user.go:27.37,29.2 1 0 -make-backend/internal/database/repos/audit_log_repo.go:30.48,32.2 1 0 -make-backend/internal/database/repos/audit_log_repo.go:44.175,48.16 3 0 -make-backend/internal/database/repos/audit_log_repo.go:48.16,50.3 1 0 -make-backend/internal/database/repos/audit_log_repo.go:52.2,55.16 3 0 -make-backend/internal/database/repos/audit_log_repo.go:55.16,57.3 1 0 -make-backend/internal/database/repos/audit_log_repo.go:59.2,59.23 1 0 -make-backend/internal/database/repos/audit_log_repo.go:62.121,65.38 3 0 -make-backend/internal/database/repos/audit_log_repo.go:65.38,68.3 2 0 -make-backend/internal/database/repos/audit_log_repo.go:69.2,75.65 2 0 -make-backend/internal/database/repos/audit_log_repo.go:75.65,78.3 1 0 -make-backend/internal/database/repos/audit_log_repo.go:78.8,78.71 1 0 -make-backend/internal/database/repos/audit_log_repo.go:78.71,81.3 2 0 -make-backend/internal/database/repos/audit_log_repo.go:81.8,85.33 3 0 -make-backend/internal/database/repos/audit_log_repo.go:85.33,87.4 1 0 -make-backend/internal/database/repos/audit_log_repo.go:88.3,89.52 2 0 -make-backend/internal/database/repos/audit_log_repo.go:92.2,92.35 1 0 -make-backend/internal/database/repos/audit_log_repo.go:92.35,96.3 3 0 -make-backend/internal/database/repos/audit_log_repo.go:97.2,97.33 1 0 -make-backend/internal/database/repos/audit_log_repo.go:97.33,101.3 3 0 -make-backend/internal/database/repos/audit_log_repo.go:103.2,109.27 2 0 -make-backend/internal/database/repos/audit_log_repo.go:109.27,110.22 1 0 -make-backend/internal/database/repos/audit_log_repo.go:110.22,112.4 1 0 -make-backend/internal/database/repos/audit_log_repo.go:112.9,112.28 1 0 -make-backend/internal/database/repos/audit_log_repo.go:112.28,117.4 3 0 -make-backend/internal/database/repos/audit_log_repo.go:120.2,120.29 1 0 -make-backend/internal/database/repos/audit_log_repo.go:120.29,125.3 4 0 -make-backend/internal/database/repos/audit_log_repo.go:127.2,132.16 4 0 -make-backend/internal/database/repos/audit_log_repo.go:132.16,134.3 1 0 -make-backend/internal/database/repos/audit_log_repo.go:135.2,136.18 2 0 -make-backend/internal/database/repos/audit_log_repo.go:136.18,147.17 3 0 -make-backend/internal/database/repos/audit_log_repo.go:147.17,149.4 1 0 -make-backend/internal/database/repos/audit_log_repo.go:150.3,150.27 1 0 -make-backend/internal/database/repos/audit_log_repo.go:153.2,153.35 1 0 -make-backend/internal/database/repos/audit_log_repo.go:153.35,155.3 1 0 -make-backend/internal/database/repos/audit_log_repo.go:157.2,157.18 1 0 -make-backend/internal/database/repos/device_repo.go:22.89,49.16 4 0 -make-backend/internal/database/repos/device_repo.go:49.16,51.3 1 0 -make-backend/internal/database/repos/device_repo.go:53.2,53.31 1 0 -make-backend/internal/database/repos/device_repo.go:56.92,83.16 4 0 -make-backend/internal/database/repos/device_repo.go:83.16,85.3 1 0 -make-backend/internal/database/repos/device_repo.go:87.2,87.31 1 0 -make-backend/internal/database/repos/device_repo.go:90.101,136.16 4 0 -make-backend/internal/database/repos/device_repo.go:136.16,138.3 1 0 -make-backend/internal/database/repos/device_repo.go:140.2,140.28 1 0 -make-backend/internal/database/repos/device_repo.go:143.142,155.16 4 0 -make-backend/internal/database/repos/device_repo.go:155.16,157.3 1 0 -make-backend/internal/database/repos/device_repo.go:159.2,159.36 1 0 -make-backend/internal/database/repos/device_repo.go:162.122,193.16 4 0 -make-backend/internal/database/repos/device_repo.go:193.16,195.3 1 0 -make-backend/internal/database/repos/device_repo.go:197.2,197.35 1 0 -make-backend/internal/database/repos/device_repo.go:200.157,219.16 4 0 -make-backend/internal/database/repos/device_repo.go:219.16,221.3 1 0 -make-backend/internal/database/repos/device_repo.go:223.2,223.28 1 0 -make-backend/internal/database/repos/equipment_repo.go:17.98,56.16 4 0 -make-backend/internal/database/repos/equipment_repo.go:56.16,58.3 1 0 -make-backend/internal/database/repos/equipment_repo.go:60.2,60.31 1 0 -make-backend/internal/database/repos/group_repo.go:54.102,57.16 2 0 -make-backend/internal/database/repos/group_repo.go:57.16,59.3 1 0 -make-backend/internal/database/repos/group_repo.go:60.2,60.15 1 0 -make-backend/internal/database/repos/group_repo.go:60.15,62.3 1 0 -make-backend/internal/database/repos/group_repo.go:65.2,66.16 2 0 -make-backend/internal/database/repos/group_repo.go:66.16,68.3 1 0 -make-backend/internal/database/repos/group_repo.go:70.2,70.15 1 0 -make-backend/internal/database/repos/group_repo.go:70.15,71.14 1 0 -make-backend/internal/database/repos/group_repo.go:72.42,73.20 1 0 -make-backend/internal/database/repos/group_repo.go:74.43,75.21 1 0 -make-backend/internal/database/repos/group_repo.go:76.43,77.20 1 0 -make-backend/internal/database/repos/group_repo.go:78.11,79.64 1 0 -make-backend/internal/database/repos/group_repo.go:87.2,87.24 1 0 -make-backend/internal/database/repos/group_repo.go:90.111,93.16 2 0 -make-backend/internal/database/repos/group_repo.go:93.16,95.3 1 0 -make-backend/internal/database/repos/group_repo.go:96.2,96.15 1 0 -make-backend/internal/database/repos/group_repo.go:96.15,98.3 1 0 -make-backend/internal/database/repos/group_repo.go:103.2,103.24 1 0 -make-backend/internal/database/repos/group_repo.go:107.137,111.16 3 0 -make-backend/internal/database/repos/group_repo.go:111.16,113.3 1 0 -make-backend/internal/database/repos/group_repo.go:115.2,115.12 1 0 -make-backend/internal/database/repos/group_repo.go:118.105,122.16 3 0 -make-backend/internal/database/repos/group_repo.go:122.16,124.3 1 0 -make-backend/internal/database/repos/group_repo.go:126.2,127.18 2 0 -make-backend/internal/database/repos/group_repo.go:127.18,134.17 4 0 -make-backend/internal/database/repos/group_repo.go:134.17,136.4 1 0 -make-backend/internal/database/repos/group_repo.go:137.3,137.30 1 0 -make-backend/internal/database/repos/group_repo.go:140.2,140.35 1 0 -make-backend/internal/database/repos/group_repo.go:140.35,142.3 1 0 -make-backend/internal/database/repos/group_repo.go:144.2,144.19 1 0 -make-backend/internal/database/repos/group_repo.go:149.99,154.16 3 0 -make-backend/internal/database/repos/group_repo.go:154.16,156.3 1 0 -make-backend/internal/database/repos/group_repo.go:158.2,159.18 2 0 -make-backend/internal/database/repos/group_repo.go:159.18,166.17 4 0 -make-backend/internal/database/repos/group_repo.go:166.17,168.4 1 0 -make-backend/internal/database/repos/group_repo.go:169.3,169.30 1 0 -make-backend/internal/database/repos/group_repo.go:172.2,172.35 1 0 -make-backend/internal/database/repos/group_repo.go:172.35,174.3 1 0 -make-backend/internal/database/repos/group_repo.go:176.2,176.19 1 0 -make-backend/internal/database/repos/group_repo.go:181.96,185.16 3 0 -make-backend/internal/database/repos/group_repo.go:185.16,187.3 1 0 -make-backend/internal/database/repos/group_repo.go:188.2,191.18 3 0 -make-backend/internal/database/repos/group_repo.go:191.18,194.17 3 0 -make-backend/internal/database/repos/group_repo.go:194.17,196.4 1 0 -make-backend/internal/database/repos/group_repo.go:197.3,197.33 1 0 -make-backend/internal/database/repos/group_repo.go:200.2,200.35 1 0 -make-backend/internal/database/repos/group_repo.go:200.35,202.3 1 0 -make-backend/internal/database/repos/group_repo.go:203.2,203.20 1 0 -make-backend/internal/database/repos/group_repo.go:207.92,215.16 3 0 -make-backend/internal/database/repos/group_repo.go:215.16,217.3 1 0 -make-backend/internal/database/repos/group_repo.go:218.2,221.18 3 0 -make-backend/internal/database/repos/group_repo.go:221.18,224.17 3 0 -make-backend/internal/database/repos/group_repo.go:224.17,226.4 1 0 -make-backend/internal/database/repos/group_repo.go:227.3,227.33 1 0 -make-backend/internal/database/repos/group_repo.go:230.2,230.35 1 0 -make-backend/internal/database/repos/group_repo.go:230.35,232.3 1 0 -make-backend/internal/database/repos/group_repo.go:233.2,233.20 1 0 -make-backend/internal/database/repos/group_repo.go:236.113,240.16 3 0 -make-backend/internal/database/repos/group_repo.go:240.16,242.3 1 0 -make-backend/internal/database/repos/group_repo.go:243.2,246.18 3 0 -make-backend/internal/database/repos/group_repo.go:246.18,252.17 3 0 -make-backend/internal/database/repos/group_repo.go:252.17,254.4 1 0 -make-backend/internal/database/repos/group_repo.go:255.3,255.33 1 0 -make-backend/internal/database/repos/group_repo.go:258.2,258.35 1 0 -make-backend/internal/database/repos/group_repo.go:258.35,260.3 1 0 -make-backend/internal/database/repos/group_repo.go:262.2,262.20 1 0 -make-backend/internal/database/repos/group_repo.go:267.96,268.24 1 0 -make-backend/internal/database/repos/group_repo.go:272.94,273.24 1 0 -make-backend/internal/database/repos/group_repo.go:277.112,283.16 4 0 -make-backend/internal/database/repos/group_repo.go:283.16,285.3 1 0 -make-backend/internal/database/repos/group_repo.go:286.2,286.20 1 0 -make-backend/internal/database/repos/group_repo.go:289.110,300.16 4 0 -make-backend/internal/database/repos/group_repo.go:300.16,302.3 1 0 -make-backend/internal/database/repos/group_repo.go:303.2,303.20 1 0 -make-backend/internal/database/repos/group_repo.go:306.123,312.16 4 0 -make-backend/internal/database/repos/group_repo.go:312.16,314.3 1 0 -make-backend/internal/database/repos/group_repo.go:315.2,315.25 1 0 -make-backend/internal/database/repos/group_repo.go:318.131,324.16 4 0 -make-backend/internal/database/repos/group_repo.go:324.16,326.3 1 0 -make-backend/internal/database/repos/group_repo.go:327.2,327.25 1 0 -make-backend/internal/database/repos/group_repo.go:331.71,338.16 4 0 -make-backend/internal/database/repos/group_repo.go:338.16,340.3 1 0 -make-backend/internal/database/repos/group_repo.go:342.2,342.23 1 0 -make-backend/internal/database/repos/group_repo.go:345.96,351.16 4 0 -make-backend/internal/database/repos/group_repo.go:351.16,353.3 1 0 -make-backend/internal/database/repos/group_repo.go:355.2,355.20 1 0 -make-backend/internal/database/repos/group_repo.go:358.96,364.16 4 0 -make-backend/internal/database/repos/group_repo.go:364.16,366.3 1 0 -make-backend/internal/database/repos/group_repo.go:368.2,368.20 1 0 -make-backend/internal/database/repos/group_repo.go:372.86,389.16 5 0 -make-backend/internal/database/repos/group_repo.go:389.16,391.3 1 0 -make-backend/internal/database/repos/group_repo.go:392.2,392.22 1 0 -make-backend/internal/database/repos/group_repo.go:392.22,395.3 1 0 -make-backend/internal/database/repos/group_repo.go:395.8,397.3 1 0 -make-backend/internal/database/repos/group_repo.go:399.2,399.21 1 0 -make-backend/internal/database/repos/group_repo.go:403.128,408.16 3 0 -make-backend/internal/database/repos/group_repo.go:408.16,410.3 1 0 -make-backend/internal/database/repos/group_repo.go:412.2,412.12 1 0 -make-backend/internal/database/repos/group_repo.go:415.107,419.16 3 0 -make-backend/internal/database/repos/group_repo.go:419.16,421.3 1 0 -make-backend/internal/database/repos/group_repo.go:423.2,424.18 2 0 -make-backend/internal/database/repos/group_repo.go:424.18,430.17 3 0 -make-backend/internal/database/repos/group_repo.go:430.17,432.4 1 0 -make-backend/internal/database/repos/group_repo.go:433.3,433.36 1 0 -make-backend/internal/database/repos/group_repo.go:436.2,436.35 1 0 -make-backend/internal/database/repos/group_repo.go:436.35,438.3 1 0 -make-backend/internal/database/repos/group_repo.go:440.2,440.21 1 0 -make-backend/internal/database/repos/group_repo.go:444.113,448.16 3 0 -make-backend/internal/database/repos/group_repo.go:448.16,450.3 1 0 -make-backend/internal/database/repos/group_repo.go:452.2,453.18 2 0 -make-backend/internal/database/repos/group_repo.go:453.18,459.17 3 0 -make-backend/internal/database/repos/group_repo.go:459.17,461.4 1 0 -make-backend/internal/database/repos/group_repo.go:462.3,462.36 1 0 -make-backend/internal/database/repos/group_repo.go:465.2,465.35 1 0 -make-backend/internal/database/repos/group_repo.go:465.35,467.3 1 0 -make-backend/internal/database/repos/group_repo.go:469.2,469.21 1 0 -make-backend/internal/database/repos/group_repo.go:472.101,475.16 3 0 -make-backend/internal/database/repos/group_repo.go:475.16,477.3 1 0 -make-backend/internal/database/repos/group_repo.go:478.2,479.16 2 0 -make-backend/internal/database/repos/group_repo.go:479.16,481.3 1 0 -make-backend/internal/database/repos/group_repo.go:482.2,482.21 1 0 -make-backend/internal/database/repos/image_repo.go:17.86,27.16 4 0 -make-backend/internal/database/repos/image_repo.go:27.16,29.3 1 0 -make-backend/internal/database/repos/image_repo.go:31.2,31.27 1 0 -make-backend/internal/database/repos/makerspace_repo.go:23.101,49.16 4 0 -make-backend/internal/database/repos/makerspace_repo.go:49.16,51.3 1 0 -make-backend/internal/database/repos/makerspace_repo.go:53.2,53.32 1 0 -make-backend/internal/database/repos/makerspace_repo.go:56.103,62.16 4 0 -make-backend/internal/database/repos/makerspace_repo.go:62.16,64.3 1 0 -make-backend/internal/database/repos/makerspace_repo.go:66.2,66.23 1 0 -make-backend/internal/database/repos/makerspace_repo.go:69.86,73.16 3 0 -make-backend/internal/database/repos/makerspace_repo.go:73.16,75.3 1 0 -make-backend/internal/database/repos/makerspace_repo.go:77.2,77.18 1 0 -make-backend/internal/database/repos/makerspace_repo.go:80.96,84.16 3 0 -make-backend/internal/database/repos/makerspace_repo.go:84.16,86.3 1 0 -make-backend/internal/database/repos/makerspace_repo.go:88.2,88.12 1 0 -make-backend/internal/database/repos/makerspace_repo.go:91.94,95.16 3 0 -make-backend/internal/database/repos/makerspace_repo.go:95.16,97.3 1 0 -make-backend/internal/database/repos/makerspace_repo.go:99.2,99.12 1 0 -make-backend/internal/database/repos/makerspace_repo.go:102.102,121.16 3 0 -make-backend/internal/database/repos/makerspace_repo.go:121.16,123.3 1 0 -make-backend/internal/database/repos/makerspace_repo.go:124.2,127.18 3 0 -make-backend/internal/database/repos/makerspace_repo.go:127.18,144.17 3 0 -make-backend/internal/database/repos/makerspace_repo.go:144.17,146.4 1 0 -make-backend/internal/database/repos/makerspace_repo.go:148.3,148.31 1 0 -make-backend/internal/database/repos/makerspace_repo.go:151.2,151.35 1 0 -make-backend/internal/database/repos/makerspace_repo.go:151.35,153.3 1 0 -make-backend/internal/database/repos/makerspace_repo.go:155.2,155.19 1 0 -make-backend/internal/database/repos/makerspace_repo.go:158.114,169.16 3 0 -make-backend/internal/database/repos/makerspace_repo.go:169.16,171.3 1 0 -make-backend/internal/database/repos/makerspace_repo.go:172.2,175.18 3 0 -make-backend/internal/database/repos/makerspace_repo.go:175.18,186.17 3 0 -make-backend/internal/database/repos/makerspace_repo.go:186.17,188.4 1 0 -make-backend/internal/database/repos/makerspace_repo.go:190.3,190.55 1 0 -make-backend/internal/database/repos/makerspace_repo.go:193.2,193.35 1 0 -make-backend/internal/database/repos/makerspace_repo.go:193.35,195.3 1 0 -make-backend/internal/database/repos/makerspace_repo.go:197.2,197.27 1 0 -make-backend/internal/database/repos/user_repo.go:25.83,58.16 4 0 -make-backend/internal/database/repos/user_repo.go:58.16,60.3 1 0 -make-backend/internal/database/repos/user_repo.go:62.2,62.26 1 0 -make-backend/internal/database/repos/user_repo.go:65.92,98.16 4 0 -make-backend/internal/database/repos/user_repo.go:98.16,100.3 1 0 -make-backend/internal/database/repos/user_repo.go:102.2,102.26 1 0 -make-backend/internal/database/repos/user_repo.go:105.79,111.16 4 0 -make-backend/internal/database/repos/user_repo.go:111.16,113.3 1 0 -make-backend/internal/database/repos/user_repo.go:115.2,115.20 1 0 -make-backend/internal/database/repos/user_repo.go:118.73,124.16 4 0 -make-backend/internal/database/repos/user_repo.go:124.16,126.3 1 0 -make-backend/internal/database/repos/user_repo.go:128.2,128.23 1 0 -make-backend/internal/database/repos/user_repo.go:131.71,137.16 4 0 -make-backend/internal/database/repos/user_repo.go:137.16,139.3 1 0 -make-backend/internal/database/repos/user_repo.go:141.2,141.21 1 0 -make-backend/internal/database/repos/user_repo.go:144.73,150.16 4 0 -make-backend/internal/database/repos/user_repo.go:150.16,152.3 1 0 -make-backend/internal/database/repos/user_repo.go:154.2,154.23 1 0 -make-backend/internal/database/repos/user_repo.go:157.100,163.16 4 0 -make-backend/internal/database/repos/user_repo.go:163.16,165.3 1 0 -make-backend/internal/database/repos/user_repo.go:167.2,167.23 1 0 -make-backend/internal/database/repos/user_repo.go:170.98,176.16 4 0 -make-backend/internal/database/repos/user_repo.go:176.16,178.3 1 0 -make-backend/internal/database/repos/user_repo.go:180.2,180.21 1 0 -make-backend/internal/database/repos/user_repo.go:183.99,189.16 4 0 -make-backend/internal/database/repos/user_repo.go:189.16,191.3 1 0 -make-backend/internal/database/repos/user_repo.go:193.2,193.23 1 0 -make-backend/internal/database/repos/zone_repo.go:18.83,36.16 4 0 -make-backend/internal/database/repos/zone_repo.go:36.16,38.3 1 0 -make-backend/internal/database/repos/zone_repo.go:40.2,40.26 1 0 -make-backend/internal/database/repos/zone_repo.go:43.106,47.16 3 0 -make-backend/internal/database/repos/zone_repo.go:47.16,49.3 1 0 -make-backend/internal/database/repos/zone_repo.go:50.2,54.18 3 0 -make-backend/internal/database/repos/zone_repo.go:54.18,58.17 3 0 -make-backend/internal/database/repos/zone_repo.go:58.17,60.4 1 0 -make-backend/internal/database/repos/zone_repo.go:62.3,62.31 1 0 -make-backend/internal/database/repos/zone_repo.go:65.2,65.34 1 0 -make-backend/internal/database/repos/zone_repo.go:65.34,67.3 1 0 -make-backend/internal/database/repos/zone_repo.go:69.2,69.19 1 0 -make-backend/internal/gql/scalars/clock_time.go:11.54,12.46 1 0 -make-backend/internal/gql/scalars/clock_time.go:12.46,14.3 1 0 -make-backend/internal/gql/scalars/clock_time.go:17.51,19.9 2 0 -make-backend/internal/gql/scalars/clock_time.go:19.9,21.3 1 0 -make-backend/internal/gql/scalars/clock_time.go:23.2,23.36 1 0 -make-backend/internal/gql/scalars/date.go:11.49,12.46 1 0 -make-backend/internal/gql/scalars/date.go:12.46,14.3 1 0 -make-backend/internal/gql/scalars/date.go:17.46,19.9 2 0 -make-backend/internal/gql/scalars/date.go:19.9,21.3 1 0 -make-backend/internal/gql/scalars/date.go:23.2,23.38 1 0 -make-backend/internal/gql/generated.go:27.63,29.2 1 0 -make-backend/internal/gql/generated.go:366.49,367.25 1 0 -make-backend/internal/gql/generated.go:367.25,369.3 1 0 -make-backend/internal/gql/generated.go:370.2,370.21 1 0 -make-backend/internal/gql/generated.go:373.141,376.32 3 0 -make-backend/internal/gql/generated.go:378.34,379.54 1 0 -make-backend/internal/gql/generated.go:379.54,380.9 1 0 -make-backend/internal/gql/generated.go:383.3,383.73 1 0 -make-backend/internal/gql/generated.go:384.33,385.53 1 0 -make-backend/internal/gql/generated.go:385.53,386.9 1 0 -make-backend/internal/gql/generated.go:389.3,389.72 1 0 -make-backend/internal/gql/generated.go:390.26,391.47 1 0 -make-backend/internal/gql/generated.go:391.47,392.9 1 0 -make-backend/internal/gql/generated.go:395.3,395.66 1 0 -make-backend/internal/gql/generated.go:396.29,397.50 1 0 -make-backend/internal/gql/generated.go:397.50,398.9 1 0 -make-backend/internal/gql/generated.go:401.3,401.69 1 0 -make-backend/internal/gql/generated.go:402.37,403.57 1 0 -make-backend/internal/gql/generated.go:403.57,404.9 1 0 -make-backend/internal/gql/generated.go:407.3,407.76 1 0 -make-backend/internal/gql/generated.go:409.34,410.55 1 0 -make-backend/internal/gql/generated.go:410.55,411.9 1 0 -make-backend/internal/gql/generated.go:414.3,414.74 1 0 -make-backend/internal/gql/generated.go:415.28,416.49 1 0 -make-backend/internal/gql/generated.go:416.49,417.9 1 0 -make-backend/internal/gql/generated.go:420.3,420.68 1 0 -make-backend/internal/gql/generated.go:421.30,422.51 1 0 -make-backend/internal/gql/generated.go:422.51,423.9 1 0 -make-backend/internal/gql/generated.go:426.3,426.70 1 0 -make-backend/internal/gql/generated.go:428.37,429.58 1 0 -make-backend/internal/gql/generated.go:429.58,430.9 1 0 -make-backend/internal/gql/generated.go:433.3,433.77 1 0 -make-backend/internal/gql/generated.go:434.29,435.50 1 0 -make-backend/internal/gql/generated.go:435.50,436.9 1 0 -make-backend/internal/gql/generated.go:439.3,439.69 1 0 -make-backend/internal/gql/generated.go:441.31,442.52 1 0 -make-backend/internal/gql/generated.go:442.52,443.9 1 0 -make-backend/internal/gql/generated.go:446.3,446.71 1 0 -make-backend/internal/gql/generated.go:447.39,448.58 1 0 -make-backend/internal/gql/generated.go:448.58,449.9 1 0 -make-backend/internal/gql/generated.go:452.3,452.77 1 0 -make-backend/internal/gql/generated.go:453.29,454.50 1 0 -make-backend/internal/gql/generated.go:454.50,455.9 1 0 -make-backend/internal/gql/generated.go:458.3,458.69 1 0 -make-backend/internal/gql/generated.go:459.28,460.49 1 0 -make-backend/internal/gql/generated.go:460.49,461.9 1 0 -make-backend/internal/gql/generated.go:464.3,464.68 1 0 -make-backend/internal/gql/generated.go:465.34,466.54 1 0 -make-backend/internal/gql/generated.go:466.54,467.9 1 0 -make-backend/internal/gql/generated.go:470.3,470.73 1 0 -make-backend/internal/gql/generated.go:471.42,472.62 1 0 -make-backend/internal/gql/generated.go:472.62,473.9 1 0 -make-backend/internal/gql/generated.go:476.3,476.81 1 0 -make-backend/internal/gql/generated.go:477.40,478.60 1 0 -make-backend/internal/gql/generated.go:478.60,479.9 1 0 -make-backend/internal/gql/generated.go:482.3,482.79 1 0 -make-backend/internal/gql/generated.go:483.36,484.56 1 0 -make-backend/internal/gql/generated.go:484.56,485.9 1 0 -make-backend/internal/gql/generated.go:488.3,488.75 1 0 -make-backend/internal/gql/generated.go:489.36,490.56 1 0 -make-backend/internal/gql/generated.go:490.56,491.9 1 0 -make-backend/internal/gql/generated.go:494.3,494.75 1 0 -make-backend/internal/gql/generated.go:496.42,497.61 1 0 -make-backend/internal/gql/generated.go:497.61,498.9 1 0 -make-backend/internal/gql/generated.go:501.3,501.80 1 0 -make-backend/internal/gql/generated.go:502.47,503.66 1 0 -make-backend/internal/gql/generated.go:503.66,504.9 1 0 -make-backend/internal/gql/generated.go:507.3,507.85 1 0 -make-backend/internal/gql/generated.go:508.37,509.58 1 0 -make-backend/internal/gql/generated.go:509.58,510.9 1 0 -make-backend/internal/gql/generated.go:513.3,513.77 1 0 -make-backend/internal/gql/generated.go:515.27,516.48 1 0 -make-backend/internal/gql/generated.go:516.48,517.9 1 0 -make-backend/internal/gql/generated.go:520.3,520.67 1 0 -make-backend/internal/gql/generated.go:521.25,522.46 1 0 -make-backend/internal/gql/generated.go:522.46,523.9 1 0 -make-backend/internal/gql/generated.go:526.3,526.65 1 0 -make-backend/internal/gql/generated.go:527.36,528.56 1 0 -make-backend/internal/gql/generated.go:528.56,529.9 1 0 -make-backend/internal/gql/generated.go:532.3,532.75 1 0 -make-backend/internal/gql/generated.go:533.28,534.49 1 0 -make-backend/internal/gql/generated.go:534.49,535.9 1 0 -make-backend/internal/gql/generated.go:538.3,538.68 1 0 -make-backend/internal/gql/generated.go:540.29,541.49 1 0 -make-backend/internal/gql/generated.go:541.49,542.9 1 0 -make-backend/internal/gql/generated.go:545.3,545.68 1 0 -make-backend/internal/gql/generated.go:546.30,547.50 1 0 -make-backend/internal/gql/generated.go:547.50,548.9 1 0 -make-backend/internal/gql/generated.go:551.3,551.69 1 0 -make-backend/internal/gql/generated.go:553.33,554.53 1 0 -make-backend/internal/gql/generated.go:554.53,555.9 1 0 -make-backend/internal/gql/generated.go:558.3,558.72 1 0 -make-backend/internal/gql/generated.go:559.29,560.50 1 0 -make-backend/internal/gql/generated.go:560.50,561.9 1 0 -make-backend/internal/gql/generated.go:564.3,564.69 1 0 -make-backend/internal/gql/generated.go:565.34,566.53 1 0 -make-backend/internal/gql/generated.go:566.53,567.9 1 0 -make-backend/internal/gql/generated.go:570.3,570.72 1 0 -make-backend/internal/gql/generated.go:571.36,572.56 1 0 -make-backend/internal/gql/generated.go:572.56,573.9 1 0 -make-backend/internal/gql/generated.go:576.3,576.75 1 0 -make-backend/internal/gql/generated.go:577.32,578.52 1 0 -make-backend/internal/gql/generated.go:578.52,579.9 1 0 -make-backend/internal/gql/generated.go:582.3,582.71 1 0 -make-backend/internal/gql/generated.go:584.25,585.46 1 0 -make-backend/internal/gql/generated.go:585.46,586.9 1 0 -make-backend/internal/gql/generated.go:589.3,589.65 1 0 -make-backend/internal/gql/generated.go:590.25,591.46 1 0 -make-backend/internal/gql/generated.go:591.46,592.9 1 0 -make-backend/internal/gql/generated.go:595.3,595.65 1 0 -make-backend/internal/gql/generated.go:596.19,597.40 1 0 -make-backend/internal/gql/generated.go:597.40,598.9 1 0 -make-backend/internal/gql/generated.go:601.3,601.59 1 0 -make-backend/internal/gql/generated.go:602.26,603.46 1 0 -make-backend/internal/gql/generated.go:603.46,604.9 1 0 -make-backend/internal/gql/generated.go:607.3,607.65 1 0 -make-backend/internal/gql/generated.go:608.30,609.50 1 0 -make-backend/internal/gql/generated.go:609.50,610.9 1 0 -make-backend/internal/gql/generated.go:613.3,613.69 1 0 -make-backend/internal/gql/generated.go:614.21,615.42 1 0 -make-backend/internal/gql/generated.go:615.42,616.9 1 0 -make-backend/internal/gql/generated.go:619.3,619.61 1 0 -make-backend/internal/gql/generated.go:620.23,621.44 1 0 -make-backend/internal/gql/generated.go:621.44,622.9 1 0 -make-backend/internal/gql/generated.go:625.3,625.63 1 0 -make-backend/internal/gql/generated.go:626.19,627.40 1 0 -make-backend/internal/gql/generated.go:627.40,628.9 1 0 -make-backend/internal/gql/generated.go:631.3,631.59 1 0 -make-backend/internal/gql/generated.go:632.32,633.52 1 0 -make-backend/internal/gql/generated.go:633.52,634.9 1 0 -make-backend/internal/gql/generated.go:637.3,637.71 1 0 -make-backend/internal/gql/generated.go:639.30,640.50 1 0 -make-backend/internal/gql/generated.go:640.50,641.9 1 0 -make-backend/internal/gql/generated.go:644.3,644.69 1 0 -make-backend/internal/gql/generated.go:645.29,646.49 1 0 -make-backend/internal/gql/generated.go:646.49,647.9 1 0 -make-backend/internal/gql/generated.go:650.3,650.68 1 0 -make-backend/internal/gql/generated.go:651.25,652.46 1 0 -make-backend/internal/gql/generated.go:652.46,653.9 1 0 -make-backend/internal/gql/generated.go:656.3,656.65 1 0 -make-backend/internal/gql/generated.go:658.31,659.52 1 0 -make-backend/internal/gql/generated.go:659.52,660.9 1 0 -make-backend/internal/gql/generated.go:663.3,663.71 1 0 -make-backend/internal/gql/generated.go:664.26,665.47 1 0 -make-backend/internal/gql/generated.go:665.47,666.9 1 0 -make-backend/internal/gql/generated.go:669.3,669.66 1 0 -make-backend/internal/gql/generated.go:670.22,671.43 1 0 -make-backend/internal/gql/generated.go:671.43,672.9 1 0 -make-backend/internal/gql/generated.go:675.3,675.62 1 0 -make-backend/internal/gql/generated.go:676.28,677.48 1 0 -make-backend/internal/gql/generated.go:677.48,678.9 1 0 -make-backend/internal/gql/generated.go:681.3,681.67 1 0 -make-backend/internal/gql/generated.go:682.24,683.45 1 0 -make-backend/internal/gql/generated.go:683.45,684.9 1 0 -make-backend/internal/gql/generated.go:687.3,687.64 1 0 -make-backend/internal/gql/generated.go:688.33,689.53 1 0 -make-backend/internal/gql/generated.go:689.53,690.9 1 0 -make-backend/internal/gql/generated.go:693.3,693.72 1 0 -make-backend/internal/gql/generated.go:694.38,695.57 1 0 -make-backend/internal/gql/generated.go:695.57,696.9 1 0 -make-backend/internal/gql/generated.go:699.3,699.76 1 0 -make-backend/internal/gql/generated.go:700.36,701.56 1 0 -make-backend/internal/gql/generated.go:701.56,702.9 1 0 -make-backend/internal/gql/generated.go:705.3,705.75 1 0 -make-backend/internal/gql/generated.go:706.30,707.51 1 0 -make-backend/internal/gql/generated.go:707.51,708.9 1 0 -make-backend/internal/gql/generated.go:711.3,711.70 1 0 -make-backend/internal/gql/generated.go:712.44,713.64 1 0 -make-backend/internal/gql/generated.go:713.64,714.9 1 0 -make-backend/internal/gql/generated.go:717.3,717.83 1 0 -make-backend/internal/gql/generated.go:718.36,719.56 1 0 -make-backend/internal/gql/generated.go:719.56,720.9 1 0 -make-backend/internal/gql/generated.go:723.3,723.75 1 0 -make-backend/internal/gql/generated.go:724.32,725.51 1 0 -make-backend/internal/gql/generated.go:725.51,726.9 1 0 -make-backend/internal/gql/generated.go:729.3,729.70 1 0 -make-backend/internal/gql/generated.go:730.27,731.47 1 0 -make-backend/internal/gql/generated.go:731.47,732.9 1 0 -make-backend/internal/gql/generated.go:735.3,735.66 1 0 -make-backend/internal/gql/generated.go:736.28,737.48 1 0 -make-backend/internal/gql/generated.go:737.48,738.9 1 0 -make-backend/internal/gql/generated.go:741.3,741.67 1 0 -make-backend/internal/gql/generated.go:742.27,743.47 1 0 -make-backend/internal/gql/generated.go:743.47,744.9 1 0 -make-backend/internal/gql/generated.go:747.3,747.66 1 0 -make-backend/internal/gql/generated.go:749.45,750.64 1 0 -make-backend/internal/gql/generated.go:750.64,751.9 1 0 -make-backend/internal/gql/generated.go:754.3,754.83 1 0 -make-backend/internal/gql/generated.go:755.40,756.60 1 0 -make-backend/internal/gql/generated.go:756.60,757.9 1 0 -make-backend/internal/gql/generated.go:760.3,760.79 1 0 -make-backend/internal/gql/generated.go:761.30,762.51 1 0 -make-backend/internal/gql/generated.go:762.51,763.9 1 0 -make-backend/internal/gql/generated.go:766.3,766.70 1 0 -make-backend/internal/gql/generated.go:767.32,768.53 1 0 -make-backend/internal/gql/generated.go:768.53,769.9 1 0 -make-backend/internal/gql/generated.go:772.3,772.72 1 0 -make-backend/internal/gql/generated.go:774.27,775.48 1 0 -make-backend/internal/gql/generated.go:775.48,776.9 1 0 -make-backend/internal/gql/generated.go:779.3,779.67 1 0 -make-backend/internal/gql/generated.go:780.18,781.39 1 0 -make-backend/internal/gql/generated.go:781.39,782.9 1 0 -make-backend/internal/gql/generated.go:785.3,785.58 1 0 -make-backend/internal/gql/generated.go:786.26,787.46 1 0 -make-backend/internal/gql/generated.go:787.46,788.9 1 0 -make-backend/internal/gql/generated.go:791.3,791.65 1 0 -make-backend/internal/gql/generated.go:792.20,793.41 1 0 -make-backend/internal/gql/generated.go:793.41,794.9 1 0 -make-backend/internal/gql/generated.go:797.3,797.60 1 0 -make-backend/internal/gql/generated.go:799.26,800.46 1 0 -make-backend/internal/gql/generated.go:800.46,801.9 1 0 -make-backend/internal/gql/generated.go:804.3,804.65 1 0 -make-backend/internal/gql/generated.go:805.25,806.45 1 0 -make-backend/internal/gql/generated.go:806.45,807.9 1 0 -make-backend/internal/gql/generated.go:810.3,810.64 1 0 -make-backend/internal/gql/generated.go:811.17,812.38 1 0 -make-backend/internal/gql/generated.go:812.38,813.9 1 0 -make-backend/internal/gql/generated.go:816.3,816.57 1 0 -make-backend/internal/gql/generated.go:817.21,818.42 1 0 -make-backend/internal/gql/generated.go:818.42,819.9 1 0 -make-backend/internal/gql/generated.go:822.3,822.61 1 0 -make-backend/internal/gql/generated.go:823.26,824.46 1 0 -make-backend/internal/gql/generated.go:824.46,825.9 1 0 -make-backend/internal/gql/generated.go:828.3,828.65 1 0 -make-backend/internal/gql/generated.go:829.25,830.45 1 0 -make-backend/internal/gql/generated.go:830.45,831.9 1 0 -make-backend/internal/gql/generated.go:834.3,834.64 1 0 -make-backend/internal/gql/generated.go:835.24,836.44 1 0 -make-backend/internal/gql/generated.go:836.44,837.9 1 0 -make-backend/internal/gql/generated.go:840.3,840.63 1 0 -make-backend/internal/gql/generated.go:842.18,843.39 1 0 -make-backend/internal/gql/generated.go:843.39,844.9 1 0 -make-backend/internal/gql/generated.go:847.3,847.58 1 0 -make-backend/internal/gql/generated.go:848.26,849.47 1 0 -make-backend/internal/gql/generated.go:849.47,850.9 1 0 -make-backend/internal/gql/generated.go:853.3,853.66 1 0 -make-backend/internal/gql/generated.go:855.29,856.49 1 0 -make-backend/internal/gql/generated.go:856.49,857.9 1 0 -make-backend/internal/gql/generated.go:860.3,860.68 1 0 -make-backend/internal/gql/generated.go:861.28,862.49 1 0 -make-backend/internal/gql/generated.go:862.49,863.9 1 0 -make-backend/internal/gql/generated.go:866.3,866.68 1 0 -make-backend/internal/gql/generated.go:867.25,868.46 1 0 -make-backend/internal/gql/generated.go:868.46,869.9 1 0 -make-backend/internal/gql/generated.go:872.3,872.65 1 0 -make-backend/internal/gql/generated.go:874.32,875.53 1 0 -make-backend/internal/gql/generated.go:875.53,876.9 1 0 -make-backend/internal/gql/generated.go:879.3,879.72 1 0 -make-backend/internal/gql/generated.go:880.29,881.49 1 0 -make-backend/internal/gql/generated.go:881.49,882.9 1 0 -make-backend/internal/gql/generated.go:885.3,885.68 1 0 -make-backend/internal/gql/generated.go:886.27,887.48 1 0 -make-backend/internal/gql/generated.go:887.48,888.9 1 0 -make-backend/internal/gql/generated.go:891.3,891.67 1 0 -make-backend/internal/gql/generated.go:892.26,893.47 1 0 -make-backend/internal/gql/generated.go:893.47,894.9 1 0 -make-backend/internal/gql/generated.go:897.3,897.66 1 0 -make-backend/internal/gql/generated.go:898.23,899.44 1 0 -make-backend/internal/gql/generated.go:899.44,900.9 1 0 -make-backend/internal/gql/generated.go:903.3,903.63 1 0 -make-backend/internal/gql/generated.go:904.29,905.49 1 0 -make-backend/internal/gql/generated.go:905.49,906.9 1 0 -make-backend/internal/gql/generated.go:909.3,909.68 1 0 -make-backend/internal/gql/generated.go:910.25,911.46 1 0 -make-backend/internal/gql/generated.go:911.46,912.9 1 0 -make-backend/internal/gql/generated.go:915.3,915.65 1 0 -make-backend/internal/gql/generated.go:916.29,917.50 1 0 -make-backend/internal/gql/generated.go:917.50,918.9 1 0 -make-backend/internal/gql/generated.go:921.3,921.69 1 0 -make-backend/internal/gql/generated.go:922.29,923.50 1 0 -make-backend/internal/gql/generated.go:923.50,924.9 1 0 -make-backend/internal/gql/generated.go:927.3,927.69 1 0 -make-backend/internal/gql/generated.go:928.26,929.47 1 0 -make-backend/internal/gql/generated.go:929.47,930.9 1 0 -make-backend/internal/gql/generated.go:933.3,933.66 1 0 -make-backend/internal/gql/generated.go:935.34,936.55 1 0 -make-backend/internal/gql/generated.go:936.55,937.9 1 0 -make-backend/internal/gql/generated.go:940.3,940.74 1 0 -make-backend/internal/gql/generated.go:941.42,942.63 1 0 -make-backend/internal/gql/generated.go:942.63,943.9 1 0 -make-backend/internal/gql/generated.go:946.3,946.82 1 0 -make-backend/internal/gql/generated.go:948.35,949.56 1 0 -make-backend/internal/gql/generated.go:949.56,950.9 1 0 -make-backend/internal/gql/generated.go:953.3,954.17 2 0 -make-backend/internal/gql/generated.go:954.17,956.4 1 0 -make-backend/internal/gql/generated.go:958.3,958.121 1 0 -make-backend/internal/gql/generated.go:959.35,960.56 1 0 -make-backend/internal/gql/generated.go:960.56,961.9 1 0 -make-backend/internal/gql/generated.go:964.3,965.17 2 0 -make-backend/internal/gql/generated.go:965.17,967.4 1 0 -make-backend/internal/gql/generated.go:969.3,969.93 1 0 -make-backend/internal/gql/generated.go:971.33,972.54 1 0 -make-backend/internal/gql/generated.go:972.54,973.9 1 0 -make-backend/internal/gql/generated.go:976.3,976.73 1 0 -make-backend/internal/gql/generated.go:977.30,978.50 1 0 -make-backend/internal/gql/generated.go:978.50,979.9 1 0 -make-backend/internal/gql/generated.go:982.3,982.69 1 0 -make-backend/internal/gql/generated.go:983.29,984.50 1 0 -make-backend/internal/gql/generated.go:984.50,985.9 1 0 -make-backend/internal/gql/generated.go:988.3,988.69 1 0 -make-backend/internal/gql/generated.go:989.26,990.47 1 0 -make-backend/internal/gql/generated.go:990.47,991.9 1 0 -make-backend/internal/gql/generated.go:994.3,994.66 1 0 -make-backend/internal/gql/generated.go:995.29,996.50 1 0 -make-backend/internal/gql/generated.go:996.50,997.9 1 0 -make-backend/internal/gql/generated.go:1000.3,1000.69 1 0 -make-backend/internal/gql/generated.go:1001.26,1002.47 1 0 -make-backend/internal/gql/generated.go:1002.47,1003.9 1 0 -make-backend/internal/gql/generated.go:1006.3,1006.66 1 0 -make-backend/internal/gql/generated.go:1008.35,1009.56 1 0 -make-backend/internal/gql/generated.go:1009.56,1010.9 1 0 -make-backend/internal/gql/generated.go:1013.3,1013.75 1 0 -make-backend/internal/gql/generated.go:1014.32,1015.53 1 0 -make-backend/internal/gql/generated.go:1015.53,1016.9 1 0 -make-backend/internal/gql/generated.go:1019.3,1019.72 1 0 -make-backend/internal/gql/generated.go:1021.35,1022.55 1 0 -make-backend/internal/gql/generated.go:1022.55,1023.9 1 0 -make-backend/internal/gql/generated.go:1026.3,1026.74 1 0 -make-backend/internal/gql/generated.go:1027.28,1028.49 1 0 -make-backend/internal/gql/generated.go:1028.49,1029.9 1 0 -make-backend/internal/gql/generated.go:1032.3,1032.68 1 0 -make-backend/internal/gql/generated.go:1033.25,1034.46 1 0 -make-backend/internal/gql/generated.go:1034.46,1035.9 1 0 -make-backend/internal/gql/generated.go:1038.3,1038.65 1 0 -make-backend/internal/gql/generated.go:1039.28,1040.49 1 0 -make-backend/internal/gql/generated.go:1040.49,1041.9 1 0 -make-backend/internal/gql/generated.go:1044.3,1044.68 1 0 -make-backend/internal/gql/generated.go:1046.28,1047.49 1 0 -make-backend/internal/gql/generated.go:1047.49,1048.9 1 0 -make-backend/internal/gql/generated.go:1051.3,1052.17 2 0 -make-backend/internal/gql/generated.go:1052.17,1054.4 1 0 -make-backend/internal/gql/generated.go:1056.3,1056.86 1 0 -make-backend/internal/gql/generated.go:1057.35,1058.56 1 0 -make-backend/internal/gql/generated.go:1058.56,1059.9 1 0 -make-backend/internal/gql/generated.go:1062.3,1063.17 2 0 -make-backend/internal/gql/generated.go:1063.17,1065.4 1 0 -make-backend/internal/gql/generated.go:1067.3,1067.123 1 0 -make-backend/internal/gql/generated.go:1068.34,1069.55 1 0 -make-backend/internal/gql/generated.go:1069.55,1070.9 1 0 -make-backend/internal/gql/generated.go:1073.3,1074.17 2 0 -make-backend/internal/gql/generated.go:1074.17,1076.4 1 0 -make-backend/internal/gql/generated.go:1078.3,1078.122 1 0 -make-backend/internal/gql/generated.go:1079.27,1080.48 1 0 -make-backend/internal/gql/generated.go:1080.48,1081.9 1 0 -make-backend/internal/gql/generated.go:1084.3,1084.67 1 0 -make-backend/internal/gql/generated.go:1085.22,1086.43 1 0 -make-backend/internal/gql/generated.go:1086.43,1087.9 1 0 -make-backend/internal/gql/generated.go:1090.3,1091.17 2 0 -make-backend/internal/gql/generated.go:1091.17,1093.4 1 0 -make-backend/internal/gql/generated.go:1095.3,1095.80 1 0 -make-backend/internal/gql/generated.go:1096.25,1097.46 1 0 -make-backend/internal/gql/generated.go:1097.46,1098.9 1 0 -make-backend/internal/gql/generated.go:1101.3,1102.17 2 0 -make-backend/internal/gql/generated.go:1102.17,1104.4 1 0 -make-backend/internal/gql/generated.go:1106.3,1106.83 1 0 -make-backend/internal/gql/generated.go:1108.29,1109.50 1 0 -make-backend/internal/gql/generated.go:1109.50,1110.9 1 0 -make-backend/internal/gql/generated.go:1113.3,1114.17 2 0 -make-backend/internal/gql/generated.go:1114.17,1116.4 1 0 -make-backend/internal/gql/generated.go:1118.3,1118.114 1 0 -make-backend/internal/gql/generated.go:1119.37,1120.58 1 0 -make-backend/internal/gql/generated.go:1120.58,1121.9 1 0 -make-backend/internal/gql/generated.go:1124.3,1125.17 2 0 -make-backend/internal/gql/generated.go:1125.17,1127.4 1 0 -make-backend/internal/gql/generated.go:1129.3,1129.122 1 0 -make-backend/internal/gql/generated.go:1130.26,1131.47 1 0 -make-backend/internal/gql/generated.go:1131.47,1132.9 1 0 -make-backend/internal/gql/generated.go:1135.3,1136.17 2 0 -make-backend/internal/gql/generated.go:1136.17,1138.4 1 0 -make-backend/internal/gql/generated.go:1140.3,1140.84 1 0 -make-backend/internal/gql/generated.go:1141.30,1142.51 1 0 -make-backend/internal/gql/generated.go:1142.51,1143.9 1 0 -make-backend/internal/gql/generated.go:1146.3,1147.17 2 0 -make-backend/internal/gql/generated.go:1147.17,1149.4 1 0 -make-backend/internal/gql/generated.go:1151.3,1151.93 1 0 -make-backend/internal/gql/generated.go:1152.20,1153.41 1 0 -make-backend/internal/gql/generated.go:1153.41,1154.9 1 0 -make-backend/internal/gql/generated.go:1157.3,1158.17 2 0 -make-backend/internal/gql/generated.go:1158.17,1160.4 1 0 -make-backend/internal/gql/generated.go:1162.3,1162.78 1 0 -make-backend/internal/gql/generated.go:1163.20,1164.41 1 0 -make-backend/internal/gql/generated.go:1164.41,1165.9 1 0 -make-backend/internal/gql/generated.go:1168.3,1169.17 2 0 -make-backend/internal/gql/generated.go:1169.17,1171.4 1 0 -make-backend/internal/gql/generated.go:1173.3,1173.78 1 0 -make-backend/internal/gql/generated.go:1174.35,1175.56 1 0 -make-backend/internal/gql/generated.go:1175.56,1176.9 1 0 -make-backend/internal/gql/generated.go:1179.3,1180.17 2 0 -make-backend/internal/gql/generated.go:1180.17,1182.4 1 0 -make-backend/internal/gql/generated.go:1184.3,1184.104 1 0 -make-backend/internal/gql/generated.go:1186.30,1187.51 1 0 -make-backend/internal/gql/generated.go:1187.51,1188.9 1 0 -make-backend/internal/gql/generated.go:1191.3,1191.70 1 0 -make-backend/internal/gql/generated.go:1192.33,1193.54 1 0 -make-backend/internal/gql/generated.go:1193.54,1194.9 1 0 -make-backend/internal/gql/generated.go:1197.3,1197.73 1 0 -make-backend/internal/gql/generated.go:1198.30,1199.50 1 0 -make-backend/internal/gql/generated.go:1199.50,1200.9 1 0 -make-backend/internal/gql/generated.go:1203.3,1203.69 1 0 -make-backend/internal/gql/generated.go:1204.34,1205.54 1 0 -make-backend/internal/gql/generated.go:1205.54,1206.9 1 0 -make-backend/internal/gql/generated.go:1209.3,1209.73 1 0 -make-backend/internal/gql/generated.go:1210.24,1211.45 1 0 -make-backend/internal/gql/generated.go:1211.45,1212.9 1 0 -make-backend/internal/gql/generated.go:1215.3,1215.64 1 0 -make-backend/internal/gql/generated.go:1216.37,1217.57 1 0 -make-backend/internal/gql/generated.go:1217.57,1218.9 1 0 -make-backend/internal/gql/generated.go:1221.3,1221.76 1 0 -make-backend/internal/gql/generated.go:1222.32,1223.52 1 0 -make-backend/internal/gql/generated.go:1223.52,1224.9 1 0 -make-backend/internal/gql/generated.go:1227.3,1227.71 1 0 -make-backend/internal/gql/generated.go:1228.29,1229.49 1 0 -make-backend/internal/gql/generated.go:1229.49,1230.9 1 0 -make-backend/internal/gql/generated.go:1233.3,1233.68 1 0 -make-backend/internal/gql/generated.go:1235.33,1236.53 1 0 -make-backend/internal/gql/generated.go:1236.53,1237.9 1 0 -make-backend/internal/gql/generated.go:1240.3,1240.72 1 0 -make-backend/internal/gql/generated.go:1241.32,1242.52 1 0 -make-backend/internal/gql/generated.go:1242.52,1243.9 1 0 -make-backend/internal/gql/generated.go:1246.3,1246.71 1 0 -make-backend/internal/gql/generated.go:1247.24,1248.45 1 0 -make-backend/internal/gql/generated.go:1248.45,1249.9 1 0 -make-backend/internal/gql/generated.go:1252.3,1252.64 1 0 -make-backend/internal/gql/generated.go:1253.35,1254.55 1 0 -make-backend/internal/gql/generated.go:1254.55,1255.9 1 0 -make-backend/internal/gql/generated.go:1258.3,1258.74 1 0 -make-backend/internal/gql/generated.go:1259.28,1260.49 1 0 -make-backend/internal/gql/generated.go:1260.49,1261.9 1 0 -make-backend/internal/gql/generated.go:1264.3,1264.68 1 0 -make-backend/internal/gql/generated.go:1265.31,1266.51 1 0 -make-backend/internal/gql/generated.go:1266.51,1267.9 1 0 -make-backend/internal/gql/generated.go:1270.3,1270.70 1 0 -make-backend/internal/gql/generated.go:1272.38,1273.59 1 0 -make-backend/internal/gql/generated.go:1273.59,1274.9 1 0 -make-backend/internal/gql/generated.go:1277.3,1277.78 1 0 -make-backend/internal/gql/generated.go:1278.33,1279.54 1 0 -make-backend/internal/gql/generated.go:1279.54,1280.9 1 0 -make-backend/internal/gql/generated.go:1283.3,1283.73 1 0 -make-backend/internal/gql/generated.go:1284.35,1285.55 1 0 -make-backend/internal/gql/generated.go:1285.55,1286.9 1 0 -make-backend/internal/gql/generated.go:1289.3,1289.74 1 0 -make-backend/internal/gql/generated.go:1290.34,1291.55 1 0 -make-backend/internal/gql/generated.go:1291.55,1292.9 1 0 -make-backend/internal/gql/generated.go:1295.3,1295.74 1 0 -make-backend/internal/gql/generated.go:1296.31,1297.52 1 0 -make-backend/internal/gql/generated.go:1297.52,1298.9 1 0 -make-backend/internal/gql/generated.go:1301.3,1301.71 1 0 -make-backend/internal/gql/generated.go:1302.31,1303.52 1 0 -make-backend/internal/gql/generated.go:1303.52,1304.9 1 0 -make-backend/internal/gql/generated.go:1307.3,1307.71 1 0 -make-backend/internal/gql/generated.go:1309.33,1310.53 1 0 -make-backend/internal/gql/generated.go:1310.53,1311.9 1 0 -make-backend/internal/gql/generated.go:1314.3,1314.72 1 0 -make-backend/internal/gql/generated.go:1315.29,1316.50 1 0 -make-backend/internal/gql/generated.go:1316.50,1317.9 1 0 -make-backend/internal/gql/generated.go:1320.3,1320.69 1 0 -make-backend/internal/gql/generated.go:1321.36,1322.56 1 0 -make-backend/internal/gql/generated.go:1322.56,1323.9 1 0 -make-backend/internal/gql/generated.go:1326.3,1326.75 1 0 -make-backend/internal/gql/generated.go:1327.32,1328.52 1 0 -make-backend/internal/gql/generated.go:1328.52,1329.9 1 0 -make-backend/internal/gql/generated.go:1332.3,1332.71 1 0 -make-backend/internal/gql/generated.go:1333.35,1334.55 1 0 -make-backend/internal/gql/generated.go:1334.55,1335.9 1 0 -make-backend/internal/gql/generated.go:1338.3,1338.74 1 0 -make-backend/internal/gql/generated.go:1340.27,1341.47 1 0 -make-backend/internal/gql/generated.go:1341.47,1342.9 1 0 -make-backend/internal/gql/generated.go:1345.3,1345.66 1 0 -make-backend/internal/gql/generated.go:1346.21,1347.42 1 0 -make-backend/internal/gql/generated.go:1347.42,1348.9 1 0 -make-backend/internal/gql/generated.go:1351.3,1351.61 1 0 -make-backend/internal/gql/generated.go:1352.25,1353.46 1 0 -make-backend/internal/gql/generated.go:1353.46,1354.9 1 0 -make-backend/internal/gql/generated.go:1357.3,1357.65 1 0 -make-backend/internal/gql/generated.go:1358.26,1359.46 1 0 -make-backend/internal/gql/generated.go:1359.46,1360.9 1 0 -make-backend/internal/gql/generated.go:1363.3,1363.65 1 0 -make-backend/internal/gql/generated.go:1365.28,1366.48 1 0 -make-backend/internal/gql/generated.go:1366.48,1367.9 1 0 -make-backend/internal/gql/generated.go:1370.3,1370.67 1 0 -make-backend/internal/gql/generated.go:1371.27,1372.48 1 0 -make-backend/internal/gql/generated.go:1372.48,1373.9 1 0 -make-backend/internal/gql/generated.go:1376.3,1376.67 1 0 -make-backend/internal/gql/generated.go:1377.24,1378.45 1 0 -make-backend/internal/gql/generated.go:1378.45,1379.9 1 0 -make-backend/internal/gql/generated.go:1382.3,1382.64 1 0 -make-backend/internal/gql/generated.go:1384.25,1385.46 1 0 -make-backend/internal/gql/generated.go:1385.46,1386.9 1 0 -make-backend/internal/gql/generated.go:1389.3,1389.65 1 0 -make-backend/internal/gql/generated.go:1390.21,1391.42 1 0 -make-backend/internal/gql/generated.go:1391.42,1392.9 1 0 -make-backend/internal/gql/generated.go:1395.3,1395.61 1 0 -make-backend/internal/gql/generated.go:1396.32,1397.52 1 0 -make-backend/internal/gql/generated.go:1397.52,1398.9 1 0 -make-backend/internal/gql/generated.go:1401.3,1401.71 1 0 -make-backend/internal/gql/generated.go:1402.23,1403.44 1 0 -make-backend/internal/gql/generated.go:1403.44,1404.9 1 0 -make-backend/internal/gql/generated.go:1407.3,1407.63 1 0 -make-backend/internal/gql/generated.go:1409.20,1410.41 1 0 -make-backend/internal/gql/generated.go:1410.41,1411.9 1 0 -make-backend/internal/gql/generated.go:1414.3,1414.60 1 0 -make-backend/internal/gql/generated.go:1415.23,1416.44 1 0 -make-backend/internal/gql/generated.go:1416.44,1417.9 1 0 -make-backend/internal/gql/generated.go:1420.3,1420.63 1 0 -make-backend/internal/gql/generated.go:1421.23,1422.43 1 0 -make-backend/internal/gql/generated.go:1422.43,1423.9 1 0 -make-backend/internal/gql/generated.go:1426.3,1426.62 1 0 -make-backend/internal/gql/generated.go:1427.20,1428.41 1 0 -make-backend/internal/gql/generated.go:1428.41,1429.9 1 0 -make-backend/internal/gql/generated.go:1432.3,1432.60 1 0 -make-backend/internal/gql/generated.go:1433.24,1434.45 1 0 -make-backend/internal/gql/generated.go:1434.45,1435.9 1 0 -make-backend/internal/gql/generated.go:1438.3,1438.64 1 0 -make-backend/internal/gql/generated.go:1439.28,1440.48 1 0 -make-backend/internal/gql/generated.go:1440.48,1441.9 1 0 -make-backend/internal/gql/generated.go:1444.3,1444.67 1 0 -make-backend/internal/gql/generated.go:1445.17,1446.38 1 0 -make-backend/internal/gql/generated.go:1446.38,1447.9 1 0 -make-backend/internal/gql/generated.go:1450.3,1450.57 1 0 -make-backend/internal/gql/generated.go:1451.24,1452.44 1 0 -make-backend/internal/gql/generated.go:1452.44,1453.9 1 0 -make-backend/internal/gql/generated.go:1456.3,1456.63 1 0 -make-backend/internal/gql/generated.go:1457.23,1458.44 1 0 -make-backend/internal/gql/generated.go:1458.44,1459.9 1 0 -make-backend/internal/gql/generated.go:1462.3,1462.63 1 0 -make-backend/internal/gql/generated.go:1463.20,1464.41 1 0 -make-backend/internal/gql/generated.go:1464.41,1465.9 1 0 -make-backend/internal/gql/generated.go:1468.3,1468.60 1 0 -make-backend/internal/gql/generated.go:1469.23,1470.44 1 0 -make-backend/internal/gql/generated.go:1470.44,1471.9 1 0 -make-backend/internal/gql/generated.go:1474.3,1474.63 1 0 -make-backend/internal/gql/generated.go:1475.29,1476.49 1 0 -make-backend/internal/gql/generated.go:1476.49,1477.9 1 0 -make-backend/internal/gql/generated.go:1480.3,1480.68 1 0 -make-backend/internal/gql/generated.go:1482.21,1483.42 1 0 -make-backend/internal/gql/generated.go:1483.42,1484.9 1 0 -make-backend/internal/gql/generated.go:1487.3,1487.61 1 0 -make-backend/internal/gql/generated.go:1488.17,1489.38 1 0 -make-backend/internal/gql/generated.go:1489.38,1490.9 1 0 -make-backend/internal/gql/generated.go:1493.3,1493.57 1 0 -make-backend/internal/gql/generated.go:1494.28,1495.48 1 0 -make-backend/internal/gql/generated.go:1495.48,1496.9 1 0 -make-backend/internal/gql/generated.go:1499.3,1499.67 1 0 -make-backend/internal/gql/generated.go:1500.19,1501.40 1 0 -make-backend/internal/gql/generated.go:1501.40,1502.9 1 0 -make-backend/internal/gql/generated.go:1505.3,1505.59 1 0 -make-backend/internal/gql/generated.go:1508.2,1508.17 1 0 -make-backend/internal/gql/generated.go:1511.78,1517.35 5 0 -make-backend/internal/gql/generated.go:1518.17,1519.54 1 0 -make-backend/internal/gql/generated.go:1519.54,1522.13 3 0 -make-backend/internal/gql/generated.go:1522.13,1526.5 3 0 -make-backend/internal/gql/generated.go:1526.10,1527.50 1 0 -make-backend/internal/gql/generated.go:1527.50,1534.6 6 0 -make-backend/internal/gql/generated.go:1534.11,1536.6 1 0 -make-backend/internal/gql/generated.go:1538.4,1541.42 4 0 -make-backend/internal/gql/generated.go:1541.42,1544.5 2 0 -make-backend/internal/gql/generated.go:1546.4,1546.20 1 0 -make-backend/internal/gql/generated.go:1548.20,1549.54 1 0 -make-backend/internal/gql/generated.go:1549.54,1550.14 1 0 -make-backend/internal/gql/generated.go:1550.14,1552.5 1 0 -make-backend/internal/gql/generated.go:1553.4,1561.5 6 0 -make-backend/internal/gql/generated.go:1564.10,1565.86 1 0 -make-backend/internal/gql/generated.go:1577.21,1586.2 1 0 -make-backend/internal/gql/generated.go:1591.41,1593.16 2 0 -make-backend/internal/gql/generated.go:1593.16,1594.68 1 0 -make-backend/internal/gql/generated.go:1596.2,1596.21 1 0 -make-backend/internal/gql/generated.go:1624.139,1625.20 1 0 -make-backend/internal/gql/generated.go:1626.12,1627.56 1 0 -make-backend/internal/gql/generated.go:1628.14,1629.58 1 0 -make-backend/internal/gql/generated.go:1630.18,1631.62 1 0 -make-backend/internal/gql/generated.go:1633.2,1633.94 1 0 -make-backend/internal/gql/generated.go:1636.140,1637.20 1 0 -make-backend/internal/gql/generated.go:1638.12,1639.57 1 0 -make-backend/internal/gql/generated.go:1640.20,1641.65 1 0 -make-backend/internal/gql/generated.go:1643.2,1643.95 1 0 -make-backend/internal/gql/generated.go:1646.136,1647.20 1 0 -make-backend/internal/gql/generated.go:1648.16,1649.57 1 0 -make-backend/internal/gql/generated.go:1650.18,1651.59 1 0 -make-backend/internal/gql/generated.go:1652.23,1653.64 1 0 -make-backend/internal/gql/generated.go:1654.26,1655.67 1 0 -make-backend/internal/gql/generated.go:1656.21,1657.62 1 0 -make-backend/internal/gql/generated.go:1658.23,1659.64 1 0 -make-backend/internal/gql/generated.go:1660.15,1661.56 1 0 -make-backend/internal/gql/generated.go:1662.27,1663.68 1 0 -make-backend/internal/gql/generated.go:1664.29,1665.70 1 0 -make-backend/internal/gql/generated.go:1667.2,1667.91 1 0 -make-backend/internal/gql/generated.go:1670.141,1671.20 1 0 -make-backend/internal/gql/generated.go:1672.24,1673.70 1 0 -make-backend/internal/gql/generated.go:1674.29,1675.75 1 0 -make-backend/internal/gql/generated.go:1676.19,1677.65 1 0 -make-backend/internal/gql/generated.go:1679.2,1679.96 1 0 -make-backend/internal/gql/generated.go:1682.130,1683.20 1 0 -make-backend/internal/gql/generated.go:1684.12,1685.47 1 0 -make-backend/internal/gql/generated.go:1686.14,1687.49 1 0 -make-backend/internal/gql/generated.go:1688.12,1689.47 1 0 -make-backend/internal/gql/generated.go:1690.16,1691.51 1 0 -make-backend/internal/gql/generated.go:1692.18,1693.53 1 0 -make-backend/internal/gql/generated.go:1694.18,1695.53 1 0 -make-backend/internal/gql/generated.go:1696.25,1697.60 1 0 -make-backend/internal/gql/generated.go:1698.19,1699.54 1 0 -make-backend/internal/gql/generated.go:1700.23,1701.58 1 0 -make-backend/internal/gql/generated.go:1703.2,1703.85 1 0 -make-backend/internal/gql/generated.go:1706.129,1707.20 1 0 -make-backend/internal/gql/generated.go:1708.12,1709.46 1 0 -make-backend/internal/gql/generated.go:1710.20,1711.54 1 0 -make-backend/internal/gql/generated.go:1712.14,1713.48 1 0 -make-backend/internal/gql/generated.go:1714.21,1715.55 1 0 -make-backend/internal/gql/generated.go:1717.2,1717.84 1 0 -make-backend/internal/gql/generated.go:1720.134,1721.20 1 0 -make-backend/internal/gql/generated.go:1722.12,1723.51 1 0 -make-backend/internal/gql/generated.go:1724.14,1725.53 1 0 -make-backend/internal/gql/generated.go:1726.18,1727.57 1 0 -make-backend/internal/gql/generated.go:1728.21,1729.60 1 0 -make-backend/internal/gql/generated.go:1730.18,1731.57 1 0 -make-backend/internal/gql/generated.go:1732.18,1733.57 1 0 -make-backend/internal/gql/generated.go:1734.16,1735.55 1 0 -make-backend/internal/gql/generated.go:1736.18,1737.57 1 0 -make-backend/internal/gql/generated.go:1738.15,1739.54 1 0 -make-backend/internal/gql/generated.go:1740.15,1741.54 1 0 -make-backend/internal/gql/generated.go:1743.2,1743.89 1 0 -make-backend/internal/gql/generated.go:1746.141,1747.20 1 0 -make-backend/internal/gql/generated.go:1748.16,1749.62 1 0 -make-backend/internal/gql/generated.go:1750.24,1751.70 1 0 -make-backend/internal/gql/generated.go:1753.2,1753.96 1 0 -make-backend/internal/gql/generated.go:1756.141,1757.20 1 0 -make-backend/internal/gql/generated.go:1758.14,1759.60 1 0 -make-backend/internal/gql/generated.go:1760.17,1761.63 1 0 -make-backend/internal/gql/generated.go:1763.2,1763.96 1 0 -make-backend/internal/gql/generated.go:1766.128,1767.20 1 0 -make-backend/internal/gql/generated.go:1768.12,1769.45 1 0 -make-backend/internal/gql/generated.go:1770.15,1771.48 1 0 -make-backend/internal/gql/generated.go:1772.19,1773.52 1 0 -make-backend/internal/gql/generated.go:1774.18,1775.51 1 0 -make-backend/internal/gql/generated.go:1776.18,1777.51 1 0 -make-backend/internal/gql/generated.go:1778.19,1779.52 1 0 -make-backend/internal/gql/generated.go:1780.24,1781.57 1 0 -make-backend/internal/gql/generated.go:1782.18,1783.51 1 0 -make-backend/internal/gql/generated.go:1784.15,1785.48 1 0 -make-backend/internal/gql/generated.go:1786.15,1787.48 1 0 -make-backend/internal/gql/generated.go:1788.23,1789.56 1 0 -make-backend/internal/gql/generated.go:1790.18,1791.51 1 0 -make-backend/internal/gql/generated.go:1793.2,1793.83 1 0 -make-backend/internal/gql/generated.go:1796.128,1797.20 1 0 -make-backend/internal/gql/generated.go:1798.12,1799.45 1 0 -make-backend/internal/gql/generated.go:1800.23,1801.56 1 0 -make-backend/internal/gql/generated.go:1802.14,1803.47 1 0 -make-backend/internal/gql/generated.go:1804.16,1805.49 1 0 -make-backend/internal/gql/generated.go:1807.2,1807.83 1 0 -make-backend/internal/gql/generated.go:1810.135,1811.20 1 0 -make-backend/internal/gql/generated.go:1812.14,1813.54 1 0 -make-backend/internal/gql/generated.go:1814.21,1815.61 1 0 -make-backend/internal/gql/generated.go:1816.22,1817.62 1 0 -make-backend/internal/gql/generated.go:1818.19,1819.59 1 0 -make-backend/internal/gql/generated.go:1820.14,1821.54 1 0 -make-backend/internal/gql/generated.go:1823.2,1823.90 1 0 -make-backend/internal/gql/generated.go:1826.135,1827.20 1 0 -make-backend/internal/gql/generated.go:1828.14,1829.54 1 0 -make-backend/internal/gql/generated.go:1830.21,1831.61 1 0 -make-backend/internal/gql/generated.go:1832.22,1833.62 1 0 -make-backend/internal/gql/generated.go:1834.27,1835.67 1 0 -make-backend/internal/gql/generated.go:1837.2,1837.90 1 0 -make-backend/internal/gql/generated.go:1840.131,1841.20 1 0 -make-backend/internal/gql/generated.go:1842.14,1843.50 1 0 -make-backend/internal/gql/generated.go:1844.21,1845.57 1 0 -make-backend/internal/gql/generated.go:1846.14,1847.50 1 0 -make-backend/internal/gql/generated.go:1848.14,1849.50 1 0 -make-backend/internal/gql/generated.go:1850.22,1851.58 1 0 -make-backend/internal/gql/generated.go:1852.27,1853.63 1 0 -make-backend/internal/gql/generated.go:1855.2,1855.86 1 0 -make-backend/internal/gql/generated.go:1858.136,1859.20 1 0 -make-backend/internal/gql/generated.go:1860.14,1861.55 1 0 -make-backend/internal/gql/generated.go:1862.21,1863.62 1 0 -make-backend/internal/gql/generated.go:1864.14,1865.55 1 0 -make-backend/internal/gql/generated.go:1866.22,1867.63 1 0 -make-backend/internal/gql/generated.go:1868.22,1869.63 1 0 -make-backend/internal/gql/generated.go:1870.27,1871.68 1 0 -make-backend/internal/gql/generated.go:1873.2,1873.91 1 0 -make-backend/internal/gql/generated.go:1876.132,1877.20 1 0 -make-backend/internal/gql/generated.go:1878.21,1879.58 1 0 -make-backend/internal/gql/generated.go:1880.15,1881.52 1 0 -make-backend/internal/gql/generated.go:1882.19,1883.56 1 0 -make-backend/internal/gql/generated.go:1884.22,1885.59 1 0 -make-backend/internal/gql/generated.go:1886.26,1887.63 1 0 -make-backend/internal/gql/generated.go:1888.20,1889.57 1 0 -make-backend/internal/gql/generated.go:1891.2,1891.87 1 0 -make-backend/internal/gql/generated.go:1894.130,1895.20 1 0 -make-backend/internal/gql/generated.go:1896.14,1897.49 1 0 -make-backend/internal/gql/generated.go:1898.14,1899.49 1 0 -make-backend/internal/gql/generated.go:1900.21,1901.56 1 0 -make-backend/internal/gql/generated.go:1902.24,1903.59 1 0 -make-backend/internal/gql/generated.go:1904.16,1905.51 1 0 -make-backend/internal/gql/generated.go:1906.20,1907.55 1 0 -make-backend/internal/gql/generated.go:1908.23,1909.58 1 0 -make-backend/internal/gql/generated.go:1910.20,1911.55 1 0 -make-backend/internal/gql/generated.go:1912.21,1913.56 1 0 -make-backend/internal/gql/generated.go:1914.16,1915.51 1 0 -make-backend/internal/gql/generated.go:1916.17,1917.52 1 0 -make-backend/internal/gql/generated.go:1919.2,1919.85 1 0 -make-backend/internal/gql/generated.go:1926.135,1930.52 3 0 -make-backend/internal/gql/generated.go:1930.52,1932.4 1 0 -make-backend/internal/gql/generated.go:1933.2,1933.16 1 0 -make-backend/internal/gql/generated.go:1933.16,1935.3 1 0 -make-backend/internal/gql/generated.go:1936.2,1938.50 2 0 -make-backend/internal/gql/generated.go:1938.50,1940.4 1 0 -make-backend/internal/gql/generated.go:1941.2,1941.16 1 0 -make-backend/internal/gql/generated.go:1941.16,1943.3 1 0 -make-backend/internal/gql/generated.go:1944.2,1945.18 2 0 -make-backend/internal/gql/generated.go:1948.135,1952.49 3 0 -make-backend/internal/gql/generated.go:1952.49,1954.4 1 0 -make-backend/internal/gql/generated.go:1955.2,1955.16 1 0 -make-backend/internal/gql/generated.go:1955.16,1957.3 1 0 -make-backend/internal/gql/generated.go:1958.2,1959.18 2 0 -make-backend/internal/gql/generated.go:1962.122,1966.52 3 0 -make-backend/internal/gql/generated.go:1966.52,1968.4 1 0 -make-backend/internal/gql/generated.go:1969.2,1969.16 1 0 -make-backend/internal/gql/generated.go:1969.16,1971.3 1 0 -make-backend/internal/gql/generated.go:1972.2,1973.18 2 0 -make-backend/internal/gql/generated.go:1976.128,1980.49 3 0 -make-backend/internal/gql/generated.go:1980.49,1982.4 1 0 -make-backend/internal/gql/generated.go:1983.2,1983.16 1 0 -make-backend/internal/gql/generated.go:1983.16,1985.3 1 0 -make-backend/internal/gql/generated.go:1986.2,1987.18 2 0 -make-backend/internal/gql/generated.go:1990.135,1994.49 3 0 -make-backend/internal/gql/generated.go:1994.49,1996.4 1 0 -make-backend/internal/gql/generated.go:1997.2,1997.16 1 0 -make-backend/internal/gql/generated.go:1997.16,1999.3 1 0 -make-backend/internal/gql/generated.go:2000.2,2002.49 2 0 -make-backend/internal/gql/generated.go:2002.49,2004.4 1 0 -make-backend/internal/gql/generated.go:2005.2,2005.16 1 0 -make-backend/internal/gql/generated.go:2005.16,2007.3 1 0 -make-backend/internal/gql/generated.go:2008.2,2009.18 2 0 -make-backend/internal/gql/generated.go:2012.134,2016.49 3 0 -make-backend/internal/gql/generated.go:2016.49,2018.4 1 0 -make-backend/internal/gql/generated.go:2019.2,2019.16 1 0 -make-backend/internal/gql/generated.go:2019.16,2021.3 1 0 -make-backend/internal/gql/generated.go:2022.2,2024.49 2 0 -make-backend/internal/gql/generated.go:2024.49,2026.4 1 0 -make-backend/internal/gql/generated.go:2027.2,2027.16 1 0 -make-backend/internal/gql/generated.go:2027.16,2029.3 1 0 -make-backend/internal/gql/generated.go:2030.2,2031.18 2 0 -make-backend/internal/gql/generated.go:2034.122,2038.49 3 0 -make-backend/internal/gql/generated.go:2038.49,2040.4 1 0 -make-backend/internal/gql/generated.go:2041.2,2041.16 1 0 -make-backend/internal/gql/generated.go:2041.16,2043.3 1 0 -make-backend/internal/gql/generated.go:2044.2,2045.18 2 0 -make-backend/internal/gql/generated.go:2048.125,2052.49 3 0 -make-backend/internal/gql/generated.go:2052.49,2054.4 1 0 -make-backend/internal/gql/generated.go:2055.2,2055.16 1 0 -make-backend/internal/gql/generated.go:2055.16,2057.3 1 0 -make-backend/internal/gql/generated.go:2058.2,2059.18 2 0 -make-backend/internal/gql/generated.go:2062.137,2066.49 3 0 -make-backend/internal/gql/generated.go:2066.49,2068.4 1 0 -make-backend/internal/gql/generated.go:2069.2,2069.16 1 0 -make-backend/internal/gql/generated.go:2069.16,2071.3 1 0 -make-backend/internal/gql/generated.go:2072.2,2074.49 2 0 -make-backend/internal/gql/generated.go:2074.49,2076.4 1 0 -make-backend/internal/gql/generated.go:2077.2,2077.16 1 0 -make-backend/internal/gql/generated.go:2077.16,2079.3 1 0 -make-backend/internal/gql/generated.go:2080.2,2081.18 2 0 -make-backend/internal/gql/generated.go:2084.129,2088.49 3 0 -make-backend/internal/gql/generated.go:2088.49,2090.4 1 0 -make-backend/internal/gql/generated.go:2091.2,2091.16 1 0 -make-backend/internal/gql/generated.go:2091.16,2093.3 1 0 -make-backend/internal/gql/generated.go:2094.2,2096.49 2 0 -make-backend/internal/gql/generated.go:2096.49,2098.4 1 0 -make-backend/internal/gql/generated.go:2099.2,2099.16 1 0 -make-backend/internal/gql/generated.go:2099.16,2101.3 1 0 -make-backend/internal/gql/generated.go:2102.2,2103.18 2 0 -make-backend/internal/gql/generated.go:2106.126,2110.49 3 0 -make-backend/internal/gql/generated.go:2110.49,2112.4 1 0 -make-backend/internal/gql/generated.go:2113.2,2113.16 1 0 -make-backend/internal/gql/generated.go:2113.16,2115.3 1 0 -make-backend/internal/gql/generated.go:2116.2,2117.18 2 0 -make-backend/internal/gql/generated.go:2120.130,2124.49 3 0 -make-backend/internal/gql/generated.go:2124.49,2126.4 1 0 -make-backend/internal/gql/generated.go:2127.2,2127.16 1 0 -make-backend/internal/gql/generated.go:2127.16,2129.3 1 0 -make-backend/internal/gql/generated.go:2130.2,2131.18 2 0 -make-backend/internal/gql/generated.go:2134.120,2138.49 3 0 -make-backend/internal/gql/generated.go:2138.49,2140.4 1 0 -make-backend/internal/gql/generated.go:2141.2,2141.16 1 0 -make-backend/internal/gql/generated.go:2141.16,2143.3 1 0 -make-backend/internal/gql/generated.go:2144.2,2145.18 2 0 -make-backend/internal/gql/generated.go:2148.120,2152.49 3 0 -make-backend/internal/gql/generated.go:2152.49,2154.4 1 0 -make-backend/internal/gql/generated.go:2155.2,2155.16 1 0 -make-backend/internal/gql/generated.go:2155.16,2157.3 1 0 -make-backend/internal/gql/generated.go:2158.2,2159.18 2 0 -make-backend/internal/gql/generated.go:2162.135,2166.49 3 0 -make-backend/internal/gql/generated.go:2166.49,2168.4 1 0 -make-backend/internal/gql/generated.go:2169.2,2169.16 1 0 -make-backend/internal/gql/generated.go:2169.16,2171.3 1 0 -make-backend/internal/gql/generated.go:2172.2,2173.18 2 0 -make-backend/internal/gql/generated.go:2176.126,2180.51 3 0 -make-backend/internal/gql/generated.go:2180.51,2182.4 1 0 -make-backend/internal/gql/generated.go:2183.2,2183.16 1 0 -make-backend/internal/gql/generated.go:2183.16,2185.3 1 0 -make-backend/internal/gql/generated.go:2186.2,2187.18 2 0 -make-backend/internal/gql/generated.go:2190.122,2194.51 3 0 -make-backend/internal/gql/generated.go:2194.51,2196.4 1 0 -make-backend/internal/gql/generated.go:2197.2,2197.16 1 0 -make-backend/internal/gql/generated.go:2197.16,2199.3 1 0 -make-backend/internal/gql/generated.go:2200.2,2201.18 2 0 -make-backend/internal/gql/generated.go:2204.127,2208.50 3 0 -make-backend/internal/gql/generated.go:2208.50,2210.4 1 0 -make-backend/internal/gql/generated.go:2211.2,2211.16 1 0 -make-backend/internal/gql/generated.go:2211.16,2213.3 1 0 -make-backend/internal/gql/generated.go:2214.2,2215.18 2 0 -make-backend/internal/gql/generated.go:2218.123,2222.50 3 0 -make-backend/internal/gql/generated.go:2222.50,2224.4 1 0 -make-backend/internal/gql/generated.go:2225.2,2225.16 1 0 -make-backend/internal/gql/generated.go:2225.16,2227.3 1 0 -make-backend/internal/gql/generated.go:2228.2,2229.18 2 0 -make-backend/internal/gql/generated.go:2236.149,2241.90 1 0 -make-backend/internal/gql/generated.go:2241.90,2243.4 1 0 -make-backend/internal/gql/generated.go:2244.42,2246.4 1 0 -make-backend/internal/gql/generated.go:2248.83,2250.4 1 0 -make-backend/internal/gql/generated.go:2255.146,2257.2 1 0 -make-backend/internal/gql/generated.go:2259.156,2264.90 1 0 -make-backend/internal/gql/generated.go:2264.90,2266.4 1 0 -make-backend/internal/gql/generated.go:2267.42,2269.4 1 0 -make-backend/internal/gql/generated.go:2271.83,2273.4 1 0 -make-backend/internal/gql/generated.go:2278.153,2280.2 1 0 -make-backend/internal/gql/generated.go:2282.157,2287.90 1 0 -make-backend/internal/gql/generated.go:2287.90,2289.4 1 0 -make-backend/internal/gql/generated.go:2290.42,2292.4 1 0 -make-backend/internal/gql/generated.go:2294.83,2296.4 1 0 -make-backend/internal/gql/generated.go:2301.154,2303.2 1 0 -make-backend/internal/gql/generated.go:2305.152,2310.90 1 0 -make-backend/internal/gql/generated.go:2310.90,2312.4 1 0 -make-backend/internal/gql/generated.go:2313.42,2315.4 1 0 -make-backend/internal/gql/generated.go:2317.106,2319.4 1 0 -make-backend/internal/gql/generated.go:2324.149,2326.2 1 0 -make-backend/internal/gql/generated.go:2328.160,2333.90 1 0 -make-backend/internal/gql/generated.go:2333.90,2335.4 1 0 -make-backend/internal/gql/generated.go:2336.42,2338.4 1 0 -make-backend/internal/gql/generated.go:2340.83,2342.4 1 0 -make-backend/internal/gql/generated.go:2347.157,2349.2 1 0 -make-backend/internal/gql/generated.go:2351.153,2356.90 1 0 -make-backend/internal/gql/generated.go:2356.90,2358.4 1 0 -make-backend/internal/gql/generated.go:2359.42,2361.4 1 0 -make-backend/internal/gql/generated.go:2363.86,2365.4 1 0 -make-backend/internal/gql/generated.go:2370.148,2372.2 1 0 -make-backend/internal/gql/generated.go:2374.155,2379.90 1 0 -make-backend/internal/gql/generated.go:2379.90,2381.4 1 0 -make-backend/internal/gql/generated.go:2382.42,2384.4 1 0 -make-backend/internal/gql/generated.go:2386.83,2388.4 1 0 -make-backend/internal/gql/generated.go:2393.150,2395.2 1 0 -make-backend/internal/gql/generated.go:2397.159,2402.90 1 0 -make-backend/internal/gql/generated.go:2402.90,2404.4 1 0 -make-backend/internal/gql/generated.go:2405.42,2407.4 1 0 -make-backend/internal/gql/generated.go:2409.104,2411.4 1 0 -make-backend/internal/gql/generated.go:2416.154,2422.97 1 0 -make-backend/internal/gql/generated.go:2422.97,2424.4 1 0 -make-backend/internal/gql/generated.go:2426.2,2426.16 1 0 -make-backend/internal/gql/generated.go:2429.155,2434.90 1 0 -make-backend/internal/gql/generated.go:2434.90,2436.4 1 0 -make-backend/internal/gql/generated.go:2437.42,2439.4 1 0 -make-backend/internal/gql/generated.go:2441.86,2443.4 1 0 -make-backend/internal/gql/generated.go:2448.149,2450.2 1 0 -make-backend/internal/gql/generated.go:2452.163,2457.90 1 0 -make-backend/internal/gql/generated.go:2457.90,2459.4 1 0 -make-backend/internal/gql/generated.go:2460.42,2462.4 1 0 -make-backend/internal/gql/generated.go:2464.104,2466.4 1 0 -make-backend/internal/gql/generated.go:2471.157,2477.97 1 0 -make-backend/internal/gql/generated.go:2477.97,2479.4 1 0 -make-backend/internal/gql/generated.go:2481.2,2481.16 1 0 -make-backend/internal/gql/generated.go:2484.151,2489.90 1 0 -make-backend/internal/gql/generated.go:2489.90,2491.4 1 0 -make-backend/internal/gql/generated.go:2492.42,2494.4 1 0 -make-backend/internal/gql/generated.go:2496.93,2498.4 1 0 -make-backend/internal/gql/generated.go:2503.149,2509.97 1 0 -make-backend/internal/gql/generated.go:2509.97,2511.4 1 0 -make-backend/internal/gql/generated.go:2513.2,2513.16 1 0 -make-backend/internal/gql/generated.go:2516.153,2521.90 1 0 -make-backend/internal/gql/generated.go:2521.90,2523.4 1 0 -make-backend/internal/gql/generated.go:2524.42,2526.4 1 0 -make-backend/internal/gql/generated.go:2528.83,2530.4 1 0 -make-backend/internal/gql/generated.go:2535.151,2537.2 1 0 -make-backend/internal/gql/generated.go:2539.158,2544.90 1 0 -make-backend/internal/gql/generated.go:2544.90,2546.4 1 0 -make-backend/internal/gql/generated.go:2547.42,2549.4 1 0 -make-backend/internal/gql/generated.go:2551.83,2553.4 1 0 -make-backend/internal/gql/generated.go:2558.156,2560.2 1 0 -make-backend/internal/gql/generated.go:2562.161,2567.90 1 0 -make-backend/internal/gql/generated.go:2567.90,2569.4 1 0 -make-backend/internal/gql/generated.go:2570.42,2572.4 1 0 -make-backend/internal/gql/generated.go:2574.86,2576.4 1 0 -make-backend/internal/gql/generated.go:2581.159,2583.2 1 0 -make-backend/internal/gql/generated.go:2585.156,2590.90 1 0 -make-backend/internal/gql/generated.go:2590.90,2592.4 1 0 -make-backend/internal/gql/generated.go:2593.42,2595.4 1 0 -make-backend/internal/gql/generated.go:2597.90,2599.4 1 0 -make-backend/internal/gql/generated.go:2604.154,2606.2 1 0 -make-backend/internal/gql/generated.go:2608.158,2613.90 1 0 -make-backend/internal/gql/generated.go:2613.90,2615.4 1 0 -make-backend/internal/gql/generated.go:2616.42,2618.4 1 0 -make-backend/internal/gql/generated.go:2620.90,2622.4 1 0 -make-backend/internal/gql/generated.go:2627.156,2629.2 1 0 -make-backend/internal/gql/generated.go:2631.150,2636.90 1 0 -make-backend/internal/gql/generated.go:2636.90,2638.4 1 0 -make-backend/internal/gql/generated.go:2639.42,2641.4 1 0 -make-backend/internal/gql/generated.go:2643.104,2645.4 1 0 -make-backend/internal/gql/generated.go:2650.148,2656.97 1 0 -make-backend/internal/gql/generated.go:2656.97,2658.4 1 0 -make-backend/internal/gql/generated.go:2660.2,2660.16 1 0 -make-backend/internal/gql/generated.go:2663.162,2668.90 1 0 -make-backend/internal/gql/generated.go:2668.90,2670.4 1 0 -make-backend/internal/gql/generated.go:2671.42,2673.4 1 0 -make-backend/internal/gql/generated.go:2675.104,2677.4 1 0 -make-backend/internal/gql/generated.go:2682.160,2688.97 1 0 -make-backend/internal/gql/generated.go:2688.97,2690.4 1 0 -make-backend/internal/gql/generated.go:2692.2,2692.16 1 0 -make-backend/internal/gql/generated.go:2695.164,2700.90 1 0 -make-backend/internal/gql/generated.go:2700.90,2702.4 1 0 -make-backend/internal/gql/generated.go:2703.42,2705.4 1 0 -make-backend/internal/gql/generated.go:2707.104,2709.4 1 0 -make-backend/internal/gql/generated.go:2714.162,2720.97 1 0 -make-backend/internal/gql/generated.go:2720.97,2722.4 1 0 -make-backend/internal/gql/generated.go:2724.2,2724.16 1 0 -make-backend/internal/gql/generated.go:2727.169,2732.90 1 0 -make-backend/internal/gql/generated.go:2732.90,2734.4 1 0 -make-backend/internal/gql/generated.go:2735.42,2737.4 1 0 -make-backend/internal/gql/generated.go:2739.84,2741.4 1 0 -make-backend/internal/gql/generated.go:2746.162,2748.2 1 0 -make-backend/internal/gql/generated.go:2750.174,2755.90 1 0 -make-backend/internal/gql/generated.go:2755.90,2757.4 1 0 -make-backend/internal/gql/generated.go:2758.42,2760.4 1 0 -make-backend/internal/gql/generated.go:2762.84,2764.4 1 0 -make-backend/internal/gql/generated.go:2769.167,2771.2 1 0 -make-backend/internal/gql/generated.go:2773.164,2778.90 1 0 -make-backend/internal/gql/generated.go:2778.90,2780.4 1 0 -make-backend/internal/gql/generated.go:2781.42,2783.4 1 0 -make-backend/internal/gql/generated.go:2785.84,2787.4 1 0 -make-backend/internal/gql/generated.go:2792.157,2794.2 1 0 -make-backend/internal/gql/generated.go:2796.147,2801.90 1 0 -make-backend/internal/gql/generated.go:2801.90,2803.4 1 0 -make-backend/internal/gql/generated.go:2804.42,2806.4 1 0 -make-backend/internal/gql/generated.go:2808.83,2810.4 1 0 -make-backend/internal/gql/generated.go:2815.145,2817.2 1 0 -make-backend/internal/gql/generated.go:2819.150,2824.90 1 0 -make-backend/internal/gql/generated.go:2824.90,2826.4 1 0 -make-backend/internal/gql/generated.go:2827.42,2829.4 1 0 -make-backend/internal/gql/generated.go:2831.86,2833.4 1 0 -make-backend/internal/gql/generated.go:2838.148,2840.2 1 0 -make-backend/internal/gql/generated.go:2842.149,2847.90 1 0 -make-backend/internal/gql/generated.go:2847.90,2849.4 1 0 -make-backend/internal/gql/generated.go:2850.42,2852.4 1 0 -make-backend/internal/gql/generated.go:2854.86,2856.4 1 0 -make-backend/internal/gql/generated.go:2861.147,2863.2 1 0 -make-backend/internal/gql/generated.go:2865.158,2870.90 1 0 -make-backend/internal/gql/generated.go:2870.90,2872.4 1 0 -make-backend/internal/gql/generated.go:2873.42,2875.4 1 0 -make-backend/internal/gql/generated.go:2877.84,2879.4 1 0 -make-backend/internal/gql/generated.go:2884.156,2886.2 1 0 -make-backend/internal/gql/generated.go:2888.150,2893.90 1 0 -make-backend/internal/gql/generated.go:2893.90,2895.4 1 0 -make-backend/internal/gql/generated.go:2896.42,2898.4 1 0 -make-backend/internal/gql/generated.go:2900.86,2902.4 1 0 -make-backend/internal/gql/generated.go:2907.150,2909.2 1 0 -make-backend/internal/gql/generated.go:2911.149,2916.90 1 0 -make-backend/internal/gql/generated.go:2916.90,2918.4 1 0 -make-backend/internal/gql/generated.go:2919.42,2921.4 1 0 -make-backend/internal/gql/generated.go:2923.86,2925.4 1 0 -make-backend/internal/gql/generated.go:2930.149,2932.2 1 0 -make-backend/internal/gql/generated.go:2934.158,2939.90 1 0 -make-backend/internal/gql/generated.go:2939.90,2941.4 1 0 -make-backend/internal/gql/generated.go:2942.42,2944.4 1 0 -make-backend/internal/gql/generated.go:2946.83,2948.4 1 0 -make-backend/internal/gql/generated.go:2953.156,2955.2 1 0 -make-backend/internal/gql/generated.go:2957.156,2962.90 1 0 -make-backend/internal/gql/generated.go:2962.90,2964.4 1 0 -make-backend/internal/gql/generated.go:2965.42,2967.4 1 0 -make-backend/internal/gql/generated.go:2969.83,2971.4 1 0 -make-backend/internal/gql/generated.go:2976.154,2978.2 1 0 -make-backend/internal/gql/generated.go:2980.154,2985.90 1 0 -make-backend/internal/gql/generated.go:2985.90,2987.4 1 0 -make-backend/internal/gql/generated.go:2988.42,2990.4 1 0 -make-backend/internal/gql/generated.go:2992.90,2994.4 1 0 -make-backend/internal/gql/generated.go:2999.152,3001.2 1 0 -make-backend/internal/gql/generated.go:3003.155,3008.90 1 0 -make-backend/internal/gql/generated.go:3008.90,3010.4 1 0 -make-backend/internal/gql/generated.go:3011.42,3013.4 1 0 -make-backend/internal/gql/generated.go:3015.90,3017.4 1 0 -make-backend/internal/gql/generated.go:3022.153,3024.2 1 0 -make-backend/internal/gql/generated.go:3026.151,3031.90 1 0 -make-backend/internal/gql/generated.go:3031.90,3033.4 1 0 -make-backend/internal/gql/generated.go:3034.42,3036.4 1 0 -make-backend/internal/gql/generated.go:3038.84,3040.4 1 0 -make-backend/internal/gql/generated.go:3045.149,3047.2 1 0 -make-backend/internal/gql/generated.go:3049.135,3054.90 1 0 -make-backend/internal/gql/generated.go:3054.90,3056.4 1 0 -make-backend/internal/gql/generated.go:3057.42,3059.4 1 0 -make-backend/internal/gql/generated.go:3061.83,3063.4 1 0 -make-backend/internal/gql/generated.go:3068.139,3070.2 1 0 -make-backend/internal/gql/generated.go:3072.137,3077.90 1 0 -make-backend/internal/gql/generated.go:3077.90,3079.4 1 0 -make-backend/internal/gql/generated.go:3080.42,3082.4 1 0 -make-backend/internal/gql/generated.go:3084.86,3086.4 1 0 -make-backend/internal/gql/generated.go:3091.141,3093.2 1 0 -make-backend/internal/gql/generated.go:3095.135,3100.90 1 0 -make-backend/internal/gql/generated.go:3100.90,3102.4 1 0 -make-backend/internal/gql/generated.go:3103.42,3105.4 1 0 -make-backend/internal/gql/generated.go:3107.86,3109.4 1 0 -make-backend/internal/gql/generated.go:3114.139,3116.2 1 0 -make-backend/internal/gql/generated.go:3118.139,3123.90 1 0 -make-backend/internal/gql/generated.go:3123.90,3125.4 1 0 -make-backend/internal/gql/generated.go:3126.42,3128.4 1 0 -make-backend/internal/gql/generated.go:3130.89,3132.4 1 0 -make-backend/internal/gql/generated.go:3137.143,3139.2 1 0 -make-backend/internal/gql/generated.go:3141.141,3146.90 1 0 -make-backend/internal/gql/generated.go:3146.90,3148.4 1 0 -make-backend/internal/gql/generated.go:3149.42,3151.4 1 0 -make-backend/internal/gql/generated.go:3153.87,3155.4 1 0 -make-backend/internal/gql/generated.go:3160.145,3162.2 1 0 -make-backend/internal/gql/generated.go:3164.141,3169.90 1 0 -make-backend/internal/gql/generated.go:3169.90,3171.4 1 0 -make-backend/internal/gql/generated.go:3172.42,3174.4 1 0 -make-backend/internal/gql/generated.go:3176.87,3178.4 1 0 -make-backend/internal/gql/generated.go:3183.145,3185.2 1 0 -make-backend/internal/gql/generated.go:3187.148,3192.90 1 0 -make-backend/internal/gql/generated.go:3192.90,3194.4 1 0 -make-backend/internal/gql/generated.go:3195.42,3197.4 1 0 -make-backend/internal/gql/generated.go:3199.87,3201.4 1 0 -make-backend/internal/gql/generated.go:3206.152,3208.2 1 0 -make-backend/internal/gql/generated.go:3210.142,3215.90 1 0 -make-backend/internal/gql/generated.go:3215.90,3217.4 1 0 -make-backend/internal/gql/generated.go:3218.42,3220.4 1 0 -make-backend/internal/gql/generated.go:3221.69,3224.57 2 0 -make-backend/internal/gql/generated.go:3224.57,3225.37 1 0 -make-backend/internal/gql/generated.go:3225.37,3228.6 2 0 -make-backend/internal/gql/generated.go:3229.5,3229.55 1 0 -make-backend/internal/gql/generated.go:3232.4,3233.15 2 0 -make-backend/internal/gql/generated.go:3235.83,3237.4 1 0 -make-backend/internal/gql/generated.go:3242.146,3244.2 1 0 -make-backend/internal/gql/generated.go:3246.146,3251.90 1 0 -make-backend/internal/gql/generated.go:3251.90,3253.4 1 0 -make-backend/internal/gql/generated.go:3254.42,3256.4 1 0 -make-backend/internal/gql/generated.go:3258.83,3260.4 1 0 -make-backend/internal/gql/generated.go:3265.150,3267.2 1 0 -make-backend/internal/gql/generated.go:3269.148,3274.90 1 0 -make-backend/internal/gql/generated.go:3274.90,3276.4 1 0 -make-backend/internal/gql/generated.go:3277.42,3279.4 1 0 -make-backend/internal/gql/generated.go:3281.83,3283.4 1 0 -make-backend/internal/gql/generated.go:3288.149,3290.2 1 0 -make-backend/internal/gql/generated.go:3292.149,3297.90 1 0 -make-backend/internal/gql/generated.go:3297.90,3299.4 1 0 -make-backend/internal/gql/generated.go:3300.42,3302.4 1 0 -make-backend/internal/gql/generated.go:3304.83,3306.4 1 0 -make-backend/internal/gql/generated.go:3311.150,3313.2 1 0 -make-backend/internal/gql/generated.go:3315.144,3320.90 1 0 -make-backend/internal/gql/generated.go:3320.90,3322.4 1 0 -make-backend/internal/gql/generated.go:3323.42,3325.4 1 0 -make-backend/internal/gql/generated.go:3327.102,3329.4 1 0 -make-backend/internal/gql/generated.go:3334.145,3336.2 1 0 -make-backend/internal/gql/generated.go:3338.141,3343.90 1 0 -make-backend/internal/gql/generated.go:3343.90,3345.4 1 0 -make-backend/internal/gql/generated.go:3346.42,3348.4 1 0 -make-backend/internal/gql/generated.go:3350.83,3352.4 1 0 -make-backend/internal/gql/generated.go:3357.142,3359.2 1 0 -make-backend/internal/gql/generated.go:3361.143,3366.90 1 0 -make-backend/internal/gql/generated.go:3366.90,3368.4 1 0 -make-backend/internal/gql/generated.go:3369.42,3371.4 1 0 -make-backend/internal/gql/generated.go:3373.86,3375.4 1 0 -make-backend/internal/gql/generated.go:3380.144,3382.2 1 0 -make-backend/internal/gql/generated.go:3384.147,3389.90 1 0 -make-backend/internal/gql/generated.go:3389.90,3391.4 1 0 -make-backend/internal/gql/generated.go:3392.42,3394.4 1 0 -make-backend/internal/gql/generated.go:3396.86,3398.4 1 0 -make-backend/internal/gql/generated.go:3403.148,3405.2 1 0 -make-backend/internal/gql/generated.go:3407.146,3412.90 1 0 -make-backend/internal/gql/generated.go:3412.90,3414.4 1 0 -make-backend/internal/gql/generated.go:3415.42,3417.4 1 0 -make-backend/internal/gql/generated.go:3419.83,3421.4 1 0 -make-backend/internal/gql/generated.go:3426.147,3428.2 1 0 -make-backend/internal/gql/generated.go:3430.145,3435.90 1 0 -make-backend/internal/gql/generated.go:3435.90,3437.4 1 0 -make-backend/internal/gql/generated.go:3438.42,3440.4 1 0 -make-backend/internal/gql/generated.go:3442.84,3444.4 1 0 -make-backend/internal/gql/generated.go:3449.146,3451.2 1 0 -make-backend/internal/gql/generated.go:3453.147,3458.90 1 0 -make-backend/internal/gql/generated.go:3458.90,3460.4 1 0 -make-backend/internal/gql/generated.go:3461.42,3463.4 1 0 -make-backend/internal/gql/generated.go:3465.84,3467.4 1 0 -make-backend/internal/gql/generated.go:3472.148,3474.2 1 0 -make-backend/internal/gql/generated.go:3476.146,3481.90 1 0 -make-backend/internal/gql/generated.go:3481.90,3483.4 1 0 -make-backend/internal/gql/generated.go:3484.42,3486.4 1 0 -make-backend/internal/gql/generated.go:3488.86,3490.4 1 0 -make-backend/internal/gql/generated.go:3495.147,3497.2 1 0 -make-backend/internal/gql/generated.go:3499.151,3504.90 1 0 -make-backend/internal/gql/generated.go:3504.90,3506.4 1 0 -make-backend/internal/gql/generated.go:3507.42,3509.4 1 0 -make-backend/internal/gql/generated.go:3511.86,3513.4 1 0 -make-backend/internal/gql/generated.go:3518.152,3520.2 1 0 -make-backend/internal/gql/generated.go:3522.150,3527.90 1 0 -make-backend/internal/gql/generated.go:3527.90,3529.4 1 0 -make-backend/internal/gql/generated.go:3530.42,3532.4 1 0 -make-backend/internal/gql/generated.go:3534.86,3536.4 1 0 -make-backend/internal/gql/generated.go:3541.151,3543.2 1 0 -make-backend/internal/gql/generated.go:3545.149,3550.90 1 0 -make-backend/internal/gql/generated.go:3550.90,3552.4 1 0 -make-backend/internal/gql/generated.go:3553.42,3555.4 1 0 -make-backend/internal/gql/generated.go:3557.84,3559.4 1 0 -make-backend/internal/gql/generated.go:3564.150,3566.2 1 0 -make-backend/internal/gql/generated.go:3568.155,3573.90 1 0 -make-backend/internal/gql/generated.go:3573.90,3575.4 1 0 -make-backend/internal/gql/generated.go:3576.42,3578.4 1 0 -make-backend/internal/gql/generated.go:3580.84,3582.4 1 0 -make-backend/internal/gql/generated.go:3587.156,3589.2 1 0 -make-backend/internal/gql/generated.go:3591.163,3596.90 1 0 -make-backend/internal/gql/generated.go:3596.90,3598.4 1 0 -make-backend/internal/gql/generated.go:3599.42,3601.4 1 0 -make-backend/internal/gql/generated.go:3603.86,3605.4 1 0 -make-backend/internal/gql/generated.go:3610.164,3612.2 1 0 -make-backend/internal/gql/generated.go:3614.152,3619.90 1 0 -make-backend/internal/gql/generated.go:3619.90,3621.4 1 0 -make-backend/internal/gql/generated.go:3622.42,3624.4 1 0 -make-backend/internal/gql/generated.go:3626.84,3628.4 1 0 -make-backend/internal/gql/generated.go:3633.153,3635.2 1 0 -make-backend/internal/gql/generated.go:3637.157,3642.90 1 0 -make-backend/internal/gql/generated.go:3642.90,3644.4 1 0 -make-backend/internal/gql/generated.go:3645.42,3647.4 1 0 -make-backend/internal/gql/generated.go:3649.84,3651.4 1 0 -make-backend/internal/gql/generated.go:3656.158,3658.2 1 0 -make-backend/internal/gql/generated.go:3660.155,3665.90 1 0 -make-backend/internal/gql/generated.go:3665.90,3667.4 1 0 -make-backend/internal/gql/generated.go:3668.42,3670.4 1 0 -make-backend/internal/gql/generated.go:3672.84,3674.4 1 0 -make-backend/internal/gql/generated.go:3679.156,3681.2 1 0 -make-backend/internal/gql/generated.go:3683.157,3688.90 1 0 -make-backend/internal/gql/generated.go:3688.90,3690.4 1 0 -make-backend/internal/gql/generated.go:3691.42,3693.4 1 0 -make-backend/internal/gql/generated.go:3695.83,3697.4 1 0 -make-backend/internal/gql/generated.go:3702.150,3704.2 1 0 -make-backend/internal/gql/generated.go:3706.167,3711.90 1 0 -make-backend/internal/gql/generated.go:3711.90,3713.4 1 0 -make-backend/internal/gql/generated.go:3714.42,3716.4 1 0 -make-backend/internal/gql/generated.go:3718.83,3720.4 1 0 -make-backend/internal/gql/generated.go:3725.160,3727.2 1 0 -make-backend/internal/gql/generated.go:3729.159,3734.90 1 0 -make-backend/internal/gql/generated.go:3734.90,3736.4 1 0 -make-backend/internal/gql/generated.go:3737.42,3739.4 1 0 -make-backend/internal/gql/generated.go:3741.86,3743.4 1 0 -make-backend/internal/gql/generated.go:3748.152,3750.2 1 0 -make-backend/internal/gql/generated.go:3752.172,3757.90 1 0 -make-backend/internal/gql/generated.go:3757.90,3759.4 1 0 -make-backend/internal/gql/generated.go:3760.42,3762.4 1 0 -make-backend/internal/gql/generated.go:3764.84,3766.4 1 0 -make-backend/internal/gql/generated.go:3771.165,3773.2 1 0 -make-backend/internal/gql/generated.go:3775.133,3780.90 1 0 -make-backend/internal/gql/generated.go:3780.90,3782.4 1 0 -make-backend/internal/gql/generated.go:3783.42,3785.4 1 0 -make-backend/internal/gql/generated.go:3787.83,3789.4 1 0 -make-backend/internal/gql/generated.go:3794.138,3796.2 1 0 -make-backend/internal/gql/generated.go:3798.141,3803.90 1 0 -make-backend/internal/gql/generated.go:3803.90,3805.4 1 0 -make-backend/internal/gql/generated.go:3806.42,3808.4 1 0 -make-backend/internal/gql/generated.go:3810.83,3812.4 1 0 -make-backend/internal/gql/generated.go:3817.146,3819.2 1 0 -make-backend/internal/gql/generated.go:3821.135,3826.90 1 0 -make-backend/internal/gql/generated.go:3826.90,3828.4 1 0 -make-backend/internal/gql/generated.go:3829.42,3831.4 1 0 -make-backend/internal/gql/generated.go:3833.86,3835.4 1 0 -make-backend/internal/gql/generated.go:3840.140,3842.2 1 0 -make-backend/internal/gql/generated.go:3844.142,3849.90 1 0 -make-backend/internal/gql/generated.go:3849.90,3851.4 1 0 -make-backend/internal/gql/generated.go:3852.42,3854.4 1 0 -make-backend/internal/gql/generated.go:3856.86,3858.4 1 0 -make-backend/internal/gql/generated.go:3863.147,3865.2 1 0 -make-backend/internal/gql/generated.go:3867.131,3872.90 1 0 -make-backend/internal/gql/generated.go:3872.90,3874.4 1 0 -make-backend/internal/gql/generated.go:3875.42,3877.4 1 0 -make-backend/internal/gql/generated.go:3879.83,3881.4 1 0 -make-backend/internal/gql/generated.go:3886.137,3888.2 1 0 -make-backend/internal/gql/generated.go:3890.139,3895.90 1 0 -make-backend/internal/gql/generated.go:3895.90,3897.4 1 0 -make-backend/internal/gql/generated.go:3898.42,3900.4 1 0 -make-backend/internal/gql/generated.go:3902.83,3904.4 1 0 -make-backend/internal/gql/generated.go:3909.145,3911.2 1 0 -make-backend/internal/gql/generated.go:3913.139,3918.90 1 0 -make-backend/internal/gql/generated.go:3918.90,3920.4 1 0 -make-backend/internal/gql/generated.go:3921.42,3923.4 1 0 -make-backend/internal/gql/generated.go:3925.84,3927.4 1 0 -make-backend/internal/gql/generated.go:3932.145,3934.2 1 0 -make-backend/internal/gql/generated.go:3936.138,3941.90 1 0 -make-backend/internal/gql/generated.go:3941.90,3943.4 1 0 -make-backend/internal/gql/generated.go:3944.42,3946.4 1 0 -make-backend/internal/gql/generated.go:3948.83,3950.4 1 0 -make-backend/internal/gql/generated.go:3955.144,3957.2 1 0 -make-backend/internal/gql/generated.go:3959.135,3964.90 1 0 -make-backend/internal/gql/generated.go:3964.90,3966.4 1 0 -make-backend/internal/gql/generated.go:3967.42,3969.4 1 0 -make-backend/internal/gql/generated.go:3971.86,3973.4 1 0 -make-backend/internal/gql/generated.go:3978.141,3980.2 1 0 -make-backend/internal/gql/generated.go:3982.140,3987.90 1 0 -make-backend/internal/gql/generated.go:3987.90,3989.4 1 0 -make-backend/internal/gql/generated.go:3990.42,3992.4 1 0 -make-backend/internal/gql/generated.go:3994.89,3996.4 1 0 -make-backend/internal/gql/generated.go:4001.146,4003.2 1 0 -make-backend/internal/gql/generated.go:4005.140,4010.90 1 0 -make-backend/internal/gql/generated.go:4010.90,4012.4 1 0 -make-backend/internal/gql/generated.go:4013.42,4015.4 1 0 -make-backend/internal/gql/generated.go:4017.90,4019.4 1 0 -make-backend/internal/gql/generated.go:4024.146,4026.2 1 0 -make-backend/internal/gql/generated.go:4028.133,4033.90 1 0 -make-backend/internal/gql/generated.go:4033.90,4035.4 1 0 -make-backend/internal/gql/generated.go:4036.42,4038.4 1 0 -make-backend/internal/gql/generated.go:4040.83,4042.4 1 0 -make-backend/internal/gql/generated.go:4047.138,4049.2 1 0 -make-backend/internal/gql/generated.go:4051.141,4056.90 1 0 -make-backend/internal/gql/generated.go:4056.90,4058.4 1 0 -make-backend/internal/gql/generated.go:4059.42,4061.4 1 0 -make-backend/internal/gql/generated.go:4063.86,4065.4 1 0 -make-backend/internal/gql/generated.go:4070.146,4072.2 1 0 -make-backend/internal/gql/generated.go:4074.149,4079.90 1 0 -make-backend/internal/gql/generated.go:4079.90,4081.4 1 0 -make-backend/internal/gql/generated.go:4082.42,4084.4 1 0 -make-backend/internal/gql/generated.go:4086.86,4088.4 1 0 -make-backend/internal/gql/generated.go:4093.149,4095.2 1 0 -make-backend/internal/gql/generated.go:4097.145,4102.90 1 0 -make-backend/internal/gql/generated.go:4102.90,4104.4 1 0 -make-backend/internal/gql/generated.go:4105.42,4107.4 1 0 -make-backend/internal/gql/generated.go:4109.86,4111.4 1 0 -make-backend/internal/gql/generated.go:4116.145,4118.2 1 0 -make-backend/internal/gql/generated.go:4120.148,4125.90 1 0 -make-backend/internal/gql/generated.go:4125.90,4127.4 1 0 -make-backend/internal/gql/generated.go:4128.42,4130.4 1 0 -make-backend/internal/gql/generated.go:4132.86,4134.4 1 0 -make-backend/internal/gql/generated.go:4139.148,4141.2 1 0 -make-backend/internal/gql/generated.go:4143.143,4148.90 1 0 -make-backend/internal/gql/generated.go:4148.90,4150.4 1 0 -make-backend/internal/gql/generated.go:4151.42,4153.4 1 0 -make-backend/internal/gql/generated.go:4155.83,4157.4 1 0 -make-backend/internal/gql/generated.go:4162.143,4164.2 1 0 -make-backend/internal/gql/generated.go:4166.145,4171.90 1 0 -make-backend/internal/gql/generated.go:4171.90,4173.4 1 0 -make-backend/internal/gql/generated.go:4174.42,4176.4 1 0 -make-backend/internal/gql/generated.go:4178.86,4180.4 1 0 -make-backend/internal/gql/generated.go:4185.145,4187.2 1 0 -make-backend/internal/gql/generated.go:4189.149,4194.90 1 0 -make-backend/internal/gql/generated.go:4194.90,4196.4 1 0 -make-backend/internal/gql/generated.go:4197.42,4199.4 1 0 -make-backend/internal/gql/generated.go:4201.86,4203.4 1 0 -make-backend/internal/gql/generated.go:4208.149,4210.2 1 0 -make-backend/internal/gql/generated.go:4212.152,4217.90 1 0 -make-backend/internal/gql/generated.go:4217.90,4219.4 1 0 -make-backend/internal/gql/generated.go:4220.42,4222.4 1 0 -make-backend/internal/gql/generated.go:4224.86,4226.4 1 0 -make-backend/internal/gql/generated.go:4231.152,4233.2 1 0 -make-backend/internal/gql/generated.go:4235.149,4240.90 1 0 -make-backend/internal/gql/generated.go:4240.90,4242.4 1 0 -make-backend/internal/gql/generated.go:4243.42,4245.4 1 0 -make-backend/internal/gql/generated.go:4247.86,4249.4 1 0 -make-backend/internal/gql/generated.go:4254.149,4256.2 1 0 -make-backend/internal/gql/generated.go:4258.149,4263.90 1 0 -make-backend/internal/gql/generated.go:4263.90,4265.4 1 0 -make-backend/internal/gql/generated.go:4266.42,4268.4 1 0 -make-backend/internal/gql/generated.go:4270.86,4272.4 1 0 -make-backend/internal/gql/generated.go:4277.149,4279.2 1 0 -make-backend/internal/gql/generated.go:4281.147,4286.90 1 0 -make-backend/internal/gql/generated.go:4286.90,4288.4 1 0 -make-backend/internal/gql/generated.go:4289.42,4291.4 1 0 -make-backend/internal/gql/generated.go:4293.84,4295.4 1 0 -make-backend/internal/gql/generated.go:4300.147,4302.2 1 0 -make-backend/internal/gql/generated.go:4304.149,4309.90 1 0 -make-backend/internal/gql/generated.go:4309.90,4311.4 1 0 -make-backend/internal/gql/generated.go:4312.42,4314.4 1 0 -make-backend/internal/gql/generated.go:4316.86,4318.4 1 0 -make-backend/internal/gql/generated.go:4323.149,4325.2 1 0 -make-backend/internal/gql/generated.go:4327.146,4332.90 1 0 -make-backend/internal/gql/generated.go:4332.90,4334.4 1 0 -make-backend/internal/gql/generated.go:4335.42,4337.4 1 0 -make-backend/internal/gql/generated.go:4339.94,4341.4 1 0 -make-backend/internal/gql/generated.go:4346.146,4352.97 1 0 -make-backend/internal/gql/generated.go:4352.97,4354.4 1 0 -make-backend/internal/gql/generated.go:4356.2,4356.16 1 0 -make-backend/internal/gql/generated.go:4359.146,4364.90 1 0 -make-backend/internal/gql/generated.go:4364.90,4366.4 1 0 -make-backend/internal/gql/generated.go:4367.42,4369.4 1 0 -make-backend/internal/gql/generated.go:4371.104,4373.4 1 0 -make-backend/internal/gql/generated.go:4378.146,4380.2 1 0 -make-backend/internal/gql/generated.go:4382.161,4387.90 1 0 -make-backend/internal/gql/generated.go:4387.90,4389.4 1 0 -make-backend/internal/gql/generated.go:4390.42,4392.4 1 0 -make-backend/internal/gql/generated.go:4394.83,4396.4 1 0 -make-backend/internal/gql/generated.go:4401.154,4403.2 1 0 -make-backend/internal/gql/generated.go:4405.169,4410.90 1 0 -make-backend/internal/gql/generated.go:4410.90,4412.4 1 0 -make-backend/internal/gql/generated.go:4413.42,4415.4 1 0 -make-backend/internal/gql/generated.go:4417.106,4419.4 1 0 -make-backend/internal/gql/generated.go:4424.162,4426.2 1 0 -make-backend/internal/gql/generated.go:4428.131,4433.90 1 0 -make-backend/internal/gql/generated.go:4433.90,4435.4 1 0 -make-backend/internal/gql/generated.go:4436.42,4439.4 2 0 -make-backend/internal/gql/generated.go:4441.83,4443.4 1 0 -make-backend/internal/gql/generated.go:4448.157,4454.97 1 0 -make-backend/internal/gql/generated.go:4454.97,4456.4 1 0 -make-backend/internal/gql/generated.go:4458.2,4458.15 1 0 -make-backend/internal/gql/generated.go:4458.15,4459.31 1 0 -make-backend/internal/gql/generated.go:4459.31,4462.4 2 0 -make-backend/internal/gql/generated.go:4464.2,4465.110 2 0 -make-backend/internal/gql/generated.go:4465.110,4468.3 2 0 -make-backend/internal/gql/generated.go:4469.2,4469.16 1 0 -make-backend/internal/gql/generated.go:4472.131,4477.90 1 0 -make-backend/internal/gql/generated.go:4477.90,4479.4 1 0 -make-backend/internal/gql/generated.go:4480.42,4483.4 2 0 -make-backend/internal/gql/generated.go:4485.84,4487.4 1 0 -make-backend/internal/gql/generated.go:4492.157,4498.97 1 0 -make-backend/internal/gql/generated.go:4498.97,4500.4 1 0 -make-backend/internal/gql/generated.go:4502.2,4502.15 1 0 -make-backend/internal/gql/generated.go:4502.15,4503.31 1 0 -make-backend/internal/gql/generated.go:4503.31,4506.4 2 0 -make-backend/internal/gql/generated.go:4508.2,4509.110 2 0 -make-backend/internal/gql/generated.go:4509.110,4512.3 2 0 -make-backend/internal/gql/generated.go:4513.2,4513.16 1 0 -make-backend/internal/gql/generated.go:4516.151,4521.90 1 0 -make-backend/internal/gql/generated.go:4521.90,4523.4 1 0 -make-backend/internal/gql/generated.go:4524.42,4526.4 1 0 -make-backend/internal/gql/generated.go:4528.86,4530.4 1 0 -make-backend/internal/gql/generated.go:4535.150,4537.2 1 0 -make-backend/internal/gql/generated.go:4539.147,4544.90 1 0 -make-backend/internal/gql/generated.go:4544.90,4546.4 1 0 -make-backend/internal/gql/generated.go:4547.42,4549.4 1 0 -make-backend/internal/gql/generated.go:4551.86,4553.4 1 0 -make-backend/internal/gql/generated.go:4558.146,4560.2 1 0 -make-backend/internal/gql/generated.go:4562.150,4567.90 1 0 -make-backend/internal/gql/generated.go:4567.90,4569.4 1 0 -make-backend/internal/gql/generated.go:4570.42,4572.4 1 0 -make-backend/internal/gql/generated.go:4574.86,4576.4 1 0 -make-backend/internal/gql/generated.go:4581.149,4583.2 1 0 -make-backend/internal/gql/generated.go:4585.150,4590.90 1 0 -make-backend/internal/gql/generated.go:4590.90,4592.4 1 0 -make-backend/internal/gql/generated.go:4593.42,4595.4 1 0 -make-backend/internal/gql/generated.go:4597.106,4599.4 1 0 -make-backend/internal/gql/generated.go:4604.149,4610.97 1 0 -make-backend/internal/gql/generated.go:4610.97,4612.4 1 0 -make-backend/internal/gql/generated.go:4614.2,4614.16 1 0 -make-backend/internal/gql/generated.go:4617.147,4622.90 1 0 -make-backend/internal/gql/generated.go:4622.90,4624.4 1 0 -make-backend/internal/gql/generated.go:4625.42,4627.4 1 0 -make-backend/internal/gql/generated.go:4629.86,4631.4 1 0 -make-backend/internal/gql/generated.go:4636.146,4638.2 1 0 -make-backend/internal/gql/generated.go:4640.154,4645.90 1 0 -make-backend/internal/gql/generated.go:4645.90,4647.4 1 0 -make-backend/internal/gql/generated.go:4648.42,4650.4 1 0 -make-backend/internal/gql/generated.go:4652.86,4654.4 1 0 -make-backend/internal/gql/generated.go:4659.153,4661.2 1 0 -make-backend/internal/gql/generated.go:4663.159,4668.90 1 0 -make-backend/internal/gql/generated.go:4668.90,4670.4 1 0 -make-backend/internal/gql/generated.go:4671.42,4673.4 1 0 -make-backend/internal/gql/generated.go:4675.86,4677.4 1 0 -make-backend/internal/gql/generated.go:4682.152,4684.2 1 0 -make-backend/internal/gql/generated.go:4686.162,4691.90 1 0 -make-backend/internal/gql/generated.go:4691.90,4693.4 1 0 -make-backend/internal/gql/generated.go:4694.42,4696.4 1 0 -make-backend/internal/gql/generated.go:4698.85,4700.4 1 0 -make-backend/internal/gql/generated.go:4705.155,4707.2 1 0 -make-backend/internal/gql/generated.go:4709.147,4714.90 1 0 -make-backend/internal/gql/generated.go:4714.90,4716.4 1 0 -make-backend/internal/gql/generated.go:4717.42,4719.4 1 0 -make-backend/internal/gql/generated.go:4721.83,4723.4 1 0 -make-backend/internal/gql/generated.go:4728.145,4730.2 1 0 -make-backend/internal/gql/generated.go:4732.157,4737.90 1 0 -make-backend/internal/gql/generated.go:4737.90,4739.4 1 0 -make-backend/internal/gql/generated.go:4740.42,4742.4 1 0 -make-backend/internal/gql/generated.go:4744.86,4746.4 1 0 -make-backend/internal/gql/generated.go:4751.155,4753.2 1 0 -make-backend/internal/gql/generated.go:4755.150,4760.90 1 0 -make-backend/internal/gql/generated.go:4760.90,4762.4 1 0 -make-backend/internal/gql/generated.go:4763.42,4765.4 1 0 -make-backend/internal/gql/generated.go:4767.86,4769.4 1 0 -make-backend/internal/gql/generated.go:4774.148,4776.2 1 0 -make-backend/internal/gql/generated.go:4778.150,4783.90 1 0 -make-backend/internal/gql/generated.go:4783.90,4785.4 1 0 -make-backend/internal/gql/generated.go:4786.42,4788.4 1 0 -make-backend/internal/gql/generated.go:4790.86,4792.4 1 0 -make-backend/internal/gql/generated.go:4797.148,4799.2 1 0 -make-backend/internal/gql/generated.go:4801.122,4806.90 1 0 -make-backend/internal/gql/generated.go:4806.90,4808.4 1 0 -make-backend/internal/gql/generated.go:4809.42,4812.4 2 0 -make-backend/internal/gql/generated.go:4814.98,4816.4 1 0 -make-backend/internal/gql/generated.go:4821.148,4827.97 1 0 -make-backend/internal/gql/generated.go:4827.97,4829.4 1 0 -make-backend/internal/gql/generated.go:4831.2,4831.15 1 0 -make-backend/internal/gql/generated.go:4831.15,4832.31 1 0 -make-backend/internal/gql/generated.go:4832.31,4835.4 2 0 -make-backend/internal/gql/generated.go:4837.2,4838.101 2 0 -make-backend/internal/gql/generated.go:4838.101,4841.3 2 0 -make-backend/internal/gql/generated.go:4842.2,4842.16 1 0 -make-backend/internal/gql/generated.go:4845.118,4850.90 1 0 -make-backend/internal/gql/generated.go:4850.90,4852.4 1 0 -make-backend/internal/gql/generated.go:4853.42,4856.4 2 0 -make-backend/internal/gql/generated.go:4858.94,4860.4 1 0 -make-backend/internal/gql/generated.go:4865.144,4871.97 1 0 -make-backend/internal/gql/generated.go:4871.97,4873.4 1 0 -make-backend/internal/gql/generated.go:4875.2,4875.15 1 0 -make-backend/internal/gql/generated.go:4875.15,4876.31 1 0 -make-backend/internal/gql/generated.go:4876.31,4879.4 2 0 -make-backend/internal/gql/generated.go:4881.2,4882.97 2 0 -make-backend/internal/gql/generated.go:4882.97,4885.3 2 0 -make-backend/internal/gql/generated.go:4886.2,4886.16 1 0 -make-backend/internal/gql/generated.go:4889.124,4894.90 1 0 -make-backend/internal/gql/generated.go:4894.90,4896.4 1 0 -make-backend/internal/gql/generated.go:4897.42,4900.4 2 0 -make-backend/internal/gql/generated.go:4902.100,4904.4 1 0 -make-backend/internal/gql/generated.go:4909.150,4915.97 1 0 -make-backend/internal/gql/generated.go:4915.97,4917.4 1 0 -make-backend/internal/gql/generated.go:4919.2,4919.15 1 0 -make-backend/internal/gql/generated.go:4919.15,4920.31 1 0 -make-backend/internal/gql/generated.go:4920.31,4923.4 2 0 -make-backend/internal/gql/generated.go:4925.2,4926.103 2 0 -make-backend/internal/gql/generated.go:4926.103,4929.3 2 0 -make-backend/internal/gql/generated.go:4930.2,4930.16 1 0 -make-backend/internal/gql/generated.go:4933.121,4938.90 1 0 -make-backend/internal/gql/generated.go:4938.90,4940.4 1 0 -make-backend/internal/gql/generated.go:4941.42,4944.4 2 0 -make-backend/internal/gql/generated.go:4946.93,4948.4 1 0 -make-backend/internal/gql/generated.go:4953.147,4959.97 1 0 -make-backend/internal/gql/generated.go:4959.97,4961.4 1 0 -make-backend/internal/gql/generated.go:4963.2,4963.15 1 0 -make-backend/internal/gql/generated.go:4963.15,4964.31 1 0 -make-backend/internal/gql/generated.go:4964.31,4967.4 2 0 -make-backend/internal/gql/generated.go:4969.2,4970.100 2 0 -make-backend/internal/gql/generated.go:4970.100,4973.3 2 0 -make-backend/internal/gql/generated.go:4974.2,4974.16 1 0 -make-backend/internal/gql/generated.go:4977.126,4982.90 1 0 -make-backend/internal/gql/generated.go:4982.90,4984.4 1 0 -make-backend/internal/gql/generated.go:4985.42,4988.4 2 0 -make-backend/internal/gql/generated.go:4990.107,4992.4 1 0 -make-backend/internal/gql/generated.go:4997.152,5003.97 1 0 -make-backend/internal/gql/generated.go:5003.97,5005.4 1 0 -make-backend/internal/gql/generated.go:5007.2,5007.15 1 0 -make-backend/internal/gql/generated.go:5007.15,5008.31 1 0 -make-backend/internal/gql/generated.go:5008.31,5011.4 2 0 -make-backend/internal/gql/generated.go:5013.2,5014.105 2 0 -make-backend/internal/gql/generated.go:5014.105,5017.3 2 0 -make-backend/internal/gql/generated.go:5018.2,5018.16 1 0 -make-backend/internal/gql/generated.go:5021.125,5026.90 1 0 -make-backend/internal/gql/generated.go:5026.90,5028.4 1 0 -make-backend/internal/gql/generated.go:5029.42,5032.4 2 0 -make-backend/internal/gql/generated.go:5034.84,5036.4 1 0 -make-backend/internal/gql/generated.go:5041.151,5047.97 1 0 -make-backend/internal/gql/generated.go:5047.97,5049.4 1 0 -make-backend/internal/gql/generated.go:5051.2,5051.15 1 0 -make-backend/internal/gql/generated.go:5051.15,5052.31 1 0 -make-backend/internal/gql/generated.go:5052.31,5055.4 2 0 -make-backend/internal/gql/generated.go:5057.2,5058.104 2 0 -make-backend/internal/gql/generated.go:5058.104,5061.3 2 0 -make-backend/internal/gql/generated.go:5062.2,5062.16 1 0 -make-backend/internal/gql/generated.go:5065.133,5070.90 1 0 -make-backend/internal/gql/generated.go:5070.90,5072.4 1 0 -make-backend/internal/gql/generated.go:5073.42,5076.4 2 0 -make-backend/internal/gql/generated.go:5078.84,5080.4 1 0 -make-backend/internal/gql/generated.go:5085.159,5091.97 1 0 -make-backend/internal/gql/generated.go:5091.97,5093.4 1 0 -make-backend/internal/gql/generated.go:5095.2,5095.15 1 0 -make-backend/internal/gql/generated.go:5095.15,5096.31 1 0 -make-backend/internal/gql/generated.go:5096.31,5099.4 2 0 -make-backend/internal/gql/generated.go:5101.2,5102.112 2 0 -make-backend/internal/gql/generated.go:5102.112,5105.3 2 0 -make-backend/internal/gql/generated.go:5106.2,5106.16 1 0 -make-backend/internal/gql/generated.go:5109.131,5114.90 1 0 -make-backend/internal/gql/generated.go:5114.90,5116.4 1 0 -make-backend/internal/gql/generated.go:5117.42,5120.4 2 0 -make-backend/internal/gql/generated.go:5122.84,5124.4 1 0 -make-backend/internal/gql/generated.go:5129.157,5135.97 1 0 -make-backend/internal/gql/generated.go:5135.97,5137.4 1 0 -make-backend/internal/gql/generated.go:5139.2,5139.15 1 0 -make-backend/internal/gql/generated.go:5139.15,5140.31 1 0 -make-backend/internal/gql/generated.go:5140.31,5143.4 2 0 -make-backend/internal/gql/generated.go:5145.2,5146.110 2 0 -make-backend/internal/gql/generated.go:5146.110,5149.3 2 0 -make-backend/internal/gql/generated.go:5150.2,5150.16 1 0 -make-backend/internal/gql/generated.go:5153.130,5158.90 1 0 -make-backend/internal/gql/generated.go:5158.90,5160.4 1 0 -make-backend/internal/gql/generated.go:5161.42,5164.4 2 0 -make-backend/internal/gql/generated.go:5166.84,5168.4 1 0 -make-backend/internal/gql/generated.go:5173.156,5179.97 1 0 -make-backend/internal/gql/generated.go:5179.97,5181.4 1 0 -make-backend/internal/gql/generated.go:5183.2,5183.15 1 0 -make-backend/internal/gql/generated.go:5183.15,5184.31 1 0 -make-backend/internal/gql/generated.go:5184.31,5187.4 2 0 -make-backend/internal/gql/generated.go:5189.2,5190.109 2 0 -make-backend/internal/gql/generated.go:5190.109,5193.3 2 0 -make-backend/internal/gql/generated.go:5194.2,5194.16 1 0 -make-backend/internal/gql/generated.go:5197.116,5202.90 1 0 -make-backend/internal/gql/generated.go:5202.90,5204.4 1 0 -make-backend/internal/gql/generated.go:5205.42,5208.4 2 0 -make-backend/internal/gql/generated.go:5210.92,5212.4 1 0 -make-backend/internal/gql/generated.go:5217.142,5223.97 1 0 -make-backend/internal/gql/generated.go:5223.97,5225.4 1 0 -make-backend/internal/gql/generated.go:5227.2,5227.15 1 0 -make-backend/internal/gql/generated.go:5227.15,5228.31 1 0 -make-backend/internal/gql/generated.go:5228.31,5231.4 2 0 -make-backend/internal/gql/generated.go:5233.2,5234.95 2 0 -make-backend/internal/gql/generated.go:5234.95,5237.3 2 0 -make-backend/internal/gql/generated.go:5238.2,5238.16 1 0 -make-backend/internal/gql/generated.go:5241.123,5246.90 1 0 -make-backend/internal/gql/generated.go:5246.90,5248.4 1 0 -make-backend/internal/gql/generated.go:5249.42,5251.4 1 0 -make-backend/internal/gql/generated.go:5253.92,5255.4 1 0 -make-backend/internal/gql/generated.go:5260.147,5266.97 1 0 -make-backend/internal/gql/generated.go:5266.97,5268.4 1 0 -make-backend/internal/gql/generated.go:5270.2,5270.16 1 0 -make-backend/internal/gql/generated.go:5273.116,5278.90 1 0 -make-backend/internal/gql/generated.go:5278.90,5280.4 1 0 -make-backend/internal/gql/generated.go:5281.42,5284.4 2 0 -make-backend/internal/gql/generated.go:5286.92,5288.4 1 0 -make-backend/internal/gql/generated.go:5293.142,5299.97 1 0 -make-backend/internal/gql/generated.go:5299.97,5301.4 1 0 -make-backend/internal/gql/generated.go:5303.2,5303.15 1 0 -make-backend/internal/gql/generated.go:5303.15,5304.31 1 0 -make-backend/internal/gql/generated.go:5304.31,5307.4 2 0 -make-backend/internal/gql/generated.go:5309.2,5310.95 2 0 -make-backend/internal/gql/generated.go:5310.95,5313.3 2 0 -make-backend/internal/gql/generated.go:5314.2,5314.16 1 0 -make-backend/internal/gql/generated.go:5317.131,5322.90 1 0 -make-backend/internal/gql/generated.go:5322.90,5324.4 1 0 -make-backend/internal/gql/generated.go:5325.42,5328.4 2 0 -make-backend/internal/gql/generated.go:5330.94,5332.4 1 0 -make-backend/internal/gql/generated.go:5337.157,5343.97 1 0 -make-backend/internal/gql/generated.go:5343.97,5345.4 1 0 -make-backend/internal/gql/generated.go:5347.2,5347.15 1 0 -make-backend/internal/gql/generated.go:5347.15,5348.31 1 0 -make-backend/internal/gql/generated.go:5348.31,5351.4 2 0 -make-backend/internal/gql/generated.go:5353.2,5354.110 2 0 -make-backend/internal/gql/generated.go:5354.110,5357.3 2 0 -make-backend/internal/gql/generated.go:5358.2,5358.16 1 0 -make-backend/internal/gql/generated.go:5361.118,5366.90 1 0 -make-backend/internal/gql/generated.go:5366.90,5368.4 1 0 -make-backend/internal/gql/generated.go:5369.42,5372.4 2 0 -make-backend/internal/gql/generated.go:5374.99,5376.4 1 0 -make-backend/internal/gql/generated.go:5381.144,5387.97 1 0 -make-backend/internal/gql/generated.go:5387.97,5389.4 1 0 -make-backend/internal/gql/generated.go:5391.2,5391.15 1 0 -make-backend/internal/gql/generated.go:5391.15,5392.31 1 0 -make-backend/internal/gql/generated.go:5392.31,5395.4 2 0 -make-backend/internal/gql/generated.go:5397.2,5398.97 2 0 -make-backend/internal/gql/generated.go:5398.97,5401.3 2 0 -make-backend/internal/gql/generated.go:5402.2,5402.16 1 0 -make-backend/internal/gql/generated.go:5405.120,5410.90 1 0 -make-backend/internal/gql/generated.go:5410.90,5412.4 1 0 -make-backend/internal/gql/generated.go:5413.42,5415.4 1 0 -make-backend/internal/gql/generated.go:5417.101,5419.4 1 0 -make-backend/internal/gql/generated.go:5424.144,5430.97 1 0 -make-backend/internal/gql/generated.go:5430.97,5432.4 1 0 -make-backend/internal/gql/generated.go:5434.2,5434.16 1 0 -make-backend/internal/gql/generated.go:5437.145,5442.90 1 0 -make-backend/internal/gql/generated.go:5442.90,5444.4 1 0 -make-backend/internal/gql/generated.go:5445.42,5447.4 1 0 -make-backend/internal/gql/generated.go:5449.83,5451.4 1 0 -make-backend/internal/gql/generated.go:5456.144,5458.2 1 0 -make-backend/internal/gql/generated.go:5460.150,5465.90 1 0 -make-backend/internal/gql/generated.go:5465.90,5467.4 1 0 -make-backend/internal/gql/generated.go:5468.42,5470.4 1 0 -make-backend/internal/gql/generated.go:5472.84,5474.4 1 0 -make-backend/internal/gql/generated.go:5479.149,5481.2 1 0 -make-backend/internal/gql/generated.go:5483.158,5488.90 1 0 -make-backend/internal/gql/generated.go:5488.90,5490.4 1 0 -make-backend/internal/gql/generated.go:5491.42,5493.4 1 0 -make-backend/internal/gql/generated.go:5495.84,5497.4 1 0 -make-backend/internal/gql/generated.go:5502.157,5504.2 1 0 -make-backend/internal/gql/generated.go:5506.155,5511.90 1 0 -make-backend/internal/gql/generated.go:5511.90,5513.4 1 0 -make-backend/internal/gql/generated.go:5514.42,5516.4 1 0 -make-backend/internal/gql/generated.go:5518.83,5520.4 1 0 -make-backend/internal/gql/generated.go:5525.154,5527.2 1 0 -make-backend/internal/gql/generated.go:5529.154,5534.90 1 0 -make-backend/internal/gql/generated.go:5534.90,5536.4 1 0 -make-backend/internal/gql/generated.go:5537.42,5539.4 1 0 -make-backend/internal/gql/generated.go:5541.86,5543.4 1 0 -make-backend/internal/gql/generated.go:5548.153,5550.2 1 0 -make-backend/internal/gql/generated.go:5552.153,5557.90 1 0 -make-backend/internal/gql/generated.go:5557.90,5559.4 1 0 -make-backend/internal/gql/generated.go:5560.42,5562.4 1 0 -make-backend/internal/gql/generated.go:5564.89,5566.4 1 0 -make-backend/internal/gql/generated.go:5571.152,5573.2 1 0 -make-backend/internal/gql/generated.go:5575.151,5580.90 1 0 -make-backend/internal/gql/generated.go:5580.90,5582.4 1 0 -make-backend/internal/gql/generated.go:5583.42,5585.4 1 0 -make-backend/internal/gql/generated.go:5587.89,5589.4 1 0 -make-backend/internal/gql/generated.go:5594.150,5596.2 1 0 -make-backend/internal/gql/generated.go:5598.151,5603.90 1 0 -make-backend/internal/gql/generated.go:5603.90,5605.4 1 0 -make-backend/internal/gql/generated.go:5606.42,5608.4 1 0 -make-backend/internal/gql/generated.go:5610.84,5612.4 1 0 -make-backend/internal/gql/generated.go:5617.150,5619.2 1 0 -make-backend/internal/gql/generated.go:5621.145,5626.90 1 0 -make-backend/internal/gql/generated.go:5626.90,5628.4 1 0 -make-backend/internal/gql/generated.go:5629.42,5631.4 1 0 -make-backend/internal/gql/generated.go:5633.83,5635.4 1 0 -make-backend/internal/gql/generated.go:5640.144,5642.2 1 0 -make-backend/internal/gql/generated.go:5644.156,5649.90 1 0 -make-backend/internal/gql/generated.go:5649.90,5651.4 1 0 -make-backend/internal/gql/generated.go:5652.42,5654.4 1 0 -make-backend/internal/gql/generated.go:5656.83,5658.4 1 0 -make-backend/internal/gql/generated.go:5663.155,5665.2 1 0 -make-backend/internal/gql/generated.go:5667.153,5672.90 1 0 -make-backend/internal/gql/generated.go:5672.90,5674.4 1 0 -make-backend/internal/gql/generated.go:5675.42,5677.4 1 0 -make-backend/internal/gql/generated.go:5679.83,5681.4 1 0 -make-backend/internal/gql/generated.go:5686.152,5688.2 1 0 -make-backend/internal/gql/generated.go:5690.152,5695.90 1 0 -make-backend/internal/gql/generated.go:5695.90,5697.4 1 0 -make-backend/internal/gql/generated.go:5698.42,5700.4 1 0 -make-backend/internal/gql/generated.go:5702.83,5704.4 1 0 -make-backend/internal/gql/generated.go:5709.151,5711.2 1 0 -make-backend/internal/gql/generated.go:5713.154,5718.90 1 0 -make-backend/internal/gql/generated.go:5718.90,5720.4 1 0 -make-backend/internal/gql/generated.go:5721.42,5723.4 1 0 -make-backend/internal/gql/generated.go:5725.89,5727.4 1 0 -make-backend/internal/gql/generated.go:5732.153,5734.2 1 0 -make-backend/internal/gql/generated.go:5736.149,5741.90 1 0 -make-backend/internal/gql/generated.go:5741.90,5743.4 1 0 -make-backend/internal/gql/generated.go:5744.42,5746.4 1 0 -make-backend/internal/gql/generated.go:5748.86,5750.4 1 0 -make-backend/internal/gql/generated.go:5755.148,5757.2 1 0 -make-backend/internal/gql/generated.go:5759.161,5764.90 1 0 -make-backend/internal/gql/generated.go:5764.90,5766.4 1 0 -make-backend/internal/gql/generated.go:5767.42,5769.4 1 0 -make-backend/internal/gql/generated.go:5771.86,5773.4 1 0 -make-backend/internal/gql/generated.go:5778.155,5780.2 1 0 -make-backend/internal/gql/generated.go:5782.157,5787.90 1 0 -make-backend/internal/gql/generated.go:5787.90,5789.4 1 0 -make-backend/internal/gql/generated.go:5790.42,5792.4 1 0 -make-backend/internal/gql/generated.go:5794.86,5796.4 1 0 -make-backend/internal/gql/generated.go:5801.151,5803.2 1 0 -make-backend/internal/gql/generated.go:5805.160,5810.90 1 0 -make-backend/internal/gql/generated.go:5810.90,5812.4 1 0 -make-backend/internal/gql/generated.go:5813.42,5815.4 1 0 -make-backend/internal/gql/generated.go:5817.86,5819.4 1 0 -make-backend/internal/gql/generated.go:5824.154,5826.2 1 0 -make-backend/internal/gql/generated.go:5828.159,5833.90 1 0 -make-backend/internal/gql/generated.go:5833.90,5835.4 1 0 -make-backend/internal/gql/generated.go:5836.42,5838.4 1 0 -make-backend/internal/gql/generated.go:5840.87,5842.4 1 0 -make-backend/internal/gql/generated.go:5847.153,5849.2 1 0 -make-backend/internal/gql/generated.go:5851.157,5856.90 1 0 -make-backend/internal/gql/generated.go:5856.90,5858.4 1 0 -make-backend/internal/gql/generated.go:5859.42,5861.4 1 0 -make-backend/internal/gql/generated.go:5863.86,5865.4 1 0 -make-backend/internal/gql/generated.go:5870.151,5872.2 1 0 -make-backend/internal/gql/generated.go:5874.164,5879.90 1 0 -make-backend/internal/gql/generated.go:5879.90,5881.4 1 0 -make-backend/internal/gql/generated.go:5882.42,5884.4 1 0 -make-backend/internal/gql/generated.go:5886.86,5888.4 1 0 -make-backend/internal/gql/generated.go:5893.158,5895.2 1 0 -make-backend/internal/gql/generated.go:5897.158,5902.90 1 0 -make-backend/internal/gql/generated.go:5902.90,5904.4 1 0 -make-backend/internal/gql/generated.go:5905.42,5907.4 1 0 -make-backend/internal/gql/generated.go:5909.83,5911.4 1 0 -make-backend/internal/gql/generated.go:5916.156,5918.2 1 0 -make-backend/internal/gql/generated.go:5920.157,5925.90 1 0 -make-backend/internal/gql/generated.go:5925.90,5927.4 1 0 -make-backend/internal/gql/generated.go:5928.42,5930.4 1 0 -make-backend/internal/gql/generated.go:5932.89,5934.4 1 0 -make-backend/internal/gql/generated.go:5939.155,5941.2 1 0 -make-backend/internal/gql/generated.go:5943.154,5948.90 1 0 -make-backend/internal/gql/generated.go:5948.90,5950.4 1 0 -make-backend/internal/gql/generated.go:5951.42,5953.4 1 0 -make-backend/internal/gql/generated.go:5955.90,5957.4 1 0 -make-backend/internal/gql/generated.go:5962.152,5964.2 1 0 -make-backend/internal/gql/generated.go:5966.155,5971.90 1 0 -make-backend/internal/gql/generated.go:5971.90,5973.4 1 0 -make-backend/internal/gql/generated.go:5974.42,5976.4 1 0 -make-backend/internal/gql/generated.go:5978.90,5980.4 1 0 -make-backend/internal/gql/generated.go:5985.153,5987.2 1 0 -make-backend/internal/gql/generated.go:5989.151,5994.90 1 0 -make-backend/internal/gql/generated.go:5994.90,5996.4 1 0 -make-backend/internal/gql/generated.go:5997.42,5999.4 1 0 -make-backend/internal/gql/generated.go:6001.84,6003.4 1 0 -make-backend/internal/gql/generated.go:6008.149,6010.2 1 0 -make-backend/internal/gql/generated.go:6012.139,6017.90 1 0 -make-backend/internal/gql/generated.go:6017.90,6019.4 1 0 -make-backend/internal/gql/generated.go:6020.42,6022.4 1 0 -make-backend/internal/gql/generated.go:6024.83,6026.4 1 0 -make-backend/internal/gql/generated.go:6031.141,6033.2 1 0 -make-backend/internal/gql/generated.go:6035.144,6040.90 1 0 -make-backend/internal/gql/generated.go:6040.90,6042.4 1 0 -make-backend/internal/gql/generated.go:6043.42,6045.4 1 0 -make-backend/internal/gql/generated.go:6047.83,6049.4 1 0 -make-backend/internal/gql/generated.go:6054.146,6056.2 1 0 -make-backend/internal/gql/generated.go:6058.145,6063.90 1 0 -make-backend/internal/gql/generated.go:6063.90,6065.4 1 0 -make-backend/internal/gql/generated.go:6066.42,6068.4 1 0 -make-backend/internal/gql/generated.go:6070.86,6072.4 1 0 -make-backend/internal/gql/generated.go:6077.147,6079.2 1 0 -make-backend/internal/gql/generated.go:6081.143,6086.90 1 0 -make-backend/internal/gql/generated.go:6086.90,6088.4 1 0 -make-backend/internal/gql/generated.go:6089.42,6091.4 1 0 -make-backend/internal/gql/generated.go:6093.89,6095.4 1 0 -make-backend/internal/gql/generated.go:6100.145,6102.2 1 0 -make-backend/internal/gql/generated.go:6104.147,6109.90 1 0 -make-backend/internal/gql/generated.go:6109.90,6111.4 1 0 -make-backend/internal/gql/generated.go:6112.42,6114.4 1 0 -make-backend/internal/gql/generated.go:6116.86,6118.4 1 0 -make-backend/internal/gql/generated.go:6123.148,6125.2 1 0 -make-backend/internal/gql/generated.go:6127.143,6132.90 1 0 -make-backend/internal/gql/generated.go:6132.90,6134.4 1 0 -make-backend/internal/gql/generated.go:6135.42,6137.4 1 0 -make-backend/internal/gql/generated.go:6139.86,6141.4 1 0 -make-backend/internal/gql/generated.go:6146.144,6148.2 1 0 -make-backend/internal/gql/generated.go:6150.146,6155.90 1 0 -make-backend/internal/gql/generated.go:6155.90,6157.4 1 0 -make-backend/internal/gql/generated.go:6158.42,6160.4 1 0 -make-backend/internal/gql/generated.go:6162.86,6164.4 1 0 -make-backend/internal/gql/generated.go:6169.147,6171.2 1 0 -make-backend/internal/gql/generated.go:6173.139,6178.90 1 0 -make-backend/internal/gql/generated.go:6178.90,6180.4 1 0 -make-backend/internal/gql/generated.go:6181.42,6183.4 1 0 -make-backend/internal/gql/generated.go:6185.83,6187.4 1 0 -make-backend/internal/gql/generated.go:6192.141,6194.2 1 0 -make-backend/internal/gql/generated.go:6196.141,6201.90 1 0 -make-backend/internal/gql/generated.go:6201.90,6203.4 1 0 -make-backend/internal/gql/generated.go:6204.42,6206.4 1 0 -make-backend/internal/gql/generated.go:6208.86,6210.4 1 0 -make-backend/internal/gql/generated.go:6215.143,6217.2 1 0 -make-backend/internal/gql/generated.go:6219.150,6224.90 1 0 -make-backend/internal/gql/generated.go:6224.90,6226.4 1 0 -make-backend/internal/gql/generated.go:6227.42,6229.4 1 0 -make-backend/internal/gql/generated.go:6231.84,6233.4 1 0 -make-backend/internal/gql/generated.go:6238.152,6240.2 1 0 -make-backend/internal/gql/generated.go:6242.143,6247.90 1 0 -make-backend/internal/gql/generated.go:6247.90,6249.4 1 0 -make-backend/internal/gql/generated.go:6250.42,6252.4 1 0 -make-backend/internal/gql/generated.go:6254.102,6256.4 1 0 -make-backend/internal/gql/generated.go:6261.145,6263.2 1 0 -make-backend/internal/gql/generated.go:6265.131,6270.90 1 0 -make-backend/internal/gql/generated.go:6270.90,6272.4 1 0 -make-backend/internal/gql/generated.go:6273.42,6275.4 1 0 -make-backend/internal/gql/generated.go:6277.83,6279.4 1 0 -make-backend/internal/gql/generated.go:6284.137,6286.2 1 0 -make-backend/internal/gql/generated.go:6288.134,6293.90 1 0 -make-backend/internal/gql/generated.go:6293.90,6295.4 1 0 -make-backend/internal/gql/generated.go:6296.42,6298.4 1 0 -make-backend/internal/gql/generated.go:6300.86,6302.4 1 0 -make-backend/internal/gql/generated.go:6307.140,6309.2 1 0 -make-backend/internal/gql/generated.go:6311.138,6316.90 1 0 -make-backend/internal/gql/generated.go:6316.90,6318.4 1 0 -make-backend/internal/gql/generated.go:6319.42,6321.4 1 0 -make-backend/internal/gql/generated.go:6323.86,6325.4 1 0 -make-backend/internal/gql/generated.go:6330.144,6332.2 1 0 -make-backend/internal/gql/generated.go:6334.137,6339.90 1 0 -make-backend/internal/gql/generated.go:6339.90,6341.4 1 0 -make-backend/internal/gql/generated.go:6342.42,6344.4 1 0 -make-backend/internal/gql/generated.go:6346.86,6348.4 1 0 -make-backend/internal/gql/generated.go:6353.143,6355.2 1 0 -make-backend/internal/gql/generated.go:6357.137,6362.90 1 0 -make-backend/internal/gql/generated.go:6362.90,6364.4 1 0 -make-backend/internal/gql/generated.go:6365.42,6367.4 1 0 -make-backend/internal/gql/generated.go:6369.86,6371.4 1 0 -make-backend/internal/gql/generated.go:6376.143,6378.2 1 0 -make-backend/internal/gql/generated.go:6380.138,6385.90 1 0 -make-backend/internal/gql/generated.go:6385.90,6387.4 1 0 -make-backend/internal/gql/generated.go:6388.42,6390.4 1 0 -make-backend/internal/gql/generated.go:6392.89,6394.4 1 0 -make-backend/internal/gql/generated.go:6399.144,6401.2 1 0 -make-backend/internal/gql/generated.go:6403.143,6408.90 1 0 -make-backend/internal/gql/generated.go:6408.90,6410.4 1 0 -make-backend/internal/gql/generated.go:6411.42,6413.4 1 0 -make-backend/internal/gql/generated.go:6415.84,6417.4 1 0 -make-backend/internal/gql/generated.go:6422.149,6424.2 1 0 -make-backend/internal/gql/generated.go:6426.137,6431.90 1 0 -make-backend/internal/gql/generated.go:6431.90,6433.4 1 0 -make-backend/internal/gql/generated.go:6434.42,6436.4 1 0 -make-backend/internal/gql/generated.go:6438.84,6440.4 1 0 -make-backend/internal/gql/generated.go:6445.143,6447.2 1 0 -make-backend/internal/gql/generated.go:6449.134,6454.90 1 0 -make-backend/internal/gql/generated.go:6454.90,6456.4 1 0 -make-backend/internal/gql/generated.go:6457.42,6459.4 1 0 -make-backend/internal/gql/generated.go:6461.86,6463.4 1 0 -make-backend/internal/gql/generated.go:6468.140,6470.2 1 0 -make-backend/internal/gql/generated.go:6472.134,6477.90 1 0 -make-backend/internal/gql/generated.go:6477.90,6479.4 1 0 -make-backend/internal/gql/generated.go:6480.42,6482.4 1 0 -make-backend/internal/gql/generated.go:6484.84,6486.4 1 0 -make-backend/internal/gql/generated.go:6491.140,6493.2 1 0 -make-backend/internal/gql/generated.go:6495.142,6500.90 1 0 -make-backend/internal/gql/generated.go:6500.90,6502.4 1 0 -make-backend/internal/gql/generated.go:6503.42,6505.4 1 0 -make-backend/internal/gql/generated.go:6507.85,6509.4 1 0 -make-backend/internal/gql/generated.go:6514.148,6516.2 1 0 -make-backend/internal/gql/generated.go:6518.137,6523.90 1 0 -make-backend/internal/gql/generated.go:6523.90,6525.4 1 0 -make-backend/internal/gql/generated.go:6526.42,6528.4 1 0 -make-backend/internal/gql/generated.go:6529.69,6532.57 2 0 -make-backend/internal/gql/generated.go:6532.57,6533.37 1 0 -make-backend/internal/gql/generated.go:6533.37,6536.6 2 0 -make-backend/internal/gql/generated.go:6537.5,6537.55 1 0 -make-backend/internal/gql/generated.go:6540.4,6541.15 2 0 -make-backend/internal/gql/generated.go:6543.86,6545.4 1 0 -make-backend/internal/gql/generated.go:6550.143,6552.2 1 0 -make-backend/internal/gql/generated.go:6554.131,6559.90 1 0 -make-backend/internal/gql/generated.go:6559.90,6561.4 1 0 -make-backend/internal/gql/generated.go:6562.42,6564.4 1 0 -make-backend/internal/gql/generated.go:6566.83,6568.4 1 0 -make-backend/internal/gql/generated.go:6573.137,6575.2 1 0 -make-backend/internal/gql/generated.go:6577.142,6582.90 1 0 -make-backend/internal/gql/generated.go:6582.90,6584.4 1 0 -make-backend/internal/gql/generated.go:6585.42,6587.4 1 0 -make-backend/internal/gql/generated.go:6589.83,6591.4 1 0 -make-backend/internal/gql/generated.go:6596.148,6598.2 1 0 -make-backend/internal/gql/generated.go:6600.133,6605.90 1 0 -make-backend/internal/gql/generated.go:6605.90,6607.4 1 0 -make-backend/internal/gql/generated.go:6608.42,6610.4 1 0 -make-backend/internal/gql/generated.go:6612.86,6614.4 1 0 -make-backend/internal/gql/generated.go:6619.139,6621.2 1 0 -make-backend/internal/gql/generated.go:6623.135,6628.90 1 0 -make-backend/internal/gql/generated.go:6628.90,6630.4 1 0 -make-backend/internal/gql/generated.go:6631.42,6633.4 1 0 -make-backend/internal/gql/generated.go:6635.84,6637.4 1 0 -make-backend/internal/gql/generated.go:6642.141,6644.2 1 0 -make-backend/internal/gql/generated.go:6646.152,6651.90 1 0 -make-backend/internal/gql/generated.go:6651.90,6653.4 1 0 -make-backend/internal/gql/generated.go:6654.42,6656.4 1 0 -make-backend/internal/gql/generated.go:6658.86,6660.4 1 0 -make-backend/internal/gql/generated.go:6665.146,6667.2 1 0 -make-backend/internal/gql/generated.go:6669.159,6674.90 1 0 -make-backend/internal/gql/generated.go:6674.90,6676.4 1 0 -make-backend/internal/gql/generated.go:6677.42,6679.4 1 0 -make-backend/internal/gql/generated.go:6681.87,6683.4 1 0 -make-backend/internal/gql/generated.go:6688.153,6690.2 1 0 -make-backend/internal/gql/generated.go:6692.160,6697.90 1 0 -make-backend/internal/gql/generated.go:6697.90,6699.4 1 0 -make-backend/internal/gql/generated.go:6700.42,6702.4 1 0 -make-backend/internal/gql/generated.go:6704.84,6706.4 1 0 -make-backend/internal/gql/generated.go:6711.154,6713.2 1 0 -make-backend/internal/gql/generated.go:6715.157,6720.90 1 0 -make-backend/internal/gql/generated.go:6720.90,6722.4 1 0 -make-backend/internal/gql/generated.go:6723.42,6725.4 1 0 -make-backend/internal/gql/generated.go:6727.88,6729.4 1 0 -make-backend/internal/gql/generated.go:6734.151,6736.2 1 0 -make-backend/internal/gql/generated.go:6738.152,6743.90 1 0 -make-backend/internal/gql/generated.go:6743.90,6745.4 1 0 -make-backend/internal/gql/generated.go:6746.42,6748.4 1 0 -make-backend/internal/gql/generated.go:6750.106,6752.4 1 0 -make-backend/internal/gql/generated.go:6757.148,6763.97 1 0 -make-backend/internal/gql/generated.go:6763.97,6765.4 1 0 -make-backend/internal/gql/generated.go:6767.2,6767.15 1 0 -make-backend/internal/gql/generated.go:6767.15,6768.31 1 0 -make-backend/internal/gql/generated.go:6768.31,6771.4 2 0 -make-backend/internal/gql/generated.go:6773.2,6774.101 2 0 -make-backend/internal/gql/generated.go:6774.101,6777.3 2 0 -make-backend/internal/gql/generated.go:6778.2,6778.16 1 0 -make-backend/internal/gql/generated.go:6781.152,6786.90 1 0 -make-backend/internal/gql/generated.go:6786.90,6788.4 1 0 -make-backend/internal/gql/generated.go:6789.42,6791.4 1 0 -make-backend/internal/gql/generated.go:6793.86,6795.4 1 0 -make-backend/internal/gql/generated.go:6800.146,6802.2 1 0 -make-backend/internal/gql/generated.go:6804.159,6809.90 1 0 -make-backend/internal/gql/generated.go:6809.90,6811.4 1 0 -make-backend/internal/gql/generated.go:6812.42,6814.4 1 0 -make-backend/internal/gql/generated.go:6816.87,6818.4 1 0 -make-backend/internal/gql/generated.go:6823.153,6825.2 1 0 -make-backend/internal/gql/generated.go:6827.160,6832.90 1 0 -make-backend/internal/gql/generated.go:6832.90,6834.4 1 0 -make-backend/internal/gql/generated.go:6835.42,6837.4 1 0 -make-backend/internal/gql/generated.go:6839.84,6841.4 1 0 -make-backend/internal/gql/generated.go:6846.154,6848.2 1 0 -make-backend/internal/gql/generated.go:6850.165,6855.90 1 0 -make-backend/internal/gql/generated.go:6855.90,6857.4 1 0 -make-backend/internal/gql/generated.go:6858.42,6860.4 1 0 -make-backend/internal/gql/generated.go:6862.87,6864.4 1 0 -make-backend/internal/gql/generated.go:6869.159,6871.2 1 0 -make-backend/internal/gql/generated.go:6873.144,6878.90 1 0 -make-backend/internal/gql/generated.go:6878.90,6880.4 1 0 -make-backend/internal/gql/generated.go:6881.42,6883.4 1 0 -make-backend/internal/gql/generated.go:6885.86,6887.4 1 0 -make-backend/internal/gql/generated.go:6892.142,6894.2 1 0 -make-backend/internal/gql/generated.go:6896.151,6901.90 1 0 -make-backend/internal/gql/generated.go:6901.90,6903.4 1 0 -make-backend/internal/gql/generated.go:6904.42,6906.4 1 0 -make-backend/internal/gql/generated.go:6908.87,6910.4 1 0 -make-backend/internal/gql/generated.go:6915.149,6917.2 1 0 -make-backend/internal/gql/generated.go:6919.144,6924.90 1 0 -make-backend/internal/gql/generated.go:6924.90,6926.4 1 0 -make-backend/internal/gql/generated.go:6927.42,6929.4 1 0 -make-backend/internal/gql/generated.go:6931.106,6933.4 1 0 -make-backend/internal/gql/generated.go:6938.144,6944.97 1 0 -make-backend/internal/gql/generated.go:6944.97,6946.4 1 0 -make-backend/internal/gql/generated.go:6948.2,6948.15 1 0 -make-backend/internal/gql/generated.go:6948.15,6949.31 1 0 -make-backend/internal/gql/generated.go:6949.31,6952.4 2 0 -make-backend/internal/gql/generated.go:6954.2,6955.97 2 0 -make-backend/internal/gql/generated.go:6955.97,6958.3 2 0 -make-backend/internal/gql/generated.go:6959.2,6959.16 1 0 -make-backend/internal/gql/generated.go:6962.144,6967.90 1 0 -make-backend/internal/gql/generated.go:6967.90,6969.4 1 0 -make-backend/internal/gql/generated.go:6970.42,6972.4 1 0 -make-backend/internal/gql/generated.go:6974.99,6976.4 1 0 -make-backend/internal/gql/generated.go:6981.142,6987.97 1 0 -make-backend/internal/gql/generated.go:6987.97,6989.4 1 0 -make-backend/internal/gql/generated.go:6991.2,6991.16 1 0 -make-backend/internal/gql/generated.go:6994.152,6999.90 1 0 -make-backend/internal/gql/generated.go:6999.90,7001.4 1 0 -make-backend/internal/gql/generated.go:7002.42,7004.4 1 0 -make-backend/internal/gql/generated.go:7006.84,7008.4 1 0 -make-backend/internal/gql/generated.go:7013.150,7015.2 1 0 -make-backend/internal/gql/generated.go:7017.157,7022.90 1 0 -make-backend/internal/gql/generated.go:7022.90,7024.4 1 0 -make-backend/internal/gql/generated.go:7025.42,7027.4 1 0 -make-backend/internal/gql/generated.go:7029.87,7031.4 1 0 -make-backend/internal/gql/generated.go:7036.155,7038.2 1 0 -make-backend/internal/gql/generated.go:7040.154,7045.90 1 0 -make-backend/internal/gql/generated.go:7045.90,7047.4 1 0 -make-backend/internal/gql/generated.go:7048.42,7050.4 1 0 -make-backend/internal/gql/generated.go:7052.86,7054.4 1 0 -make-backend/internal/gql/generated.go:7059.147,7061.2 1 0 -make-backend/internal/gql/generated.go:7063.161,7068.90 1 0 -make-backend/internal/gql/generated.go:7068.90,7070.4 1 0 -make-backend/internal/gql/generated.go:7071.42,7073.4 1 0 -make-backend/internal/gql/generated.go:7075.87,7077.4 1 0 -make-backend/internal/gql/generated.go:7082.154,7084.2 1 0 -make-backend/internal/gql/generated.go:7086.154,7091.90 1 0 -make-backend/internal/gql/generated.go:7091.90,7093.4 1 0 -make-backend/internal/gql/generated.go:7094.42,7096.4 1 0 -make-backend/internal/gql/generated.go:7098.99,7100.4 1 0 -make-backend/internal/gql/generated.go:7105.147,7111.97 1 0 -make-backend/internal/gql/generated.go:7111.97,7113.4 1 0 -make-backend/internal/gql/generated.go:7115.2,7115.16 1 0 -make-backend/internal/gql/generated.go:7118.162,7123.90 1 0 -make-backend/internal/gql/generated.go:7123.90,7125.4 1 0 -make-backend/internal/gql/generated.go:7126.42,7128.4 1 0 -make-backend/internal/gql/generated.go:7130.87,7132.4 1 0 -make-backend/internal/gql/generated.go:7137.155,7139.2 1 0 -make-backend/internal/gql/generated.go:7141.162,7146.90 1 0 -make-backend/internal/gql/generated.go:7146.90,7148.4 1 0 -make-backend/internal/gql/generated.go:7149.42,7151.4 1 0 -make-backend/internal/gql/generated.go:7153.84,7155.4 1 0 -make-backend/internal/gql/generated.go:7160.155,7162.2 1 0 -make-backend/internal/gql/generated.go:7164.167,7169.90 1 0 -make-backend/internal/gql/generated.go:7169.90,7171.4 1 0 -make-backend/internal/gql/generated.go:7172.42,7174.4 1 0 -make-backend/internal/gql/generated.go:7176.87,7178.4 1 0 -make-backend/internal/gql/generated.go:7183.160,7185.2 1 0 -make-backend/internal/gql/generated.go:7187.153,7192.90 1 0 -make-backend/internal/gql/generated.go:7192.90,7194.4 1 0 -make-backend/internal/gql/generated.go:7195.42,7197.4 1 0 -make-backend/internal/gql/generated.go:7199.87,7201.4 1 0 -make-backend/internal/gql/generated.go:7206.150,7208.2 1 0 -make-backend/internal/gql/generated.go:7210.147,7215.90 1 0 -make-backend/internal/gql/generated.go:7215.90,7217.4 1 0 -make-backend/internal/gql/generated.go:7218.42,7220.4 1 0 -make-backend/internal/gql/generated.go:7222.100,7224.4 1 0 -make-backend/internal/gql/generated.go:7229.144,7235.97 1 0 -make-backend/internal/gql/generated.go:7235.97,7237.4 1 0 -make-backend/internal/gql/generated.go:7239.2,7239.16 1 0 -make-backend/internal/gql/generated.go:7242.151,7247.90 1 0 -make-backend/internal/gql/generated.go:7247.90,7249.4 1 0 -make-backend/internal/gql/generated.go:7250.42,7252.4 1 0 -make-backend/internal/gql/generated.go:7254.99,7256.4 1 0 -make-backend/internal/gql/generated.go:7261.148,7267.97 1 0 -make-backend/internal/gql/generated.go:7267.97,7269.4 1 0 -make-backend/internal/gql/generated.go:7271.2,7271.16 1 0 -make-backend/internal/gql/generated.go:7274.154,7279.90 1 0 -make-backend/internal/gql/generated.go:7279.90,7281.4 1 0 -make-backend/internal/gql/generated.go:7282.42,7284.4 1 0 -make-backend/internal/gql/generated.go:7286.99,7288.4 1 0 -make-backend/internal/gql/generated.go:7293.151,7299.97 1 0 -make-backend/internal/gql/generated.go:7299.97,7301.4 1 0 -make-backend/internal/gql/generated.go:7303.2,7303.16 1 0 -make-backend/internal/gql/generated.go:7306.158,7311.90 1 0 -make-backend/internal/gql/generated.go:7311.90,7313.4 1 0 -make-backend/internal/gql/generated.go:7314.42,7316.4 1 0 -make-backend/internal/gql/generated.go:7318.99,7320.4 1 0 -make-backend/internal/gql/generated.go:7325.155,7331.97 1 0 -make-backend/internal/gql/generated.go:7331.97,7333.4 1 0 -make-backend/internal/gql/generated.go:7335.2,7335.16 1 0 -make-backend/internal/gql/generated.go:7338.152,7343.90 1 0 -make-backend/internal/gql/generated.go:7343.90,7345.4 1 0 -make-backend/internal/gql/generated.go:7346.42,7348.4 1 0 -make-backend/internal/gql/generated.go:7350.105,7352.4 1 0 -make-backend/internal/gql/generated.go:7357.149,7363.97 1 0 -make-backend/internal/gql/generated.go:7363.97,7365.4 1 0 -make-backend/internal/gql/generated.go:7367.2,7367.16 1 0 -make-backend/internal/gql/generated.go:7370.142,7375.90 1 0 -make-backend/internal/gql/generated.go:7375.90,7377.4 1 0 -make-backend/internal/gql/generated.go:7378.42,7380.4 1 0 -make-backend/internal/gql/generated.go:7382.86,7384.4 1 0 -make-backend/internal/gql/generated.go:7389.141,7391.2 1 0 -make-backend/internal/gql/generated.go:7393.142,7398.90 1 0 -make-backend/internal/gql/generated.go:7398.90,7400.4 1 0 -make-backend/internal/gql/generated.go:7401.42,7403.4 1 0 -make-backend/internal/gql/generated.go:7405.87,7407.4 1 0 -make-backend/internal/gql/generated.go:7412.141,7414.2 1 0 -make-backend/internal/gql/generated.go:7416.149,7421.90 1 0 -make-backend/internal/gql/generated.go:7421.90,7423.4 1 0 -make-backend/internal/gql/generated.go:7424.42,7426.4 1 0 -make-backend/internal/gql/generated.go:7428.87,7430.4 1 0 -make-backend/internal/gql/generated.go:7435.148,7437.2 1 0 -make-backend/internal/gql/generated.go:7439.152,7444.90 1 0 -make-backend/internal/gql/generated.go:7444.90,7446.4 1 0 -make-backend/internal/gql/generated.go:7447.42,7449.4 1 0 -make-backend/internal/gql/generated.go:7451.87,7453.4 1 0 -make-backend/internal/gql/generated.go:7458.151,7460.2 1 0 -make-backend/internal/gql/generated.go:7462.144,7467.90 1 0 -make-backend/internal/gql/generated.go:7467.90,7469.4 1 0 -make-backend/internal/gql/generated.go:7470.42,7473.4 2 0 -make-backend/internal/gql/generated.go:7475.101,7477.4 1 0 -make-backend/internal/gql/generated.go:7482.145,7488.97 1 0 -make-backend/internal/gql/generated.go:7488.97,7490.4 1 0 -make-backend/internal/gql/generated.go:7492.2,7492.15 1 0 -make-backend/internal/gql/generated.go:7492.15,7493.31 1 0 -make-backend/internal/gql/generated.go:7493.31,7496.4 2 0 -make-backend/internal/gql/generated.go:7498.2,7499.98 2 0 -make-backend/internal/gql/generated.go:7499.98,7502.3 2 0 -make-backend/internal/gql/generated.go:7503.2,7503.16 1 0 -make-backend/internal/gql/generated.go:7506.148,7511.90 1 0 -make-backend/internal/gql/generated.go:7511.90,7513.4 1 0 -make-backend/internal/gql/generated.go:7514.42,7516.4 1 0 -make-backend/internal/gql/generated.go:7518.100,7520.4 1 0 -make-backend/internal/gql/generated.go:7525.147,7531.97 1 0 -make-backend/internal/gql/generated.go:7531.97,7533.4 1 0 -make-backend/internal/gql/generated.go:7535.2,7535.16 1 0 -make-backend/internal/gql/generated.go:7538.151,7543.90 1 0 -make-backend/internal/gql/generated.go:7543.90,7545.4 1 0 -make-backend/internal/gql/generated.go:7546.42,7548.4 1 0 -make-backend/internal/gql/generated.go:7550.100,7552.4 1 0 -make-backend/internal/gql/generated.go:7557.150,7563.97 1 0 -make-backend/internal/gql/generated.go:7563.97,7565.4 1 0 -make-backend/internal/gql/generated.go:7567.2,7567.16 1 0 -make-backend/internal/gql/generated.go:7570.148,7575.90 1 0 -make-backend/internal/gql/generated.go:7575.90,7577.4 1 0 -make-backend/internal/gql/generated.go:7578.42,7581.4 2 0 -make-backend/internal/gql/generated.go:7583.105,7585.4 1 0 -make-backend/internal/gql/generated.go:7590.149,7596.97 1 0 -make-backend/internal/gql/generated.go:7596.97,7598.4 1 0 -make-backend/internal/gql/generated.go:7600.2,7600.15 1 0 -make-backend/internal/gql/generated.go:7600.15,7601.31 1 0 -make-backend/internal/gql/generated.go:7601.31,7604.4 2 0 -make-backend/internal/gql/generated.go:7606.2,7607.102 2 0 -make-backend/internal/gql/generated.go:7607.102,7610.3 2 0 -make-backend/internal/gql/generated.go:7611.2,7611.16 1 0 -make-backend/internal/gql/generated.go:7614.149,7619.90 1 0 -make-backend/internal/gql/generated.go:7619.90,7621.4 1 0 -make-backend/internal/gql/generated.go:7622.42,7624.4 1 0 -make-backend/internal/gql/generated.go:7626.106,7628.4 1 0 -make-backend/internal/gql/generated.go:7633.148,7639.97 1 0 -make-backend/internal/gql/generated.go:7639.97,7641.4 1 0 -make-backend/internal/gql/generated.go:7643.2,7643.16 1 0 -make-backend/internal/gql/generated.go:7646.144,7651.90 1 0 -make-backend/internal/gql/generated.go:7651.90,7653.4 1 0 -make-backend/internal/gql/generated.go:7654.42,7656.4 1 0 -make-backend/internal/gql/generated.go:7658.99,7660.4 1 0 -make-backend/internal/gql/generated.go:7665.143,7671.97 1 0 -make-backend/internal/gql/generated.go:7671.97,7673.4 1 0 -make-backend/internal/gql/generated.go:7675.2,7675.16 1 0 -make-backend/internal/gql/generated.go:7678.145,7683.90 1 0 -make-backend/internal/gql/generated.go:7683.90,7685.4 1 0 -make-backend/internal/gql/generated.go:7686.42,7688.4 1 0 -make-backend/internal/gql/generated.go:7690.84,7692.4 1 0 -make-backend/internal/gql/generated.go:7697.144,7699.2 1 0 -make-backend/internal/gql/generated.go:7709.135,7710.29 1 0 -make-backend/internal/gql/generated.go:7711.11,7712.22 1 0 -make-backend/internal/gql/generated.go:7713.27,7714.42 1 0 -make-backend/internal/gql/generated.go:7715.28,7716.17 1 0 -make-backend/internal/gql/generated.go:7716.17,7718.4 1 0 -make-backend/internal/gql/generated.go:7719.3,7719.41 1 0 -make-backend/internal/gql/generated.go:7720.27,7721.42 1 0 -make-backend/internal/gql/generated.go:7722.28,7723.17 1 0 -make-backend/internal/gql/generated.go:7723.17,7725.4 1 0 -make-backend/internal/gql/generated.go:7726.3,7726.41 1 0 -make-backend/internal/gql/generated.go:7727.10,7728.50 1 0 -make-backend/internal/gql/generated.go:7728.50,7730.4 1 0 -make-backend/internal/gql/generated.go:7730.9,7731.124 1 0 -make-backend/internal/gql/generated.go:7736.131,7737.29 1 0 -make-backend/internal/gql/generated.go:7738.11,7739.22 1 0 -make-backend/internal/gql/generated.go:7740.25,7741.17 1 0 -make-backend/internal/gql/generated.go:7741.17,7743.4 1 0 -make-backend/internal/gql/generated.go:7744.3,7744.38 1 0 -make-backend/internal/gql/generated.go:7745.32,7746.17 1 0 -make-backend/internal/gql/generated.go:7746.17,7748.4 1 0 -make-backend/internal/gql/generated.go:7749.3,7749.45 1 0 -make-backend/internal/gql/generated.go:7750.27,7751.17 1 0 -make-backend/internal/gql/generated.go:7751.17,7753.4 1 0 -make-backend/internal/gql/generated.go:7754.3,7754.40 1 0 -make-backend/internal/gql/generated.go:7755.26,7756.17 1 0 -make-backend/internal/gql/generated.go:7756.17,7758.4 1 0 -make-backend/internal/gql/generated.go:7759.3,7759.39 1 0 -make-backend/internal/gql/generated.go:7760.10,7761.50 1 0 -make-backend/internal/gql/generated.go:7761.50,7763.4 1 0 -make-backend/internal/gql/generated.go:7763.9,7764.122 1 0 -make-backend/internal/gql/generated.go:7775.132,7781.31 5 0 -make-backend/internal/gql/generated.go:7781.31,7782.21 1 0 -make-backend/internal/gql/generated.go:7783.21,7784.58 1 0 -make-backend/internal/gql/generated.go:7785.13,7787.37 2 0 -make-backend/internal/gql/generated.go:7787.37,7789.5 1 0 -make-backend/internal/gql/generated.go:7790.20,7792.37 2 0 -make-backend/internal/gql/generated.go:7792.37,7794.5 1 0 -make-backend/internal/gql/generated.go:7795.21,7797.37 2 0 -make-backend/internal/gql/generated.go:7797.37,7799.5 1 0 -make-backend/internal/gql/generated.go:7800.16,7802.45 2 0 -make-backend/internal/gql/generated.go:7802.45,7804.5 1 0 -make-backend/internal/gql/generated.go:7805.24,7807.37 2 0 -make-backend/internal/gql/generated.go:7807.37,7809.5 1 0 -make-backend/internal/gql/generated.go:7810.11,7811.55 1 0 -make-backend/internal/gql/generated.go:7814.2,7815.22 2 0 -make-backend/internal/gql/generated.go:7815.22,7817.3 1 0 -make-backend/internal/gql/generated.go:7819.2,7828.12 3 0 -make-backend/internal/gql/generated.go:7833.136,7839.31 5 0 -make-backend/internal/gql/generated.go:7839.31,7840.21 1 0 -make-backend/internal/gql/generated.go:7841.21,7842.60 1 0 -make-backend/internal/gql/generated.go:7843.13,7845.37 2 0 -make-backend/internal/gql/generated.go:7845.37,7847.5 1 0 -make-backend/internal/gql/generated.go:7848.15,7851.89 2 0 -make-backend/internal/gql/generated.go:7851.89,7852.18 1 0 -make-backend/internal/gql/generated.go:7852.18,7853.34 1 0 -make-backend/internal/gql/generated.go:7853.34,7855.7 1 0 -make-backend/internal/gql/generated.go:7857.5,7858.28 2 0 -make-backend/internal/gql/generated.go:7858.28,7860.6 1 0 -make-backend/internal/gql/generated.go:7861.5,7861.15 1 0 -make-backend/internal/gql/generated.go:7864.4,7864.26 1 0 -make-backend/internal/gql/generated.go:7864.26,7867.91 3 0 -make-backend/internal/gql/generated.go:7867.91,7869.6 1 0 -make-backend/internal/gql/generated.go:7871.5,7871.50 1 0 -make-backend/internal/gql/generated.go:7871.50,7873.13 2 0 -make-backend/internal/gql/generated.go:7873.13,7876.7 2 0 -make-backend/internal/gql/generated.go:7877.6,7877.33 1 0 -make-backend/internal/gql/generated.go:7881.5,7882.13 2 0 -make-backend/internal/gql/generated.go:7885.4,7885.68 1 0 -make-backend/internal/gql/generated.go:7885.68,7885.98 1 0 -make-backend/internal/gql/generated.go:7886.19,7888.37 2 0 -make-backend/internal/gql/generated.go:7888.37,7890.5 1 0 -make-backend/internal/gql/generated.go:7891.11,7892.55 1 0 -make-backend/internal/gql/generated.go:7895.2,7896.22 2 0 -make-backend/internal/gql/generated.go:7896.22,7898.3 1 0 -make-backend/internal/gql/generated.go:7900.2,7909.12 3 0 -make-backend/internal/gql/generated.go:7914.138,7920.31 5 0 -make-backend/internal/gql/generated.go:7920.31,7921.21 1 0 -make-backend/internal/gql/generated.go:7922.21,7923.61 1 0 -make-backend/internal/gql/generated.go:7924.13,7926.37 2 0 -make-backend/internal/gql/generated.go:7926.37,7928.5 1 0 -make-backend/internal/gql/generated.go:7929.21,7931.37 2 0 -make-backend/internal/gql/generated.go:7931.37,7933.5 1 0 -make-backend/internal/gql/generated.go:7934.11,7935.55 1 0 -make-backend/internal/gql/generated.go:7938.2,7939.22 2 0 -make-backend/internal/gql/generated.go:7939.22,7941.3 1 0 -make-backend/internal/gql/generated.go:7943.2,7952.12 3 0 -make-backend/internal/gql/generated.go:7957.130,7963.31 5 0 -make-backend/internal/gql/generated.go:7963.31,7964.21 1 0 -make-backend/internal/gql/generated.go:7965.21,7966.57 1 0 -make-backend/internal/gql/generated.go:7967.17,7969.37 2 0 -make-backend/internal/gql/generated.go:7969.37,7971.5 1 0 -make-backend/internal/gql/generated.go:7972.19,7974.37 2 0 -make-backend/internal/gql/generated.go:7974.37,7976.5 1 0 -make-backend/internal/gql/generated.go:7977.24,7979.37 2 0 -make-backend/internal/gql/generated.go:7979.37,7981.5 1 0 -make-backend/internal/gql/generated.go:7982.27,7984.37 2 0 -make-backend/internal/gql/generated.go:7984.37,7986.5 1 0 -make-backend/internal/gql/generated.go:7987.22,7989.45 2 0 -make-backend/internal/gql/generated.go:7989.45,7991.5 1 0 -make-backend/internal/gql/generated.go:7992.24,7994.45 2 0 -make-backend/internal/gql/generated.go:7994.45,7996.5 1 0 -make-backend/internal/gql/generated.go:7997.16,7999.37 2 0 -make-backend/internal/gql/generated.go:7999.37,8001.5 1 0 -make-backend/internal/gql/generated.go:8002.28,8004.45 2 0 -make-backend/internal/gql/generated.go:8004.45,8006.5 1 0 -make-backend/internal/gql/generated.go:8007.30,8009.45 2 0 -make-backend/internal/gql/generated.go:8009.45,8011.5 1 0 -make-backend/internal/gql/generated.go:8012.11,8013.55 1 0 -make-backend/internal/gql/generated.go:8016.2,8017.22 2 0 -make-backend/internal/gql/generated.go:8017.22,8019.3 1 0 -make-backend/internal/gql/generated.go:8021.2,8030.12 3 0 -make-backend/internal/gql/generated.go:8035.140,8041.31 5 0 -make-backend/internal/gql/generated.go:8041.31,8042.21 1 0 -make-backend/internal/gql/generated.go:8043.21,8044.62 1 0 -make-backend/internal/gql/generated.go:8045.25,8047.37 2 0 -make-backend/internal/gql/generated.go:8047.37,8049.5 1 0 -make-backend/internal/gql/generated.go:8050.30,8052.37 2 0 -make-backend/internal/gql/generated.go:8052.37,8054.5 1 0 -make-backend/internal/gql/generated.go:8055.20,8057.37 2 0 -make-backend/internal/gql/generated.go:8057.37,8059.5 1 0 -make-backend/internal/gql/generated.go:8060.11,8061.55 1 0 -make-backend/internal/gql/generated.go:8064.2,8065.22 2 0 -make-backend/internal/gql/generated.go:8065.22,8067.3 1 0 -make-backend/internal/gql/generated.go:8069.2,8078.12 3 0 -make-backend/internal/gql/generated.go:8083.130,8089.31 5 0 -make-backend/internal/gql/generated.go:8089.31,8090.21 1 0 -make-backend/internal/gql/generated.go:8091.21,8092.57 1 0 -make-backend/internal/gql/generated.go:8093.13,8095.37 2 0 -make-backend/internal/gql/generated.go:8095.37,8097.5 1 0 -make-backend/internal/gql/generated.go:8098.16,8100.37 2 0 -make-backend/internal/gql/generated.go:8100.37,8102.5 1 0 -make-backend/internal/gql/generated.go:8103.15,8105.37 2 0 -make-backend/internal/gql/generated.go:8105.37,8107.5 1 0 -make-backend/internal/gql/generated.go:8108.24,8110.45 2 0 -make-backend/internal/gql/generated.go:8110.45,8112.5 1 0 -make-backend/internal/gql/generated.go:8113.11,8114.55 1 0 -make-backend/internal/gql/generated.go:8117.2,8118.22 2 0 -make-backend/internal/gql/generated.go:8118.22,8120.3 1 0 -make-backend/internal/gql/generated.go:8122.2,8131.12 3 0 -make-backend/internal/gql/generated.go:8136.126,8142.31 5 0 -make-backend/internal/gql/generated.go:8142.31,8143.21 1 0 -make-backend/internal/gql/generated.go:8144.21,8145.55 1 0 -make-backend/internal/gql/generated.go:8146.20,8148.37 2 0 -make-backend/internal/gql/generated.go:8148.37,8150.5 1 0 -make-backend/internal/gql/generated.go:8151.19,8153.37 2 0 -make-backend/internal/gql/generated.go:8153.37,8155.5 1 0 -make-backend/internal/gql/generated.go:8156.11,8157.55 1 0 -make-backend/internal/gql/generated.go:8160.2,8161.22 2 0 -make-backend/internal/gql/generated.go:8161.22,8163.3 1 0 -make-backend/internal/gql/generated.go:8165.2,8174.12 3 0 -make-backend/internal/gql/generated.go:8179.130,8185.31 5 0 -make-backend/internal/gql/generated.go:8185.31,8186.21 1 0 -make-backend/internal/gql/generated.go:8187.21,8188.57 1 0 -make-backend/internal/gql/generated.go:8189.24,8191.37 2 0 -make-backend/internal/gql/generated.go:8191.37,8193.5 1 0 -make-backend/internal/gql/generated.go:8194.22,8196.37 2 0 -make-backend/internal/gql/generated.go:8196.37,8198.5 1 0 -make-backend/internal/gql/generated.go:8199.20,8201.45 2 0 -make-backend/internal/gql/generated.go:8201.45,8203.5 1 0 -make-backend/internal/gql/generated.go:8204.21,8206.45 2 0 -make-backend/internal/gql/generated.go:8206.45,8208.5 1 0 -make-backend/internal/gql/generated.go:8209.17,8211.37 2 0 -make-backend/internal/gql/generated.go:8211.37,8213.5 1 0 -make-backend/internal/gql/generated.go:8214.11,8215.55 1 0 -make-backend/internal/gql/generated.go:8218.2,8219.22 2 0 -make-backend/internal/gql/generated.go:8219.22,8221.3 1 0 -make-backend/internal/gql/generated.go:8223.2,8232.12 3 0 -make-backend/internal/gql/generated.go:8237.118,8243.31 5 0 -make-backend/internal/gql/generated.go:8243.31,8244.21 1 0 -make-backend/internal/gql/generated.go:8245.21,8246.51 1 0 -make-backend/internal/gql/generated.go:8247.13,8249.37 2 0 -make-backend/internal/gql/generated.go:8249.37,8251.5 1 0 -make-backend/internal/gql/generated.go:8252.15,8254.37 2 0 -make-backend/internal/gql/generated.go:8254.37,8256.5 1 0 -make-backend/internal/gql/generated.go:8257.13,8259.37 2 0 -make-backend/internal/gql/generated.go:8259.37,8261.5 1 0 -make-backend/internal/gql/generated.go:8262.17,8264.37 2 0 -make-backend/internal/gql/generated.go:8264.37,8266.5 1 0 -make-backend/internal/gql/generated.go:8267.19,8269.45 2 0 -make-backend/internal/gql/generated.go:8269.45,8271.5 1 0 -make-backend/internal/gql/generated.go:8272.19,8274.45 2 0 -make-backend/internal/gql/generated.go:8274.45,8276.5 1 0 -make-backend/internal/gql/generated.go:8277.26,8279.45 2 0 -make-backend/internal/gql/generated.go:8279.45,8281.5 1 0 -make-backend/internal/gql/generated.go:8282.20,8284.37 2 0 -make-backend/internal/gql/generated.go:8284.37,8286.5 1 0 -make-backend/internal/gql/generated.go:8287.24,8289.37 2 0 -make-backend/internal/gql/generated.go:8289.37,8291.5 1 0 -make-backend/internal/gql/generated.go:8292.11,8293.55 1 0 -make-backend/internal/gql/generated.go:8296.2,8297.22 2 0 -make-backend/internal/gql/generated.go:8297.22,8299.3 1 0 -make-backend/internal/gql/generated.go:8301.2,8310.12 3 0 -make-backend/internal/gql/generated.go:8315.124,8321.31 5 0 -make-backend/internal/gql/generated.go:8321.31,8322.21 1 0 -make-backend/internal/gql/generated.go:8323.21,8324.54 1 0 -make-backend/internal/gql/generated.go:8325.20,8327.37 2 0 -make-backend/internal/gql/generated.go:8327.37,8329.5 1 0 -make-backend/internal/gql/generated.go:8330.21,8332.37 2 0 -make-backend/internal/gql/generated.go:8332.37,8334.5 1 0 -make-backend/internal/gql/generated.go:8335.16,8337.45 2 0 -make-backend/internal/gql/generated.go:8337.45,8339.5 1 0 -make-backend/internal/gql/generated.go:8340.11,8341.55 1 0 -make-backend/internal/gql/generated.go:8344.2,8345.22 2 0 -make-backend/internal/gql/generated.go:8345.22,8347.3 1 0 -make-backend/internal/gql/generated.go:8349.2,8358.12 3 0 -make-backend/internal/gql/generated.go:8363.124,8369.31 5 0 -make-backend/internal/gql/generated.go:8369.31,8370.21 1 0 -make-backend/internal/gql/generated.go:8371.21,8372.54 1 0 -make-backend/internal/gql/generated.go:8373.13,8375.37 2 0 -make-backend/internal/gql/generated.go:8375.37,8377.5 1 0 -make-backend/internal/gql/generated.go:8378.15,8380.37 2 0 -make-backend/internal/gql/generated.go:8380.37,8382.5 1 0 -make-backend/internal/gql/generated.go:8383.19,8385.37 2 0 -make-backend/internal/gql/generated.go:8385.37,8387.5 1 0 -make-backend/internal/gql/generated.go:8388.18,8390.37 2 0 -make-backend/internal/gql/generated.go:8390.37,8392.5 1 0 -make-backend/internal/gql/generated.go:8393.17,8395.37 2 0 -make-backend/internal/gql/generated.go:8395.37,8397.5 1 0 -make-backend/internal/gql/generated.go:8398.19,8400.45 2 0 -make-backend/internal/gql/generated.go:8400.45,8402.5 1 0 -make-backend/internal/gql/generated.go:8403.18,8405.37 2 0 -make-backend/internal/gql/generated.go:8405.37,8407.5 1 0 -make-backend/internal/gql/generated.go:8408.23,8410.37 2 0 -make-backend/internal/gql/generated.go:8410.37,8412.5 1 0 -make-backend/internal/gql/generated.go:8413.22,8415.37 2 0 -make-backend/internal/gql/generated.go:8415.37,8417.5 1 0 -make-backend/internal/gql/generated.go:8418.21,8420.37 2 0 -make-backend/internal/gql/generated.go:8420.37,8422.5 1 0 -make-backend/internal/gql/generated.go:8423.27,8425.37 2 0 -make-backend/internal/gql/generated.go:8425.37,8427.5 1 0 -make-backend/internal/gql/generated.go:8428.35,8430.37 2 0 -make-backend/internal/gql/generated.go:8430.37,8432.5 1 0 -make-backend/internal/gql/generated.go:8433.24,8435.37 2 0 -make-backend/internal/gql/generated.go:8435.37,8437.5 1 0 -make-backend/internal/gql/generated.go:8438.29,8440.37 2 0 -make-backend/internal/gql/generated.go:8440.37,8442.5 1 0 -make-backend/internal/gql/generated.go:8443.27,8445.37 2 0 -make-backend/internal/gql/generated.go:8445.37,8447.5 1 0 -make-backend/internal/gql/generated.go:8448.11,8449.55 1 0 -make-backend/internal/gql/generated.go:8452.2,8453.22 2 0 -make-backend/internal/gql/generated.go:8453.22,8455.3 1 0 -make-backend/internal/gql/generated.go:8457.2,8466.12 3 0 -make-backend/internal/gql/generated.go:8471.140,8477.31 5 0 -make-backend/internal/gql/generated.go:8477.31,8478.21 1 0 -make-backend/internal/gql/generated.go:8479.21,8480.62 1 0 -make-backend/internal/gql/generated.go:8481.13,8483.37 2 0 -make-backend/internal/gql/generated.go:8483.37,8485.5 1 0 -make-backend/internal/gql/generated.go:8486.23,8488.37 2 0 -make-backend/internal/gql/generated.go:8488.37,8490.5 1 0 -make-backend/internal/gql/generated.go:8491.15,8493.37 2 0 -make-backend/internal/gql/generated.go:8493.37,8495.5 1 0 -make-backend/internal/gql/generated.go:8496.28,8498.45 2 0 -make-backend/internal/gql/generated.go:8498.45,8500.5 1 0 -make-backend/internal/gql/generated.go:8501.11,8502.55 1 0 -make-backend/internal/gql/generated.go:8505.2,8506.22 2 0 -make-backend/internal/gql/generated.go:8506.22,8508.3 1 0 -make-backend/internal/gql/generated.go:8510.2,8519.12 3 0 -make-backend/internal/gql/generated.go:8524.116,8530.31 5 0 -make-backend/internal/gql/generated.go:8530.31,8531.21 1 0 -make-backend/internal/gql/generated.go:8532.21,8533.50 1 0 -make-backend/internal/gql/generated.go:8534.13,8536.37 2 0 -make-backend/internal/gql/generated.go:8536.37,8538.5 1 0 -make-backend/internal/gql/generated.go:8539.21,8541.37 2 0 -make-backend/internal/gql/generated.go:8541.37,8543.5 1 0 -make-backend/internal/gql/generated.go:8544.15,8546.37 2 0 -make-backend/internal/gql/generated.go:8546.37,8548.5 1 0 -make-backend/internal/gql/generated.go:8549.22,8551.37 2 0 -make-backend/internal/gql/generated.go:8551.37,8553.5 1 0 -make-backend/internal/gql/generated.go:8554.11,8555.55 1 0 -make-backend/internal/gql/generated.go:8558.2,8559.22 2 0 -make-backend/internal/gql/generated.go:8559.22,8561.3 1 0 -make-backend/internal/gql/generated.go:8563.2,8572.12 3 0 -make-backend/internal/gql/generated.go:8577.114,8583.31 5 0 -make-backend/internal/gql/generated.go:8583.31,8584.21 1 0 -make-backend/internal/gql/generated.go:8585.21,8586.49 1 0 -make-backend/internal/gql/generated.go:8587.13,8589.37 2 0 -make-backend/internal/gql/generated.go:8589.37,8591.5 1 0 -make-backend/internal/gql/generated.go:8592.21,8594.37 2 0 -make-backend/internal/gql/generated.go:8594.37,8596.5 1 0 -make-backend/internal/gql/generated.go:8597.21,8599.45 2 0 -make-backend/internal/gql/generated.go:8599.45,8601.5 1 0 -make-backend/internal/gql/generated.go:8602.20,8604.37 2 0 -make-backend/internal/gql/generated.go:8604.37,8606.5 1 0 -make-backend/internal/gql/generated.go:8607.17,8609.37 2 0 -make-backend/internal/gql/generated.go:8609.37,8611.5 1 0 -make-backend/internal/gql/generated.go:8612.22,8614.37 2 0 -make-backend/internal/gql/generated.go:8614.37,8616.5 1 0 -make-backend/internal/gql/generated.go:8617.22,8619.45 2 0 -make-backend/internal/gql/generated.go:8619.45,8621.5 1 0 -make-backend/internal/gql/generated.go:8622.11,8623.55 1 0 -make-backend/internal/gql/generated.go:8626.2,8627.22 2 0 -make-backend/internal/gql/generated.go:8627.22,8629.3 1 0 -make-backend/internal/gql/generated.go:8631.2,8640.12 3 0 -make-backend/internal/gql/generated.go:8645.116,8651.31 5 0 -make-backend/internal/gql/generated.go:8651.31,8652.21 1 0 -make-backend/internal/gql/generated.go:8653.21,8654.50 1 0 -make-backend/internal/gql/generated.go:8655.13,8657.37 2 0 -make-backend/internal/gql/generated.go:8657.37,8659.5 1 0 -make-backend/internal/gql/generated.go:8660.21,8662.37 2 0 -make-backend/internal/gql/generated.go:8662.37,8664.5 1 0 -make-backend/internal/gql/generated.go:8665.11,8666.55 1 0 -make-backend/internal/gql/generated.go:8669.2,8670.22 2 0 -make-backend/internal/gql/generated.go:8670.22,8672.3 1 0 -make-backend/internal/gql/generated.go:8674.2,8683.12 3 0 -make-backend/internal/gql/generated.go:8688.126,8694.31 5 0 -make-backend/internal/gql/generated.go:8694.31,8695.21 1 0 -make-backend/internal/gql/generated.go:8696.21,8697.55 1 0 -make-backend/internal/gql/generated.go:8698.19,8700.37 2 0 -make-backend/internal/gql/generated.go:8700.37,8702.5 1 0 -make-backend/internal/gql/generated.go:8703.15,8705.37 2 0 -make-backend/internal/gql/generated.go:8705.37,8707.5 1 0 -make-backend/internal/gql/generated.go:8708.18,8710.37 2 0 -make-backend/internal/gql/generated.go:8710.37,8712.5 1 0 -make-backend/internal/gql/generated.go:8713.11,8714.55 1 0 -make-backend/internal/gql/generated.go:8717.2,8718.22 2 0 -make-backend/internal/gql/generated.go:8718.22,8720.3 1 0 -make-backend/internal/gql/generated.go:8722.2,8731.12 3 0 -make-backend/internal/gql/generated.go:8736.126,8742.31 5 0 -make-backend/internal/gql/generated.go:8742.31,8743.21 1 0 -make-backend/internal/gql/generated.go:8744.21,8745.55 1 0 -make-backend/internal/gql/generated.go:8746.13,8748.37 2 0 -make-backend/internal/gql/generated.go:8748.37,8750.5 1 0 -make-backend/internal/gql/generated.go:8751.15,8753.37 2 0 -make-backend/internal/gql/generated.go:8753.37,8755.5 1 0 -make-backend/internal/gql/generated.go:8756.19,8758.37 2 0 -make-backend/internal/gql/generated.go:8758.37,8760.5 1 0 -make-backend/internal/gql/generated.go:8761.22,8763.37 2 0 -make-backend/internal/gql/generated.go:8763.37,8765.5 1 0 -make-backend/internal/gql/generated.go:8766.19,8768.37 2 0 -make-backend/internal/gql/generated.go:8768.37,8770.5 1 0 -make-backend/internal/gql/generated.go:8771.19,8773.45 2 0 -make-backend/internal/gql/generated.go:8773.45,8775.5 1 0 -make-backend/internal/gql/generated.go:8776.17,8778.37 2 0 -make-backend/internal/gql/generated.go:8778.37,8780.5 1 0 -make-backend/internal/gql/generated.go:8781.19,8783.37 2 0 -make-backend/internal/gql/generated.go:8783.37,8785.5 1 0 -make-backend/internal/gql/generated.go:8786.16,8789.89 2 0 -make-backend/internal/gql/generated.go:8789.89,8790.18 1 0 -make-backend/internal/gql/generated.go:8790.18,8791.34 1 0 -make-backend/internal/gql/generated.go:8791.34,8793.7 1 0 -make-backend/internal/gql/generated.go:8795.5,8796.28 2 0 -make-backend/internal/gql/generated.go:8796.28,8798.6 1 0 -make-backend/internal/gql/generated.go:8799.5,8799.15 1 0 -make-backend/internal/gql/generated.go:8802.4,8802.26 1 0 -make-backend/internal/gql/generated.go:8802.26,8805.91 3 0 -make-backend/internal/gql/generated.go:8805.91,8807.6 1 0 -make-backend/internal/gql/generated.go:8809.5,8809.50 1 0 -make-backend/internal/gql/generated.go:8809.50,8811.13 2 0 -make-backend/internal/gql/generated.go:8811.13,8814.7 2 0 -make-backend/internal/gql/generated.go:8815.6,8815.33 1 0 -make-backend/internal/gql/generated.go:8819.5,8820.13 2 0 -make-backend/internal/gql/generated.go:8823.4,8823.68 1 0 -make-backend/internal/gql/generated.go:8823.68,8823.98 1 0 -make-backend/internal/gql/generated.go:8824.16,8827.89 2 0 -make-backend/internal/gql/generated.go:8827.89,8828.18 1 0 -make-backend/internal/gql/generated.go:8828.18,8829.34 1 0 -make-backend/internal/gql/generated.go:8829.34,8831.7 1 0 -make-backend/internal/gql/generated.go:8833.5,8834.28 2 0 -make-backend/internal/gql/generated.go:8834.28,8836.6 1 0 -make-backend/internal/gql/generated.go:8837.5,8837.15 1 0 -make-backend/internal/gql/generated.go:8840.4,8840.26 1 0 -make-backend/internal/gql/generated.go:8840.26,8843.91 3 0 -make-backend/internal/gql/generated.go:8843.91,8845.6 1 0 -make-backend/internal/gql/generated.go:8847.5,8847.50 1 0 -make-backend/internal/gql/generated.go:8847.50,8849.13 2 0 -make-backend/internal/gql/generated.go:8849.13,8852.7 2 0 -make-backend/internal/gql/generated.go:8853.6,8853.33 1 0 -make-backend/internal/gql/generated.go:8857.5,8858.13 2 0 -make-backend/internal/gql/generated.go:8861.4,8861.68 1 0 -make-backend/internal/gql/generated.go:8861.68,8861.98 1 0 -make-backend/internal/gql/generated.go:8862.11,8863.55 1 0 -make-backend/internal/gql/generated.go:8866.2,8867.22 2 0 -make-backend/internal/gql/generated.go:8867.22,8869.3 1 0 -make-backend/internal/gql/generated.go:8871.2,8880.12 3 0 -make-backend/internal/gql/generated.go:8885.140,8891.31 5 0 -make-backend/internal/gql/generated.go:8891.31,8892.21 1 0 -make-backend/internal/gql/generated.go:8893.21,8894.62 1 0 -make-backend/internal/gql/generated.go:8895.17,8897.37 2 0 -make-backend/internal/gql/generated.go:8897.37,8899.5 1 0 -make-backend/internal/gql/generated.go:8900.25,8902.37 2 0 -make-backend/internal/gql/generated.go:8902.37,8904.5 1 0 -make-backend/internal/gql/generated.go:8905.11,8906.55 1 0 -make-backend/internal/gql/generated.go:8909.2,8910.22 2 0 -make-backend/internal/gql/generated.go:8910.22,8912.3 1 0 -make-backend/internal/gql/generated.go:8914.2,8923.12 3 0 -make-backend/internal/gql/generated.go:8928.100,8937.31 6 0 -make-backend/internal/gql/generated.go:8937.31,8943.21 2 0 -make-backend/internal/gql/generated.go:8944.21,8945.53 1 0 -make-backend/internal/gql/generated.go:8946.27,8947.123 1 0 -make-backend/internal/gql/generated.go:8947.123,8949.5 1 0 -make-backend/internal/gql/generated.go:8950.4,8950.37 1 0 -make-backend/internal/gql/generated.go:8950.37,8952.5 1 0 -make-backend/internal/gql/generated.go:8953.27,8954.123 1 0 -make-backend/internal/gql/generated.go:8954.123,8956.5 1 0 -make-backend/internal/gql/generated.go:8957.4,8957.37 1 0 -make-backend/internal/gql/generated.go:8957.37,8959.5 1 0 -make-backend/internal/gql/generated.go:8960.11,8961.55 1 0 -make-backend/internal/gql/generated.go:8964.2,8965.22 2 0 -make-backend/internal/gql/generated.go:8965.22,8967.3 1 0 -make-backend/internal/gql/generated.go:8969.2,8978.12 3 0 -make-backend/internal/gql/generated.go:8983.128,8989.31 5 0 -make-backend/internal/gql/generated.go:8989.31,8990.21 1 0 -make-backend/internal/gql/generated.go:8991.21,8992.56 1 0 -make-backend/internal/gql/generated.go:8993.19,8995.37 2 0 -make-backend/internal/gql/generated.go:8995.37,8997.5 1 0 -make-backend/internal/gql/generated.go:8998.15,9000.37 2 0 -make-backend/internal/gql/generated.go:9000.37,9002.5 1 0 -make-backend/internal/gql/generated.go:9003.18,9005.37 2 0 -make-backend/internal/gql/generated.go:9005.37,9007.5 1 0 -make-backend/internal/gql/generated.go:9008.18,9010.37 2 0 -make-backend/internal/gql/generated.go:9010.37,9012.5 1 0 -make-backend/internal/gql/generated.go:9013.15,9015.37 2 0 -make-backend/internal/gql/generated.go:9015.37,9017.5 1 0 -make-backend/internal/gql/generated.go:9018.22,9020.37 2 0 -make-backend/internal/gql/generated.go:9020.37,9022.5 1 0 -make-backend/internal/gql/generated.go:9023.11,9024.55 1 0 -make-backend/internal/gql/generated.go:9027.2,9028.22 2 0 -make-backend/internal/gql/generated.go:9028.22,9030.3 1 0 -make-backend/internal/gql/generated.go:9032.2,9041.12 3 0 -make-backend/internal/gql/generated.go:9046.140,9052.31 5 0 -make-backend/internal/gql/generated.go:9052.31,9053.21 1 0 -make-backend/internal/gql/generated.go:9054.21,9055.62 1 0 -make-backend/internal/gql/generated.go:9056.15,9058.37 2 0 -make-backend/internal/gql/generated.go:9058.37,9060.5 1 0 -make-backend/internal/gql/generated.go:9061.18,9064.89 2 0 -make-backend/internal/gql/generated.go:9064.89,9065.18 1 0 -make-backend/internal/gql/generated.go:9065.18,9066.34 1 0 -make-backend/internal/gql/generated.go:9066.34,9068.7 1 0 -make-backend/internal/gql/generated.go:9070.5,9071.36 2 0 -make-backend/internal/gql/generated.go:9071.36,9073.6 1 0 -make-backend/internal/gql/generated.go:9074.5,9074.15 1 0 -make-backend/internal/gql/generated.go:9077.4,9077.26 1 0 -make-backend/internal/gql/generated.go:9077.26,9080.91 3 0 -make-backend/internal/gql/generated.go:9080.91,9082.6 1 0 -make-backend/internal/gql/generated.go:9084.5,9084.50 1 0 -make-backend/internal/gql/generated.go:9084.50,9086.13 2 0 -make-backend/internal/gql/generated.go:9086.13,9089.7 2 0 -make-backend/internal/gql/generated.go:9090.6,9090.33 1 0 -make-backend/internal/gql/generated.go:9094.5,9095.13 2 0 -make-backend/internal/gql/generated.go:9098.4,9098.68 1 0 -make-backend/internal/gql/generated.go:9098.68,9098.98 1 0 -make-backend/internal/gql/generated.go:9099.11,9100.55 1 0 -make-backend/internal/gql/generated.go:9103.2,9104.22 2 0 -make-backend/internal/gql/generated.go:9104.22,9106.3 1 0 -make-backend/internal/gql/generated.go:9108.2,9117.12 3 0 -make-backend/internal/gql/generated.go:9122.130,9128.31 5 0 -make-backend/internal/gql/generated.go:9128.31,9129.21 1 0 -make-backend/internal/gql/generated.go:9130.21,9131.57 1 0 -make-backend/internal/gql/generated.go:9132.13,9134.37 2 0 -make-backend/internal/gql/generated.go:9134.37,9136.5 1 0 -make-backend/internal/gql/generated.go:9137.23,9139.37 2 0 -make-backend/internal/gql/generated.go:9139.37,9141.5 1 0 -make-backend/internal/gql/generated.go:9142.16,9144.37 2 0 -make-backend/internal/gql/generated.go:9144.37,9146.5 1 0 -make-backend/internal/gql/generated.go:9147.16,9149.37 2 0 -make-backend/internal/gql/generated.go:9149.37,9151.5 1 0 -make-backend/internal/gql/generated.go:9152.11,9153.55 1 0 -make-backend/internal/gql/generated.go:9156.2,9157.22 2 0 -make-backend/internal/gql/generated.go:9157.22,9159.3 1 0 -make-backend/internal/gql/generated.go:9161.2,9170.12 3 0 -make-backend/internal/gql/generated.go:9175.97,9184.31 6 0 -make-backend/internal/gql/generated.go:9184.31,9190.21 2 0 -make-backend/internal/gql/generated.go:9191.21,9192.50 1 0 -make-backend/internal/gql/generated.go:9193.21,9196.89 2 0 -make-backend/internal/gql/generated.go:9196.89,9197.18 1 0 -make-backend/internal/gql/generated.go:9197.18,9198.34 1 0 -make-backend/internal/gql/generated.go:9198.34,9200.7 1 0 -make-backend/internal/gql/generated.go:9202.5,9203.36 2 0 -make-backend/internal/gql/generated.go:9203.36,9205.6 1 0 -make-backend/internal/gql/generated.go:9206.5,9206.15 1 0 -make-backend/internal/gql/generated.go:9209.4,9209.55 1 0 -make-backend/internal/gql/generated.go:9209.55,9211.50 1 0 -make-backend/internal/gql/generated.go:9211.50,9211.80 1 0 -make-backend/internal/gql/generated.go:9214.4,9214.68 1 0 -make-backend/internal/gql/generated.go:9214.68,9214.92 1 0 -make-backend/internal/gql/generated.go:9215.17,9218.89 2 0 -make-backend/internal/gql/generated.go:9218.89,9219.18 1 0 -make-backend/internal/gql/generated.go:9219.18,9220.34 1 0 -make-backend/internal/gql/generated.go:9220.34,9222.7 1 0 -make-backend/internal/gql/generated.go:9224.5,9225.36 2 0 -make-backend/internal/gql/generated.go:9225.36,9227.6 1 0 -make-backend/internal/gql/generated.go:9228.5,9228.15 1 0 -make-backend/internal/gql/generated.go:9231.4,9231.55 1 0 -make-backend/internal/gql/generated.go:9231.55,9233.50 1 0 -make-backend/internal/gql/generated.go:9233.50,9233.80 1 0 -make-backend/internal/gql/generated.go:9236.4,9236.68 1 0 -make-backend/internal/gql/generated.go:9236.68,9236.92 1 0 -make-backend/internal/gql/generated.go:9237.23,9240.89 2 0 -make-backend/internal/gql/generated.go:9240.89,9241.18 1 0 -make-backend/internal/gql/generated.go:9241.18,9242.34 1 0 -make-backend/internal/gql/generated.go:9242.34,9244.7 1 0 -make-backend/internal/gql/generated.go:9246.5,9247.36 2 0 -make-backend/internal/gql/generated.go:9247.36,9249.6 1 0 -make-backend/internal/gql/generated.go:9250.5,9250.15 1 0 -make-backend/internal/gql/generated.go:9253.4,9253.55 1 0 -make-backend/internal/gql/generated.go:9253.55,9255.50 1 0 -make-backend/internal/gql/generated.go:9255.50,9255.80 1 0 -make-backend/internal/gql/generated.go:9258.4,9258.68 1 0 -make-backend/internal/gql/generated.go:9258.68,9258.92 1 0 -make-backend/internal/gql/generated.go:9259.20,9262.89 2 0 -make-backend/internal/gql/generated.go:9262.89,9263.18 1 0 -make-backend/internal/gql/generated.go:9263.18,9264.34 1 0 -make-backend/internal/gql/generated.go:9264.34,9266.7 1 0 -make-backend/internal/gql/generated.go:9268.5,9269.28 2 0 -make-backend/internal/gql/generated.go:9269.28,9271.6 1 0 -make-backend/internal/gql/generated.go:9272.5,9272.15 1 0 -make-backend/internal/gql/generated.go:9275.4,9275.55 1 0 -make-backend/internal/gql/generated.go:9275.55,9277.50 1 0 -make-backend/internal/gql/generated.go:9277.50,9277.80 1 0 -make-backend/internal/gql/generated.go:9280.4,9280.68 1 0 -make-backend/internal/gql/generated.go:9280.68,9280.92 1 0 -make-backend/internal/gql/generated.go:9281.25,9284.89 2 0 -make-backend/internal/gql/generated.go:9284.89,9285.18 1 0 -make-backend/internal/gql/generated.go:9285.18,9286.34 1 0 -make-backend/internal/gql/generated.go:9286.34,9288.7 1 0 -make-backend/internal/gql/generated.go:9290.5,9291.28 2 0 -make-backend/internal/gql/generated.go:9291.28,9293.6 1 0 -make-backend/internal/gql/generated.go:9294.5,9294.15 1 0 -make-backend/internal/gql/generated.go:9297.4,9297.55 1 0 -make-backend/internal/gql/generated.go:9297.55,9299.50 1 0 -make-backend/internal/gql/generated.go:9299.50,9299.80 1 0 -make-backend/internal/gql/generated.go:9302.4,9302.68 1 0 -make-backend/internal/gql/generated.go:9302.68,9302.92 1 0 -make-backend/internal/gql/generated.go:9303.24,9306.89 2 0 -make-backend/internal/gql/generated.go:9306.89,9307.18 1 0 -make-backend/internal/gql/generated.go:9307.18,9308.34 1 0 -make-backend/internal/gql/generated.go:9308.34,9310.7 1 0 -make-backend/internal/gql/generated.go:9312.5,9313.28 2 0 -make-backend/internal/gql/generated.go:9313.28,9315.6 1 0 -make-backend/internal/gql/generated.go:9316.5,9316.15 1 0 -make-backend/internal/gql/generated.go:9319.4,9319.55 1 0 -make-backend/internal/gql/generated.go:9319.55,9321.50 1 0 -make-backend/internal/gql/generated.go:9321.50,9321.80 1 0 -make-backend/internal/gql/generated.go:9324.4,9324.68 1 0 -make-backend/internal/gql/generated.go:9324.68,9324.92 1 0 -make-backend/internal/gql/generated.go:9325.32,9328.89 2 0 -make-backend/internal/gql/generated.go:9328.89,9329.18 1 0 -make-backend/internal/gql/generated.go:9329.18,9330.34 1 0 -make-backend/internal/gql/generated.go:9330.34,9332.7 1 0 -make-backend/internal/gql/generated.go:9334.5,9335.28 2 0 -make-backend/internal/gql/generated.go:9335.28,9337.6 1 0 -make-backend/internal/gql/generated.go:9338.5,9338.15 1 0 -make-backend/internal/gql/generated.go:9341.4,9341.55 1 0 -make-backend/internal/gql/generated.go:9341.55,9343.50 1 0 -make-backend/internal/gql/generated.go:9343.50,9343.80 1 0 -make-backend/internal/gql/generated.go:9346.4,9346.68 1 0 -make-backend/internal/gql/generated.go:9346.68,9346.92 1 0 -make-backend/internal/gql/generated.go:9347.30,9350.89 2 0 -make-backend/internal/gql/generated.go:9350.89,9351.18 1 0 -make-backend/internal/gql/generated.go:9351.18,9352.34 1 0 -make-backend/internal/gql/generated.go:9352.34,9354.7 1 0 -make-backend/internal/gql/generated.go:9356.5,9357.28 2 0 -make-backend/internal/gql/generated.go:9357.28,9359.6 1 0 -make-backend/internal/gql/generated.go:9360.5,9360.15 1 0 -make-backend/internal/gql/generated.go:9363.4,9363.55 1 0 -make-backend/internal/gql/generated.go:9363.55,9365.50 1 0 -make-backend/internal/gql/generated.go:9365.50,9365.80 1 0 -make-backend/internal/gql/generated.go:9368.4,9368.68 1 0 -make-backend/internal/gql/generated.go:9368.68,9368.92 1 0 -make-backend/internal/gql/generated.go:9369.29,9372.89 2 0 -make-backend/internal/gql/generated.go:9372.89,9373.18 1 0 -make-backend/internal/gql/generated.go:9373.18,9374.34 1 0 -make-backend/internal/gql/generated.go:9374.34,9376.7 1 0 -make-backend/internal/gql/generated.go:9378.5,9379.28 2 0 -make-backend/internal/gql/generated.go:9379.28,9381.6 1 0 -make-backend/internal/gql/generated.go:9382.5,9382.15 1 0 -make-backend/internal/gql/generated.go:9385.4,9385.55 1 0 -make-backend/internal/gql/generated.go:9385.55,9387.50 1 0 -make-backend/internal/gql/generated.go:9387.50,9387.80 1 0 -make-backend/internal/gql/generated.go:9390.4,9390.68 1 0 -make-backend/internal/gql/generated.go:9390.68,9390.92 1 0 -make-backend/internal/gql/generated.go:9391.15,9394.89 2 0 -make-backend/internal/gql/generated.go:9394.89,9395.18 1 0 -make-backend/internal/gql/generated.go:9395.18,9396.34 1 0 -make-backend/internal/gql/generated.go:9396.34,9398.7 1 0 -make-backend/internal/gql/generated.go:9400.5,9401.28 2 0 -make-backend/internal/gql/generated.go:9401.28,9403.6 1 0 -make-backend/internal/gql/generated.go:9404.5,9404.15 1 0 -make-backend/internal/gql/generated.go:9407.4,9407.55 1 0 -make-backend/internal/gql/generated.go:9407.55,9409.50 1 0 -make-backend/internal/gql/generated.go:9409.50,9409.80 1 0 -make-backend/internal/gql/generated.go:9412.4,9412.68 1 0 -make-backend/internal/gql/generated.go:9412.68,9412.92 1 0 -make-backend/internal/gql/generated.go:9413.22,9416.89 2 0 -make-backend/internal/gql/generated.go:9416.89,9417.18 1 0 -make-backend/internal/gql/generated.go:9417.18,9418.34 1 0 -make-backend/internal/gql/generated.go:9418.34,9420.7 1 0 -make-backend/internal/gql/generated.go:9422.5,9423.28 2 0 -make-backend/internal/gql/generated.go:9423.28,9425.6 1 0 -make-backend/internal/gql/generated.go:9426.5,9426.15 1 0 -make-backend/internal/gql/generated.go:9429.4,9429.55 1 0 -make-backend/internal/gql/generated.go:9429.55,9431.50 1 0 -make-backend/internal/gql/generated.go:9431.50,9431.80 1 0 -make-backend/internal/gql/generated.go:9434.4,9434.68 1 0 -make-backend/internal/gql/generated.go:9434.68,9434.92 1 0 -make-backend/internal/gql/generated.go:9435.15,9438.89 2 0 -make-backend/internal/gql/generated.go:9438.89,9439.18 1 0 -make-backend/internal/gql/generated.go:9439.18,9440.34 1 0 -make-backend/internal/gql/generated.go:9440.34,9442.7 1 0 -make-backend/internal/gql/generated.go:9444.5,9445.28 2 0 -make-backend/internal/gql/generated.go:9445.28,9447.6 1 0 -make-backend/internal/gql/generated.go:9448.5,9448.15 1 0 -make-backend/internal/gql/generated.go:9451.4,9451.55 1 0 -make-backend/internal/gql/generated.go:9451.55,9453.50 1 0 -make-backend/internal/gql/generated.go:9453.50,9453.80 1 0 -make-backend/internal/gql/generated.go:9456.4,9456.68 1 0 -make-backend/internal/gql/generated.go:9456.68,9456.92 1 0 -make-backend/internal/gql/generated.go:9457.30,9460.89 2 0 -make-backend/internal/gql/generated.go:9460.89,9461.18 1 0 -make-backend/internal/gql/generated.go:9461.18,9462.34 1 0 -make-backend/internal/gql/generated.go:9462.34,9464.7 1 0 -make-backend/internal/gql/generated.go:9466.5,9467.28 2 0 -make-backend/internal/gql/generated.go:9467.28,9469.6 1 0 -make-backend/internal/gql/generated.go:9470.5,9470.15 1 0 -make-backend/internal/gql/generated.go:9473.4,9473.55 1 0 -make-backend/internal/gql/generated.go:9473.55,9475.50 1 0 -make-backend/internal/gql/generated.go:9475.50,9475.80 1 0 -make-backend/internal/gql/generated.go:9478.4,9478.68 1 0 -make-backend/internal/gql/generated.go:9478.68,9478.92 1 0 -make-backend/internal/gql/generated.go:9479.17,9480.123 1 0 -make-backend/internal/gql/generated.go:9480.123,9482.5 1 0 -make-backend/internal/gql/generated.go:9483.4,9483.45 1 0 -make-backend/internal/gql/generated.go:9483.45,9485.5 1 0 -make-backend/internal/gql/generated.go:9486.19,9487.123 1 0 -make-backend/internal/gql/generated.go:9487.123,9489.5 1 0 -make-backend/internal/gql/generated.go:9490.4,9490.45 1 0 -make-backend/internal/gql/generated.go:9490.45,9492.5 1 0 -make-backend/internal/gql/generated.go:9493.11,9494.55 1 0 -make-backend/internal/gql/generated.go:9497.2,9498.22 2 0 -make-backend/internal/gql/generated.go:9498.22,9500.3 1 0 -make-backend/internal/gql/generated.go:9502.2,9511.12 3 0 -make-backend/internal/gql/generated.go:9516.128,9522.31 5 0 -make-backend/internal/gql/generated.go:9522.31,9523.21 1 0 -make-backend/internal/gql/generated.go:9524.21,9525.56 1 0 -make-backend/internal/gql/generated.go:9526.13,9528.37 2 0 -make-backend/internal/gql/generated.go:9528.37,9530.5 1 0 -make-backend/internal/gql/generated.go:9531.18,9533.45 2 0 -make-backend/internal/gql/generated.go:9533.45,9535.5 1 0 -make-backend/internal/gql/generated.go:9536.26,9538.45 2 0 -make-backend/internal/gql/generated.go:9538.45,9540.5 1 0 -make-backend/internal/gql/generated.go:9541.23,9543.37 2 0 -make-backend/internal/gql/generated.go:9543.37,9545.5 1 0 -make-backend/internal/gql/generated.go:9546.22,9548.37 2 0 -make-backend/internal/gql/generated.go:9548.37,9550.5 1 0 -make-backend/internal/gql/generated.go:9551.21,9553.37 2 0 -make-backend/internal/gql/generated.go:9553.37,9555.5 1 0 -make-backend/internal/gql/generated.go:9556.19,9558.37 2 0 -make-backend/internal/gql/generated.go:9558.37,9560.5 1 0 -make-backend/internal/gql/generated.go:9561.19,9563.37 2 0 -make-backend/internal/gql/generated.go:9563.37,9565.5 1 0 -make-backend/internal/gql/generated.go:9566.11,9567.55 1 0 -make-backend/internal/gql/generated.go:9570.2,9571.22 2 0 -make-backend/internal/gql/generated.go:9571.22,9573.3 1 0 -make-backend/internal/gql/generated.go:9575.2,9584.12 3 0 -make-backend/internal/gql/generated.go:9589.128,9595.31 5 0 -make-backend/internal/gql/generated.go:9595.31,9596.21 1 0 -make-backend/internal/gql/generated.go:9597.21,9598.56 1 0 -make-backend/internal/gql/generated.go:9599.13,9601.37 2 0 -make-backend/internal/gql/generated.go:9601.37,9603.5 1 0 -make-backend/internal/gql/generated.go:9604.24,9606.37 2 0 -make-backend/internal/gql/generated.go:9606.37,9608.5 1 0 -make-backend/internal/gql/generated.go:9609.21,9611.37 2 0 -make-backend/internal/gql/generated.go:9611.37,9613.5 1 0 -make-backend/internal/gql/generated.go:9614.20,9616.37 2 0 -make-backend/internal/gql/generated.go:9616.37,9618.5 1 0 -make-backend/internal/gql/generated.go:9619.22,9621.37 2 0 -make-backend/internal/gql/generated.go:9621.37,9623.5 1 0 -make-backend/internal/gql/generated.go:9624.17,9626.37 2 0 -make-backend/internal/gql/generated.go:9626.37,9628.5 1 0 -make-backend/internal/gql/generated.go:9629.11,9630.55 1 0 -make-backend/internal/gql/generated.go:9633.2,9634.22 2 0 -make-backend/internal/gql/generated.go:9634.22,9636.3 1 0 -make-backend/internal/gql/generated.go:9638.2,9647.12 3 0 -make-backend/internal/gql/generated.go:9652.138,9658.31 5 0 -make-backend/internal/gql/generated.go:9658.31,9659.21 1 0 -make-backend/internal/gql/generated.go:9660.21,9661.61 1 0 -make-backend/internal/gql/generated.go:9662.19,9664.37 2 0 -make-backend/internal/gql/generated.go:9664.37,9666.5 1 0 -make-backend/internal/gql/generated.go:9667.15,9669.37 2 0 -make-backend/internal/gql/generated.go:9669.37,9671.5 1 0 -make-backend/internal/gql/generated.go:9672.18,9674.37 2 0 -make-backend/internal/gql/generated.go:9674.37,9676.5 1 0 -make-backend/internal/gql/generated.go:9677.17,9679.45 2 0 -make-backend/internal/gql/generated.go:9679.45,9681.5 1 0 -make-backend/internal/gql/generated.go:9682.15,9684.37 2 0 -make-backend/internal/gql/generated.go:9684.37,9686.5 1 0 -make-backend/internal/gql/generated.go:9687.22,9689.37 2 0 -make-backend/internal/gql/generated.go:9689.37,9691.5 1 0 -make-backend/internal/gql/generated.go:9692.11,9693.55 1 0 -make-backend/internal/gql/generated.go:9696.2,9697.22 2 0 -make-backend/internal/gql/generated.go:9697.22,9699.3 1 0 -make-backend/internal/gql/generated.go:9701.2,9710.12 3 0 -make-backend/internal/gql/generated.go:9715.130,9721.31 5 0 -make-backend/internal/gql/generated.go:9721.31,9722.21 1 0 -make-backend/internal/gql/generated.go:9723.21,9724.57 1 0 -make-backend/internal/gql/generated.go:9725.24,9727.37 2 0 -make-backend/internal/gql/generated.go:9727.37,9729.5 1 0 -make-backend/internal/gql/generated.go:9730.23,9732.37 2 0 -make-backend/internal/gql/generated.go:9732.37,9734.5 1 0 -make-backend/internal/gql/generated.go:9735.20,9737.45 2 0 -make-backend/internal/gql/generated.go:9737.45,9739.5 1 0 -make-backend/internal/gql/generated.go:9740.21,9742.45 2 0 -make-backend/internal/gql/generated.go:9742.45,9744.5 1 0 -make-backend/internal/gql/generated.go:9745.17,9747.37 2 0 -make-backend/internal/gql/generated.go:9747.37,9749.5 1 0 -make-backend/internal/gql/generated.go:9750.11,9751.55 1 0 -make-backend/internal/gql/generated.go:9754.2,9755.22 2 0 -make-backend/internal/gql/generated.go:9755.22,9757.3 1 0 -make-backend/internal/gql/generated.go:9759.2,9768.12 3 0 -make-backend/internal/gql/generated.go:9773.122,9779.31 5 0 -make-backend/internal/gql/generated.go:9779.31,9780.21 1 0 -make-backend/internal/gql/generated.go:9781.21,9782.53 1 0 -make-backend/internal/gql/generated.go:9783.13,9785.37 2 0 -make-backend/internal/gql/generated.go:9785.37,9787.5 1 0 -make-backend/internal/gql/generated.go:9788.18,9790.37 2 0 -make-backend/internal/gql/generated.go:9790.37,9792.5 1 0 -make-backend/internal/gql/generated.go:9793.19,9795.37 2 0 -make-backend/internal/gql/generated.go:9795.37,9797.5 1 0 -make-backend/internal/gql/generated.go:9798.17,9800.37 2 0 -make-backend/internal/gql/generated.go:9800.37,9802.5 1 0 -make-backend/internal/gql/generated.go:9803.11,9804.55 1 0 -make-backend/internal/gql/generated.go:9807.2,9808.22 2 0 -make-backend/internal/gql/generated.go:9808.22,9810.3 1 0 -make-backend/internal/gql/generated.go:9812.2,9821.12 3 0 -make-backend/internal/gql/generated.go:9826.124,9832.31 5 0 -make-backend/internal/gql/generated.go:9832.31,9833.21 1 0 -make-backend/internal/gql/generated.go:9834.21,9835.54 1 0 -make-backend/internal/gql/generated.go:9836.19,9838.37 2 0 -make-backend/internal/gql/generated.go:9838.37,9840.5 1 0 -make-backend/internal/gql/generated.go:9841.15,9843.37 2 0 -make-backend/internal/gql/generated.go:9843.37,9845.5 1 0 -make-backend/internal/gql/generated.go:9846.18,9848.37 2 0 -make-backend/internal/gql/generated.go:9848.37,9850.5 1 0 -make-backend/internal/gql/generated.go:9851.11,9852.55 1 0 -make-backend/internal/gql/generated.go:9855.2,9856.22 2 0 -make-backend/internal/gql/generated.go:9856.22,9858.3 1 0 -make-backend/internal/gql/generated.go:9860.2,9869.12 3 0 -make-backend/internal/gql/generated.go:9874.122,9880.31 5 0 -make-backend/internal/gql/generated.go:9880.31,9881.21 1 0 -make-backend/internal/gql/generated.go:9882.21,9883.53 1 0 -make-backend/internal/gql/generated.go:9884.13,9886.37 2 0 -make-backend/internal/gql/generated.go:9886.37,9888.5 1 0 -make-backend/internal/gql/generated.go:9889.15,9891.37 2 0 -make-backend/internal/gql/generated.go:9891.37,9893.5 1 0 -make-backend/internal/gql/generated.go:9894.24,9896.45 2 0 -make-backend/internal/gql/generated.go:9896.45,9898.5 1 0 -make-backend/internal/gql/generated.go:9899.17,9902.89 2 0 -make-backend/internal/gql/generated.go:9902.89,9903.18 1 0 -make-backend/internal/gql/generated.go:9903.18,9904.34 1 0 -make-backend/internal/gql/generated.go:9904.34,9906.7 1 0 -make-backend/internal/gql/generated.go:9908.5,9909.28 2 0 -make-backend/internal/gql/generated.go:9909.28,9911.6 1 0 -make-backend/internal/gql/generated.go:9912.5,9912.15 1 0 -make-backend/internal/gql/generated.go:9915.4,9915.26 1 0 -make-backend/internal/gql/generated.go:9915.26,9918.91 3 0 -make-backend/internal/gql/generated.go:9918.91,9920.6 1 0 -make-backend/internal/gql/generated.go:9922.5,9922.50 1 0 -make-backend/internal/gql/generated.go:9922.50,9924.13 2 0 -make-backend/internal/gql/generated.go:9924.13,9927.7 2 0 -make-backend/internal/gql/generated.go:9928.6,9928.33 1 0 -make-backend/internal/gql/generated.go:9932.5,9933.13 2 0 -make-backend/internal/gql/generated.go:9936.4,9936.68 1 0 -make-backend/internal/gql/generated.go:9936.68,9936.98 1 0 -make-backend/internal/gql/generated.go:9937.11,9938.55 1 0 -make-backend/internal/gql/generated.go:9941.2,9942.22 2 0 -make-backend/internal/gql/generated.go:9942.22,9944.3 1 0 -make-backend/internal/gql/generated.go:9946.2,9955.12 3 0 -make-backend/internal/gql/generated.go:9960.114,9966.31 5 0 -make-backend/internal/gql/generated.go:9966.31,9967.21 1 0 -make-backend/internal/gql/generated.go:9968.21,9969.49 1 0 -make-backend/internal/gql/generated.go:9970.13,9972.37 2 0 -make-backend/internal/gql/generated.go:9972.37,9974.5 1 0 -make-backend/internal/gql/generated.go:9975.16,9977.37 2 0 -make-backend/internal/gql/generated.go:9977.37,9979.5 1 0 -make-backend/internal/gql/generated.go:9980.20,9982.37 2 0 -make-backend/internal/gql/generated.go:9982.37,9984.5 1 0 -make-backend/internal/gql/generated.go:9985.19,9987.37 2 0 -make-backend/internal/gql/generated.go:9987.37,9989.5 1 0 -make-backend/internal/gql/generated.go:9990.19,9992.37 2 0 -make-backend/internal/gql/generated.go:9992.37,9994.5 1 0 -make-backend/internal/gql/generated.go:9995.20,9997.37 2 0 -make-backend/internal/gql/generated.go:9997.37,9999.5 1 0 -make-backend/internal/gql/generated.go:10000.25,10002.37 2 0 -make-backend/internal/gql/generated.go:10002.37,10004.5 1 0 -make-backend/internal/gql/generated.go:10005.19,10007.37 2 0 -make-backend/internal/gql/generated.go:10007.37,10009.5 1 0 -make-backend/internal/gql/generated.go:10010.16,10012.37 2 0 -make-backend/internal/gql/generated.go:10012.37,10014.5 1 0 -make-backend/internal/gql/generated.go:10015.16,10017.37 2 0 -make-backend/internal/gql/generated.go:10017.37,10019.5 1 0 -make-backend/internal/gql/generated.go:10020.24,10022.45 2 0 -make-backend/internal/gql/generated.go:10022.45,10024.5 1 0 -make-backend/internal/gql/generated.go:10025.19,10027.37 2 0 -make-backend/internal/gql/generated.go:10027.37,10029.5 1 0 -make-backend/internal/gql/generated.go:10030.11,10031.55 1 0 -make-backend/internal/gql/generated.go:10034.2,10035.22 2 0 -make-backend/internal/gql/generated.go:10035.22,10037.3 1 0 -make-backend/internal/gql/generated.go:10039.2,10048.12 3 0 -make-backend/internal/gql/generated.go:10053.114,10059.31 5 0 -make-backend/internal/gql/generated.go:10059.31,10060.21 1 0 -make-backend/internal/gql/generated.go:10061.21,10062.49 1 0 -make-backend/internal/gql/generated.go:10063.13,10065.37 2 0 -make-backend/internal/gql/generated.go:10065.37,10067.5 1 0 -make-backend/internal/gql/generated.go:10068.24,10070.37 2 0 -make-backend/internal/gql/generated.go:10070.37,10072.5 1 0 -make-backend/internal/gql/generated.go:10073.15,10075.37 2 0 -make-backend/internal/gql/generated.go:10075.37,10077.5 1 0 -make-backend/internal/gql/generated.go:10078.17,10080.37 2 0 -make-backend/internal/gql/generated.go:10080.37,10082.5 1 0 -make-backend/internal/gql/generated.go:10083.11,10084.55 1 0 -make-backend/internal/gql/generated.go:10087.2,10088.22 2 0 -make-backend/internal/gql/generated.go:10088.22,10090.3 1 0 -make-backend/internal/gql/generated.go:10092.2,10101.12 3 0 -make-backend/internal/gql/generated.go:10106.133,10112.31 5 0 -make-backend/internal/gql/generated.go:10112.31,10113.21 1 0 -make-backend/internal/gql/generated.go:10114.21,10115.56 1 0 -make-backend/internal/gql/generated.go:10116.15,10118.37 2 0 -make-backend/internal/gql/generated.go:10118.37,10120.5 1 0 -make-backend/internal/gql/generated.go:10121.22,10123.45 2 0 -make-backend/internal/gql/generated.go:10123.45,10125.5 1 0 -make-backend/internal/gql/generated.go:10126.23,10128.37 2 0 -make-backend/internal/gql/generated.go:10128.37,10130.5 1 0 -make-backend/internal/gql/generated.go:10131.20,10133.37 2 0 -make-backend/internal/gql/generated.go:10133.37,10135.5 1 0 -make-backend/internal/gql/generated.go:10136.15,10138.37 2 0 -make-backend/internal/gql/generated.go:10138.37,10140.5 1 0 -make-backend/internal/gql/generated.go:10141.11,10142.55 1 0 -make-backend/internal/gql/generated.go:10145.2,10146.22 2 0 -make-backend/internal/gql/generated.go:10146.22,10148.3 1 0 -make-backend/internal/gql/generated.go:10150.2,10159.12 3 0 -make-backend/internal/gql/generated.go:10164.133,10170.31 5 0 -make-backend/internal/gql/generated.go:10170.31,10171.21 1 0 -make-backend/internal/gql/generated.go:10172.21,10173.56 1 0 -make-backend/internal/gql/generated.go:10174.15,10176.37 2 0 -make-backend/internal/gql/generated.go:10176.37,10178.5 1 0 -make-backend/internal/gql/generated.go:10179.22,10181.45 2 0 -make-backend/internal/gql/generated.go:10181.45,10183.5 1 0 -make-backend/internal/gql/generated.go:10184.23,10186.37 2 0 -make-backend/internal/gql/generated.go:10186.37,10188.5 1 0 -make-backend/internal/gql/generated.go:10189.28,10191.45 2 0 -make-backend/internal/gql/generated.go:10191.45,10193.5 1 0 -make-backend/internal/gql/generated.go:10194.11,10195.55 1 0 -make-backend/internal/gql/generated.go:10198.2,10199.22 2 0 -make-backend/internal/gql/generated.go:10199.22,10201.3 1 0 -make-backend/internal/gql/generated.go:10203.2,10212.12 3 0 -make-backend/internal/gql/generated.go:10217.125,10223.31 5 0 -make-backend/internal/gql/generated.go:10223.31,10224.21 1 0 -make-backend/internal/gql/generated.go:10225.21,10226.52 1 0 -make-backend/internal/gql/generated.go:10227.15,10229.37 2 0 -make-backend/internal/gql/generated.go:10229.37,10231.5 1 0 -make-backend/internal/gql/generated.go:10232.22,10234.45 2 0 -make-backend/internal/gql/generated.go:10234.45,10236.5 1 0 -make-backend/internal/gql/generated.go:10237.15,10239.37 2 0 -make-backend/internal/gql/generated.go:10239.37,10241.5 1 0 -make-backend/internal/gql/generated.go:10242.15,10244.37 2 0 -make-backend/internal/gql/generated.go:10244.37,10246.5 1 0 -make-backend/internal/gql/generated.go:10247.23,10249.37 2 0 -make-backend/internal/gql/generated.go:10249.37,10251.5 1 0 -make-backend/internal/gql/generated.go:10252.28,10254.45 2 0 -make-backend/internal/gql/generated.go:10254.45,10256.5 1 0 -make-backend/internal/gql/generated.go:10257.11,10258.55 1 0 -make-backend/internal/gql/generated.go:10261.2,10262.22 2 0 -make-backend/internal/gql/generated.go:10262.22,10264.3 1 0 -make-backend/internal/gql/generated.go:10266.2,10275.12 3 0 -make-backend/internal/gql/generated.go:10280.135,10286.31 5 0 -make-backend/internal/gql/generated.go:10286.31,10287.21 1 0 -make-backend/internal/gql/generated.go:10288.21,10289.57 1 0 -make-backend/internal/gql/generated.go:10290.15,10292.37 2 0 -make-backend/internal/gql/generated.go:10292.37,10294.5 1 0 -make-backend/internal/gql/generated.go:10295.22,10297.45 2 0 -make-backend/internal/gql/generated.go:10297.45,10299.5 1 0 -make-backend/internal/gql/generated.go:10300.15,10302.37 2 0 -make-backend/internal/gql/generated.go:10302.37,10304.5 1 0 -make-backend/internal/gql/generated.go:10305.23,10307.45 2 0 -make-backend/internal/gql/generated.go:10307.45,10309.5 1 0 -make-backend/internal/gql/generated.go:10310.23,10312.37 2 0 -make-backend/internal/gql/generated.go:10312.37,10314.5 1 0 -make-backend/internal/gql/generated.go:10315.28,10317.45 2 0 -make-backend/internal/gql/generated.go:10317.45,10319.5 1 0 -make-backend/internal/gql/generated.go:10320.11,10321.55 1 0 -make-backend/internal/gql/generated.go:10324.2,10325.22 2 0 -make-backend/internal/gql/generated.go:10325.22,10327.3 1 0 -make-backend/internal/gql/generated.go:10329.2,10338.12 3 0 -make-backend/internal/gql/generated.go:10343.127,10349.31 5 0 -make-backend/internal/gql/generated.go:10349.31,10350.21 1 0 -make-backend/internal/gql/generated.go:10351.21,10352.53 1 0 -make-backend/internal/gql/generated.go:10353.22,10355.45 2 0 -make-backend/internal/gql/generated.go:10355.45,10357.5 1 0 -make-backend/internal/gql/generated.go:10358.16,10360.37 2 0 -make-backend/internal/gql/generated.go:10360.37,10362.5 1 0 -make-backend/internal/gql/generated.go:10363.20,10365.37 2 0 -make-backend/internal/gql/generated.go:10365.37,10367.5 1 0 -make-backend/internal/gql/generated.go:10368.23,10370.45 2 0 -make-backend/internal/gql/generated.go:10370.45,10372.5 1 0 -make-backend/internal/gql/generated.go:10373.27,10375.45 2 0 -make-backend/internal/gql/generated.go:10375.45,10377.5 1 0 -make-backend/internal/gql/generated.go:10378.21,10380.37 2 0 -make-backend/internal/gql/generated.go:10380.37,10382.5 1 0 -make-backend/internal/gql/generated.go:10383.11,10384.55 1 0 -make-backend/internal/gql/generated.go:10387.2,10388.22 2 0 -make-backend/internal/gql/generated.go:10388.22,10390.3 1 0 -make-backend/internal/gql/generated.go:10392.2,10401.12 3 0 -make-backend/internal/gql/generated.go:10406.123,10412.31 5 0 -make-backend/internal/gql/generated.go:10412.31,10413.21 1 0 -make-backend/internal/gql/generated.go:10414.21,10415.51 1 0 -make-backend/internal/gql/generated.go:10416.15,10418.37 2 0 -make-backend/internal/gql/generated.go:10418.37,10420.5 1 0 -make-backend/internal/gql/generated.go:10421.15,10423.45 2 0 -make-backend/internal/gql/generated.go:10423.45,10425.5 1 0 -make-backend/internal/gql/generated.go:10426.22,10428.45 2 0 -make-backend/internal/gql/generated.go:10428.45,10430.5 1 0 -make-backend/internal/gql/generated.go:10431.25,10433.45 2 0 -make-backend/internal/gql/generated.go:10433.45,10435.5 1 0 -make-backend/internal/gql/generated.go:10436.17,10438.45 2 0 -make-backend/internal/gql/generated.go:10438.45,10440.5 1 0 -make-backend/internal/gql/generated.go:10441.21,10443.45 2 0 -make-backend/internal/gql/generated.go:10443.45,10445.5 1 0 -make-backend/internal/gql/generated.go:10446.24,10448.45 2 0 -make-backend/internal/gql/generated.go:10448.45,10450.5 1 0 -make-backend/internal/gql/generated.go:10451.21,10453.45 2 0 -make-backend/internal/gql/generated.go:10453.45,10455.5 1 0 -make-backend/internal/gql/generated.go:10456.22,10458.45 2 0 -make-backend/internal/gql/generated.go:10458.45,10460.5 1 0 -make-backend/internal/gql/generated.go:10461.17,10463.45 2 0 -make-backend/internal/gql/generated.go:10463.45,10465.5 1 0 -make-backend/internal/gql/generated.go:10466.18,10468.45 2 0 -make-backend/internal/gql/generated.go:10468.45,10470.5 1 0 -make-backend/internal/gql/generated.go:10471.11,10472.55 1 0 -make-backend/internal/gql/generated.go:10475.2,10476.22 2 0 -make-backend/internal/gql/generated.go:10476.22,10478.3 1 0 -make-backend/internal/gql/generated.go:10480.2,10489.12 3 0 -make-backend/internal/gql/generated.go:10496.204,10498.2 1 0 -make-backend/internal/gql/generated.go:10500.212,10501.116 1 0 -make-backend/internal/gql/generated.go:10501.116,10505.3 3 0 -make-backend/internal/gql/generated.go:10507.2,10507.24 1 0 -make-backend/internal/gql/generated.go:10507.24,10508.24 1 0 -make-backend/internal/gql/generated.go:10508.24,10510.4 1 0 -make-backend/internal/gql/generated.go:10513.2,10513.12 1 0 -make-backend/internal/gql/generated.go:10516.210,10518.2 1 0 -make-backend/internal/gql/generated.go:10520.94,10523.2 2 0 -make-backend/internal/gql/generated.go:10525.119,10528.25 3 0 -make-backend/internal/gql/generated.go:10528.25,10529.64 1 0 -make-backend/internal/gql/generated.go:10529.64,10531.4 1 0 -make-backend/internal/gql/generated.go:10533.2,10533.12 1 0 -make-backend/internal/gql/generated.go:10536.103,10539.2 2 0 -make-backend/internal/gql/generated.go:10541.128,10544.25 3 0 -make-backend/internal/gql/generated.go:10544.25,10545.64 1 0 -make-backend/internal/gql/generated.go:10545.64,10547.4 1 0 -make-backend/internal/gql/generated.go:10549.2,10549.12 1 0 -make-backend/internal/gql/generated.go:10552.177,10554.2 1 0 -make-backend/internal/gql/generated.go:10556.174,10558.2 1 0 -make-backend/internal/gql/generated.go:10560.178,10561.14 1 0 -make-backend/internal/gql/generated.go:10561.14,10562.64 1 0 -make-backend/internal/gql/generated.go:10562.64,10564.4 1 0 -make-backend/internal/gql/generated.go:10565.3,10565.22 1 0 -make-backend/internal/gql/generated.go:10567.2,10567.31 1 0 -make-backend/internal/gql/generated.go:10570.191,10574.2 3 0 -make-backend/internal/gql/generated.go:10576.216,10578.2 1 0 -make-backend/internal/gql/generated.go:10580.87,10583.2 2 0 -make-backend/internal/gql/generated.go:10585.112,10588.25 3 0 -make-backend/internal/gql/generated.go:10588.25,10589.64 1 0 -make-backend/internal/gql/generated.go:10589.64,10591.4 1 0 -make-backend/internal/gql/generated.go:10593.2,10593.12 1 0 -make-backend/internal/gql/generated.go:10596.88,10599.2 2 0 -make-backend/internal/gql/generated.go:10601.113,10604.25 3 0 -make-backend/internal/gql/generated.go:10604.25,10605.64 1 0 -make-backend/internal/gql/generated.go:10605.64,10607.4 1 0 -make-backend/internal/gql/generated.go:10609.2,10609.12 1 0 -make-backend/internal/gql/generated.go:10612.204,10613.14 1 0 -make-backend/internal/gql/generated.go:10613.14,10614.64 1 0 -make-backend/internal/gql/generated.go:10614.64,10616.4 1 0 -make-backend/internal/gql/generated.go:10617.3,10617.22 1 0 -make-backend/internal/gql/generated.go:10619.2,10619.41 1 0 -make-backend/internal/gql/generated.go:10622.212,10623.116 1 0 -make-backend/internal/gql/generated.go:10623.116,10627.3 3 0 -make-backend/internal/gql/generated.go:10629.2,10629.24 1 0 -make-backend/internal/gql/generated.go:10629.24,10630.24 1 0 -make-backend/internal/gql/generated.go:10630.24,10632.4 1 0 -make-backend/internal/gql/generated.go:10635.2,10635.12 1 0 -make-backend/internal/gql/generated.go:10638.222,10639.116 1 0 -make-backend/internal/gql/generated.go:10639.116,10643.3 3 0 -make-backend/internal/gql/generated.go:10645.2,10645.24 1 0 -make-backend/internal/gql/generated.go:10645.24,10646.24 1 0 -make-backend/internal/gql/generated.go:10646.24,10648.4 1 0 -make-backend/internal/gql/generated.go:10651.2,10651.12 1 0 -make-backend/internal/gql/generated.go:10654.214,10655.14 1 0 -make-backend/internal/gql/generated.go:10655.14,10656.64 1 0 -make-backend/internal/gql/generated.go:10656.64,10658.4 1 0 -make-backend/internal/gql/generated.go:10659.3,10659.22 1 0 -make-backend/internal/gql/generated.go:10661.2,10661.43 1 0 -make-backend/internal/gql/generated.go:10664.210,10666.2 1 0 -make-backend/internal/gql/generated.go:10668.218,10669.116 1 0 -make-backend/internal/gql/generated.go:10669.116,10673.3 3 0 -make-backend/internal/gql/generated.go:10675.2,10675.24 1 0 -make-backend/internal/gql/generated.go:10675.24,10676.24 1 0 -make-backend/internal/gql/generated.go:10676.24,10678.4 1 0 -make-backend/internal/gql/generated.go:10681.2,10681.12 1 0 -make-backend/internal/gql/generated.go:10684.97,10687.2 2 0 -make-backend/internal/gql/generated.go:10689.122,10692.25 3 0 -make-backend/internal/gql/generated.go:10692.25,10693.64 1 0 -make-backend/internal/gql/generated.go:10693.64,10695.4 1 0 -make-backend/internal/gql/generated.go:10697.2,10697.12 1 0 -make-backend/internal/gql/generated.go:10700.103,10703.2 2 0 -make-backend/internal/gql/generated.go:10705.128,10708.25 3 0 -make-backend/internal/gql/generated.go:10708.25,10709.64 1 0 -make-backend/internal/gql/generated.go:10709.64,10711.4 1 0 -make-backend/internal/gql/generated.go:10713.2,10713.12 1 0 -make-backend/internal/gql/generated.go:10716.198,10717.14 1 0 -make-backend/internal/gql/generated.go:10717.14,10718.64 1 0 -make-backend/internal/gql/generated.go:10718.64,10720.4 1 0 -make-backend/internal/gql/generated.go:10721.3,10721.22 1 0 -make-backend/internal/gql/generated.go:10723.2,10723.39 1 0 -make-backend/internal/gql/generated.go:10726.206,10727.116 1 0 -make-backend/internal/gql/generated.go:10727.116,10731.3 3 0 -make-backend/internal/gql/generated.go:10733.2,10733.24 1 0 -make-backend/internal/gql/generated.go:10733.24,10734.24 1 0 -make-backend/internal/gql/generated.go:10734.24,10736.4 1 0 -make-backend/internal/gql/generated.go:10739.2,10739.12 1 0 -make-backend/internal/gql/generated.go:10742.171,10744.2 1 0 -make-backend/internal/gql/generated.go:10746.175,10747.14 1 0 -make-backend/internal/gql/generated.go:10747.14,10748.64 1 0 -make-backend/internal/gql/generated.go:10748.64,10750.4 1 0 -make-backend/internal/gql/generated.go:10751.3,10751.22 1 0 -make-backend/internal/gql/generated.go:10753.2,10753.30 1 0 -make-backend/internal/gql/generated.go:10756.171,10758.2 1 0 -make-backend/internal/gql/generated.go:10760.183,10761.116 1 0 -make-backend/internal/gql/generated.go:10761.116,10765.3 3 0 -make-backend/internal/gql/generated.go:10767.2,10767.24 1 0 -make-backend/internal/gql/generated.go:10767.24,10768.24 1 0 -make-backend/internal/gql/generated.go:10768.24,10770.4 1 0 -make-backend/internal/gql/generated.go:10773.2,10773.12 1 0 -make-backend/internal/gql/generated.go:10776.175,10777.14 1 0 -make-backend/internal/gql/generated.go:10777.14,10778.64 1 0 -make-backend/internal/gql/generated.go:10778.64,10780.4 1 0 -make-backend/internal/gql/generated.go:10781.3,10781.22 1 0 -make-backend/internal/gql/generated.go:10783.2,10783.30 1 0 -make-backend/internal/gql/generated.go:10786.209,10788.2 1 0 -make-backend/internal/gql/generated.go:10790.217,10791.116 1 0 -make-backend/internal/gql/generated.go:10791.116,10795.3 3 0 -make-backend/internal/gql/generated.go:10797.2,10797.24 1 0 -make-backend/internal/gql/generated.go:10797.24,10798.24 1 0 -make-backend/internal/gql/generated.go:10798.24,10800.4 1 0 -make-backend/internal/gql/generated.go:10803.2,10803.12 1 0 -make-backend/internal/gql/generated.go:10806.110,10809.2 2 0 -make-backend/internal/gql/generated.go:10811.135,10814.25 3 0 -make-backend/internal/gql/generated.go:10814.25,10815.64 1 0 -make-backend/internal/gql/generated.go:10815.64,10817.4 1 0 -make-backend/internal/gql/generated.go:10819.2,10819.12 1 0 -make-backend/internal/gql/generated.go:10822.118,10827.24 5 0 -make-backend/internal/gql/generated.go:10827.24,10830.17 3 0 -make-backend/internal/gql/generated.go:10830.17,10832.4 1 0 -make-backend/internal/gql/generated.go:10834.2,10834.17 1 0 -make-backend/internal/gql/generated.go:10837.143,10838.116 1 0 -make-backend/internal/gql/generated.go:10838.116,10842.3 3 0 -make-backend/internal/gql/generated.go:10844.2,10844.24 1 0 -make-backend/internal/gql/generated.go:10844.24,10845.24 1 0 -make-backend/internal/gql/generated.go:10845.24,10847.4 1 0 -make-backend/internal/gql/generated.go:10850.2,10850.12 1 0 -make-backend/internal/gql/generated.go:10853.209,10855.2 1 0 -make-backend/internal/gql/generated.go:10857.197,10859.2 1 0 -make-backend/internal/gql/generated.go:10861.212,10863.2 1 0 -make-backend/internal/gql/generated.go:10865.220,10866.116 1 0 -make-backend/internal/gql/generated.go:10866.116,10870.3 3 0 -make-backend/internal/gql/generated.go:10872.2,10872.24 1 0 -make-backend/internal/gql/generated.go:10872.24,10873.24 1 0 -make-backend/internal/gql/generated.go:10873.24,10875.4 1 0 -make-backend/internal/gql/generated.go:10878.2,10878.12 1 0 -make-backend/internal/gql/generated.go:10881.194,10883.2 1 0 -make-backend/internal/gql/generated.go:10885.202,10886.116 1 0 -make-backend/internal/gql/generated.go:10886.116,10890.3 3 0 -make-backend/internal/gql/generated.go:10892.2,10892.24 1 0 -make-backend/internal/gql/generated.go:10892.24,10893.24 1 0 -make-backend/internal/gql/generated.go:10893.24,10895.4 1 0 -make-backend/internal/gql/generated.go:10898.2,10898.12 1 0 -make-backend/internal/gql/generated.go:10901.198,10902.14 1 0 -make-backend/internal/gql/generated.go:10902.14,10903.64 1 0 -make-backend/internal/gql/generated.go:10903.64,10905.4 1 0 -make-backend/internal/gql/generated.go:10906.3,10906.22 1 0 -make-backend/internal/gql/generated.go:10908.2,10908.32 1 0 -make-backend/internal/gql/generated.go:10911.101,10914.2 2 0 -make-backend/internal/gql/generated.go:10916.126,10919.25 3 0 -make-backend/internal/gql/generated.go:10919.25,10920.64 1 0 -make-backend/internal/gql/generated.go:10920.64,10922.4 1 0 -make-backend/internal/gql/generated.go:10924.2,10924.12 1 0 -make-backend/internal/gql/generated.go:10927.192,10928.14 1 0 -make-backend/internal/gql/generated.go:10928.14,10930.3 1 0 -make-backend/internal/gql/generated.go:10931.2,10933.44 3 0 -make-backend/internal/gql/generated.go:10936.217,10937.14 1 0 -make-backend/internal/gql/generated.go:10937.14,10939.3 1 0 -make-backend/internal/gql/generated.go:10940.2,10943.12 4 0 -make-backend/internal/gql/generated.go:10946.211,10947.14 1 0 -make-backend/internal/gql/generated.go:10947.14,10949.3 1 0 -make-backend/internal/gql/generated.go:10950.2,10950.42 1 0 -make-backend/internal/gql/generated.go:10953.199,10954.14 1 0 -make-backend/internal/gql/generated.go:10954.14,10956.3 1 0 -make-backend/internal/gql/generated.go:10957.2,10957.38 1 0 -make-backend/internal/gql/generated.go:10960.94,10963.2 2 0 -make-backend/internal/gql/generated.go:10965.119,10970.2 4 0 -make-backend/internal/gql/generated.go:10972.98,10973.14 1 0 -make-backend/internal/gql/generated.go:10973.14,10975.3 1 0 -make-backend/internal/gql/generated.go:10976.2,10977.44 2 0 -make-backend/internal/gql/generated.go:10980.123,10981.14 1 0 -make-backend/internal/gql/generated.go:10981.14,10983.3 1 0 -make-backend/internal/gql/generated.go:10984.2,10987.12 4 0 -make-backend/internal/gql/generated.go:10990.112,10991.14 1 0 -make-backend/internal/gql/generated.go:10991.14,10993.3 1 0 -make-backend/internal/gql/generated.go:10994.2,10995.44 2 0 -make-backend/internal/gql/generated.go:10998.137,10999.14 1 0 -make-backend/internal/gql/generated.go:10999.14,11001.3 1 0 -make-backend/internal/gql/generated.go:11002.2,11005.12 4 0 -make-backend/internal/gql/generated.go:11008.181,11009.14 1 0 -make-backend/internal/gql/generated.go:11009.14,11011.3 1 0 -make-backend/internal/gql/generated.go:11012.2,11012.32 1 0 -make-backend/internal/gql/generated.go:11015.180,11016.14 1 0 -make-backend/internal/gql/generated.go:11016.14,11018.3 1 0 -make-backend/internal/gql/generated.go:11019.2,11021.44 3 0 -make-backend/internal/gql/generated.go:11024.205,11025.14 1 0 -make-backend/internal/gql/generated.go:11025.14,11027.3 1 0 -make-backend/internal/gql/generated.go:11028.2,11031.12 4 0 -make-backend/internal/gql/generated.go:11034.91,11035.14 1 0 -make-backend/internal/gql/generated.go:11035.14,11037.3 1 0 -make-backend/internal/gql/generated.go:11038.2,11039.44 2 0 -make-backend/internal/gql/generated.go:11042.116,11043.14 1 0 -make-backend/internal/gql/generated.go:11043.14,11045.3 1 0 -make-backend/internal/gql/generated.go:11046.2,11049.12 4 0 -make-backend/internal/gql/generated.go:11052.96,11053.14 1 0 -make-backend/internal/gql/generated.go:11053.14,11055.3 1 0 -make-backend/internal/gql/generated.go:11056.2,11057.44 2 0 -make-backend/internal/gql/generated.go:11060.121,11061.14 1 0 -make-backend/internal/gql/generated.go:11061.14,11063.3 1 0 -make-backend/internal/gql/generated.go:11064.2,11067.12 4 0 -make-backend/internal/gql/generated.go:11070.193,11071.14 1 0 -make-backend/internal/gql/generated.go:11071.14,11073.3 1 0 -make-backend/internal/gql/generated.go:11074.2,11074.36 1 0 -make-backend/internal/gql/generated.go:11077.101,11078.14 1 0 -make-backend/internal/gql/generated.go:11078.14,11080.3 1 0 -make-backend/internal/gql/generated.go:11081.2,11082.44 2 0 -make-backend/internal/gql/generated.go:11085.126,11086.14 1 0 -make-backend/internal/gql/generated.go:11086.14,11088.3 1 0 -make-backend/internal/gql/generated.go:11089.2,11092.12 4 0 -make-backend/internal/gql/generated.go:11095.107,11096.14 1 0 -make-backend/internal/gql/generated.go:11096.14,11098.3 1 0 -make-backend/internal/gql/generated.go:11099.2,11100.44 2 0 -make-backend/internal/gql/generated.go:11103.132,11104.14 1 0 -make-backend/internal/gql/generated.go:11104.14,11106.3 1 0 -make-backend/internal/gql/generated.go:11107.2,11110.12 4 0 -make-backend/internal/gql/generated.go:11113.217,11114.14 1 0 -make-backend/internal/gql/generated.go:11114.14,11116.3 1 0 -make-backend/internal/gql/generated.go:11117.2,11117.116 1 0 -make-backend/internal/gql/generated.go:11117.116,11121.3 3 0 -make-backend/internal/gql/generated.go:11123.2,11123.24 1 0 -make-backend/internal/gql/generated.go:11123.24,11124.24 1 0 -make-backend/internal/gql/generated.go:11124.24,11126.4 1 0 -make-backend/internal/gql/generated.go:11129.2,11129.12 1 0 -make-backend/internal/gql/generated.go:11132.205,11133.14 1 0 -make-backend/internal/gql/generated.go:11133.14,11135.3 1 0 -make-backend/internal/gql/generated.go:11136.2,11136.116 1 0 -make-backend/internal/gql/generated.go:11136.116,11140.3 3 0 -make-backend/internal/gql/generated.go:11142.2,11142.24 1 0 -make-backend/internal/gql/generated.go:11142.24,11143.24 1 0 -make-backend/internal/gql/generated.go:11143.24,11145.4 1 0 -make-backend/internal/gql/generated.go:11148.2,11148.12 1 0 -make-backend/internal/gql/generated.go:11151.220,11152.14 1 0 -make-backend/internal/gql/generated.go:11152.14,11154.3 1 0 -make-backend/internal/gql/generated.go:11155.2,11155.116 1 0 -make-backend/internal/gql/generated.go:11155.116,11159.3 3 0 -make-backend/internal/gql/generated.go:11161.2,11161.24 1 0 -make-backend/internal/gql/generated.go:11161.24,11162.24 1 0 -make-backend/internal/gql/generated.go:11162.24,11164.4 1 0 -make-backend/internal/gql/generated.go:11167.2,11167.12 1 0 -make-backend/internal/gql/generated.go:11170.204,11171.14 1 0 -make-backend/internal/gql/generated.go:11171.14,11173.3 1 0 -make-backend/internal/gql/generated.go:11174.2,11174.34 1 0 -make-backend/internal/gql/generated.go:11177.202,11178.14 1 0 -make-backend/internal/gql/generated.go:11178.14,11180.3 1 0 -make-backend/internal/gql/generated.go:11181.2,11181.116 1 0 -make-backend/internal/gql/generated.go:11181.116,11185.3 3 0 -make-backend/internal/gql/generated.go:11187.2,11187.24 1 0 -make-backend/internal/gql/generated.go:11187.24,11188.24 1 0 -make-backend/internal/gql/generated.go:11188.24,11190.4 1 0 -make-backend/internal/gql/generated.go:11193.2,11193.12 1 0 -make-backend/internal/gql/generated.go:11196.198,11197.14 1 0 -make-backend/internal/gql/generated.go:11197.14,11199.3 1 0 -make-backend/internal/gql/generated.go:11200.2,11200.32 1 0 -make-backend/internal/gql/resolvers/device.resolvers.go:15.103,17.2 1 0 -make-backend/internal/gql/resolvers/device.resolvers.go:20.85,22.16 2 0 -make-backend/internal/gql/resolvers/device.resolvers.go:22.16,24.3 1 0 -make-backend/internal/gql/resolvers/device.resolvers.go:25.2,25.17 1 0 -make-backend/internal/gql/resolvers/device.resolvers.go:29.97,31.16 2 0 -make-backend/internal/gql/resolvers/device.resolvers.go:31.16,33.3 1 0 -make-backend/internal/gql/resolvers/device.resolvers.go:34.2,34.17 1 0 -make-backend/internal/gql/resolvers/device.resolvers.go:38.66,38.104 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:16.87,20.16 3 0 -make-backend/internal/gql/resolvers/group.resolvers.go:20.16,22.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:23.2,24.16 2 0 -make-backend/internal/gql/resolvers/group.resolvers.go:24.16,26.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:27.2,27.14 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:27.14,29.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:30.2,30.19 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:34.111,37.16 3 0 -make-backend/internal/gql/resolvers/group.resolvers.go:37.16,39.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:40.2,40.14 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:40.14,42.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:44.2,45.47 2 0 -make-backend/internal/gql/resolvers/group.resolvers.go:45.47,47.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:48.2,48.47 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:48.47,50.17 2 0 -make-backend/internal/gql/resolvers/group.resolvers.go:50.17,52.4 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:53.3,56.10 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:58.2,59.59 2 0 -make-backend/internal/gql/resolvers/group.resolvers.go:59.59,61.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:62.2,63.33 2 0 -make-backend/internal/gql/resolvers/group.resolvers.go:63.33,65.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:66.2,66.22 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:70.99,74.16 3 0 -make-backend/internal/gql/resolvers/group.resolvers.go:74.16,76.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:77.2,77.21 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:77.21,79.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:81.2,82.16 2 0 -make-backend/internal/gql/resolvers/group.resolvers.go:86.107,90.16 3 0 -make-backend/internal/gql/resolvers/group.resolvers.go:90.16,92.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:93.2,93.21 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:93.21,95.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:97.2,98.16 2 0 -make-backend/internal/gql/resolvers/group.resolvers.go:103.108,107.16 3 0 -make-backend/internal/gql/resolvers/group.resolvers.go:107.16,109.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:110.2,110.28 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:110.28,112.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:113.2,114.16 2 0 -make-backend/internal/gql/resolvers/group.resolvers.go:114.16,116.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:117.2,117.28 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:117.28,119.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:120.2,120.68 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:124.107,128.16 3 0 -make-backend/internal/gql/resolvers/group.resolvers.go:128.16,130.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:131.2,131.21 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:131.21,133.3 1 0 -make-backend/internal/gql/resolvers/group.resolvers.go:134.2,134.67 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:15.105,17.16 2 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:17.16,19.3 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:21.2,21.19 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:25.115,27.16 2 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:27.16,29.3 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:31.2,32.34 2 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:32.34,34.3 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:36.2,36.19 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:40.105,42.16 2 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:42.16,44.3 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:46.2,46.16 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:50.88,52.16 2 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:52.16,54.3 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:56.2,56.21 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:60.93,62.16 2 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:62.16,64.3 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:66.2,66.24 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:70.56,70.89 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:73.52,73.83 1 0 -make-backend/internal/gql/resolvers/makerspace.resolvers.go:76.46,76.74 1 0 -make-backend/internal/gql/resolvers/training.resolvers.go:16.112,17.57 1 0 -make-backend/internal/gql/resolvers/training.resolvers.go:21.110,23.2 1 0 -make-backend/internal/gql/resolvers/training.resolvers.go:26.70,28.2 1 0 -make-backend/internal/gql/resolvers/training.resolvers.go:31.52,31.83 1 0 -make-backend/internal/gql/resolvers/user.resolvers.go:16.81,17.51 1 0 -make-backend/internal/gql/resolvers/user.resolvers.go:21.80,26.2 3 0 -make-backend/internal/gql/resolvers/zones.resolvers.go:15.81,17.16 2 0 -make-backend/internal/gql/resolvers/zones.resolvers.go:17.16,19.3 1 0 -make-backend/internal/gql/resolvers/zones.resolvers.go:21.2,21.18 1 0 -make-backend/internal/gql/resolvers/zones.resolvers.go:25.108,26.81 1 0 diff --git a/internal/database/group_test.go b/internal/database/group_test.go index 6b9d370d..65e7853b 100644 --- a/internal/database/group_test.go +++ b/internal/database/group_test.go @@ -1,225 +1,15 @@ package database import ( - "context" - "database/sql" - "embed" - "fmt" - "log" "log/slog" - "make-backend/internal/database/models" - "sync" "testing" - - "github.com/pressly/goose/v3" - "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/modules/postgres" ) -type testContext struct { - users []struct { - id int - email string - } - beatlesMusicians models.Group - beatlesManagers models.Group - brits models.Group -} - -var localContext testContext = testContext{ - users: []struct { - id int - email string - }{ - {email: "brian@beatles.com"}, - {email: "john@beatles.com"}, - {email: "paul@beatles.com"}, - {email: "george@beatles.com"}, - {email: "ringo@beatles.com"}, - }, -} - -func setupTestDB(t *testing.T) (*sql.DB, func(), error) { - ctx := context.Background() - - dbName := "testdb" - dbUser := "test_user" - dbPassword := "test_password" - - postgresContainer, err := postgres.Run(ctx, - "postgres:16-alpine", - postgres.WithDatabase(dbName), - postgres.WithUsername(dbUser), - postgres.WithPassword(dbPassword), - postgres.BasicWaitStrategies(), - ) - deferer := func() { - if err := testcontainers.TerminateContainer(postgresContainer); err != nil { - t.Logf("failed to terminate container: %s", err) - } - } - if err != nil { - t.Logf("failed to start container: %s", err) - return nil, func() {}, err - } - - connStr := postgresContainer.MustConnectionString(ctx, "sslmode=disable") - slog.Info("connecting to test postgres", "conn", connStr) - - db, err := sql.Open("postgres", connStr) - if err != nil { - log.Fatal(err) - } - - if err := db.Ping(); err != nil { - return nil, deferer, err - } - - err = migrateTestDB(t, db) - if err != nil { - return db, deferer, err - } - - store := NewStore(db) - fillTestData(t, store) - - return db, deferer, nil - -} - -//go:embed migrations/*.sql -var testEmbedMigrations embed.FS - -func migrateTestDB(t *testing.T, db *sql.DB) error { - // Migrations - t.Log("Running migrations...") - goose.SetBaseFS(testEmbedMigrations) - if err := goose.SetDialect("postgres"); err != nil { - return fmt.Errorf("Failed to set goose dialect: %w", err) - } - - if err := goose.Up(db, "migrations"); err != nil { - return fmt.Errorf("Failed to run migrations: %w", err) - } - return nil -} - -func fillTestUsers(t *testing.T, store *Store) { - for i, u := range localContext.users { - id, err := store.Users.CreateUser(t.Context(), u.email) - if err != nil { - t.Fatal("failed to add test user", err) - } - localContext.users[i].id = id - } -} - -func makeTestGroups(t *testing.T, store *Store) { - managerGroupID, err := store.Groups.GetAdminGroupId(t.Context()) - if err != nil { - t.Fatal("Failed to find root group", err) - } - localContext.beatlesManagers, err = store.Groups.CreateGroup(t.Context(), models.Group{ - ManagerId: managerGroupID, - Name: "The Beatles Managers", - Description: "", - }) - if err != nil { - t.Fatal("failed to create manager group", err) - } - localContext.beatlesMusicians, err = store.Groups.CreateGroup(t.Context(), models.Group{ - ManagerId: localContext.beatlesManagers.Id, - Name: "The beatles musicians", - Description: "the members of the beatles", - }) - if err != nil { - t.Fatal("failed to create musician group", err) - } - - localContext.brits, err = store.Groups.CreateGroup(t.Context(), models.Group{ - ManagerId: managerGroupID, - Name: "British People", - Description: "", - }) - if err != nil { - t.Fatal("failed to create british group", err) - } - - err = store.Groups.AddSubgroupToGroup(t.Context(), localContext.beatlesMusicians.Id, localContext.brits.Id, models.GroupViewPermission_SeeSelf) - if err != nil { - t.Fatal("Failed to add beatles subgroup to british super group") - } - - err = store.Groups.AddSubgroupToGroup(t.Context(), localContext.beatlesManagers.Id, localContext.brits.Id, models.GroupViewPermission_SeeSelf) - if err != nil { - t.Fatal("Failed to add beatles managers subgroup to british super group") - } -} - -func addUsersToTestGroups(t *testing.T, store *Store) { - for _, email := range []string{ - "john@beatles.com", - "paul@beatles.com", - "george@beatles.com", - "ringo@beatles.com", - } { - user, err := store.Users.GetUserByEmail(t.Context(), email) - if err != nil { - t.Fatalf("couldn't find user with email '%s': %v", email, err) - } - err = store.Groups.AddUserToGroup(t.Context(), user.Id, localContext.beatlesMusicians.Id, models.GroupViewPermission_SeeAll) - if err != nil { - t.Fatalf("Failed to add %+v to group %+v", user, localContext.beatlesMusicians) - } - } - - user, err := store.Users.GetUserByEmail(t.Context(), "brian@beatles.com") - if err != nil { - t.Fatalf("couldn't find user with email '%s': %v", "brian@beatles.com", err) - } - err = store.Groups.AddUserToGroup(t.Context(), user.Id, localContext.beatlesManagers.Id, models.GroupViewPermission_SeeAll) - if err != nil { - t.Fatalf("Failed to add %+v to group %+v", user, localContext.beatlesManagers) - } - -} - -func fillTestData(t *testing.T, store *Store) { - fillTestUsers(t, store) - makeTestGroups(t, store) - addUsersToTestGroups(t, store) - -} - -var localLock sync.Mutex -var localDB *sql.DB = nil -var localStore *Store = nil -var localCleanup func() = func() {} - -func verifyDb(t *testing.T) (*sql.DB, *Store) { - if testing.Short() { - t.Skip("Skipping db test in short mode.") - return nil, nil - } - localLock.Lock() - defer localLock.Unlock() - if localDB != nil { - return localDB, localStore - } - var err error - localDB, localCleanup, err = setupTestDB(t) - if err != nil { - t.Fatal("Failed to setup test DB", err) - } - localStore = NewStore(localDB) - return localDB, localStore -} - func TestAddedUsers(t *testing.T) { if testing.Short() { t.Skip("Skipping db test in short mode.") } - _, store := verifyDb(t) + _, store := VerifyDb(slog.Default()) for _, user := range localContext.users { user, err := store.Users.GetUserByEmail(t.Context(), user.email) if err != nil { @@ -232,7 +22,7 @@ func TestGroupMembership(t *testing.T) { if testing.Short() { t.Skip("Skipping db test in short mode.") } - _, store := verifyDb(t) + _, store := VerifyDb(slog.Default()) for _, email := range []string{ "john@beatles.com", "paul@beatles.com", @@ -257,7 +47,7 @@ func TestSubgroupMembership(t *testing.T) { if testing.Short() { t.Skip("Skipping db test in short mode.") } - _, store := verifyDb(t) + _, store := VerifyDb(slog.Default()) for _, email := range []string{ "john@beatles.com", "paul@beatles.com", diff --git a/internal/database/mock_data.go b/internal/database/mock_data.go new file mode 100644 index 00000000..b8398477 --- /dev/null +++ b/internal/database/mock_data.go @@ -0,0 +1,225 @@ +package database + +import ( + "context" + "database/sql" + "embed" + "fmt" + "log" + "log/slog" + "make-backend/internal/database/models" + "sync" + + "github.com/pressly/goose/v3" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/postgres" +) + +type testContext struct { + users []struct { + id int + email string + } + beatlesMusicians models.Group + beatlesManagers models.Group + brits models.Group +} + +var localContext testContext = testContext{ + users: []struct { + id int + email string + }{ + {email: "brian@beatles.com"}, + {email: "john@beatles.com"}, + {email: "paul@beatles.com"}, + {email: "george@beatles.com"}, + {email: "ringo@beatles.com"}, + }, +} + +func fillTestUsers(ctx context.Context, l *slog.Logger, store *Store) bool { + for i, u := range localContext.users { + id, err := store.Users.CreateUser(ctx, u.email) + if err != nil { + l.Error("failed to add test user", "err", err) + return false + } + localContext.users[i].id = id + } + return true +} + +func makeTestGroups(ctx context.Context, l *slog.Logger, store *Store) bool { + managerGroupID, err := store.Groups.GetAdminGroupId(ctx) + if err != nil { + l.Error("Failed to find root group", "err", err) + return false + } + localContext.beatlesManagers, err = store.Groups.CreateGroup(ctx, models.Group{ + ManagerId: managerGroupID, + Name: "The Beatles Managers", + Description: "", + }) + if err != nil { + l.Error("failed to create manager group", "err", err) + return false + } + localContext.beatlesMusicians, err = store.Groups.CreateGroup(ctx, models.Group{ + ManagerId: localContext.beatlesManagers.Id, + Name: "The beatles musicians", + Description: "the members of the beatles", + }) + if err != nil { + l.Error("failed to create musician group", "err", err) + return false + } + + localContext.brits, err = store.Groups.CreateGroup(ctx, models.Group{ + ManagerId: managerGroupID, + Name: "British People", + Description: "", + }) + if err != nil { + l.Error("failed to create british group", "err", err) + return false + } + + err = store.Groups.AddSubgroupToGroup(ctx, localContext.beatlesMusicians.Id, localContext.brits.Id, models.GroupViewPermission_SeeSelf) + if err != nil { + l.Error("Failed to add beatles subgroup to british super group") + return false + } + + err = store.Groups.AddSubgroupToGroup(ctx, localContext.beatlesManagers.Id, localContext.brits.Id, models.GroupViewPermission_SeeSelf) + if err != nil { + l.Error("Failed to add beatles managers subgroup to british super group") + return false + } + return true +} + +func addUsersToTestGroups(ctx context.Context, t *slog.Logger, store *Store) bool { + for _, email := range []string{ + "john@beatles.com", + "paul@beatles.com", + "george@beatles.com", + "ringo@beatles.com", + } { + user, err := store.Users.GetUserByEmail(ctx, email) + if err != nil { + t.Error("couldn't find user", "email", email, "err", err) + return false + } + err = store.Groups.AddUserToGroup(ctx, user.Id, localContext.beatlesMusicians.Id, models.GroupViewPermission_SeeAll) + if err != nil { + t.Error("Failed to add ", "user", user, "group", localContext.beatlesMusicians) + return false + } + } + + user, err := store.Users.GetUserByEmail(ctx, "brian@beatles.com") + if err != nil { + t.Error("couldn't find user", "email", "brian@beatles.com", "err", err) + return false + } + err = store.Groups.AddUserToGroup(ctx, user.Id, localContext.beatlesManagers.Id, models.GroupViewPermission_SeeAll) + if err != nil { + t.Error("Failed to add to group", "user", user, "group", localContext.beatlesManagers, "err", err) + return false + } + return true + +} + +func fillTestData(ctx context.Context, l *slog.Logger, store *Store) { + fillTestUsers(ctx, l, store) + makeTestGroups(ctx, l, store) + addUsersToTestGroups(ctx, l, store) + +} + +func setupTestDB(logger *slog.Logger) (*sql.DB, func(), error) { + ctx := context.Background() + + dbName := "testdb" + dbUser := "test_user" + dbPassword := "test_password" + + postgresContainer, err := postgres.Run(ctx, + "postgres:16-alpine", + postgres.WithDatabase(dbName), + postgres.WithUsername(dbUser), + postgres.WithPassword(dbPassword), + postgres.BasicWaitStrategies(), + ) + deferer := func() { + if err := testcontainers.TerminateContainer(postgresContainer); err != nil { + logger.Error("failed to terminate container", "err", err) + } + } + if err != nil { + logger.Error("failed to start container", "err", err) + return nil, func() {}, err + } + + connStr := postgresContainer.MustConnectionString(ctx, "sslmode=disable") + slog.Info("connecting to test postgres", "conn", connStr) + + db, err := sql.Open("postgres", connStr) + if err != nil { + log.Fatal(err) + } + + if err := db.Ping(); err != nil { + return nil, deferer, err + } + + err = migrateTestDB(logger, db) + if err != nil { + return db, deferer, err + } + + store := NewStore(db) + fillTestData(context.TODO(), logger, store) + + return db, deferer, nil + +} + +//go:embed migrations/*.sql +var testEmbedMigrations embed.FS + +func migrateTestDB(logger *slog.Logger, db *sql.DB) error { + // Migrations + logger.Info("Running migrations...") + goose.SetBaseFS(testEmbedMigrations) + if err := goose.SetDialect("postgres"); err != nil { + return fmt.Errorf("failed to set goose dialect: %w", err) + } + + if err := goose.Up(db, "migrations"); err != nil { + return fmt.Errorf("failed to run migrations: %w", err) + } + return nil +} + +var localLock sync.Mutex +var localDB *sql.DB = nil +var localStore *Store = nil +var localCleanup func() = func() {} + +func VerifyDb(logger *slog.Logger) (*sql.DB, *Store) { + localLock.Lock() + defer localLock.Unlock() + if localDB != nil { + return localDB, localStore + } + var err error + localDB, localCleanup, err = setupTestDB(logger) + if err != nil { + logger.Error("failed to setup test DB", "err", err) + } + localStore = NewStore(localDB) + return localDB, localStore +} diff --git a/internal/database/setup.go b/internal/database/setup.go index 027b047a..f4864371 100644 --- a/internal/database/setup.go +++ b/internal/database/setup.go @@ -19,6 +19,10 @@ func SetupDB() (*sql.DB, error) { if err != nil { return db, err } + + // store := NewStore(db) + // fillTestData(context.TODO(), log.Default(), store) + return db, nil } From ea5c686e8bd33b556d9986ea47c4685dc64a9679 Mon Sep 17 00:00:00 2001 From: cowsed Date: Mon, 10 Aug 2026 14:36:10 -0400 Subject: [PATCH 07/22] more resolver testing --- internal/database/group_test.go | 53 ++++- internal/database/mock_data.go | 76 ++++--- internal/database/repos/group_repo.go | 23 ++- internal/database/setup.go | 3 - internal/gql/resolvers/group.resolvers.go | 18 +- internal/gql/resolvers/group_resolver_test.go | 194 ++++++++++++++++++ 6 files changed, 304 insertions(+), 63 deletions(-) create mode 100644 internal/gql/resolvers/group_resolver_test.go diff --git a/internal/database/group_test.go b/internal/database/group_test.go index 65e7853b..4aa46ef2 100644 --- a/internal/database/group_test.go +++ b/internal/database/group_test.go @@ -5,13 +5,48 @@ import ( "testing" ) +func TestUserGroupVisibilityGood(t *testing.T) { + if testing.Short() { + t.Skip("Skipping db test in short mode.") + } + _, store, data := VerifyTestDb(slog.Default()) + user := data.Users[0] + group := data.BeatlesMusicians + + // brian can see musicians + visible, err := store.Groups.IsGroupVisibleToUser(t.Context(), user.Id, group.Id) + if err != nil { + t.Fatalf("Failed to check group visibility of %+v to see %+v: %v", user, group, err) + } + if visible != true { + t.Fatalf("%v should be able to see %v but couldn't", user, group) + } +} +func TestUserGroupVisibilityBad(t *testing.T) { + if testing.Short() { + t.Skip("Skipping db test in short mode.") + } + _, store, data := VerifyTestDb(slog.Default()) + user := data.Users[1] + group := data.BeatlesManagers + + // musicians can't see up (unless explicitly allowed to) + visible, err := store.Groups.IsGroupVisibleToUser(t.Context(), user.Id, group.Id) + if err != nil { + t.Fatalf("Failed to check group visibility of %+v to see %+v: %v", user, group, err) + } + if visible != false { + t.Fatalf("%v should NOT be able to see %v but could", user, group) + } +} + func TestAddedUsers(t *testing.T) { if testing.Short() { t.Skip("Skipping db test in short mode.") } - _, store := VerifyDb(slog.Default()) - for _, user := range localContext.users { - user, err := store.Users.GetUserByEmail(t.Context(), user.email) + _, store, _ := VerifyTestDb(slog.Default()) + for _, user := range localContext.Users { + user, err := store.Users.GetUserByEmail(t.Context(), user.Email) if err != nil { t.Fatalf("Failed to find user with email '%s': %v", user.Email, err) } @@ -22,7 +57,7 @@ func TestGroupMembership(t *testing.T) { if testing.Short() { t.Skip("Skipping db test in short mode.") } - _, store := VerifyDb(slog.Default()) + _, store, _ := VerifyTestDb(slog.Default()) for _, email := range []string{ "john@beatles.com", "paul@beatles.com", @@ -33,12 +68,12 @@ func TestGroupMembership(t *testing.T) { if err != nil { t.Fatalf("couldn't find user with email '%s': %v", email, err) } - inGroup, _, err := store.Groups.IsUserInGroup(t.Context(), user.Id, localContext.beatlesMusicians.Id) + inGroup, _, err := store.Groups.IsUserInGroup(t.Context(), user.Id, localContext.BeatlesMusicians.Id) if err != nil { t.Fatalf("couldn't check user in group for email '%s': %v", email, err) } if !inGroup { - t.Fatalf("user with email '%s' should be in group '%s' but wasn't", email, localContext.beatlesMusicians.Name) + t.Fatalf("user with email '%s' should be in group '%s' but wasn't", email, localContext.BeatlesMusicians.Name) } } } @@ -47,7 +82,7 @@ func TestSubgroupMembership(t *testing.T) { if testing.Short() { t.Skip("Skipping db test in short mode.") } - _, store := VerifyDb(slog.Default()) + _, store, _ := VerifyTestDb(slog.Default()) for _, email := range []string{ "john@beatles.com", "paul@beatles.com", @@ -59,12 +94,12 @@ func TestSubgroupMembership(t *testing.T) { if err != nil { t.Fatalf("couldn't find user with email '%s': %v", email, err) } - inGroup, _, err := store.Groups.IsUserInGroup(t.Context(), user.Id, localContext.brits.Id) + inGroup, _, err := store.Groups.IsUserInGroup(t.Context(), user.Id, localContext.Brits.Id) if err != nil { t.Fatalf("couldn't check user in group for email '%s': %v", email, err) } if !inGroup { - t.Fatalf("user with email '%s' should be in group '%s' via subgroup but wasn't", email, localContext.beatlesMusicians.Name) + t.Fatalf("user with email '%s' should be in group '%s' via subgroup but wasn't", email, localContext.BeatlesMusicians.Name) } } } diff --git a/internal/database/mock_data.go b/internal/database/mock_data.go index b8398477..b34e5677 100644 --- a/internal/database/mock_data.go +++ b/internal/database/mock_data.go @@ -15,37 +15,38 @@ import ( "github.com/testcontainers/testcontainers-go/modules/postgres" ) -type testContext struct { - users []struct { - id int - email string - } - beatlesMusicians models.Group - beatlesManagers models.Group - brits models.Group +type TestMockData struct { + Users []struct { + Id int + Email string + } + BeatlesMusicians models.Group + OtherMusicians models.Group + BeatlesManagers models.Group + Brits models.Group } -var localContext testContext = testContext{ - users: []struct { - id int - email string +var localContext TestMockData = TestMockData{ + Users: []struct { + Id int + Email string }{ - {email: "brian@beatles.com"}, - {email: "john@beatles.com"}, - {email: "paul@beatles.com"}, - {email: "george@beatles.com"}, - {email: "ringo@beatles.com"}, + {Email: "brian@beatles.com"}, + {Email: "john@beatles.com"}, + {Email: "paul@beatles.com"}, + {Email: "george@beatles.com"}, + {Email: "ringo@beatles.com"}, }, } func fillTestUsers(ctx context.Context, l *slog.Logger, store *Store) bool { - for i, u := range localContext.users { - id, err := store.Users.CreateUser(ctx, u.email) + for i, u := range localContext.Users { + id, err := store.Users.CreateUser(ctx, u.Email) if err != nil { l.Error("failed to add test user", "err", err) return false } - localContext.users[i].id = id + localContext.Users[i].Id = id } return true } @@ -56,7 +57,7 @@ func makeTestGroups(ctx context.Context, l *slog.Logger, store *Store) bool { l.Error("Failed to find root group", "err", err) return false } - localContext.beatlesManagers, err = store.Groups.CreateGroup(ctx, models.Group{ + localContext.BeatlesManagers, err = store.Groups.CreateGroup(ctx, models.Group{ ManagerId: managerGroupID, Name: "The Beatles Managers", Description: "", @@ -65,8 +66,8 @@ func makeTestGroups(ctx context.Context, l *slog.Logger, store *Store) bool { l.Error("failed to create manager group", "err", err) return false } - localContext.beatlesMusicians, err = store.Groups.CreateGroup(ctx, models.Group{ - ManagerId: localContext.beatlesManagers.Id, + localContext.BeatlesMusicians, err = store.Groups.CreateGroup(ctx, models.Group{ + ManagerId: localContext.BeatlesManagers.Id, Name: "The beatles musicians", Description: "the members of the beatles", }) @@ -74,8 +75,17 @@ func makeTestGroups(ctx context.Context, l *slog.Logger, store *Store) bool { l.Error("failed to create musician group", "err", err) return false } + localContext.OtherMusicians, err = store.Groups.CreateGroup(ctx, models.Group{ + ManagerId: localContext.BeatlesManagers.Id, + Name: "Other musicians", + Description: "Other members the beatles don't know about", + }) + if err != nil { + l.Error("failed to create other musician group", "err", err) + return false + } - localContext.brits, err = store.Groups.CreateGroup(ctx, models.Group{ + localContext.Brits, err = store.Groups.CreateGroup(ctx, models.Group{ ManagerId: managerGroupID, Name: "British People", Description: "", @@ -85,13 +95,13 @@ func makeTestGroups(ctx context.Context, l *slog.Logger, store *Store) bool { return false } - err = store.Groups.AddSubgroupToGroup(ctx, localContext.beatlesMusicians.Id, localContext.brits.Id, models.GroupViewPermission_SeeSelf) + err = store.Groups.AddSubgroupToGroup(ctx, localContext.BeatlesMusicians.Id, localContext.Brits.Id, models.GroupViewPermission_SeeSelf) if err != nil { l.Error("Failed to add beatles subgroup to british super group") return false } - err = store.Groups.AddSubgroupToGroup(ctx, localContext.beatlesManagers.Id, localContext.brits.Id, models.GroupViewPermission_SeeSelf) + err = store.Groups.AddSubgroupToGroup(ctx, localContext.BeatlesManagers.Id, localContext.Brits.Id, models.GroupViewPermission_SeeSelf) if err != nil { l.Error("Failed to add beatles managers subgroup to british super group") return false @@ -111,9 +121,9 @@ func addUsersToTestGroups(ctx context.Context, t *slog.Logger, store *Store) boo t.Error("couldn't find user", "email", email, "err", err) return false } - err = store.Groups.AddUserToGroup(ctx, user.Id, localContext.beatlesMusicians.Id, models.GroupViewPermission_SeeAll) + err = store.Groups.AddUserToGroup(ctx, user.Id, localContext.BeatlesMusicians.Id, models.GroupViewPermission_SeeAll) if err != nil { - t.Error("Failed to add ", "user", user, "group", localContext.beatlesMusicians) + t.Error("Failed to add ", "user", user, "group", localContext.BeatlesMusicians) return false } } @@ -123,9 +133,9 @@ func addUsersToTestGroups(ctx context.Context, t *slog.Logger, store *Store) boo t.Error("couldn't find user", "email", "brian@beatles.com", "err", err) return false } - err = store.Groups.AddUserToGroup(ctx, user.Id, localContext.beatlesManagers.Id, models.GroupViewPermission_SeeAll) + err = store.Groups.AddUserToGroup(ctx, user.Id, localContext.BeatlesManagers.Id, models.GroupViewPermission_SeeAll) if err != nil { - t.Error("Failed to add to group", "user", user, "group", localContext.beatlesManagers, "err", err) + t.Error("Failed to add to group", "user", user, "group", localContext.BeatlesManagers, "err", err) return false } return true @@ -209,11 +219,11 @@ var localDB *sql.DB = nil var localStore *Store = nil var localCleanup func() = func() {} -func VerifyDb(logger *slog.Logger) (*sql.DB, *Store) { +func VerifyTestDb(logger *slog.Logger) (*sql.DB, *Store, *TestMockData) { localLock.Lock() defer localLock.Unlock() if localDB != nil { - return localDB, localStore + return localDB, localStore, &localContext } var err error localDB, localCleanup, err = setupTestDB(logger) @@ -221,5 +231,5 @@ func VerifyDb(logger *slog.Logger) (*sql.DB, *Store) { logger.Error("failed to setup test DB", "err", err) } localStore = NewStore(localDB) - return localDB, localStore + return localDB, localStore, &localContext } diff --git a/internal/database/repos/group_repo.go b/internal/database/repos/group_repo.go index 1d4ef470..0c914726 100644 --- a/internal/database/repos/group_repo.go +++ b/internal/database/repos/group_repo.go @@ -3,6 +3,7 @@ package repos import ( "context" "database/sql" + "errors" "fmt" "make-backend/internal/database/models" ) @@ -55,7 +56,7 @@ func (g *GroupRepo) IsGroupVisibleToUser(ctx context.Context, userId int, groupI // if can manage -> see all canManage, err := g.CanUserManageGroup(ctx, userId, groupId) if err != nil { - return false, fmt.Errorf("failed to check if group is visible to user: %w", err) + return false, fmt.Errorf("failed to check if group is visible to user check 1: %w", err) } if canManage { return true, nil @@ -64,7 +65,7 @@ func (g *GroupRepo) IsGroupVisibleToUser(ctx context.Context, userId int, groupI isInGroup, how, err := g.IsUserInGroup(ctx, userId, groupId) if err != nil { - return false, fmt.Errorf("failed to check if group is visible to user: %w", err) + return false, fmt.Errorf("failed to check if group is visible to user check 2: %w", err) } if isInGroup { @@ -79,13 +80,7 @@ func (g *GroupRepo) IsGroupVisibleToUser(ctx context.Context, userId int, groupI return false, fmt.Errorf("invalid view permission: %v", how) } } - // if inside - - // if see none -> false, see none - // if see some -> true, see self - // if see all -> true, see all - panic("unimplemented") - + return false, nil } func (g *GroupRepo) IsGroupVisibleToGroup(ctx context.Context, lookingGroupId int, groupId int) (bool, error) { // if can manage -> see all @@ -308,7 +303,13 @@ func (g *GroupRepo) IsUserInGroup(ctx context.Context, userId int, groupId int) query := "SELECT view_permission FROM group_membership WHERE user_id = $1 and group_id = $2" - err := g.DB.QueryRow(query, userId, groupId).Scan(&perms) + row := g.DB.QueryRow(query, userId, groupId) + + err := row.Scan(&perms) + if errors.Is(err, sql.ErrNoRows) { + return false, models.GroupViewPermission_SeeNone, nil + } + if err != nil { return false, models.GroupViewPermission_SeeNone, err } @@ -376,7 +377,7 @@ func (g *GroupRepo) GetGroupById(ctx context.Context, id int) (*models.Group, er id, manager_id, name, - description, + description FROM groups WHERE id = $1` err := g.DB.QueryRowContext(ctx, query, id).Scan( diff --git a/internal/database/setup.go b/internal/database/setup.go index f4864371..8cbaf753 100644 --- a/internal/database/setup.go +++ b/internal/database/setup.go @@ -20,9 +20,6 @@ func SetupDB() (*sql.DB, error) { return db, err } - // store := NewStore(db) - // fillTestData(context.TODO(), log.Default(), store) - return db, nil } diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index 718c3347..c2203b01 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -13,20 +13,21 @@ import ( ) // GroupByID is the resolver for the groupById field. -func (r *queryResolver) GroupByID(ctx context.Context, id int) (*models.Group, error) { +func (r *queryResolver) GroupByID(ctx context.Context, groupId int) (*models.Group, error) { userID := ctx.Value(auth.UserContextKey{}).(int) - group, err := r.Store.Groups.GetGroupById(ctx, id) - if err != nil { - return nil, err - } - visible, err := r.Store.Groups.IsGroupVisibleToUser(ctx, userID, group.Id) + visible, err := r.Store.Groups.IsGroupVisibleToUser(ctx, userID, groupId) if err != nil { return nil, err } if !visible { return nil, fmt.Errorf("group does not exist or user does not have permission to see it") } + + group, err := r.Store.Groups.GetGroupById(ctx, groupId) + if err != nil { + return nil, err + } return group, nil } @@ -42,6 +43,10 @@ func (r *queryResolver) MembersOfGroup(ctx context.Context, groupID int) ([]*mod } _, how, err := r.Store.Groups.IsUserInGroup(ctx, askingUserID, groupID) + if err != nil { + return nil, fmt.Errorf("failed to check if users in group: %w", err) + } + if how == models.GroupViewPermission_SeeNone { return nil, fmt.Errorf("group does not exist or user does not have permission to see it") } @@ -96,7 +101,6 @@ func (r *queryResolver) IsUserInGroupDirectly(ctx context.Context, userID int, g in, _, err := r.Store.Groups.IsUserInGroupDirectly(ctx, userID, groupID) return in, err - } // CanGroupManageGroup is the resolver for the canGroupManageGroup field. diff --git a/internal/gql/resolvers/group_resolver_test.go b/internal/gql/resolvers/group_resolver_test.go new file mode 100644 index 00000000..5d39abcc --- /dev/null +++ b/internal/gql/resolvers/group_resolver_test.go @@ -0,0 +1,194 @@ +package resolvers + +import ( + "context" + "log/slog" + "make-backend/internal/auth" + "make-backend/internal/database" + "testing" +) + +func helpersForResolverTest(t *testing.T) (*database.Store, *database.TestMockData, *Resolver) { + if testing.Short() { + t.Skip("Skipping db/resolver test in short mode.") + } + _, store, mock := database.VerifyTestDb(slog.Default()) + return store, mock, &Resolver{Store: store} +} + +func ContextWithUser(parent context.Context, userId int) context.Context { + return context.WithValue(parent, auth.UserContextKey{}, userId) +} + +// If you query a group for a member and you don't have visibility to that group, you should get a group not found error +func TestUserGroupVisibilityByMemberQueryGood(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + + whenUserIsBrian := ContextWithUser(t.Context(), data.Users[0].Id) + userId := 400 + + _, brianErr := resolver.Query().IsUserInGroup(whenUserIsBrian, userId, data.OtherMusicians.Id) + if brianErr != nil { + t.Errorf("failed to check membership when brian should have visibility: %v", brianErr) + } +} +func TestUserGroupVisibilityByMemberQueryBad(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + + whenUserIsJohn := ContextWithUser(t.Context(), data.Users[1].Id) + userId := 400 + + _, JohnErr := resolver.Query().IsUserInGroup(whenUserIsJohn, userId, data.OtherMusicians.Id) + if JohnErr == nil { + t.Errorf("john checking membership should return a group not found error since he has no visibility to the other musicians but got null") + } +} + +func TestUserManagingGroup(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + + trials := []struct { + askerUser int + user int + group int + + shouldError bool + shouldManage bool + }{ + {data.Users[0].Id, data.Users[0].Id, data.BeatlesMusicians.Id, false, true}, + {data.Users[1].Id, data.Users[1].Id, data.BeatlesMusicians.Id, false, false}, + {data.Users[1].Id, data.Users[1].Id, data.OtherMusicians.Id, true, false}, + } + + for _, trial := range trials { + ctx := ContextWithUser(t.Context(), trial.askerUser) + + can, err := resolver.Query().CanUserManageGroup(ctx, trial.user, trial.group) + if err != nil && !trial.shouldError { + t.Fatalf("got error when %v checks if %v can manage group %v: %v", trial.askerUser, trial.user, trial.group, err) + } else if err == nil && trial.shouldError { + t.Fatalf("should get error when %v checks if %v can manage group %v we can't see", trial.askerUser, trial.user, trial.group) + continue + } + if trial.shouldManage && can != trial.shouldManage { + t.Fatalf("%v should be able to manage %v but wasn't able to for some reason", trial.user, trial.group) + } else if !trial.shouldManage && can != trial.shouldManage { + t.Fatalf("%v should NOT be able to manage %v but wasn't able to for some reason", trial.user, trial.group) + } + } +} + +func TestGroupMembership(t *testing.T) { + + _, data, resolver := helpersForResolverTest(t) + ctx := ContextWithUser(t.Context(), data.Users[0].Id) + + testCases := []struct { + desc string + user int + group int + shouldBeMember bool + shouldBeDirect bool + }{ + {"brian as direct member of managers", data.Users[0].Id, data.BeatlesManagers.Id, true, true}, + {"brian as NOT member of beatles musicians", data.Users[0].Id, data.BeatlesMusicians.Id, false, false}, + {"john as direct member of beatles musicians", data.Users[1].Id, data.BeatlesMusicians.Id, true, true}, + {"john as indirect member of brits", data.Users[1].Id, data.Brits.Id, true, false}, + } + for _, tC := range testCases { + t.Run(tC.desc, func(t *testing.T) { + inGroup, err1 := resolver.Query().IsUserInGroup(ctx, tC.user, tC.group) + inGroupDirectly, err2 := resolver.Query().IsUserInGroup(ctx, tC.user, tC.group) + if err1 != nil { + t.Fatalf("failed to check if user %v in group %v: %v", tC.user, tC.group, err1) + } + if err2 != nil { + t.Fatalf("failed to check if user %v directly in group %v: %v", tC.user, tC.group, err2) + } + if inGroup != tC.shouldBeMember { + t.Fatalf("user %v should have membership:%v to group %v but was %v", tC.user, tC.shouldBeMember, tC.group, inGroup) + } + if inGroup != tC.shouldBeMember { + t.Fatalf("user %v should have direct membership:%v to group %v but was %v", tC.user, tC.shouldBeDirect, tC.group, inGroupDirectly) + } + }) + } +} + +func TestFindingGroupsById(t *testing.T) { + + _, data, resolver := helpersForResolverTest(t) + testCases := []struct { + desc string + askingUser int + group int + exists bool + shouldError bool + }{ + { + desc: "brian getting beatles manager group", + askingUser: data.Users[0].Id, + group: data.BeatlesManagers.Id, + exists: true, + shouldError: false, + }, + { + desc: "brian getting beatles musician group", + askingUser: data.Users[0].Id, + group: data.BeatlesMusicians.Id, + exists: true, + shouldError: false, + }, + { + desc: "john getting beatles musician group", + askingUser: data.Users[1].Id, + group: data.BeatlesMusicians.Id, + exists: true, + shouldError: false, + }, + + { + desc: "john getting beatles manager group", + askingUser: data.Users[1].Id, + group: data.BeatlesManagers.Id, + exists: true, + shouldError: true, + }, { + desc: "john getting nonexistent group", + askingUser: data.Users[1].Id, + group: -1, + exists: false, + shouldError: true, + }, + } + for _, tC := range testCases { + t.Run(tC.desc, func(t *testing.T) { + ctx := ContextWithUser(t.Context(), tC.askingUser) + g, err := resolver.Query().GroupByID(ctx, tC.group) + if !tC.shouldError && err != nil { + t.Fatalf("should not error when user %v gets group %v but got %v", tC.askingUser, tC.group, err) + return + } + if !tC.exists && (err == nil || g != nil) { + t.Fatalf("group %v didn't exist but was somehow successful in fetching. Got %+v", tC.group, g) + return + } + + if tC.shouldError && err == nil { + t.Fatalf("should error when user %v gets group %v but didn't", tC.askingUser, tC.group) + return + } + + if !tC.shouldError { + if tC.exists && g == nil { + t.Fatalf("group %v should exist but could not find it: err = %v", tC.group, err) + return + } + if tC.group != g.Id { + t.Fatalf("asked for group %v but got non-matching %+v", tC.group, g) + return + } + } + }) + } +} From 4b0675dd5225fb3f9fbf813b4799d0e783d40a1c Mon Sep 17 00:00:00 2001 From: cowsed Date: Mon, 10 Aug 2026 16:00:22 -0400 Subject: [PATCH 08/22] yet more group resolver testing --- internal/database/mock_data.go | 46 +++--- internal/database/repos/group_repo.go | 47 +++++- internal/gql/resolvers/group.resolvers.go | 22 ++- internal/gql/resolvers/group_resolver_test.go | 138 +++++++++++++++++- 4 files changed, 225 insertions(+), 28 deletions(-) diff --git a/internal/database/mock_data.go b/internal/database/mock_data.go index b34e5677..8692f949 100644 --- a/internal/database/mock_data.go +++ b/internal/database/mock_data.go @@ -22,6 +22,7 @@ type TestMockData struct { } BeatlesMusicians models.Group OtherMusicians models.Group + ExMusicians models.Group BeatlesManagers models.Group Brits models.Group } @@ -36,6 +37,7 @@ var localContext TestMockData = TestMockData{ {Email: "paul@beatles.com"}, {Email: "george@beatles.com"}, {Email: "ringo@beatles.com"}, + {Email: "pete@beatles.com"}, }, } @@ -85,6 +87,16 @@ func makeTestGroups(ctx context.Context, l *slog.Logger, store *Store) bool { return false } + localContext.ExMusicians, err = store.Groups.CreateGroup(ctx, models.Group{ + ManagerId: localContext.BeatlesManagers.Id, + Name: "The ex musicians for the beatles", + Description: "ex members of the beatles", + }) + if err != nil { + l.Error("failed to create ex musician group", "err", err) + return false + } + localContext.Brits, err = store.Groups.CreateGroup(ctx, models.Group{ ManagerId: managerGroupID, Name: "British People", @@ -106,38 +118,34 @@ func makeTestGroups(ctx context.Context, l *slog.Logger, store *Store) bool { l.Error("Failed to add beatles managers subgroup to british super group") return false } + return true } func addUsersToTestGroups(ctx context.Context, t *slog.Logger, store *Store) bool { - for _, email := range []string{ - "john@beatles.com", - "paul@beatles.com", - "george@beatles.com", - "ringo@beatles.com", + for _, member := range []struct { + email string + groupId int + }{ + {"brian@beatles.com", localContext.BeatlesManagers.Id}, + {"john@beatles.com", localContext.BeatlesMusicians.Id}, + {"paul@beatles.com", localContext.BeatlesMusicians.Id}, + {"george@beatles.com", localContext.BeatlesMusicians.Id}, + {"ringo@beatles.com", localContext.BeatlesMusicians.Id}, + {"pete@beatles.com", localContext.ExMusicians.Id}, } { - user, err := store.Users.GetUserByEmail(ctx, email) + user, err := store.Users.GetUserByEmail(ctx, member.email) if err != nil { - t.Error("couldn't find user", "email", email, "err", err) + t.Error("couldn't find user", "email", member.email, "err", err) return false } - err = store.Groups.AddUserToGroup(ctx, user.Id, localContext.BeatlesMusicians.Id, models.GroupViewPermission_SeeAll) + err = store.Groups.AddUserToGroup(ctx, user.Id, member.groupId, models.GroupViewPermission_SeeAll) if err != nil { - t.Error("Failed to add ", "user", user, "group", localContext.BeatlesMusicians) + t.Error("Failed to add ", "user", user, "group", member.groupId) return false } } - user, err := store.Users.GetUserByEmail(ctx, "brian@beatles.com") - if err != nil { - t.Error("couldn't find user", "email", "brian@beatles.com", "err", err) - return false - } - err = store.Groups.AddUserToGroup(ctx, user.Id, localContext.BeatlesManagers.Id, models.GroupViewPermission_SeeAll) - if err != nil { - t.Error("Failed to add to group", "user", user, "group", localContext.BeatlesManagers, "err", err) - return false - } return true } diff --git a/internal/database/repos/group_repo.go b/internal/database/repos/group_repo.go index 0c914726..e84cc6b0 100644 --- a/internal/database/repos/group_repo.go +++ b/internal/database/repos/group_repo.go @@ -22,6 +22,7 @@ type GroupRepository interface { GetDirectSubgroups(ctx context.Context, groupId int) ([]models.SubgroupLink, error) AddSubgroupToGroup(ctx context.Context, subgroup, supergroup int, permissions models.GroupViewPermission) error + IsGroupSubgroup(ctx context.Context, subgroup, supergroup int) (bool, models.GroupViewPermission, error) GetGroupMembers(ctx context.Context, groupId int) ([]models.MembershipToGroup, error) GetDirectGroupMembers(ctx context.Context, groupId int) ([]models.MembershipToGroup, error) @@ -86,16 +87,49 @@ func (g *GroupRepo) IsGroupVisibleToGroup(ctx context.Context, lookingGroupId in // if can manage -> see all canManage, err := g.CanGroupManageGroup(ctx, lookingGroupId, groupId) if err != nil { - return false, fmt.Errorf("failed to check if group is visible to group: %w", err) + return false, fmt.Errorf("failed to check if group is visible to group 1: %w", err) } if canManage { return true, nil } - // if see none -> false, see none - // if see some -> true, see self - // if see all -> true, see all - panic("unimplemented") + isSubgroup, perms, err := g.IsGroupSubgroup(ctx, lookingGroupId, groupId) + if err != nil { + return false, fmt.Errorf("failed to check if group is visible to group 3: %w", err) + } + if isSubgroup { + switch perms { + + case models.GroupViewPermission_SeeAll: + return true, nil + case models.GroupViewPermission_SeeNone: + return false, nil + case models.GroupViewPermission_SeeSelf: + return true, nil + default: + return false, fmt.Errorf("invalid view permission %v", perms) + } + + } + return false, nil + +} + +func (g *GroupRepo) IsGroupSubgroup(ctx context.Context, subgroup int, supergroup int) (bool, models.GroupViewPermission, error) { + var perms models.GroupViewPermission + query := `select view_permission from group_subgroups where supergroup_id = $1 and subgroup_id = $2` + + row := g.DB.QueryRowContext(ctx, query, supergroup, subgroup) + + err := row.Scan(&perms) + if errors.Is(err, sql.ErrNoRows) { + return false, models.GroupViewPermission_SeeNone, nil + } + + if err != nil { + return false, models.GroupViewPermission_SeeNone, err + } + return true, perms, nil } @@ -322,6 +356,9 @@ func (g *GroupRepo) IsUserInGroupDirectly(ctx context.Context, userId int, group query := "SELECT view_permission FROM group_membership WHERE user_id = $1 and group_id = $2" err := g.DB.QueryRow(query, userId, groupId).Scan(&perms) + if errors.Is(err, sql.ErrNoRows) { + return false, models.GroupViewPermission_SeeNone, nil + } if err != nil { return false, models.GroupViewPermission_SeeNone, err } diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index c2203b01..19a39ff0 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -47,10 +47,15 @@ func (r *queryResolver) MembersOfGroup(ctx context.Context, groupID int) ([]*mod return nil, fmt.Errorf("failed to check if users in group: %w", err) } - if how == models.GroupViewPermission_SeeNone { + canManage, err := r.Store.Groups.CanUserManageGroup(ctx, askingUserID, groupID) + if err != nil { + return nil, fmt.Errorf("failed to check if users in group: %w", err) + } + + if how == models.GroupViewPermission_SeeNone && !canManage { return nil, fmt.Errorf("group does not exist or user does not have permission to see it") } - if how == models.GroupViewPermission_SeeSelf { + if how == models.GroupViewPermission_SeeSelf && !canManage { user, err := r.Store.Users.GetUserById(ctx, askingUserID) if err != nil { return nil, fmt.Errorf("could not find querying user %w", err) @@ -60,10 +65,13 @@ func (r *queryResolver) MembersOfGroup(ctx context.Context, groupID int) ([]*mod ViewPermission: how, }}, nil } + + // otherwise can see everything members, err := r.Store.Groups.GetGroupMembers(ctx, groupID) - if !visible || how == models.GroupViewPermission_SeeNone { + if err != nil { return nil, fmt.Errorf("error finding group members: %w", err) } + members2 := []*models.MembershipToGroup{} for _, member := range members { members2 = append(members2, &member) @@ -121,6 +129,14 @@ func (r *queryResolver) CanGroupManageGroup(ctx context.Context, managerID int, if !managedVisibleToAsker { return false, fmt.Errorf("managed group does not exist or user has invalid permissions to query it") } + + managedVisibleToManager, err := r.Store.Groups.IsGroupVisibleToGroup(ctx, managerID, groupID) + if err != nil { + return false, err + } + if !managedVisibleToManager { + return false, fmt.Errorf("managed group is not visible to manager group") + } return r.Store.Groups.CanGroupManageGroup(ctx, managerID, groupID) } diff --git a/internal/gql/resolvers/group_resolver_test.go b/internal/gql/resolvers/group_resolver_test.go index 5d39abcc..eaec9b6d 100644 --- a/internal/gql/resolvers/group_resolver_test.go +++ b/internal/gql/resolvers/group_resolver_test.go @@ -5,6 +5,7 @@ import ( "log/slog" "make-backend/internal/auth" "make-backend/internal/database" + "slices" "testing" ) @@ -78,6 +79,49 @@ func TestUserManagingGroup(t *testing.T) { } } +func TestGroupManagingGroup(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + + trials := []struct { + desc string + askerUser int + manager int + group int + + shouldError bool + shouldManage bool + }{ + {"managers managing beatles", data.Users[0].Id, data.BeatlesManagers.Id, data.BeatlesMusicians.Id, false, true}, + {"subgroup managing supergroup owner", data.Users[0].Id, data.BeatlesMusicians.Id, data.Brits.Id, false, false}, + {"beatles managing managers", data.Users[1].Id, data.BeatlesMusicians.Id, data.BeatlesManagers.Id, true, false}, + {"subgroup managing supergroup member", data.Users[1].Id, data.BeatlesMusicians.Id, data.Brits.Id, false, false}, + {"sibling group managing each other", data.Users[0].Id, data.BeatlesMusicians.Id, data.OtherMusicians.Id, true, false}, + {"manager group not visible to user", data.Users[1].Id, data.BeatlesManagers.Id, data.OtherMusicians.Id, true, false}, + {"managed group not visible to user", data.Users[1].Id, data.BeatlesMusicians.Id, data.OtherMusicians.Id, true, false}, + // TODO explicitly shared groups + } + + for _, trial := range trials { + t.Run(trial.desc, func(t *testing.T) { + + ctx := ContextWithUser(t.Context(), trial.askerUser) + + can, err := resolver.Query().CanGroupManageGroup(ctx, trial.manager, trial.group) + if err != nil && !trial.shouldError { + t.Fatalf("got error when %v checks if %v can manage group %v: %v", trial.askerUser, trial.manager, trial.group, err) + } else if err == nil && trial.shouldError { + t.Fatalf("should get error when %v checks if %v can manage group %v we can't see", trial.askerUser, trial.manager, trial.group) + return + } + if trial.shouldManage && can != trial.shouldManage { + t.Fatalf("%v should be able to manage %v but wasn't able to for some reason", trial.manager, trial.group) + } else if !trial.shouldManage && can != trial.shouldManage { + t.Fatalf("%v should NOT be able to manage %v but wasn't able to for some reason", trial.manager, trial.group) + } + }) + } +} + func TestGroupMembership(t *testing.T) { _, data, resolver := helpersForResolverTest(t) @@ -98,7 +142,7 @@ func TestGroupMembership(t *testing.T) { for _, tC := range testCases { t.Run(tC.desc, func(t *testing.T) { inGroup, err1 := resolver.Query().IsUserInGroup(ctx, tC.user, tC.group) - inGroupDirectly, err2 := resolver.Query().IsUserInGroup(ctx, tC.user, tC.group) + inGroupDirectly, err2 := resolver.Query().IsUserInGroupDirectly(ctx, tC.user, tC.group) if err1 != nil { t.Fatalf("failed to check if user %v in group %v: %v", tC.user, tC.group, err1) } @@ -192,3 +236,95 @@ func TestFindingGroupsById(t *testing.T) { }) } } + +func areGroupsEqual(wantedIds, gotIds []int) bool { + for _, m := range wantedIds { + if !slices.Contains(gotIds, m) { + return false + } + } + return true +} + +func TestMembersOfGroupAsManager(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + groupId := data.BeatlesMusicians.Id + askerId := data.Users[0].Id + + ctx := ContextWithUser(t.Context(), askerId) + members, err := resolver.Query().MembersOfGroup(ctx, groupId) + if err != nil { + t.Fatalf("failed to get members of group: %v", err) + } + memberIds := []int{} + for _, m := range members { + memberIds = append(memberIds, m.UserId) + } + wantedIds := []int{} + + for _, user := range data.Users[1:5] { + wantedIds = append(wantedIds, user.Id) + } + + if !areGroupsEqual(wantedIds, memberIds) { + t.Fatalf("groups were not equal. Wanted %v. got %v", wantedIds, memberIds) + } + +} + +func TestMembersOfGroupAsSeeSelf(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + groupId := data.Brits.Id + askerId := data.Users[1].Id + + ctx := ContextWithUser(t.Context(), askerId) + members, err := resolver.Query().MembersOfGroup(ctx, groupId) + if err != nil { + t.Fatalf("failed to get members of group: %v", err) + } + memberIds := []int{} + for _, m := range members { + memberIds = append(memberIds, m.UserId) + } + wantedIds := []int{askerId} + + if !areGroupsEqual(wantedIds, memberIds) { + t.Fatalf("groups were not equal. Wanted %v. got %v", wantedIds, memberIds) + } +} + +func TestMembersOfGroupAsSeeAll(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + groupId := data.BeatlesMusicians.Id + askerId := data.Users[1].Id + + ctx := ContextWithUser(t.Context(), askerId) + members, err := resolver.Query().MembersOfGroup(ctx, groupId) + if err != nil { + t.Fatalf("failed to get members of group: %v", err) + } + memberIds := []int{} + for _, m := range members { + memberIds = append(memberIds, m.UserId) + } + wantedIds := []int{} + for _, user := range data.Users[1:5] { + wantedIds = append(wantedIds, user.Id) + } + + if !areGroupsEqual(wantedIds, memberIds) { + t.Fatalf("groups were not equal. Wanted %v. got %v", wantedIds, memberIds) + } +} + +func TestMembersOfGroupAsSeeNone(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + groupId := data.BeatlesMusicians.Id + askerId := data.Users[5].Id + + ctx := ContextWithUser(t.Context(), askerId) + _, err := resolver.Query().MembersOfGroup(ctx, groupId) + if err == nil { + t.Fatalf("see none member should not be able to see themselves: %v", err) + } +} From ef61311f0cf607a52a3f26137c15c746d2df724d Mon Sep 17 00:00:00 2001 From: cowsed Date: Mon, 10 Aug 2026 17:00:52 -0400 Subject: [PATCH 09/22] actually doing graphql things --- internal/auth/middleware.go | 17 + internal/database/repos/group_repo.go | 30 +- internal/gql/generated.go | 563 ++++++++++++++---- internal/gql/resolvers/group.resolvers.go | 120 ++-- internal/gql/resolvers/group_resolver_test.go | 2 +- internal/gql/schema/group.graphqls | 28 +- 6 files changed, 582 insertions(+), 178 deletions(-) diff --git a/internal/auth/middleware.go b/internal/auth/middleware.go index be038906..552e4d34 100644 --- a/internal/auth/middleware.go +++ b/internal/auth/middleware.go @@ -2,6 +2,8 @@ package auth import ( "context" + "errors" + "log/slog" "net/http" "github.com/alexedwards/scs/v2" @@ -9,6 +11,21 @@ import ( type UserContextKey struct{} +var ErrNotAuthenticated error = errors.New("not authenticated") + +func UserIDFromContext(ctx context.Context) *int { + userVal := ctx.Value(UserContextKey{}) + if userVal == nil { + slog.Error("UserIDFromContext called with no userID in context. Caused by mismatch between route protection middleware and what resolvers actually do") + // TODO temp until real auth works + one := 1 + return &one + } + userID := userVal.(int) + return &userID + +} + func AuthContextMiddleware(next http.Handler, sessionManager *scs.SessionManager) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/internal/database/repos/group_repo.go b/internal/database/repos/group_repo.go index e84cc6b0..35467a0d 100644 --- a/internal/database/repos/group_repo.go +++ b/internal/database/repos/group_repo.go @@ -40,7 +40,8 @@ type GroupRepository interface { CanUserManageGroup(ctx context.Context, managerUser, managedGroup int) (bool, error) CanGroupManageGroup(ctx context.Context, managerGroup, managedGroup int) (bool, error) - AllGroupsGroupCanManage(ctx context.Context, userId int) ([]int, error) + AllGroupsGroupCanManage(ctx context.Context, groupId int) ([]int, error) + AllGroupsGroupCanManageDirectly(ctx context.Context, groupId int) ([]int, error) AllGroupsVisibleToGroup(ctx context.Context, groupId int) ([]int, error) IsGroupVisibleToGroup(ctx context.Context, lookingGroupId int, groupId int) (bool, error) @@ -233,6 +234,33 @@ func (g *GroupRepo) AllGroupsGroupCanManage(ctx context.Context, managerId int) } +// AllGroupsGroupCanManage implements [GroupRepository]. +func (g *GroupRepo) AllGroupsGroupCanManageDirectly(ctx context.Context, managerId int) ([]int, error) { + query := `select id from groups where manager_id = $1` + + rows, err := g.DB.QueryContext(ctx, query, managerId) + if err != nil { + return nil, fmt.Errorf("failed to construct QueryContext: %w", err) + } + defer rows.Close() + + groups := []int{} + for rows.Next() { + var group int + err := rows.Scan(&group) + if err != nil { + return nil, fmt.Errorf("failed to scan for groups group can manage: %w", err) + } + groups = append(groups, group) + + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("failed to get for groups group can manage: %w", err) + } + return groups, nil + +} + func (g *GroupRepo) AllGroupsUserCanManage(ctx context.Context, userId int) ([]int, error) { query := ` select gm.group_id diff --git a/internal/gql/generated.go b/internal/gql/generated.go index 027daadf..de3c3944 100644 --- a/internal/gql/generated.go +++ b/internal/gql/generated.go @@ -32,7 +32,9 @@ type Config = graphql.Config[ResolverRoot, DirectiveRoot, ComplexityRoot] type ResolverRoot interface { AccessComponent() AccessComponentResolver + Group() GroupResolver Makerspace() MakerspaceResolver + MembershipToGroup() MembershipToGroupResolver Mutation() MutationResolver OptionBlockOption() OptionBlockOptionResolver Query() QueryResolver @@ -153,10 +155,14 @@ type ComplexityRoot struct { } Group struct { - Description func(childComplexity int) int - Id func(childComplexity int) int - ManagerId func(childComplexity int) int - Name func(childComplexity int) int + Description func(childComplexity int) int + DirectManagedGroups func(childComplexity int) int + DirectMembers func(childComplexity int) int + DirectSubGroups func(childComplexity int) int + Id func(childComplexity int) int + ManagerId func(childComplexity int) int + Members func(childComplexity int) int + Name func(childComplexity int) int } Hold struct { @@ -194,6 +200,7 @@ type ComplexityRoot struct { } MembershipToGroup struct { + User func(childComplexity int) int UserId func(childComplexity int) int ViewPermission func(childComplexity int) int } @@ -230,11 +237,10 @@ type ComplexityRoot struct { CanUserManageGroup func(childComplexity int, managerID int, groupID int) int CurrentUser func(childComplexity int) int Device func(childComplexity int, id int) int - GroupByID func(childComplexity int, id int) int + Group func(childComplexity int, id int) int IsUserInGroup func(childComplexity int, userID int, groupID int) int IsUserInGroupDirectly func(childComplexity int, userID int, groupID int) int Makerspace func(childComplexity int, id int) int - MembersOfGroup func(childComplexity int, groupID int) int User func(childComplexity int, id int) int Zone func(childComplexity int, id int) int ZonesByMakerspaceID func(childComplexity int, makerspaceID int) int @@ -327,10 +333,19 @@ type ComplexityRoot struct { type AccessComponentResolver interface { Type(ctx context.Context, obj *models.AccessComponent) (int, error) } +type GroupResolver interface { + DirectMembers(ctx context.Context, obj *models.Group) ([]*models.MembershipToGroup, error) + Members(ctx context.Context, obj *models.Group) ([]*models.MembershipToGroup, error) + DirectManagedGroups(ctx context.Context, obj *models.Group) ([]*models.Group, error) + DirectSubGroups(ctx context.Context, obj *models.Group) ([]*models.Group, error) +} type MakerspaceResolver interface { Zones(ctx context.Context, obj *models.Makerspace) ([]*models.Zone, error) Hours(ctx context.Context, obj *models.Makerspace) ([]models.MakerspaceHours, error) } +type MembershipToGroupResolver interface { + User(ctx context.Context, obj *models.MembershipToGroup) (*models.User, error) +} type MutationResolver interface { CreateMakerspace(ctx context.Context, name string, hidden bool) (int, error) DeleteMakerspace(ctx context.Context, id int) (bool, error) @@ -342,8 +357,7 @@ type QueryResolver interface { Makerspace(ctx context.Context, id int) (*models.Makerspace, error) Device(ctx context.Context, id int) (*models.Device, error) AccessDevice(ctx context.Context, id int) (*models.AccessDevice, error) - GroupByID(ctx context.Context, id int) (*models.Group, error) - MembersOfGroup(ctx context.Context, groupID int) ([]*models.MembershipToGroup, error) + Group(ctx context.Context, id int) (*models.Group, error) IsUserInGroup(ctx context.Context, userID int, groupID int) (bool, error) IsUserInGroupDirectly(ctx context.Context, userID int, groupID int) (bool, error) CanGroupManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) @@ -777,6 +791,24 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Group.Description(childComplexity), true + case "Group.directManagedGroups": + if e.ComplexityRoot.Group.DirectManagedGroups == nil { + break + } + + return e.ComplexityRoot.Group.DirectManagedGroups(childComplexity), true + case "Group.directMembers": + if e.ComplexityRoot.Group.DirectMembers == nil { + break + } + + return e.ComplexityRoot.Group.DirectMembers(childComplexity), true + case "Group.directSubGroups": + if e.ComplexityRoot.Group.DirectSubGroups == nil { + break + } + + return e.ComplexityRoot.Group.DirectSubGroups(childComplexity), true case "Group.id": if e.ComplexityRoot.Group.Id == nil { break @@ -789,6 +821,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Group.ManagerId(childComplexity), true + case "Group.members": + if e.ComplexityRoot.Group.Members == nil { + break + } + + return e.ComplexityRoot.Group.Members(childComplexity), true case "Group.name": if e.ComplexityRoot.Group.Name == nil { break @@ -932,6 +970,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.ComplexityRoot.Makerspace.Zones(childComplexity), true + case "MembershipToGroup.User": + if e.ComplexityRoot.MembershipToGroup.User == nil { + break + } + + return e.ComplexityRoot.MembershipToGroup.User(childComplexity), true case "MembershipToGroup.UserId": if e.ComplexityRoot.MembershipToGroup.UserId == nil { break @@ -1093,17 +1137,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Query.Device(childComplexity, args["id"].(int)), true - case "Query.groupById": - if e.ComplexityRoot.Query.GroupByID == nil { + case "Query.group": + if e.ComplexityRoot.Query.Group == nil { break } - args, err := ec.field_Query_groupById_args(ctx, rawArgs) + args, err := ec.field_Query_group_args(ctx, rawArgs) if err != nil { return 0, false } - return e.ComplexityRoot.Query.GroupByID(childComplexity, args["id"].(int)), true + return e.ComplexityRoot.Query.Group(childComplexity, args["id"].(int)), true case "Query.isUserInGroup": if e.ComplexityRoot.Query.IsUserInGroup == nil { @@ -1138,17 +1182,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Query.Makerspace(childComplexity, args["id"].(int)), true - case "Query.membersOfGroup": - if e.ComplexityRoot.Query.MembersOfGroup == nil { - break - } - - args, err := ec.field_Query_membersOfGroup_args(ctx, rawArgs) - if err != nil { - return 0, false - } - - return e.ComplexityRoot.Query.MembersOfGroup(childComplexity, args["groupID"].(int)), true case "Query.user": if e.ComplexityRoot.Query.User == nil { break @@ -1713,6 +1746,14 @@ func (ec *executionContext) childFields_Group(ctx context.Context, field graphql return ec.fieldContext_Group_name(ctx, field) case "description": return ec.fieldContext_Group_description(ctx, field) + case "directMembers": + return ec.fieldContext_Group_directMembers(ctx, field) + case "members": + return ec.fieldContext_Group_members(ctx, field) + case "directManagedGroups": + return ec.fieldContext_Group_directManagedGroups(ctx, field) + case "directSubGroups": + return ec.fieldContext_Group_directSubGroups(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Group", field.Name) } @@ -1747,6 +1788,8 @@ func (ec *executionContext) childFields_MembershipToGroup(ctx context.Context, f switch field.Name { case "UserId": return ec.fieldContext_MembershipToGroup_UserId(ctx, field) + case "User": + return ec.fieldContext_MembershipToGroup_User(ctx, field) case "ViewPermission": return ec.fieldContext_MembershipToGroup_ViewPermission(ctx, field) } @@ -2045,7 +2088,7 @@ func (ec *executionContext) field_Query_device_args(ctx context.Context, rawArgs return args, nil } -func (ec *executionContext) field_Query_groupById_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { +func (ec *executionContext) field_Query_group_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, "id", @@ -2117,20 +2160,6 @@ func (ec *executionContext) field_Query_makerspace_args(ctx context.Context, raw return args, nil } -func (ec *executionContext) field_Query_membersOfGroup_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, "groupID", - func(ctx context.Context, v any) (int, error) { - return ec.unmarshalNID2int(ctx, v) - }) - if err != nil { - return nil, err - } - args["groupID"] = arg0 - return args, 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{} @@ -3864,6 +3893,134 @@ func (ec *executionContext) fieldContext_Group_description(_ context.Context, fi return graphql.NewScalarFieldContext("Group", field, false, false, errors.New("field of type String does not have child fields")) } +func (ec *executionContext) _Group_directMembers(ctx context.Context, field graphql.CollectedField, obj *models.Group) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Group_directMembers(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Group().DirectMembers(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []*models.MembershipToGroup) graphql.Marshaler { + return ec.marshalNMembershipToGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐMembershipToGroupᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Group_directMembers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Group", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_MembershipToGroup(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Group_members(ctx context.Context, field graphql.CollectedField, obj *models.Group) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Group_members(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Group().Members(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []*models.MembershipToGroup) graphql.Marshaler { + return ec.marshalNMembershipToGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐMembershipToGroupᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Group_members(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Group", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_MembershipToGroup(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Group_directManagedGroups(ctx context.Context, field graphql.CollectedField, obj *models.Group) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Group_directManagedGroups(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Group().DirectManagedGroups(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []*models.Group) graphql.Marshaler { + return ec.marshalNGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Group_directManagedGroups(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Group", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Group(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Group_directSubGroups(ctx context.Context, field graphql.CollectedField, obj *models.Group) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Group_directSubGroups(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Group().DirectSubGroups(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []*models.Group) graphql.Marshaler { + return ec.marshalNGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Group_directSubGroups(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Group", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Group(ctx, field) + }, + } + return fc, nil +} + func (ec *executionContext) _Hold_id(ctx context.Context, field graphql.CollectedField, obj *models.Hold) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -4402,6 +4559,38 @@ func (ec *executionContext) fieldContext_MembershipToGroup_UserId(_ context.Cont return graphql.NewScalarFieldContext("MembershipToGroup", field, false, false, errors.New("field of type ID does not have child fields")) } +func (ec *executionContext) _MembershipToGroup_User(ctx context.Context, field graphql.CollectedField, obj *models.MembershipToGroup) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_MembershipToGroup_User(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.MembershipToGroup().User(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *models.User) graphql.Marshaler { + return ec.marshalNUser2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐUser(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_MembershipToGroup_User(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "MembershipToGroup", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_User(ctx, field) + }, + } + return fc, nil +} + func (ec *executionContext) _MembershipToGroup_ViewPermission(ctx context.Context, field graphql.CollectedField, obj *models.MembershipToGroup) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -4930,17 +5119,17 @@ func (ec *executionContext) fieldContext_Query_accessDevice(ctx context.Context, return fc, nil } -func (ec *executionContext) _Query_groupById(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _Query_group(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, ec.OperationContext, field, func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.fieldContext_Query_groupById(ctx, field) + return ec.fieldContext_Query_group(ctx, field) }, func(ctx context.Context) (any, error) { fc := graphql.GetFieldContext(ctx) - return ec.Resolvers.Query().GroupByID(ctx, fc.Args["id"].(int)) + return ec.Resolvers.Query().Group(ctx, fc.Args["id"].(int)) }, nil, func(ctx context.Context, selections ast.SelectionSet, v *models.Group) graphql.Marshaler { @@ -4950,7 +5139,7 @@ func (ec *executionContext) _Query_groupById(ctx context.Context, field graphql. true, ) } -func (ec *executionContext) fieldContext_Query_groupById(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Query_group(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Query", Field: field, @@ -4967,51 +5156,7 @@ func (ec *executionContext) fieldContext_Query_groupById(ctx context.Context, fi } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_groupById_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - -func (ec *executionContext) _Query_membersOfGroup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - return graphql.ResolveField( - ctx, - ec.OperationContext, - field, - func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.fieldContext_Query_membersOfGroup(ctx, field) - }, - func(ctx context.Context) (any, error) { - fc := graphql.GetFieldContext(ctx) - return ec.Resolvers.Query().MembersOfGroup(ctx, fc.Args["groupID"].(int)) - }, - nil, - func(ctx context.Context, selections ast.SelectionSet, v []*models.MembershipToGroup) graphql.Marshaler { - return ec.marshalNMembershipToGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐMembershipToGroupᚄ(ctx, selections, v) - }, - true, - true, - ) -} -func (ec *executionContext) fieldContext_Query_membersOfGroup(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.childFields_MembershipToGroup(ctx, field) - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_membersOfGroup_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Query_group_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } @@ -8534,23 +8679,175 @@ func (ec *executionContext) _Group(ctx context.Context, sel ast.SelectionSet, ob case "id": out.Values[i] = ec._Group_id(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "manager_id": out.Values[i] = ec._Group_manager_id(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "name": out.Values[i] = ec._Group_name(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "description": out.Values[i] = ec._Group_description(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) + } + case "directMembers": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Group_directMembers(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res } + + if field.IsDeferred() { + deferredFieldSet.AddField(field) + fieldIndex := len(deferredFieldSet.Values) - 1 + deferredFieldSet.Concurrently(fieldIndex, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, deferredFieldSet) + }) + + for _, deferrable := range field.Deferrables { + view, ok := deferLabelToView[deferrable.Label] + if !ok { + view = deferredFieldSet.NewView() + deferLabelToView[deferrable.Label] = view + } + view.AddIndices(fieldIndex) + } + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "members": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Group_members(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.IsDeferred() { + deferredFieldSet.AddField(field) + fieldIndex := len(deferredFieldSet.Values) - 1 + deferredFieldSet.Concurrently(fieldIndex, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, deferredFieldSet) + }) + + for _, deferrable := range field.Deferrables { + view, ok := deferLabelToView[deferrable.Label] + if !ok { + view = deferredFieldSet.NewView() + deferLabelToView[deferrable.Label] = view + } + view.AddIndices(fieldIndex) + } + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "directManagedGroups": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Group_directManagedGroups(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.IsDeferred() { + deferredFieldSet.AddField(field) + fieldIndex := len(deferredFieldSet.Values) - 1 + deferredFieldSet.Concurrently(fieldIndex, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, deferredFieldSet) + }) + + for _, deferrable := range field.Deferrables { + view, ok := deferLabelToView[deferrable.Label] + if !ok { + view = deferredFieldSet.NewView() + deferLabelToView[deferrable.Label] = view + } + view.AddIndices(fieldIndex) + } + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "directSubGroups": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Group_directSubGroups(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.IsDeferred() { + deferredFieldSet.AddField(field) + fieldIndex := len(deferredFieldSet.Values) - 1 + deferredFieldSet.Concurrently(fieldIndex, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, deferredFieldSet) + }) + + for _, deferrable := range field.Deferrables { + view, ok := deferLabelToView[deferrable.Label] + if !ok { + view = deferredFieldSet.NewView() + deferLabelToView[deferrable.Label] = view + } + view.AddIndices(fieldIndex) + } + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -8895,12 +9192,50 @@ func (ec *executionContext) _MembershipToGroup(ctx context.Context, sel ast.Sele case "UserId": out.Values[i] = ec._MembershipToGroup_UserId(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) + } + case "User": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._MembershipToGroup_User(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.IsDeferred() { + deferredFieldSet.AddField(field) + fieldIndex := len(deferredFieldSet.Values) - 1 + deferredFieldSet.Concurrently(fieldIndex, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, deferredFieldSet) + }) + + for _, deferrable := range field.Deferrables { + view, ok := deferLabelToView[deferrable.Label] + if !ok { + view = deferredFieldSet.NewView() + deferLabelToView[deferrable.Label] = view + } + view.AddIndices(fieldIndex) + } + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) case "ViewPermission": out.Values[i] = ec._MembershipToGroup_ViewPermission(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } default: panic("unknown field " + strconv.Quote(field.Name)) @@ -9256,29 +9591,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "groupById": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_groupById(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "membersOfGroup": + case "group": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -9287,7 +9600,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_membersOfGroup(ctx, field) + res = ec._Query_group(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -10557,6 +10870,22 @@ func (ec *executionContext) marshalNGroup2makeᚑbackendᚋinternalᚋdatabase return ec._Group(ctx, sel, &v) } +func (ec *executionContext) marshalNGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.Group) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalNGroup2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroup(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) marshalNGroup2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroup(ctx context.Context, sel ast.SelectionSet, v *models.Group) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index 19a39ff0..05843543 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -8,82 +8,90 @@ package resolvers import ( "context" "fmt" + "log/slog" "make-backend/internal/auth" "make-backend/internal/database/models" + "make-backend/internal/gql" ) -// GroupByID is the resolver for the groupById field. -func (r *queryResolver) GroupByID(ctx context.Context, groupId int) (*models.Group, error) { - userID := ctx.Value(auth.UserContextKey{}).(int) +// DirectMembers is the resolver for the directMembers field. +func (r *groupResolver) DirectMembers(ctx context.Context, obj *models.Group) ([]*models.MembershipToGroup, error) { + panic(fmt.Errorf("not implemented: DirectMembers - directMembers")) +} - visible, err := r.Store.Groups.IsGroupVisibleToUser(ctx, userID, groupId) +// Members is the resolver for the members field. +func (r *groupResolver) Members(ctx context.Context, obj *models.Group) ([]*models.MembershipToGroup, error) { + members, err := r.Store.Groups.GetGroupMembers(ctx, obj.Id) + slog.Info("get members", "members", members) if err != nil { return nil, err } - if !visible { - return nil, fmt.Errorf("group does not exist or user does not have permission to see it") + members2 := make([]*models.MembershipToGroup, 0, len(members)) + for _, m := range members { + members2 = append(members2, &m) } - - group, err := r.Store.Groups.GetGroupById(ctx, groupId) - if err != nil { - return nil, err - } - return group, nil + return members2, nil } -// MembersOfGroup is the resolver for the membersOfGroup field. -func (r *queryResolver) MembersOfGroup(ctx context.Context, groupID int) ([]*models.MembershipToGroup, error) { - askingUserID := ctx.Value(auth.UserContextKey{}).(int) - visible, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) +// DirectManagedGroups is the resolver for the directManagedGroups field. +func (r *groupResolver) DirectManagedGroups(ctx context.Context, obj *models.Group) ([]*models.Group, error) { + groupIds, err := r.Store.Groups.AllGroupsGroupCanManageDirectly(ctx, obj.Id) if err != nil { return nil, err } - if !visible { - return nil, fmt.Errorf("group does not exist or user does not have permission to see it") + + groups := make([]*models.Group, len(groupIds)) + for i, id := range groupIds { + g, err := r.Store.Groups.GetGroupById(ctx, id) + if err != nil { + return nil, err + } + groups[i] = g + } + return groups, nil +} - _, how, err := r.Store.Groups.IsUserInGroup(ctx, askingUserID, groupID) - if err != nil { - return nil, fmt.Errorf("failed to check if users in group: %w", err) +// DirectSubGroups is the resolver for the directSubGroups field. +func (r *groupResolver) DirectSubGroups(ctx context.Context, obj *models.Group) ([]*models.Group, error) { + panic(fmt.Errorf("not implemented: DirectSubGroups - directSubGroups")) +} + +// User is the resolver for the User field. +func (r *membershipToGroupResolver) User(ctx context.Context, obj *models.MembershipToGroup) (*models.User, error) { + return r.Store.Users.GetUserById(ctx, obj.UserId) +} + +// Group is the resolver for the group field. +func (r *queryResolver) Group(ctx context.Context, id int) (*models.Group, error) { + userId := auth.UserIDFromContext(ctx) + if userId == nil { + return nil, auth.ErrNotAuthenticated } - canManage, err := r.Store.Groups.CanUserManageGroup(ctx, askingUserID, groupID) + visible, err := r.Store.Groups.IsGroupVisibleToUser(ctx, *userId, id) if err != nil { - return nil, fmt.Errorf("failed to check if users in group: %w", err) + return nil, err } - - if how == models.GroupViewPermission_SeeNone && !canManage { + if !visible { return nil, fmt.Errorf("group does not exist or user does not have permission to see it") } - if how == models.GroupViewPermission_SeeSelf && !canManage { - user, err := r.Store.Users.GetUserById(ctx, askingUserID) - if err != nil { - return nil, fmt.Errorf("could not find querying user %w", err) - } - return []*models.MembershipToGroup{{ - UserId: user.Id, - ViewPermission: how, - }}, nil - } - // otherwise can see everything - members, err := r.Store.Groups.GetGroupMembers(ctx, groupID) + group, err := r.Store.Groups.GetGroupById(ctx, id) if err != nil { - return nil, fmt.Errorf("error finding group members: %w", err) - } - - members2 := []*models.MembershipToGroup{} - for _, member := range members { - members2 = append(members2, &member) + return nil, err } - return members2, nil + return group, nil } // IsUserInGroup is the resolver for the isUserInGroup field. func (r *queryResolver) IsUserInGroup(ctx context.Context, userID int, groupID int) (bool, error) { - askingUserID := ctx.Value(auth.UserContextKey{}).(int) + askingUserID := auth.UserIDFromContext(ctx) + if askingUserID == nil { + return false, auth.ErrNotAuthenticated + } - visibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) + visibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, *askingUserID, groupID) if err != nil { return false, err } @@ -97,9 +105,12 @@ func (r *queryResolver) IsUserInGroup(ctx context.Context, userID int, groupID i // IsUserInGroupDirectly is the resolver for the isUserInGroupDirectly field. func (r *queryResolver) IsUserInGroupDirectly(ctx context.Context, userID int, groupID int) (bool, error) { - askingUserID := ctx.Value(auth.UserContextKey{}).(int) + askingUserID := auth.UserIDFromContext(ctx) + if askingUserID == nil { + return false, auth.ErrNotAuthenticated + } - visibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) + visibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, *askingUserID, groupID) if err != nil { return false, err } @@ -153,3 +164,16 @@ func (r *queryResolver) CanUserManageGroup(ctx context.Context, managerID int, g } return r.Store.Groups.CanUserManageGroup(ctx, managerID, groupID) } + +// Group returns gql.GroupResolver implementation. +func (r *Resolver) Group() gql.GroupResolver { return &groupResolver{r} } + +// MembershipToGroup returns gql.MembershipToGroupResolver implementation. +func (r *Resolver) MembershipToGroup() gql.MembershipToGroupResolver { + return &membershipToGroupResolver{r} +} + +type ( + groupResolver struct{ *Resolver } + membershipToGroupResolver struct{ *Resolver } +) diff --git a/internal/gql/resolvers/group_resolver_test.go b/internal/gql/resolvers/group_resolver_test.go index eaec9b6d..0ead6a1a 100644 --- a/internal/gql/resolvers/group_resolver_test.go +++ b/internal/gql/resolvers/group_resolver_test.go @@ -208,7 +208,7 @@ func TestFindingGroupsById(t *testing.T) { for _, tC := range testCases { t.Run(tC.desc, func(t *testing.T) { ctx := ContextWithUser(t.Context(), tC.askingUser) - g, err := resolver.Query().GroupByID(ctx, tC.group) + g, err := resolver.Query().Group(ctx, tC.group) if !tC.shouldError && err != nil { t.Fatalf("should not error when user %v gets group %v but got %v", tC.askingUser, tC.group, err) return diff --git a/internal/gql/schema/group.graphqls b/internal/gql/schema/group.graphqls index 1e8175c0..9adf4156 100644 --- a/internal/gql/schema/group.graphqls +++ b/internal/gql/schema/group.graphqls @@ -1,12 +1,6 @@ -type Group { - id: ID! - manager_id: ID! - name: String! - description: String! -} enum GroupViewPermission { @@ -18,20 +12,32 @@ enum GroupViewPermission { type MembershipToGroup { UserId: ID! - ViewPermission: GroupViewPermission! + User: User! + ViewPermission: GroupViewPermission! } +type Group { + id: ID! + manager_id: ID! + name: String! + description: String! + + directMembers: [MembershipToGroup!]! + members: [MembershipToGroup!]! + + directManagedGroups: [Group!]! + directSubGroups: [Group!]! +} extend type Query { - groupById(id: ID!): Group! + group(id: ID!): Group! - membersOfGroup(groupID: ID!): [MembershipToGroup!]! isUserInGroup(userID: ID!, groupID: ID!): Boolean! - isUserInGroupDirectly(userID: ID!, groupID: ID!): Boolean! - + + isUserInGroupDirectly(userID: ID!, groupID: ID!): Boolean! canGroupManageGroup(managerID: ID!, groupID: ID!): Boolean! canUserManageGroup(managerID: ID!, groupID: ID!): Boolean! } \ No newline at end of file From 01ac06b4fea2f78120401748a96362a698de6aef Mon Sep 17 00:00:00 2001 From: cowsed Date: Tue, 18 Aug 2026 12:01:34 -0400 Subject: [PATCH 10/22] Update group resolver tests --- internal/gql/resolvers/group.resolvers.go | 32 +++++++++++++++---- internal/gql/resolvers/group_resolver_test.go | 18 +++++------ 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index 05843543..1bb73fe4 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -8,7 +8,6 @@ package resolvers import ( "context" "fmt" - "log/slog" "make-backend/internal/auth" "make-backend/internal/database/models" "make-backend/internal/gql" @@ -21,8 +20,20 @@ func (r *groupResolver) DirectMembers(ctx context.Context, obj *models.Group) ([ // Members is the resolver for the members field. func (r *groupResolver) Members(ctx context.Context, obj *models.Group) ([]*models.MembershipToGroup, error) { + userId := auth.UserIDFromContext(ctx) + if userId == nil { + return nil, auth.ErrNotAuthenticated + } + + visible, err := r.Store.Groups.IsGroupVisibleToUser(ctx, *userId, obj.Id) + if err != nil { + return nil, err + } + if !visible { + return nil, fmt.Errorf("group does not exist or user does not have permission to see it") + } + members, err := r.Store.Groups.GetGroupMembers(ctx, obj.Id) - slog.Info("get members", "members", members) if err != nil { return nil, err } @@ -124,16 +135,19 @@ func (r *queryResolver) IsUserInGroupDirectly(ctx context.Context, userID int, g // CanGroupManageGroup is the resolver for the canGroupManageGroup field. func (r *queryResolver) CanGroupManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) { - askingUserID := ctx.Value(auth.UserContextKey{}).(int) + askingUserID := auth.UserIDFromContext(ctx) + if askingUserID == nil { + return false, auth.ErrNotAuthenticated + } - managerVisibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, managerID) + managerVisibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, *askingUserID, managerID) if err != nil { return false, err } if !managerVisibleToAsker { return false, fmt.Errorf("manager group does not exist or user has invalid permissions to query it") } - managedVisibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) + managedVisibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, *askingUserID, groupID) if err != nil { return false, err } @@ -153,9 +167,13 @@ func (r *queryResolver) CanGroupManageGroup(ctx context.Context, managerID int, // CanUserManageGroup is the resolver for the canUserManageGroup field. func (r *queryResolver) CanUserManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) { - askingUserID := ctx.Value(auth.UserContextKey{}).(int) + askingUserID := auth.UserIDFromContext(ctx) - visibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, askingUserID, groupID) + if askingUserID == nil { + return false, auth.ErrNotAuthenticated + } + + visibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, *askingUserID, groupID) if err != nil { return false, err } diff --git a/internal/gql/resolvers/group_resolver_test.go b/internal/gql/resolvers/group_resolver_test.go index 0ead6a1a..242f11f7 100644 --- a/internal/gql/resolvers/group_resolver_test.go +++ b/internal/gql/resolvers/group_resolver_test.go @@ -248,11 +248,11 @@ func areGroupsEqual(wantedIds, gotIds []int) bool { func TestMembersOfGroupAsManager(t *testing.T) { _, data, resolver := helpersForResolverTest(t) - groupId := data.BeatlesMusicians.Id askerId := data.Users[0].Id + group := data.BeatlesMusicians ctx := ContextWithUser(t.Context(), askerId) - members, err := resolver.Query().MembersOfGroup(ctx, groupId) + members, err := resolver.Group().Members(ctx, &group) if err != nil { t.Fatalf("failed to get members of group: %v", err) } @@ -274,11 +274,11 @@ func TestMembersOfGroupAsManager(t *testing.T) { func TestMembersOfGroupAsSeeSelf(t *testing.T) { _, data, resolver := helpersForResolverTest(t) - groupId := data.Brits.Id + group := data.BeatlesMusicians askerId := data.Users[1].Id ctx := ContextWithUser(t.Context(), askerId) - members, err := resolver.Query().MembersOfGroup(ctx, groupId) + members, err := resolver.Group().Members(ctx, &group) if err != nil { t.Fatalf("failed to get members of group: %v", err) } @@ -295,11 +295,11 @@ func TestMembersOfGroupAsSeeSelf(t *testing.T) { func TestMembersOfGroupAsSeeAll(t *testing.T) { _, data, resolver := helpersForResolverTest(t) - groupId := data.BeatlesMusicians.Id + group := data.BeatlesMusicians askerId := data.Users[1].Id ctx := ContextWithUser(t.Context(), askerId) - members, err := resolver.Query().MembersOfGroup(ctx, groupId) + members, err := resolver.Group().Members(ctx, &group) if err != nil { t.Fatalf("failed to get members of group: %v", err) } @@ -319,12 +319,12 @@ func TestMembersOfGroupAsSeeAll(t *testing.T) { func TestMembersOfGroupAsSeeNone(t *testing.T) { _, data, resolver := helpersForResolverTest(t) - groupId := data.BeatlesMusicians.Id + group := data.BeatlesMusicians askerId := data.Users[5].Id ctx := ContextWithUser(t.Context(), askerId) - _, err := resolver.Query().MembersOfGroup(ctx, groupId) + members, err := resolver.Group().Members(ctx, &group) if err == nil { - t.Fatalf("see none member should not be able to see themselves: %v", err) + t.Fatalf("see none member should not be able to see themselves: saw %v", members) } } From f12b99b684c7fb4b71cf7411d86e315d0a40f229 Mon Sep 17 00:00:00 2001 From: cowsed Date: Tue, 18 Aug 2026 12:16:16 -0400 Subject: [PATCH 11/22] Tests both unit and using DB --- internal/database/mock_data.go | 15 ++++++------ internal/gql/resolvers/group.resolvers.go | 23 ++++++++++++++++++- internal/gql/resolvers/group_resolver_test.go | 15 +++++------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/internal/database/mock_data.go b/internal/database/mock_data.go index 8692f949..577b9608 100644 --- a/internal/database/mock_data.go +++ b/internal/database/mock_data.go @@ -126,20 +126,21 @@ func addUsersToTestGroups(ctx context.Context, t *slog.Logger, store *Store) boo for _, member := range []struct { email string groupId int + perm models.GroupViewPermission }{ - {"brian@beatles.com", localContext.BeatlesManagers.Id}, - {"john@beatles.com", localContext.BeatlesMusicians.Id}, - {"paul@beatles.com", localContext.BeatlesMusicians.Id}, - {"george@beatles.com", localContext.BeatlesMusicians.Id}, - {"ringo@beatles.com", localContext.BeatlesMusicians.Id}, - {"pete@beatles.com", localContext.ExMusicians.Id}, + {"brian@beatles.com", localContext.BeatlesManagers.Id, models.GroupViewPermission_SeeSelf}, + {"john@beatles.com", localContext.BeatlesMusicians.Id, models.GroupViewPermission_SeeAll}, + {"paul@beatles.com", localContext.BeatlesMusicians.Id, models.GroupViewPermission_SeeAll}, + {"george@beatles.com", localContext.BeatlesMusicians.Id, models.GroupViewPermission_SeeAll}, + {"ringo@beatles.com", localContext.BeatlesMusicians.Id, models.GroupViewPermission_SeeAll}, + {"pete@beatles.com", localContext.ExMusicians.Id, models.GroupViewPermission_SeeNone}, } { user, err := store.Users.GetUserByEmail(ctx, member.email) if err != nil { t.Error("couldn't find user", "email", member.email, "err", err) return false } - err = store.Groups.AddUserToGroup(ctx, user.Id, member.groupId, models.GroupViewPermission_SeeAll) + err = store.Groups.AddUserToGroup(ctx, user.Id, member.groupId, member.perm) if err != nil { t.Error("Failed to add ", "user", user, "group", member.groupId) return false diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index 1bb73fe4..77f18b85 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -8,6 +8,7 @@ package resolvers import ( "context" "fmt" + "log" "make-backend/internal/auth" "make-backend/internal/database/models" "make-backend/internal/gql" @@ -25,13 +26,33 @@ func (r *groupResolver) Members(ctx context.Context, obj *models.Group) ([]*mode return nil, auth.ErrNotAuthenticated } - visible, err := r.Store.Groups.IsGroupVisibleToUser(ctx, *userId, obj.Id) + visible, how, err := r.Store.Groups.IsUserInGroup(ctx, *userId, obj.Id) if err != nil { + return nil, err } + visibleByManager, err := r.Store.Groups.CanUserManageGroup(ctx, *userId, obj.Id) + if err != nil { + return nil, err + } + + visible = visible || visibleByManager if !visible { return nil, fmt.Errorf("group does not exist or user does not have permission to see it") } + log.Println("how", how, "vbm", visibleByManager) + if how == models.GroupViewPermission_SeeSelf && !visibleByManager { + m := models.MembershipToGroup{ + UserId: *userId, + ViewPermission: models.GroupViewPermission_SeeSelf, + } + ms := []*models.MembershipToGroup{ + &m, + } + return ms, nil + } + + // Permission SeeAll or manager level members, err := r.Store.Groups.GetGroupMembers(ctx, obj.Id) if err != nil { diff --git a/internal/gql/resolvers/group_resolver_test.go b/internal/gql/resolvers/group_resolver_test.go index 242f11f7..7884b64b 100644 --- a/internal/gql/resolvers/group_resolver_test.go +++ b/internal/gql/resolvers/group_resolver_test.go @@ -238,12 +238,9 @@ func TestFindingGroupsById(t *testing.T) { } func areGroupsEqual(wantedIds, gotIds []int) bool { - for _, m := range wantedIds { - if !slices.Contains(gotIds, m) { - return false - } - } - return true + slices.Sort(wantedIds) + slices.Sort(gotIds) + return slices.Equal(wantedIds, gotIds) } func TestMembersOfGroupAsManager(t *testing.T) { @@ -274,8 +271,8 @@ func TestMembersOfGroupAsManager(t *testing.T) { func TestMembersOfGroupAsSeeSelf(t *testing.T) { _, data, resolver := helpersForResolverTest(t) - group := data.BeatlesMusicians - askerId := data.Users[1].Id + group := data.BeatlesManagers + askerId := data.Users[0].Id ctx := ContextWithUser(t.Context(), askerId) members, err := resolver.Group().Members(ctx, &group) @@ -325,6 +322,6 @@ func TestMembersOfGroupAsSeeNone(t *testing.T) { ctx := ContextWithUser(t.Context(), askerId) members, err := resolver.Group().Members(ctx, &group) if err == nil { - t.Fatalf("see none member should not be able to see themselves: saw %v", members) + t.Fatalf("see none member should not be able to see group at all: saw %v", members) } } From 09689d27f8db02b715454000f4072d76de1addca Mon Sep 17 00:00:00 2001 From: cowsed Date: Tue, 18 Aug 2026 12:37:35 -0400 Subject: [PATCH 12/22] start adding test makerspace --- internal/database/mock_data.go | 17 +++++++++++++++++ internal/gql/resolvers/group_resolver_test.go | 9 +++++++++ 2 files changed, 26 insertions(+) diff --git a/internal/database/mock_data.go b/internal/database/mock_data.go index 577b9608..5dcccc85 100644 --- a/internal/database/mock_data.go +++ b/internal/database/mock_data.go @@ -25,6 +25,8 @@ type TestMockData struct { ExMusicians models.Group BeatlesManagers models.Group Brits models.Group + + Parlophone models.Makerspace } var localContext TestMockData = TestMockData{ @@ -41,6 +43,20 @@ var localContext TestMockData = TestMockData{ }, } +func makeTestMakerspace(ctx context.Context, l *slog.Logger, store *Store) bool { + id, err := store.Makerspaces.CreateMakerspace(ctx, "Parlophone", false) + if err != nil { + l.Error("Failed to create makerspace", "err", err) + return false + } + m, err := store.Makerspaces.GetMakerspaceById(ctx, id) + if err != nil { + l.Error("Failed to get created makerspace", "err", err) + return false + } + localContext.Parlophone = *m + return true +} func fillTestUsers(ctx context.Context, l *slog.Logger, store *Store) bool { for i, u := range localContext.Users { id, err := store.Users.CreateUser(ctx, u.Email) @@ -155,6 +171,7 @@ func fillTestData(ctx context.Context, l *slog.Logger, store *Store) { fillTestUsers(ctx, l, store) makeTestGroups(ctx, l, store) addUsersToTestGroups(ctx, l, store) + makeTestMakerspace(ctx, l, store) } diff --git a/internal/gql/resolvers/group_resolver_test.go b/internal/gql/resolvers/group_resolver_test.go index 7884b64b..bb23a581 100644 --- a/internal/gql/resolvers/group_resolver_test.go +++ b/internal/gql/resolvers/group_resolver_test.go @@ -325,3 +325,12 @@ func TestMembersOfGroupAsSeeNone(t *testing.T) { t.Fatalf("see none member should not be able to see group at all: saw %v", members) } } +func TestMembersOfGroupAsNotSignedIn(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + group := data.BeatlesMusicians + + members, err := resolver.Group().Members(t.Context(), &group) + if err == nil { + t.Fatalf("non signed in user should not be able to see group at all: saw %v", members) + } +} From 89cc49df636f8937f085483c39745491fddb6244 Mon Sep 17 00:00:00 2001 From: cowsed Date: Tue, 18 Aug 2026 13:09:43 -0400 Subject: [PATCH 13/22] Checks to prevent infinite cycles, group schema tidbits, extracting common errors --- internal/auth/middleware.go | 2 - .../20260703201718_initial_schema.sql | 23 +++-- internal/database/repos/group_repo.go | 11 ++- internal/gql/resolvers/group.resolvers.go | 10 +- internal/gql/resolvers/group_resolver_test.go | 91 ++++++++++++++++++- 5 files changed, 118 insertions(+), 19 deletions(-) diff --git a/internal/auth/middleware.go b/internal/auth/middleware.go index e0ebd753..940f8e6b 100644 --- a/internal/auth/middleware.go +++ b/internal/auth/middleware.go @@ -3,7 +3,6 @@ package auth import ( "context" "errors" - "log/slog" "net/http" "github.com/alexedwards/scs/v2" @@ -16,7 +15,6 @@ var ErrNotAuthenticated error = errors.New("not authenticated") func UserIDFromContext(ctx context.Context) *int { userVal := ctx.Value(UserContextKey{}) if userVal == nil { - slog.Error("UserIDFromContext called with no userID in context. Caused by mismatch between route protection middleware and what resolvers actually do") return nil } userID := userVal.(int) diff --git a/internal/database/migrations/20260703201718_initial_schema.sql b/internal/database/migrations/20260703201718_initial_schema.sql index 1cbee8ac..5ad419b4 100644 --- a/internal/database/migrations/20260703201718_initial_schema.sql +++ b/internal/database/migrations/20260703201718_initial_schema.sql @@ -44,7 +44,7 @@ CREATE TABLE images ( CREATE TABLE groups ( id SERIAL PRIMARY KEY, - name TEXT UNIQUE NOT NULL, + name TEXT NOT NULL, manager_id INT REFERENCES groups(id), description TEXT NOT NULL DEFAULT '', UNIQUE (name, manager_id) @@ -62,8 +62,8 @@ CREATE TABLE group_direct_membership( ); CREATE TABLE group_direct_subgroups ( - group_id INT REFERENCES groups(id), - subgroup_id INT REFERENCES groups(id), + group_id INT REFERENCES groups(id) ON DELETE CASCADE, + subgroup_id INT REFERENCES groups(id) ON DELETE CASCADE, view_permission INT NOT NULL DEFAULT 0 CHECK (view_permission in (0, 1, 2)), PRIMARY KEY (group_id, subgroup_id) ); @@ -143,13 +143,16 @@ create view group_management as ( ); create view group_membership as ( - select group_id, user_id, gdm.view_permission from group_direct_membership gdm - union - select distinct gs.supergroup_id, gdm.user_id, gs.view_permission - from group_subgroups gs - left join group_direct_membership gdm - on gdm.group_id = gs.subgroup_id - where user_id is not null + select group_id, user_id, MAX(view_permission) as view_permission from ( + select group_id, user_id, gdm.view_permission as view_permission from group_direct_membership gdm + union + select distinct gs.supergroup_id, gdm.user_id, gs.view_permission + from group_subgroups gs + left join group_direct_membership gdm + on gdm.group_id = gs.subgroup_id + where user_id is not null + ) as subquery + group by group_id, user_id ); diff --git a/internal/database/repos/group_repo.go b/internal/database/repos/group_repo.go index 35467a0d..9979fcfe 100644 --- a/internal/database/repos/group_repo.go +++ b/internal/database/repos/group_repo.go @@ -135,9 +135,18 @@ func (g *GroupRepo) IsGroupSubgroup(ctx context.Context, subgroup int, supergrou } func (g *GroupRepo) AddSubgroupToGroup(ctx context.Context, subgroupID, supergroupID int, permissions models.GroupViewPermission) error { + // if new supergroup is subgroup of new subgroup, would make a loop + wouldCreateCycle, _, err := g.IsGroupSubgroup(ctx, supergroupID, subgroupID) + if err != nil { + return fmt.Errorf("failed to check subgroup for cycle prevention") + } + if wouldCreateCycle { + return errors.New("not adding subgroup to group as it would cause a cycle") + } + query := `INSERT INTO group_direct_subgroups (group_id, subgroup_id, view_permission) VALUES ($1, $2, $3)` - _, err := g.DB.ExecContext(ctx, query, supergroupID, subgroupID, permissions) + _, err = g.DB.ExecContext(ctx, query, supergroupID, subgroupID, permissions) if err != nil { return fmt.Errorf("failed to add user to group: %w", err) } diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index 77f18b85..0b9e88d8 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -8,12 +8,13 @@ package resolvers import ( "context" "fmt" - "log" "make-backend/internal/auth" "make-backend/internal/database/models" "make-backend/internal/gql" ) +var ErrNoGroupOrWrongPermissions = fmt.Errorf("group does not exist or user has invalid permissions to query it") + // DirectMembers is the resolver for the directMembers field. func (r *groupResolver) DirectMembers(ctx context.Context, obj *models.Group) ([]*models.MembershipToGroup, error) { panic(fmt.Errorf("not implemented: DirectMembers - directMembers")) @@ -40,7 +41,6 @@ func (r *groupResolver) Members(ctx context.Context, obj *models.Group) ([]*mode if !visible { return nil, fmt.Errorf("group does not exist or user does not have permission to see it") } - log.Println("how", how, "vbm", visibleByManager) if how == models.GroupViewPermission_SeeSelf && !visibleByManager { m := models.MembershipToGroup{ UserId: *userId, @@ -128,7 +128,7 @@ func (r *queryResolver) IsUserInGroup(ctx context.Context, userID int, groupID i return false, err } if !visibleToAsker { - return false, fmt.Errorf("group does not exist or user has invalid permissions to query it") + return false, ErrNoGroupOrWrongPermissions } in, _, err := r.Store.Groups.IsUserInGroup(ctx, userID, groupID) @@ -147,7 +147,7 @@ func (r *queryResolver) IsUserInGroupDirectly(ctx context.Context, userID int, g return false, err } if !visibleToAsker { - return false, fmt.Errorf("group does not exist or user has invalid permissions to query it") + return false, ErrNoGroupOrWrongPermissions } in, _, err := r.Store.Groups.IsUserInGroupDirectly(ctx, userID, groupID) @@ -199,7 +199,7 @@ func (r *queryResolver) CanUserManageGroup(ctx context.Context, managerID int, g return false, err } if !visibleToAsker { - return false, fmt.Errorf("group does not exist or user has invalid permissions to query it") + return false, ErrNoGroupOrWrongPermissions } return r.Store.Groups.CanUserManageGroup(ctx, managerID, groupID) } diff --git a/internal/gql/resolvers/group_resolver_test.go b/internal/gql/resolvers/group_resolver_test.go index bb23a581..22860fd1 100644 --- a/internal/gql/resolvers/group_resolver_test.go +++ b/internal/gql/resolvers/group_resolver_test.go @@ -152,7 +152,7 @@ func TestGroupMembership(t *testing.T) { if inGroup != tC.shouldBeMember { t.Fatalf("user %v should have membership:%v to group %v but was %v", tC.user, tC.shouldBeMember, tC.group, inGroup) } - if inGroup != tC.shouldBeMember { + if inGroupDirectly != tC.shouldBeDirect { t.Fatalf("user %v should have direct membership:%v to group %v but was %v", tC.user, tC.shouldBeDirect, tC.group, inGroupDirectly) } }) @@ -334,3 +334,92 @@ func TestMembersOfGroupAsNotSignedIn(t *testing.T) { t.Fatalf("non signed in user should not be able to see group at all: saw %v", members) } } + +func TestDirectManagedGroups(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + + // Brian (Users[0]) is the asker, who belongs to BeatlesManagers. + // BeatlesManagers (which is managed by admin/root group) directly manages: + // - BeatlesMusicians + // - OtherMusicians + // - ExMusicians + ctx := ContextWithUser(t.Context(), data.Users[0].Id) + + managedGroups, err := resolver.Group().DirectManagedGroups(ctx, &data.BeatlesManagers) + if err != nil { + t.Fatalf("failed to get direct managed groups: %v", err) + } + + expectedIds := []int{ + data.BeatlesMusicians.Id, + data.OtherMusicians.Id, + data.ExMusicians.Id, + } + + gotIds := []int{} + for _, g := range managedGroups { + gotIds = append(gotIds, g.Id) + } + + if !areGroupsEqual(expectedIds, gotIds) { + t.Fatalf("direct managed groups were not equal. Expected %v, got %v", expectedIds, gotIds) + } +} + +func TestAuthenticationRequired(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + ctx := t.Context() // context with no user + + tests := []struct { + name string + run func() error + }{ + { + "Group.Members", func() error { + _, err := resolver.Group().Members(ctx, &data.BeatlesMusicians) + return err + }, + }, + { + "Query.Group", func() error { + _, err := resolver.Query().Group(ctx, data.BeatlesMusicians.Id) + return err + }, + }, + { + name: "Query.IsUserInGroup", run: func() error { + _, err := resolver.Query().IsUserInGroup(ctx, data.Users[0].Id, data.BeatlesMusicians.Id) + return err + }, + }, + { + "Query.IsUserInGroupDirectly", func() error { + _, err := resolver.Query().IsUserInGroupDirectly(ctx, data.Users[0].Id, data.BeatlesMusicians.Id) + return err + }, + }, + { + "Query.CanGroupManageGroup", func() error { + _, err := resolver.Query().CanGroupManageGroup(ctx, data.BeatlesManagers.Id, data.BeatlesMusicians.Id) + return err + }, + }, + { + "Query.CanUserManageGroup", func() error { + _, err := resolver.Query().CanUserManageGroup(ctx, data.Users[0].Id, data.BeatlesMusicians.Id) + return err + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.run() + if err == nil { + t.Error("expected error for unauthenticated user, but got nil") + } else if err != auth.ErrNotAuthenticated { + t.Errorf("expected non authenticated error %v, but got %v", auth.ErrNotAuthenticated, err) + } + }) + } +} From aa920adb16da866b9e12ec5d1943725ea22237f3 Mon Sep 17 00:00:00 2001 From: cowsed Date: Tue, 18 Aug 2026 13:33:14 -0400 Subject: [PATCH 14/22] a groups are real?!?!?!? --- .../20260703201718_initial_schema.sql | 23 ++++----- internal/database/mock_data.go | 2 + internal/database/models/group.go | 2 + internal/database/models/makerspace.go | 18 ++++--- internal/database/repos/group_repo.go | 6 ++- internal/database/repos/makerspace_repo.go | 50 ++++++++----------- internal/gql/resolvers/group.resolvers.go | 8 ++- 7 files changed, 53 insertions(+), 56 deletions(-) diff --git a/internal/database/migrations/20260703201718_initial_schema.sql b/internal/database/migrations/20260703201718_initial_schema.sql index 5ad419b4..5ab57bda 100644 --- a/internal/database/migrations/20260703201718_initial_schema.sql +++ b/internal/database/migrations/20260703201718_initial_schema.sql @@ -156,6 +156,14 @@ create view group_membership as ( ); +create view anonymous_group_membership as ( + select distinct ags.anonymous_id as agroup_id , gm.user_id as user_id + from anonymous_group_subgroups ags + left join group_membership gm + on gm.group_id = ags.group_id +); + + CREATE TABLE anonymous_groups( id SERIAL PRIMARY KEY @@ -180,8 +188,8 @@ CREATE TABLE makerspaces ( timezone TEXT NOT NULL DEFAULT 'America/New_York', -- agroup of users who can manage this space management_agroup_id INT NOT NULL REFERENCES anonymous_groups(id) ON DELETE CASCADE, - -- agroup of users who can site-set equipment state - can_change_equipment_state_agroup_id INT NOT NULL REFERENCES anonymous_groups(id) ON DELETE CASCADE + -- agroup of users who can site-set equipment state and other such actions + staff_agroup_id INT NOT NULL REFERENCES anonymous_groups(id) ON DELETE CASCADE ); CREATE TABLE restrictions ( @@ -225,17 +233,6 @@ CREATE TABLE announcements ( makerspace_id INT REFERENCES makerspaces(id) ON DELETE CASCADE ); -CREATE TABLE managers ( - user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE, - makerspace_id INT NOT NULL REFERENCES makerspaces(id) ON DELETE CASCADE, - PRIMARY KEY (user_id, makerspace_id) -); - -CREATE TABLE staff ( - user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE, - makerspace_id INT NOT NULL REFERENCES makerspaces(id) ON DELETE CASCADE, - PRIMARY KEY (user_id, makerspace_id) -); CREATE TABLE equipment ( id SERIAL PRIMARY KEY, diff --git a/internal/database/mock_data.go b/internal/database/mock_data.go index 5dcccc85..17f0368a 100644 --- a/internal/database/mock_data.go +++ b/internal/database/mock_data.go @@ -55,6 +55,8 @@ func makeTestMakerspace(ctx context.Context, l *slog.Logger, store *Store) bool return false } localContext.Parlophone = *m + + localContext.Parlophone.Description return true } func fillTestUsers(ctx context.Context, l *slog.Logger, store *Store) bool { diff --git a/internal/database/models/group.go b/internal/database/models/group.go index a714021d..51cc1f5c 100644 --- a/internal/database/models/group.go +++ b/internal/database/models/group.go @@ -6,6 +6,8 @@ import ( "strconv" ) +var ErrNoGroupOrWrongPermissions = fmt.Errorf("group does not exist or user has invalid permissions to query it") + // Determines how users see the group theyre a part of type GroupViewPermission int diff --git a/internal/database/models/makerspace.go b/internal/database/models/makerspace.go index ea5565af..5f8ef0f1 100644 --- a/internal/database/models/makerspace.go +++ b/internal/database/models/makerspace.go @@ -1,14 +1,16 @@ package models type Makerspace struct { - Id int - Name string - Subtitle string - Description string - DocsUrl string - ImageId *int32 - Hidden bool - Timezone string + Id int + Name string + Subtitle string + Description string + DocsUrl string + ImageId *int32 + Hidden bool + Timezone string + ManagementAgroupId int + StaffAgroupId int // TODO: finer grained permissions } func (m Makerspace) LogEntity() LogEntity { diff --git a/internal/database/repos/group_repo.go b/internal/database/repos/group_repo.go index 9979fcfe..34004506 100644 --- a/internal/database/repos/group_repo.go +++ b/internal/database/repos/group_repo.go @@ -48,6 +48,10 @@ type GroupRepository interface { AllGroupsUserCanManage(ctx context.Context, userId int) ([]int, error) AllGroupsUserVisibleToUser(ctx context.Context, userId int) ([]int, error) IsGroupVisibleToUser(ctx context.Context, userId int, groupId int) (bool, error) + + IsUserInAnonymousGroup(ctx context.Context, anonymousGroupId int, groupId int) + AddGroupToAnonymousGroup(ctx context.Context, anonymousGroupId int, groupId int) (bool, error) + GroupsInAnonymousGroup(ctx context.Context, anonymousGroupId int) ([]int, error) } type GroupRepo struct { @@ -390,7 +394,7 @@ func (g *GroupRepo) IsUserInGroup(ctx context.Context, userId int, groupId int) func (g *GroupRepo) IsUserInGroupDirectly(ctx context.Context, userId int, groupId int) (bool, models.GroupViewPermission, error) { var perms models.GroupViewPermission - query := "SELECT view_permission FROM group_membership WHERE user_id = $1 and group_id = $2" + query := "SELECT view_permission FROM group_direct_membership WHERE user_id = $1 and group_id = $2" err := g.DB.QueryRow(query, userId, groupId).Scan(&perms) if errors.Is(err, sql.ErrNoRows) { diff --git a/internal/database/repos/makerspace_repo.go b/internal/database/repos/makerspace_repo.go index 16d485e9..c7f05f17 100644 --- a/internal/database/repos/makerspace_repo.go +++ b/internal/database/repos/makerspace_repo.go @@ -3,7 +3,6 @@ package repos import ( "context" "database/sql" - "fmt" "make-backend/internal/database/models" ) @@ -11,8 +10,7 @@ type MakerspaceRepository interface { GetMakerspaceById(ctx context.Context, id int) (*models.Makerspace, error) CreateMakerspace(ctx context.Context, name string, hidden bool) (int, error) DeleteMakerspace(ctx context.Context, id int) (bool, error) - AddManager(ctx context.Context, makerspace_id int, user_id int) error - AddStaff(ctx context.Context, makerspace_id int, user_id int) error + GetDefaultHours(ctx context.Context, makerspace_id int) ([]*models.DefaultHours, error) } @@ -31,7 +29,9 @@ func (r *MakerspaceRepo) GetMakerspaceById(ctx context.Context, id int) (*models docs_url, image_id, hidden, - timezone + timezone, + management_agroup_id, + staff_agroup_id FROM makerspaces where makerspaces.id = $1 ` @@ -44,6 +44,8 @@ func (r *MakerspaceRepo) GetMakerspaceById(ctx context.Context, id int) (*models &makerspace_result.ImageId, &makerspace_result.Hidden, &makerspace_result.Timezone, + &makerspace_result.ManagementAgroupId, + &makerspace_result.StaffAgroupId, ) if err != nil { @@ -54,49 +56,39 @@ func (r *MakerspaceRepo) GetMakerspaceById(ctx context.Context, id int) (*models } func (r *MakerspaceRepo) CreateMakerspace(ctx context.Context, name string, hidden bool) (int, error) { - var id_result int - - query := `INSERT INTO makerspaces (name, hidden) VALUES ($1, $2) RETURNING id` + var mid_result int + var manager_agroup_id_result, staff_agroup_id_result int - err := r.DB.QueryRowContext(ctx, query, name, hidden).Scan(&id_result) + query1 := `INSERT INTO anonymous_groups DEFAULT VALUES RETURNING id` + err := r.DB.QueryRowContext(ctx, query1).Scan(&manager_agroup_id_result) if err != nil { return 0, err } - return id_result, nil -} - -func (r *MakerspaceRepo) DeleteMakerspace(ctx context.Context, id int) (bool, error) { - query := `DELETE FROM makerspaces WHERE id = $1` - - _, err := r.DB.ExecContext(ctx, query, id) + err = r.DB.QueryRowContext(ctx, query1).Scan(&staff_agroup_id_result) if err != nil { - return false, err + return 0, err } - return true, nil -} - -func (r *MakerspaceRepo) AddManager(ctx context.Context, makerspace_id int, user_id int) error { - query := `INSERT INTO managers (makerspace_id, user_id) VALUES ($1, $2)` + query2 := `INSERT INTO makerspaces (name, hidden, management_agroup_id, staff_agroup_id) VALUES ($1, $2, $3, $4) RETURNING id` - _, err := r.DB.ExecContext(ctx, query, makerspace_id, user_id) + err = r.DB.QueryRowContext(ctx, query2, name, hidden, manager_agroup_id_result, staff_agroup_id_result).Scan(&mid_result) if err != nil { - return fmt.Errorf("failed to insert manager (makerspace: %d, user: %d): %w", makerspace_id, user_id, err) + return 0, err } - return nil + return mid_result, nil } -func (r *MakerspaceRepo) AddStaff(ctx context.Context, makerspace_id int, user_id int) error { - query := `INSERT INTO staff (makerspace_id, user_id) VALUES ($1, $2)` +func (r *MakerspaceRepo) DeleteMakerspace(ctx context.Context, id int) (bool, error) { + query := `DELETE FROM makerspaces WHERE id = $1` - _, err := r.DB.ExecContext(ctx, query, makerspace_id, user_id) + _, err := r.DB.ExecContext(ctx, query, id) if err != nil { - return fmt.Errorf("failed to insert staff (makerspace: %d, user: %d): %w", makerspace_id, user_id, err) + return false, err } - return nil + return true, nil } func (r *MakerspaceRepo) GetManagers(ctx context.Context, makerspace_id int) ([]*models.User, error) { diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index 0b9e88d8..5ea87966 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -13,8 +13,6 @@ import ( "make-backend/internal/gql" ) -var ErrNoGroupOrWrongPermissions = fmt.Errorf("group does not exist or user has invalid permissions to query it") - // DirectMembers is the resolver for the directMembers field. func (r *groupResolver) DirectMembers(ctx context.Context, obj *models.Group) ([]*models.MembershipToGroup, error) { panic(fmt.Errorf("not implemented: DirectMembers - directMembers")) @@ -128,7 +126,7 @@ func (r *queryResolver) IsUserInGroup(ctx context.Context, userID int, groupID i return false, err } if !visibleToAsker { - return false, ErrNoGroupOrWrongPermissions + return false, models.ErrNoGroupOrWrongPermissions } in, _, err := r.Store.Groups.IsUserInGroup(ctx, userID, groupID) @@ -147,7 +145,7 @@ func (r *queryResolver) IsUserInGroupDirectly(ctx context.Context, userID int, g return false, err } if !visibleToAsker { - return false, ErrNoGroupOrWrongPermissions + return false, models.ErrNoGroupOrWrongPermissions } in, _, err := r.Store.Groups.IsUserInGroupDirectly(ctx, userID, groupID) @@ -199,7 +197,7 @@ func (r *queryResolver) CanUserManageGroup(ctx context.Context, managerID int, g return false, err } if !visibleToAsker { - return false, ErrNoGroupOrWrongPermissions + return false, models.ErrNoGroupOrWrongPermissions } return r.Store.Groups.CanUserManageGroup(ctx, managerID, groupID) } From 4694195b70285f95616b39d4cc21a8d1b3093443 Mon Sep 17 00:00:00 2001 From: cowsed Date: Wed, 19 Aug 2026 10:44:04 -0400 Subject: [PATCH 15/22] integrating anonymous groups --- .../20260703201718_initial_schema.sql | 24 +- internal/database/mock_data.go | 11 +- internal/database/repos/group_repo.go | 108 +++++- internal/database/repos/makerspace_repo.go | 16 +- internal/gql/generated.go | 356 +++++++++++++++++- .../gql/resolvers/makerspace.resolvers.go | 38 ++ .../gql/resolvers/makerspace_resolver_test.go | 37 ++ internal/gql/schema/makerspace.graphqls | 6 + 8 files changed, 570 insertions(+), 26 deletions(-) create mode 100644 internal/gql/resolvers/makerspace_resolver_test.go diff --git a/internal/database/migrations/20260703201718_initial_schema.sql b/internal/database/migrations/20260703201718_initial_schema.sql index 5ab57bda..e0591696 100644 --- a/internal/database/migrations/20260703201718_initial_schema.sql +++ b/internal/database/migrations/20260703201718_initial_schema.sql @@ -142,6 +142,7 @@ create view group_management as ( group by manager_group_id , group_id ); + create view group_membership as ( select group_id, user_id, MAX(view_permission) as view_permission from ( select group_id, user_id, gdm.view_permission as view_permission from group_direct_membership gdm @@ -156,14 +157,6 @@ create view group_membership as ( ); -create view anonymous_group_membership as ( - select distinct ags.anonymous_id as agroup_id , gm.user_id as user_id - from anonymous_group_subgroups ags - left join group_membership gm - on gm.group_id = ags.group_id -); - - CREATE TABLE anonymous_groups( id SERIAL PRIMARY KEY @@ -175,6 +168,15 @@ CREATE TABLE anonymous_group_subgroups( ); +create view anonymous_group_membership as ( + select distinct ags.anonymous_id as agroup_id , gm.user_id as user_id + from anonymous_group_subgroups ags + left join group_membership gm + on gm.group_id = ags.group_id +); + + + CREATE TABLE makerspaces ( id SERIAL PRIMARY KEY, @@ -395,6 +397,12 @@ DROP TABLE IF EXISTS groups; DROP TABLE IF EXISTS group_direct_membership; DROP TABLE IF EXISTS group_direct_subgroups; +DROP VIEW IF EXISTS group_noncombination_management +DROP VIEW IF EXISTS group_subgroups +DROP VIEW IF EXISTS group_management +DROP VIEW IF EXISTS group_membership +DROP VIEW IF EXISTS anonymous_group_membership + DROP TABLE IF EXISTS anonymous_groups; DROP TABLE IF EXISTS anonymous_group_subgroups; diff --git a/internal/database/mock_data.go b/internal/database/mock_data.go index 17f0368a..a83971ff 100644 --- a/internal/database/mock_data.go +++ b/internal/database/mock_data.go @@ -55,8 +55,17 @@ func makeTestMakerspace(ctx context.Context, l *slog.Logger, store *Store) bool return false } localContext.Parlophone = *m + err = store.Groups.AddGroupToAnonymousGroup(ctx, localContext.Parlophone.StaffAgroupId, localContext.BeatlesMusicians.Id) + if err != nil { + l.Error("Failed to add beatles as staff of parlophone", "err", err) + return false + } + err = store.Groups.AddGroupToAnonymousGroup(ctx, localContext.Parlophone.ManagementAgroupId, localContext.BeatlesManagers.Id) + if err != nil { + l.Error("Failed to add beatles as staff of parlophone", "err", err) + return false + } - localContext.Parlophone.Description return true } func fillTestUsers(ctx context.Context, l *slog.Logger, store *Store) bool { diff --git a/internal/database/repos/group_repo.go b/internal/database/repos/group_repo.go index 34004506..38228b36 100644 --- a/internal/database/repos/group_repo.go +++ b/internal/database/repos/group_repo.go @@ -49,15 +49,117 @@ type GroupRepository interface { AllGroupsUserVisibleToUser(ctx context.Context, userId int) ([]int, error) IsGroupVisibleToUser(ctx context.Context, userId int, groupId int) (bool, error) - IsUserInAnonymousGroup(ctx context.Context, anonymousGroupId int, groupId int) - AddGroupToAnonymousGroup(ctx context.Context, anonymousGroupId int, groupId int) (bool, error) + IsUserInAnonymousGroup(ctx context.Context, anonymousGroupId int, userId int) (bool, error) + UsersInAnonymousGroup(ctx context.Context, anonymousGroupId int) ([]models.User, error) + AddGroupToAnonymousGroup(ctx context.Context, anonymousGroupId int, groupId int) error GroupsInAnonymousGroup(ctx context.Context, anonymousGroupId int) ([]int, error) + RemoveGroupFromAnonymousGroup(ctx context.Context, anonymousGroupId int, groupId int) error } type GroupRepo struct { DB *sql.DB } +func (g *GroupRepo) UsersInAnonymousGroup(ctx context.Context, anonymousGroupId int) ([]models.User, error) { + query := ` + select + u.id, u.email, u.full_name, u.preferred_name, u.pronouns, u.join_date, u.setup_complete, u.archived, u.notes, u.admin, u.force_archive, u.card_tag + from anonymous_group_membership + left join users u on u.id = user_id + where agroup_id = $1` + + rows, err := g.DB.QueryContext(ctx, query, anonymousGroupId) + if err != nil { + return nil, fmt.Errorf("failed to construct QueryContext for GetGroupMembers: %w", err) + } + + users := []models.User{} + for rows.Next() { + var user models.User + err := rows.Scan( + &user.Id, + &user.Email, + &user.FullName, + &user.PreferredName, + &user.Pronouns, + &user.JoinDate, + &user.SetupComplete, + &user.Archived, + &user.Notes, + &user.Admin, + &user.ForceArchive, + &user.CardTag, + ) + if err != nil { + return nil, fmt.Errorf("failed to scan for user in agroup: %w", err) + } + users = append(users, user) + + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("failed to get group members: %w", err) + } + + return users, nil + +} + +func (g *GroupRepo) AddGroupToAnonymousGroup(ctx context.Context, anonymousGroupId int, groupId int) error { + query := `INSERT INTO anonymous_group_subgroups (anonymous_id, group_id) VALUES ($1, $2) ON CONFLICT DO NOTHING` + _, err := g.DB.ExecContext(ctx, query, anonymousGroupId, groupId) + if err != nil { + return fmt.Errorf("failed to add group to anonymous group: %w", err) + } + return nil +} + +// GroupsInAnonymousGroup implements [GroupRepository]. +func (g *GroupRepo) GroupsInAnonymousGroup(ctx context.Context, anonymousGroupId int) ([]int, error) { + query := `SELECT group_id FROM anonymous_group_subgroups WHERE anonymous_id = $1` + rows, err := g.DB.QueryContext(ctx, query, anonymousGroupId) + if err != nil { + return nil, fmt.Errorf("failed to query groups in anonymous group: %w", err) + } + defer rows.Close() + + var groupIds []int + for rows.Next() { + var id int + if err := rows.Scan(&id); err != nil { + return nil, fmt.Errorf("failed to scan group id in anonymous group: %w", err) + } + groupIds = append(groupIds, id) + } + if err := rows.Err(); err != nil { + return nil, err + } + return groupIds, nil +} + +func (g *GroupRepo) IsUserInAnonymousGroup(ctx context.Context, anonymousGroupId int, userId int) (bool, error) { + var inGroup bool + + query := "SELECT EXISTS(SELECT 1 FROM group_management WHERE group_id = $1 and user_id = $2)" + err := g.DB.QueryRow(query, anonymousGroupId, userId).Scan(&inGroup) + + if err != nil { + return false, err + } + return inGroup, nil + +} + +func (g *GroupRepo) RemoveGroupFromAnonymousGroup(ctx context.Context, anonymousGroupId int, groupId int) error { + query := `DELETE FROM anonymous_group_subgroups WHERE anonymous_id = $1 AND group_id = $2` + _, err := g.DB.ExecContext(ctx, query, anonymousGroupId, groupId) + if err != nil { + return fmt.Errorf("failed to remove group from anonymous group: %w", err) + } + return nil +} + +var _ GroupRepository = &GroupRepo{} + func (g *GroupRepo) IsGroupVisibleToUser(ctx context.Context, userId int, groupId int) (bool, error) { // if can manage -> see all canManage, err := g.CanUserManageGroup(ctx, userId, groupId) @@ -188,7 +290,6 @@ func (g *GroupRepo) GetDirectSubgroups(ctx context.Context, groupId int) ([]mode } -// GetSubgroups implements [GroupRepository]. func (g *GroupRepo) GetSubgroups(ctx context.Context, groupId int) ([]models.SubgroupLink, error) { query := `select subgroup_id, view_permission from group_subgroups where supergroup_id = $1` @@ -220,7 +321,6 @@ func (g *GroupRepo) GetSubgroups(ctx context.Context, groupId int) ([]models.Sub } -// AllGroupsGroupCanManage implements [GroupRepository]. func (g *GroupRepo) AllGroupsGroupCanManage(ctx context.Context, managerId int) ([]int, error) { query := `select group_id from group_management where manager_group_id = $1` diff --git a/internal/database/repos/makerspace_repo.go b/internal/database/repos/makerspace_repo.go index c7f05f17..fc0642f3 100644 --- a/internal/database/repos/makerspace_repo.go +++ b/internal/database/repos/makerspace_repo.go @@ -56,27 +56,37 @@ func (r *MakerspaceRepo) GetMakerspaceById(ctx context.Context, id int) (*models } func (r *MakerspaceRepo) CreateMakerspace(ctx context.Context, name string, hidden bool) (int, error) { + tx, err := r.DB.BeginTx(ctx, nil) + if err != nil { + return 0, err + } + defer tx.Rollback() + var mid_result int var manager_agroup_id_result, staff_agroup_id_result int query1 := `INSERT INTO anonymous_groups DEFAULT VALUES RETURNING id` - err := r.DB.QueryRowContext(ctx, query1).Scan(&manager_agroup_id_result) + err = tx.QueryRowContext(ctx, query1).Scan(&manager_agroup_id_result) if err != nil { return 0, err } - err = r.DB.QueryRowContext(ctx, query1).Scan(&staff_agroup_id_result) + err = tx.QueryRowContext(ctx, query1).Scan(&staff_agroup_id_result) if err != nil { return 0, err } query2 := `INSERT INTO makerspaces (name, hidden, management_agroup_id, staff_agroup_id) VALUES ($1, $2, $3, $4) RETURNING id` - err = r.DB.QueryRowContext(ctx, query2, name, hidden, manager_agroup_id_result, staff_agroup_id_result).Scan(&mid_result) + err = tx.QueryRowContext(ctx, query2, name, hidden, manager_agroup_id_result, staff_agroup_id_result).Scan(&mid_result) if err != nil { return 0, err } + if err = tx.Commit(); err != nil { + return 0, err + } + return mid_result, nil } diff --git a/internal/gql/generated.go b/internal/gql/generated.go index d8813681..dec1040c 100644 --- a/internal/gql/generated.go +++ b/internal/gql/generated.go @@ -187,16 +187,20 @@ type ComplexityRoot struct { } Makerspace struct { - Description func(childComplexity int) int - DocsUrl func(childComplexity int) int - Hidden func(childComplexity int) int - Hours func(childComplexity int) int - Id func(childComplexity int) int - ImageId func(childComplexity int) int - Name func(childComplexity int) int - Subtitle func(childComplexity int) int - Timezone func(childComplexity int) int - Zones func(childComplexity int) int + Description func(childComplexity int) int + DocsUrl func(childComplexity int) int + Hidden func(childComplexity int) int + Hours func(childComplexity int) int + Id func(childComplexity int) int + ImageId func(childComplexity int) int + ManagerSubgroups func(childComplexity int) int + Managers func(childComplexity int) int + Name func(childComplexity int) int + Staff func(childComplexity int) int + StaffSubgroups func(childComplexity int) int + Subtitle func(childComplexity int) int + Timezone func(childComplexity int) int + Zones func(childComplexity int) int } MembershipToGroup struct { @@ -342,6 +346,10 @@ type GroupResolver interface { type MakerspaceResolver interface { Zones(ctx context.Context, obj *models.Makerspace) ([]*models.Zone, error) Hours(ctx context.Context, obj *models.Makerspace) ([]models.MakerspaceHours, error) + Managers(ctx context.Context, obj *models.Makerspace) ([]*models.User, error) + ManagerSubgroups(ctx context.Context, obj *models.Makerspace) ([]*models.Group, error) + Staff(ctx context.Context, obj *models.Makerspace) ([]*models.User, error) + StaffSubgroups(ctx context.Context, obj *models.Makerspace) ([]*models.Group, error) } type MembershipToGroupResolver interface { User(ctx context.Context, obj *models.MembershipToGroup) (*models.User, error) @@ -945,12 +953,36 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Makerspace.ImageId(childComplexity), true + case "Makerspace.managerSubgroups": + if e.ComplexityRoot.Makerspace.ManagerSubgroups == nil { + break + } + + return e.ComplexityRoot.Makerspace.ManagerSubgroups(childComplexity), true + case "Makerspace.managers": + if e.ComplexityRoot.Makerspace.Managers == nil { + break + } + + return e.ComplexityRoot.Makerspace.Managers(childComplexity), true case "Makerspace.name": if e.ComplexityRoot.Makerspace.Name == nil { break } return e.ComplexityRoot.Makerspace.Name(childComplexity), true + case "Makerspace.staff": + if e.ComplexityRoot.Makerspace.Staff == nil { + break + } + + return e.ComplexityRoot.Makerspace.Staff(childComplexity), true + case "Makerspace.staffSubgroups": + if e.ComplexityRoot.Makerspace.StaffSubgroups == nil { + break + } + + return e.ComplexityRoot.Makerspace.StaffSubgroups(childComplexity), true case "Makerspace.subtitle": if e.ComplexityRoot.Makerspace.Subtitle == nil { break @@ -1780,6 +1812,14 @@ func (ec *executionContext) childFields_Makerspace(ctx context.Context, field gr return ec.fieldContext_Makerspace_zones(ctx, field) case "hours": return ec.fieldContext_Makerspace_hours(ctx, field) + case "managers": + return ec.fieldContext_Makerspace_managers(ctx, field) + case "managerSubgroups": + return ec.fieldContext_Makerspace_managerSubgroups(ctx, field) + case "staff": + return ec.fieldContext_Makerspace_staff(ctx, field) + case "staffSubgroups": + return ec.fieldContext_Makerspace_staffSubgroups(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Makerspace", field.Name) } @@ -4536,6 +4576,134 @@ func (ec *executionContext) fieldContext_Makerspace_hours(_ context.Context, fie return graphql.NewScalarFieldContext("Makerspace", field, true, true, errors.New("field of type MakerspaceHours does not have child fields")) } +func (ec *executionContext) _Makerspace_managers(ctx context.Context, field graphql.CollectedField, obj *models.Makerspace) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Makerspace_managers(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Makerspace().Managers(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []*models.User) graphql.Marshaler { + return ec.marshalNUser2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐUserᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Makerspace_managers(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Makerspace", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_User(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Makerspace_managerSubgroups(ctx context.Context, field graphql.CollectedField, obj *models.Makerspace) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Makerspace_managerSubgroups(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Makerspace().ManagerSubgroups(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []*models.Group) graphql.Marshaler { + return ec.marshalNGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Makerspace_managerSubgroups(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Makerspace", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Group(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Makerspace_staff(ctx context.Context, field graphql.CollectedField, obj *models.Makerspace) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Makerspace_staff(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Makerspace().Staff(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []*models.User) graphql.Marshaler { + return ec.marshalNUser2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐUserᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Makerspace_staff(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Makerspace", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_User(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Makerspace_staffSubgroups(ctx context.Context, field graphql.CollectedField, obj *models.Makerspace) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Makerspace_staffSubgroups(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Makerspace().StaffSubgroups(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []*models.Group) graphql.Marshaler { + return ec.marshalNGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Makerspace_staffSubgroups(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Makerspace", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Group(ctx, field) + }, + } + return fc, nil +} + func (ec *executionContext) _MembershipToGroup_UserId(ctx context.Context, field graphql.CollectedField, obj *models.MembershipToGroup) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -9155,6 +9323,158 @@ func (ec *executionContext) _Makerspace(ctx context.Context, sel ast.SelectionSe continue } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "managers": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Makerspace_managers(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.IsDeferred() { + deferredFieldSet.AddField(field) + fieldIndex := len(deferredFieldSet.Values) - 1 + deferredFieldSet.Concurrently(fieldIndex, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, deferredFieldSet) + }) + + for _, deferrable := range field.Deferrables { + view, ok := deferLabelToView[deferrable.Label] + if !ok { + view = deferredFieldSet.NewView() + deferLabelToView[deferrable.Label] = view + } + view.AddIndices(fieldIndex) + } + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "managerSubgroups": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Makerspace_managerSubgroups(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.IsDeferred() { + deferredFieldSet.AddField(field) + fieldIndex := len(deferredFieldSet.Values) - 1 + deferredFieldSet.Concurrently(fieldIndex, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, deferredFieldSet) + }) + + for _, deferrable := range field.Deferrables { + view, ok := deferLabelToView[deferrable.Label] + if !ok { + view = deferredFieldSet.NewView() + deferLabelToView[deferrable.Label] = view + } + view.AddIndices(fieldIndex) + } + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "staff": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Makerspace_staff(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.IsDeferred() { + deferredFieldSet.AddField(field) + fieldIndex := len(deferredFieldSet.Values) - 1 + deferredFieldSet.Concurrently(fieldIndex, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, deferredFieldSet) + }) + + for _, deferrable := range field.Deferrables { + view, ok := deferLabelToView[deferrable.Label] + if !ok { + view = deferredFieldSet.NewView() + deferLabelToView[deferrable.Label] = view + } + view.AddIndices(fieldIndex) + } + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "staffSubgroups": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Makerspace_staffSubgroups(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.IsDeferred() { + deferredFieldSet.AddField(field) + fieldIndex := len(deferredFieldSet.Values) - 1 + deferredFieldSet.Concurrently(fieldIndex, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, deferredFieldSet) + }) + + for _, deferrable := range field.Deferrables { + view, ok := deferLabelToView[deferrable.Label] + if !ok { + view = deferredFieldSet.NewView() + deferLabelToView[deferrable.Label] = view + } + view.AddIndices(fieldIndex) + } + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) default: panic("unknown field " + strconv.Quote(field.Name)) @@ -11072,6 +11392,22 @@ func (ec *executionContext) marshalNUser2makeᚑbackendᚋinternalᚋdatabaseᚋ return ec._User(ctx, sel, &v) } +func (ec *executionContext) marshalNUser2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐUserᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.User) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalNUser2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐUser(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) marshalNUser2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐUser(ctx context.Context, sel ast.SelectionSet, v *models.User) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { diff --git a/internal/gql/resolvers/makerspace.resolvers.go b/internal/gql/resolvers/makerspace.resolvers.go index dba21aaf..94f0a599 100644 --- a/internal/gql/resolvers/makerspace.resolvers.go +++ b/internal/gql/resolvers/makerspace.resolvers.go @@ -7,6 +7,7 @@ package resolvers import ( "context" + "fmt" "make-backend/internal/database/models" "make-backend/internal/gql" ) @@ -36,6 +37,43 @@ func (r *makerspaceResolver) Hours(ctx context.Context, obj *models.Makerspace) return hours, nil } +// Managers is the resolver for the managers field. +func (r *makerspaceResolver) Managers(ctx context.Context, obj *models.Makerspace) ([]*models.User, error) { + us, err := r.Store.Groups.UsersInAnonymousGroup(ctx, obj.ManagementAgroupId) + if err != nil { + return nil, err + } + users := []*models.User{} + for _, u := range us { + users = append(users, &u) + } + return users, nil +} + +// ManagerSubgroups is the resolver for the managerSubgroups field. +func (r *makerspaceResolver) ManagerSubgroups(ctx context.Context, obj *models.Makerspace) ([]*models.Group, error) { + panic(fmt.Errorf("not implemented: ManagerSubgroups - managerSubgroups")) + +} + +// Staff is the resolver for the staff field. +func (r *makerspaceResolver) Staff(ctx context.Context, obj *models.Makerspace) ([]*models.User, error) { + us, err := r.Store.Groups.UsersInAnonymousGroup(ctx, obj.StaffAgroupId) + if err != nil { + return nil, err + } + users := []*models.User{} + for _, u := range us { + users = append(users, &u) + } + return users, nil +} + +// StaffSubgroups is the resolver for the staffSubgroups field. +func (r *makerspaceResolver) StaffSubgroups(ctx context.Context, obj *models.Makerspace) ([]*models.Group, error) { + panic(fmt.Errorf("not implemented: StaffSubgroups - staffSubgroups")) +} + // CreateMakerspace is the resolver for the createMakerspace field. func (r *mutationResolver) CreateMakerspace(ctx context.Context, name string, hidden bool) (int, error) { id, err := r.Store.Makerspaces.CreateMakerspace(ctx, name, hidden) diff --git a/internal/gql/resolvers/makerspace_resolver_test.go b/internal/gql/resolvers/makerspace_resolver_test.go new file mode 100644 index 00000000..369461e7 --- /dev/null +++ b/internal/gql/resolvers/makerspace_resolver_test.go @@ -0,0 +1,37 @@ +package resolvers + +import ( + "context" + "testing" +) + +func TestMakerspaceStaff(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + wantedStaff := []int{data.Users[1].Id, data.Users[2].Id, data.Users[3].Id, data.Users[4].Id} + gotStaff, err := resolver.Makerspace().Staff(context.TODO(), &data.Parlophone) + if err != nil { + t.Fatalf("failed to get staff of makerspace %v", err) + } + sIds := []int{} + for _, user := range gotStaff { + sIds = append(sIds, user.Id) + } + if !areGroupsEqual(wantedStaff, sIds) { + t.Fatalf("staff group for makerspace not equal. Wanted %v but got %v", wantedStaff, sIds) + } +} +func TestMakerspaceManagers(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + wantedManagers := []int{data.Users[0].Id} + gotManagers, err := resolver.Makerspace().Managers(context.TODO(), &data.Parlophone) + if err != nil { + t.Fatalf("failed to get staff of makerspace %v", err) + } + mIds := []int{} + for _, user := range gotManagers { + mIds = append(mIds, user.Id) + } + if !areGroupsEqual(wantedManagers, mIds) { + t.Fatalf("manager group for makerspace not equal. Wanted %v but got %v", wantedManagers, mIds) + } +} diff --git a/internal/gql/schema/makerspace.graphqls b/internal/gql/schema/makerspace.graphqls index e7d37c2f..b5dd44b9 100644 --- a/internal/gql/schema/makerspace.graphqls +++ b/internal/gql/schema/makerspace.graphqls @@ -12,6 +12,12 @@ type Makerspace { timezone: String! zones: [Zone!]! hours: [MakerspaceHours!]! + + managers: [User!]! + managerSubgroups: [Group!]! + + staff: [User!]! + staffSubgroups: [Group!]! } type Query { From adb2389802516e30e6d6a2539effa365b910c3e2 Mon Sep 17 00:00:00 2001 From: cowsed Date: Wed, 19 Aug 2026 12:43:29 -0400 Subject: [PATCH 16/22] more agroup gqls and tests --- internal/database/mock_data.go | 4 +- internal/database/models/group.go | 4 + internal/database/repos/group_repo.go | 49 +- internal/gql/generated.go | 470 +++++++++++++++++- internal/gql/resolvers/group.resolvers.go | 47 +- internal/gql/resolvers/helpers.go | 9 + .../gql/resolvers/makerspace.resolvers.go | 27 +- .../gql/resolvers/makerspace_resolver_test.go | 76 +++ internal/gql/schema/group.graphqls | 13 +- 9 files changed, 658 insertions(+), 41 deletions(-) create mode 100644 internal/gql/resolvers/helpers.go diff --git a/internal/database/mock_data.go b/internal/database/mock_data.go index a83971ff..492b858e 100644 --- a/internal/database/mock_data.go +++ b/internal/database/mock_data.go @@ -55,12 +55,12 @@ func makeTestMakerspace(ctx context.Context, l *slog.Logger, store *Store) bool return false } localContext.Parlophone = *m - err = store.Groups.AddGroupToAnonymousGroup(ctx, localContext.Parlophone.StaffAgroupId, localContext.BeatlesMusicians.Id) + err = store.Groups.SetGroupsForAnonymousGroup(ctx, localContext.Parlophone.StaffAgroupId, []int{localContext.BeatlesMusicians.Id}) if err != nil { l.Error("Failed to add beatles as staff of parlophone", "err", err) return false } - err = store.Groups.AddGroupToAnonymousGroup(ctx, localContext.Parlophone.ManagementAgroupId, localContext.BeatlesManagers.Id) + err = store.Groups.SetGroupsForAnonymousGroup(ctx, localContext.Parlophone.ManagementAgroupId, []int{localContext.BeatlesManagers.Id}) if err != nil { l.Error("Failed to add beatles as staff of parlophone", "err", err) return false diff --git a/internal/database/models/group.go b/internal/database/models/group.go index 51cc1f5c..28180f64 100644 --- a/internal/database/models/group.go +++ b/internal/database/models/group.go @@ -32,6 +32,10 @@ type Group struct { Description string } +type AnonymousGroup struct { + Id int +} + // Stores a users membership in a group // membership is either direct: A user is manually added to a group with a certain view permission or // indirect: the user is a direct of a subgroup of the super group with view permissions defined at the subgroup relation diff --git a/internal/database/repos/group_repo.go b/internal/database/repos/group_repo.go index 38228b36..91f74074 100644 --- a/internal/database/repos/group_repo.go +++ b/internal/database/repos/group_repo.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "make-backend/internal/database/models" + "strings" ) type GroupRepository interface { @@ -51,9 +52,9 @@ type GroupRepository interface { IsUserInAnonymousGroup(ctx context.Context, anonymousGroupId int, userId int) (bool, error) UsersInAnonymousGroup(ctx context.Context, anonymousGroupId int) ([]models.User, error) - AddGroupToAnonymousGroup(ctx context.Context, anonymousGroupId int, groupId int) error - GroupsInAnonymousGroup(ctx context.Context, anonymousGroupId int) ([]int, error) - RemoveGroupFromAnonymousGroup(ctx context.Context, anonymousGroupId int, groupId int) error + + GroupsInAnonymousGroup(ctx context.Context, anonymousGroupId int) ([]models.Group, error) + SetGroupsForAnonymousGroup(ctx context.Context, anonymousGroupId int, groupIds []int) error } type GroupRepo struct { @@ -104,31 +105,49 @@ func (g *GroupRepo) UsersInAnonymousGroup(ctx context.Context, anonymousGroupId } -func (g *GroupRepo) AddGroupToAnonymousGroup(ctx context.Context, anonymousGroupId int, groupId int) error { - query := `INSERT INTO anonymous_group_subgroups (anonymous_id, group_id) VALUES ($1, $2) ON CONFLICT DO NOTHING` - _, err := g.DB.ExecContext(ctx, query, anonymousGroupId, groupId) +func (g *GroupRepo) SetGroupsForAnonymousGroup(ctx context.Context, anonymousGroupId int, groupIds []int) error { + tx, err := g.DB.BeginTx(ctx, nil) + if err != nil { + return err + } + defer tx.Rollback() + _, err = tx.ExecContext(ctx, "delete from anonymous_group_subgroups where anonymous_id = $1", anonymousGroupId) + if err != nil { + return fmt.Errorf("failed to delete old subgroups before adding new subgroups for set: %w", err) + } + + counter := 1 + valueSpots := []string{} + values := []any{} + for _, sg := range groupIds { + valueSpots = append(valueSpots, fmt.Sprintf("($%d, $%d)", counter, counter+1)) + values = append(values, anonymousGroupId, sg) + counter += 2 + } + + query := `INSERT INTO anonymous_group_subgroups (anonymous_id, group_id) VALUES ` + strings.Join(valueSpots, ", ") + _, err = tx.ExecContext(ctx, query, values...) if err != nil { return fmt.Errorf("failed to add group to anonymous group: %w", err) } - return nil + return tx.Commit() } -// GroupsInAnonymousGroup implements [GroupRepository]. -func (g *GroupRepo) GroupsInAnonymousGroup(ctx context.Context, anonymousGroupId int) ([]int, error) { - query := `SELECT group_id FROM anonymous_group_subgroups WHERE anonymous_id = $1` +func (g *GroupRepo) GroupsInAnonymousGroup(ctx context.Context, anonymousGroupId int) ([]models.Group, error) { + query := `SELECT group_id, g.name, g.description, g.manager_id FROM anonymous_group_subgroups left join groups g on g.id = group_id WHERE anonymous_id = $1` rows, err := g.DB.QueryContext(ctx, query, anonymousGroupId) if err != nil { return nil, fmt.Errorf("failed to query groups in anonymous group: %w", err) } defer rows.Close() - var groupIds []int + var groupIds []models.Group for rows.Next() { - var id int - if err := rows.Scan(&id); err != nil { - return nil, fmt.Errorf("failed to scan group id in anonymous group: %w", err) + var g models.Group + if err := rows.Scan(&g.Id, &g.Name, &g.Description, &g.ManagerId); err != nil { + return nil, fmt.Errorf("failed to scan group in anonymous group: %w", err) } - groupIds = append(groupIds, id) + groupIds = append(groupIds, g) } if err := rows.Err(); err != nil { return nil, err diff --git a/internal/gql/generated.go b/internal/gql/generated.go index dec1040c..9f301023 100644 --- a/internal/gql/generated.go +++ b/internal/gql/generated.go @@ -32,6 +32,7 @@ type Config = graphql.Config[ResolverRoot, DirectiveRoot, ComplexityRoot] type ResolverRoot interface { AccessComponent() AccessComponentResolver + AnonymousGroup() AnonymousGroupResolver Group() GroupResolver Makerspace() MakerspaceResolver MembershipToGroup() MembershipToGroupResolver @@ -98,6 +99,12 @@ type ComplexityRoot struct { Title func(childComplexity int) int } + AnonymousGroup struct { + Id func(childComplexity int) int + Members func(childComplexity int) int + Subgroups func(childComplexity int) int + } + CustomLink struct { LongUrl func(childComplexity int) int ShortUrl func(childComplexity int) int @@ -210,8 +217,9 @@ type ComplexityRoot struct { } Mutation struct { - CreateMakerspace func(childComplexity int, name string, hidden bool) int - DeleteMakerspace func(childComplexity int, id int) int + CreateMakerspace func(childComplexity int, name string, hidden bool) int + DeleteMakerspace func(childComplexity int, id int) int + SetAnonymousGroupSubgroups func(childComplexity int, agroupID int, subgroups []int) int } OptionBlock struct { @@ -237,6 +245,7 @@ type ComplexityRoot struct { Query struct { AccessDevice func(childComplexity int, id int) int + AnonymousGroup func(childComplexity int, id int) int CanGroupManageGroup func(childComplexity int, managerID int, groupID int) int CanUserManageGroup func(childComplexity int, managerID int, groupID int) int CurrentUser func(childComplexity int) int @@ -337,6 +346,10 @@ type ComplexityRoot struct { type AccessComponentResolver interface { Type(ctx context.Context, obj *models.AccessComponent) (int, error) } +type AnonymousGroupResolver interface { + Members(ctx context.Context, obj *models.AnonymousGroup) ([]*models.User, error) + Subgroups(ctx context.Context, obj *models.AnonymousGroup) ([]*models.Group, error) +} type GroupResolver interface { DirectMembers(ctx context.Context, obj *models.Group) ([]*models.MembershipToGroup, error) Members(ctx context.Context, obj *models.Group) ([]*models.MembershipToGroup, error) @@ -357,6 +370,7 @@ type MembershipToGroupResolver interface { type MutationResolver interface { CreateMakerspace(ctx context.Context, name string, hidden bool) (int, error) DeleteMakerspace(ctx context.Context, id int) (bool, error) + SetAnonymousGroupSubgroups(ctx context.Context, agroupID int, subgroups []int) (bool, error) } type OptionBlockOptionResolver interface { Correct(ctx context.Context, obj *models.OptionBlockOption) (*bool, error) @@ -366,6 +380,7 @@ type QueryResolver interface { Device(ctx context.Context, id int) (*models.Device, error) AccessDevice(ctx context.Context, id int) (*models.AccessDevice, error) Group(ctx context.Context, id int) (*models.Group, error) + AnonymousGroup(ctx context.Context, id int) (*models.AnonymousGroup, error) IsUserInGroup(ctx context.Context, userID int, groupID int) (bool, error) IsUserInGroupDirectly(ctx context.Context, userID int, groupID int) (bool, error) CanGroupManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) @@ -559,6 +574,25 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.ComplexityRoot.Announcement.Title(childComplexity), true + case "AnonymousGroup.id": + if e.ComplexityRoot.AnonymousGroup.Id == nil { + break + } + + return e.ComplexityRoot.AnonymousGroup.Id(childComplexity), true + case "AnonymousGroup.members": + if e.ComplexityRoot.AnonymousGroup.Members == nil { + break + } + + return e.ComplexityRoot.AnonymousGroup.Members(childComplexity), true + case "AnonymousGroup.subgroups": + if e.ComplexityRoot.AnonymousGroup.Subgroups == nil { + break + } + + return e.ComplexityRoot.AnonymousGroup.Subgroups(childComplexity), true + case "CustomLink.long_url": if e.ComplexityRoot.CustomLink.LongUrl == nil { break @@ -1043,6 +1077,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Mutation.DeleteMakerspace(childComplexity, args["id"].(int)), true + case "Mutation.SetAnonymousGroupSubgroups": + if e.ComplexityRoot.Mutation.SetAnonymousGroupSubgroups == nil { + break + } + + args, err := ec.field_Mutation_SetAnonymousGroupSubgroups_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Mutation.SetAnonymousGroupSubgroups(childComplexity, args["agroupID"].(int), args["subgroups"].([]int)), true case "OptionBlock.affirmation": if e.ComplexityRoot.OptionBlock.Affirmation == nil { @@ -1130,6 +1175,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Query.AccessDevice(childComplexity, args["id"].(int)), true + case "Query.anonymousGroup": + if e.ComplexityRoot.Query.AnonymousGroup == nil { + break + } + + args, err := ec.field_Query_anonymousGroup_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.AnonymousGroup(childComplexity, args["id"].(int)), true case "Query.canGroupManageGroup": if e.ComplexityRoot.Query.CanGroupManageGroup == nil { break @@ -1744,6 +1800,18 @@ func (ec *executionContext) childFields_AccessDeviceFlags(ctx context.Context, f return nil, fmt.Errorf("no field named %q was found under type AccessDeviceFlags", field.Name) } +func (ec *executionContext) childFields_AnonymousGroup(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_AnonymousGroup_id(ctx, field) + case "members": + return ec.fieldContext_AnonymousGroup_members(ctx, field) + case "subgroups": + return ec.fieldContext_AnonymousGroup_subgroups(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type AnonymousGroup", field.Name) +} + func (ec *executionContext) childFields_Device(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { case "id": @@ -2006,6 +2074,28 @@ func (ec *executionContext) childFields___Type(ctx context.Context, field graphq // region ***************************** args.gotpl ***************************** +func (ec *executionContext) field_Mutation_SetAnonymousGroupSubgroups_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, "agroupID", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["agroupID"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "subgroups", + func(ctx context.Context, v any) ([]int, error) { + return ec.unmarshalNInt2ᚕintᚄ(ctx, v) + }) + if err != nil { + return nil, err + } + args["subgroups"] = arg1 + return args, nil +} + func (ec *executionContext) field_Mutation_createMakerspace_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -2070,6 +2160,20 @@ func (ec *executionContext) field_Query_accessDevice_args(ctx context.Context, r return args, nil } +func (ec *executionContext) field_Query_anonymousGroup_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, "id", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["id"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_canGroupManageGroup_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -2954,6 +3058,93 @@ func (ec *executionContext) fieldContext_Announcement_makerspace_id(_ context.Co return graphql.NewScalarFieldContext("Announcement", field, false, false, errors.New("field of type ID does not have child fields")) } +func (ec *executionContext) _AnonymousGroup_id(ctx context.Context, field graphql.CollectedField, obj *models.AnonymousGroup) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AnonymousGroup_id(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Id, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int) graphql.Marshaler { + return ec.marshalNID2int(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AnonymousGroup_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AnonymousGroup", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _AnonymousGroup_members(ctx context.Context, field graphql.CollectedField, obj *models.AnonymousGroup) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AnonymousGroup_members(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.AnonymousGroup().Members(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []*models.User) graphql.Marshaler { + return ec.marshalNUser2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐUserᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AnonymousGroup_members(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "AnonymousGroup", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_User(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _AnonymousGroup_subgroups(ctx context.Context, field graphql.CollectedField, obj *models.AnonymousGroup) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AnonymousGroup_subgroups(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.AnonymousGroup().Subgroups(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []*models.Group) graphql.Marshaler { + return ec.marshalNGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AnonymousGroup_subgroups(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "AnonymousGroup", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Group(ctx, field) + }, + } + return fc, nil +} + func (ec *executionContext) _CustomLink_short_url(ctx context.Context, field graphql.CollectedField, obj *models.CustomLink) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -4870,6 +5061,50 @@ func (ec *executionContext) fieldContext_Mutation_deleteMakerspace(ctx context.C return fc, nil } +func (ec *executionContext) _Mutation_SetAnonymousGroupSubgroups(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Mutation_SetAnonymousGroupSubgroups(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Mutation().SetAnonymousGroupSubgroups(ctx, fc.Args["agroupID"].(int), fc.Args["subgroups"].([]int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Mutation_SetAnonymousGroupSubgroups(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_SetAnonymousGroupSubgroups_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _OptionBlock_block_id(ctx context.Context, field graphql.CollectedField, obj *models.OptionBlock) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -5331,6 +5566,50 @@ func (ec *executionContext) fieldContext_Query_group(ctx context.Context, field return fc, nil } +func (ec *executionContext) _Query_anonymousGroup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_anonymousGroup(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().AnonymousGroup(ctx, fc.Args["id"].(int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *models.AnonymousGroup) graphql.Marshaler { + return ec.marshalNAnonymousGroup2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐAnonymousGroup(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_anonymousGroup(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_AnonymousGroup(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_anonymousGroup_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query_isUserInGroup(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -8444,6 +8723,120 @@ func (ec *executionContext) _Announcement(ctx context.Context, sel ast.Selection return out } +var anonymousGroupImplementors = []string{"AnonymousGroup"} + +func (ec *executionContext) _AnonymousGroup(ctx context.Context, sel ast.SelectionSet, obj *models.AnonymousGroup) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, anonymousGroupImplementors) + + out := graphql.NewFieldSet(fields) + deferredFieldSet := graphql.NewFieldSet(nil) + deferLabelToView := make(map[string]*graphql.FieldSetView) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("AnonymousGroup") + case "id": + out.Values[i] = ec._AnonymousGroup_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "members": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._AnonymousGroup_members(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.IsDeferred() { + deferredFieldSet.AddField(field) + fieldIndex := len(deferredFieldSet.Values) - 1 + deferredFieldSet.Concurrently(fieldIndex, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, deferredFieldSet) + }) + + for _, deferrable := range field.Deferrables { + view, ok := deferLabelToView[deferrable.Label] + if !ok { + view = deferredFieldSet.NewView() + deferLabelToView[deferrable.Label] = view + } + view.AddIndices(fieldIndex) + } + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "subgroups": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._AnonymousGroup_subgroups(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.IsDeferred() { + deferredFieldSet.AddField(field) + fieldIndex := len(deferredFieldSet.Values) - 1 + deferredFieldSet.Concurrently(fieldIndex, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, deferredFieldSet) + }) + + for _, deferrable := range field.Deferrables { + view, ok := deferLabelToView[deferrable.Label] + if !ok { + view = deferredFieldSet.NewView() + deferLabelToView[deferrable.Label] = view + } + view.AddIndices(fieldIndex) + } + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferLabelToView), math.MaxInt32))) + + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Defers: deferLabelToView, + Path: graphql.GetPath(ctx), + FieldSet: deferredFieldSet, + Context: ctx, + }) + + return out +} + var customLinkImplementors = []string{"CustomLink"} func (ec *executionContext) _CustomLink(ctx context.Context, sel ast.SelectionSet, obj *models.CustomLink) graphql.Marshaler { @@ -9612,6 +10005,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } + case "SetAnonymousGroupSubgroups": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_SetAnonymousGroupSubgroups(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -9932,6 +10332,28 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "anonymousGroup": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_anonymousGroup(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "isUserInGroup": field := field @@ -11150,6 +11572,20 @@ func (ec *executionContext) marshalNAccessDeviceFlags2makeᚑbackendᚋinternal return ec._AccessDeviceFlags(ctx, sel, &v) } +func (ec *executionContext) marshalNAnonymousGroup2makeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐAnonymousGroup(ctx context.Context, sel ast.SelectionSet, v models.AnonymousGroup) graphql.Marshaler { + return ec._AnonymousGroup(ctx, sel, &v) +} + +func (ec *executionContext) marshalNAnonymousGroup2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐAnonymousGroup(ctx context.Context, sel ast.SelectionSet, v *models.AnonymousGroup) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._AnonymousGroup(ctx, sel, v) +} + func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v any) (bool, error) { res, err := graphql.UnmarshalBoolean(v) return res, graphql.ErrorOnPath(ctx, err) @@ -11258,6 +11694,36 @@ func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.Selecti return res } +func (ec *executionContext) unmarshalNInt2ᚕintᚄ(ctx context.Context, v any) ([]int, error) { + var vSlice []any + vSlice = graphql.CoerceList(v) + var err error + res := make([]int, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNInt2int(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalNInt2ᚕintᚄ(ctx context.Context, sel ast.SelectionSet, v []int) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNInt2int(ctx, sel, v[i]) + } + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) marshalNMakerspaceHours2makeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐMakerspaceHours(ctx context.Context, sel ast.SelectionSet, v models.MakerspaceHours) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index 5ea87966..2ea0829b 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -13,6 +13,25 @@ import ( "make-backend/internal/gql" ) +// Members is the resolver for the members field. +func (r *anonymousGroupResolver) Members(ctx context.Context, obj *models.AnonymousGroup) ([]*models.User, error) { + members, err := r.Store.Groups.UsersInAnonymousGroup(ctx, obj.Id) + if err != nil { + + return nil, err + } + return SliceToPtrSlice(members), nil +} + +// Subgroups is the resolver for the subgroups field. +func (r *anonymousGroupResolver) Subgroups(ctx context.Context, obj *models.AnonymousGroup) ([]*models.Group, error) { + subgroups, err := r.Store.Groups.GroupsInAnonymousGroup(ctx, obj.Id) + if err != nil { + return nil, err + } + return SliceToPtrSlice(subgroups), nil +} + // DirectMembers is the resolver for the directMembers field. func (r *groupResolver) DirectMembers(ctx context.Context, obj *models.Group) ([]*models.MembershipToGroup, error) { panic(fmt.Errorf("not implemented: DirectMembers - directMembers")) @@ -27,7 +46,6 @@ func (r *groupResolver) Members(ctx context.Context, obj *models.Group) ([]*mode visible, how, err := r.Store.Groups.IsUserInGroup(ctx, *userId, obj.Id) if err != nil { - return nil, err } visibleByManager, err := r.Store.Groups.CanUserManageGroup(ctx, *userId, obj.Id) @@ -56,11 +74,7 @@ func (r *groupResolver) Members(ctx context.Context, obj *models.Group) ([]*mode if err != nil { return nil, err } - members2 := make([]*models.MembershipToGroup, 0, len(members)) - for _, m := range members { - members2 = append(members2, &m) - } - return members2, nil + return SliceToPtrSlice(members), nil } // DirectManagedGroups is the resolver for the directManagedGroups field. @@ -92,6 +106,15 @@ func (r *membershipToGroupResolver) User(ctx context.Context, obj *models.Member return r.Store.Users.GetUserById(ctx, obj.UserId) } +// SetAnonymousGroupSubgroups is the resolver for the SetAnonymousGroupSubgroups field. +func (r *mutationResolver) SetAnonymousGroupSubgroups(ctx context.Context, agroupID int, subgroups []int) (bool, error) { + err := r.Store.Groups.SetGroupsForAnonymousGroup(ctx, agroupID, subgroups) + if err != nil { + return false, err + } + return true, nil +} + // Group is the resolver for the group field. func (r *queryResolver) Group(ctx context.Context, id int) (*models.Group, error) { userId := auth.UserIDFromContext(ctx) @@ -114,6 +137,14 @@ func (r *queryResolver) Group(ctx context.Context, id int) (*models.Group, error return group, nil } +// AnonymousGroup is the resolver for the anonymousGroup field. +func (r *queryResolver) AnonymousGroup(ctx context.Context, id int) (*models.AnonymousGroup, error) { + ag := models.AnonymousGroup{ + Id: id, + } + return &ag, nil +} + // IsUserInGroup is the resolver for the isUserInGroup field. func (r *queryResolver) IsUserInGroup(ctx context.Context, userID int, groupID int) (bool, error) { askingUserID := auth.UserIDFromContext(ctx) @@ -202,6 +233,9 @@ func (r *queryResolver) CanUserManageGroup(ctx context.Context, managerID int, g return r.Store.Groups.CanUserManageGroup(ctx, managerID, groupID) } +// AnonymousGroup returns gql.AnonymousGroupResolver implementation. +func (r *Resolver) AnonymousGroup() gql.AnonymousGroupResolver { return &anonymousGroupResolver{r} } + // Group returns gql.GroupResolver implementation. func (r *Resolver) Group() gql.GroupResolver { return &groupResolver{r} } @@ -211,6 +245,7 @@ func (r *Resolver) MembershipToGroup() gql.MembershipToGroupResolver { } type ( + anonymousGroupResolver struct{ *Resolver } groupResolver struct{ *Resolver } membershipToGroupResolver struct{ *Resolver } ) diff --git a/internal/gql/resolvers/helpers.go b/internal/gql/resolvers/helpers.go new file mode 100644 index 00000000..73af804e --- /dev/null +++ b/internal/gql/resolvers/helpers.go @@ -0,0 +1,9 @@ +package resolvers + +func SliceToPtrSlice[E any](s []E) []*E { + pointers := make([]*E, 0, len(s)) + for i := range s { + pointers = append(pointers, &s[i]) + } + return pointers +} diff --git a/internal/gql/resolvers/makerspace.resolvers.go b/internal/gql/resolvers/makerspace.resolvers.go index 94f0a599..9ff4cf8e 100644 --- a/internal/gql/resolvers/makerspace.resolvers.go +++ b/internal/gql/resolvers/makerspace.resolvers.go @@ -7,7 +7,6 @@ package resolvers import ( "context" - "fmt" "make-backend/internal/database/models" "make-backend/internal/gql" ) @@ -43,17 +42,17 @@ func (r *makerspaceResolver) Managers(ctx context.Context, obj *models.Makerspac if err != nil { return nil, err } - users := []*models.User{} - for _, u := range us { - users = append(users, &u) - } - return users, nil + + return SliceToPtrSlice(us), nil } // ManagerSubgroups is the resolver for the managerSubgroups field. func (r *makerspaceResolver) ManagerSubgroups(ctx context.Context, obj *models.Makerspace) ([]*models.Group, error) { - panic(fmt.Errorf("not implemented: ManagerSubgroups - managerSubgroups")) - + sgs, err := r.Store.Groups.GroupsInAnonymousGroup(ctx, obj.ManagementAgroupId) + if err != nil { + return nil, err + } + return SliceToPtrSlice(sgs), nil } // Staff is the resolver for the staff field. @@ -62,16 +61,16 @@ func (r *makerspaceResolver) Staff(ctx context.Context, obj *models.Makerspace) if err != nil { return nil, err } - users := []*models.User{} - for _, u := range us { - users = append(users, &u) - } - return users, nil + return SliceToPtrSlice(us), nil } // StaffSubgroups is the resolver for the staffSubgroups field. func (r *makerspaceResolver) StaffSubgroups(ctx context.Context, obj *models.Makerspace) ([]*models.Group, error) { - panic(fmt.Errorf("not implemented: StaffSubgroups - staffSubgroups")) + sgs, err := r.Store.Groups.GroupsInAnonymousGroup(ctx, obj.StaffAgroupId) + if err != nil { + return nil, err + } + return SliceToPtrSlice(sgs), nil } // CreateMakerspace is the resolver for the createMakerspace field. diff --git a/internal/gql/resolvers/makerspace_resolver_test.go b/internal/gql/resolvers/makerspace_resolver_test.go index 369461e7..3d09421f 100644 --- a/internal/gql/resolvers/makerspace_resolver_test.go +++ b/internal/gql/resolvers/makerspace_resolver_test.go @@ -35,3 +35,79 @@ func TestMakerspaceManagers(t *testing.T) { t.Fatalf("manager group for makerspace not equal. Wanted %v but got %v", wantedManagers, mIds) } } + +func TestMakerspaceStaffSubgroups(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + wantedSG := []int{data.BeatlesMusicians.Id} + gotSGs, err := resolver.Makerspace().StaffSubgroups(context.TODO(), &data.Parlophone) + if err != nil { + t.Fatalf("failed to get staff subgroups of makerspace %v", err) + } + SGIds := []int{} + for _, user := range gotSGs { + SGIds = append(SGIds, user.Id) + } + if !areGroupsEqual(wantedSG, SGIds) { + t.Fatalf("staff subgroups for makerspace not equal. Wanted %v but got %v", wantedSG, SGIds) + } +} + +func TestMakerspaceManagerSubgroups(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + wantedSG := []int{data.BeatlesManagers.Id} + gotSGs, err := resolver.Makerspace().ManagerSubgroups(context.TODO(), &data.Parlophone) + if err != nil { + t.Fatalf("failed to get manager subgroups of makerspace %v", err) + } + SGIds := []int{} + for _, user := range gotSGs { + SGIds = append(SGIds, user.Id) + } + if !areGroupsEqual(wantedSG, SGIds) { + t.Fatalf("manager subgroups for makerspace not equal. Wanted %v but got %v", wantedSG, SGIds) + } +} + +func TestAddAndRemoveFromStaffAgroup(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + groupAlreadyThere := data.BeatlesMusicians.Id + groupToAdd := data.ExMusicians.Id + midWantedSG := []int{groupAlreadyThere, groupToAdd} + endWantedSG := []int{groupAlreadyThere} + + good, err := resolver.Mutation().SetAnonymousGroupSubgroups(t.Context(), data.Parlophone.StaffAgroupId, midWantedSG) + if !good || err != nil { + t.Fatalf("failed to set agroup subgroups to %v: good: %v, err: %v", midWantedSG, good, err) + } + + // add new group + gotSGsMid, err := resolver.Makerspace().StaffSubgroups(t.Context(), &data.Parlophone) + if err != nil { + t.Fatalf("failed to get manager subgroups of makerspace after addition %v", err) + } + midSGIds := []int{} + for _, user := range gotSGsMid { + midSGIds = append(midSGIds, user.Id) + } + if !areGroupsEqual(midWantedSG, midSGIds) { + t.Fatalf("failed to add subgroup to agroup. Wanted %v but got %v", midWantedSG, midSGIds) + } + + // remove new group + good, err = resolver.Mutation().SetAnonymousGroupSubgroups(t.Context(), data.Parlophone.StaffAgroupId, endWantedSG) + if !good || err != nil { + t.Fatalf("failed to set agroup subgroups to %v: good: %v, err: %v", endWantedSG, good, err) + } + + gotSGsEnd, err := resolver.Makerspace().StaffSubgroups(t.Context(), &data.Parlophone) + if err != nil { + t.Fatalf("failed to get manager subgroups of makerspace after removal %v", err) + } + endSGIds := []int{} + for _, user := range gotSGsEnd { + endSGIds = append(endSGIds, user.Id) + } + if !areGroupsEqual(endWantedSG, endSGIds) { + t.Fatalf("failed to remove subgroup from agroup. Wanted %v but got %v", endWantedSG, endSGIds) + } +} diff --git a/internal/gql/schema/group.graphqls b/internal/gql/schema/group.graphqls index 9adf4156..f738502a 100644 --- a/internal/gql/schema/group.graphqls +++ b/internal/gql/schema/group.graphqls @@ -29,15 +29,24 @@ type Group { directSubGroups: [Group!]! } - +type AnonymousGroup{ + id: ID! + members: [User!]! + subgroups: [Group!]! +} extend type Query { group(id: ID!): Group! - + anonymousGroup(id: ID!): AnonymousGroup! + isUserInGroup(userID: ID!, groupID: ID!): Boolean! isUserInGroupDirectly(userID: ID!, groupID: ID!): Boolean! canGroupManageGroup(managerID: ID!, groupID: ID!): Boolean! canUserManageGroup(managerID: ID!, groupID: ID!): Boolean! +} + +extend type Mutation { + SetAnonymousGroupSubgroups(agroupID: ID!, subgroups: [Int!]!): Boolean! } \ No newline at end of file From 30d979731a1cd0d217dfb20ea4079fdc8eab1fc5 Mon Sep 17 00:00:00 2001 From: cowsed Date: Wed, 19 Aug 2026 13:53:23 -0400 Subject: [PATCH 17/22] more testing of agroups and their queries and mutations as well as checking permissions --- internal/database/group_test.go | 59 +++++++++++++++++++ .../20260703201718_initial_schema.sql | 39 +++++++++--- internal/database/mock_data.go | 2 +- internal/database/repos/group_repo.go | 28 +++++++++ internal/gql/resolvers/group.resolvers.go | 33 ++++++++++- .../gql/resolvers/makerspace_resolver_test.go | 23 ++++++-- 6 files changed, 169 insertions(+), 15 deletions(-) diff --git a/internal/database/group_test.go b/internal/database/group_test.go index 4aa46ef2..c504e66a 100644 --- a/internal/database/group_test.go +++ b/internal/database/group_test.go @@ -103,3 +103,62 @@ func TestSubgroupMembership(t *testing.T) { } } } + +func TestCanGroupManageAnonymousGroup(t *testing.T) { + if testing.Short() { + t.Skip("Skipping db test in short mode.") + } + _, store, data := VerifyTestDb(slog.Default()) + rootGroupId, err := store.Groups.GetAdminGroupId(t.Context()) + if err != nil { + t.Fatalf("couldn't get root group ID to continue test") + } + tests := []struct { + testName string + // params + managerGroupId int + anonymousGroupId int + want bool + wantErr bool + }{ + { + "beatles managers manage parlophone so can manage staff of parlophone", + data.BeatlesManagers.Id, + data.Parlophone.StaffAgroupId, + true, + false, + }, + { + "beatles musicians DONT manage parlophone so CANT manage staff of parlophone", + data.BeatlesMusicians.Id, + data.Parlophone.StaffAgroupId, + false, + false, + }, + { + "root group can manage any agroup so can manage staff of parlophone", + rootGroupId, + data.Parlophone.StaffAgroupId, + true, + false, + }, + } + for _, tt := range tests { + t.Run(tt.testName, func(t *testing.T) { + got, gotErr := store.Groups.CanGroupManageAnonymousGroup(t.Context(), tt.managerGroupId, tt.anonymousGroupId) + if gotErr != nil { + if !tt.wantErr { + t.Errorf("CanGroupManageAnonymousGroup() failed: %v", gotErr) + } + return + } + if tt.wantErr { + t.Fatal("CanGroupManageAnonymousGroup() succeeded unexpectedly") + } + // TODO: update the condition below to compare got with tt.want. + if got != tt.want { + t.Errorf("CanGroupManageAnonymousGroup() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/database/migrations/20260703201718_initial_schema.sql b/internal/database/migrations/20260703201718_initial_schema.sql index e0591696..070b88e9 100644 --- a/internal/database/migrations/20260703201718_initial_schema.sql +++ b/internal/database/migrations/20260703201718_initial_schema.sql @@ -176,8 +176,6 @@ create view anonymous_group_membership as ( ); - - CREATE TABLE makerspaces ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, @@ -194,6 +192,32 @@ CREATE TABLE makerspaces ( staff_agroup_id INT NOT NULL REFERENCES anonymous_groups(id) ON DELETE CASCADE ); +create view anonymous_group_management_by_group as ( + ( + -- groups in management agroup can manage staff agroup for makerspace + select ags.group_id as manager_group_id, m.staff_agroup_id as managed_agroup_id + from makerspaces m + left join anonymous_group_subgroups ags on m.management_agroup_id = ags.anonymous_id + ) union ( + -- root group can manage any agroup id + select g.id as manager_group_id, ag.id as managed_agroup_id + from anonymous_groups ag + left join groups g on TRUE + -- only group with no manager is root group + where g.manager_id is null + ) + -- NOTE: add other rules about which groups can manage agroups here and union them in +); + + +create view anonymous_group_management_by_user as ( + select gm.user_id as manager_user_id, agm.managed_agroup_id as managed_agroup_id + from anonymous_group_management_by_group agm + left join group_membership gm on gm.group_id = agm.manager_group_id + +); + + CREATE TABLE restrictions ( id SERIAL PRIMARY KEY, makerspace_id INT NOT NULL REFERENCES makerspaces(id) ON DELETE CASCADE, @@ -397,11 +421,12 @@ DROP TABLE IF EXISTS groups; DROP TABLE IF EXISTS group_direct_membership; DROP TABLE IF EXISTS group_direct_subgroups; -DROP VIEW IF EXISTS group_noncombination_management -DROP VIEW IF EXISTS group_subgroups -DROP VIEW IF EXISTS group_management -DROP VIEW IF EXISTS group_membership -DROP VIEW IF EXISTS anonymous_group_membership +DROP VIEW IF EXISTS group_noncombination_management; +DROP VIEW IF EXISTS group_subgroups; +DROP VIEW IF EXISTS group_management; +DROP VIEW IF EXISTS group_membership; +DROP VIEW IF EXISTS anonymous_group_membership; +DROP VIEW IF EXISTS anonymous_group_management_by_group; DROP TABLE IF EXISTS anonymous_groups; diff --git a/internal/database/mock_data.go b/internal/database/mock_data.go index 492b858e..89a517a4 100644 --- a/internal/database/mock_data.go +++ b/internal/database/mock_data.go @@ -62,7 +62,7 @@ func makeTestMakerspace(ctx context.Context, l *slog.Logger, store *Store) bool } err = store.Groups.SetGroupsForAnonymousGroup(ctx, localContext.Parlophone.ManagementAgroupId, []int{localContext.BeatlesManagers.Id}) if err != nil { - l.Error("Failed to add beatles as staff of parlophone", "err", err) + l.Error("Failed to add beatles managers as staff of parlophone", "err", err) return false } diff --git a/internal/database/repos/group_repo.go b/internal/database/repos/group_repo.go index 91f74074..451ca98a 100644 --- a/internal/database/repos/group_repo.go +++ b/internal/database/repos/group_repo.go @@ -55,12 +55,40 @@ type GroupRepository interface { GroupsInAnonymousGroup(ctx context.Context, anonymousGroupId int) ([]models.Group, error) SetGroupsForAnonymousGroup(ctx context.Context, anonymousGroupId int, groupIds []int) error + CanGroupManageAnonymousGroup(ctx context.Context, managerGroupId, anonymousGroupId int) (bool, error) + CanUserManageAnonymousGroup(ctx context.Context, managerUserId, anonymousGroupId int) (bool, error) } type GroupRepo struct { DB *sql.DB } +func (g *GroupRepo) CanGroupManageAnonymousGroup(ctx context.Context, managerGroupId, anonymousGroupId int) (bool, error) { + // NOTE don't edit this function to add other rules, instead add rules to the anonymous_group_management_by_group view + var canManage bool + query := "SELECT EXISTS(SELECT 1 FROM anonymous_group_management_by_group WHERE manager_group_id = $1 and managed_agroup_id = $2)" + err := g.DB.QueryRow(query, managerGroupId, anonymousGroupId).Scan(&canManage) + + if err != nil { + return false, err + } + return canManage, nil + +} + +func (g *GroupRepo) CanUserManageAnonymousGroup(ctx context.Context, managerUserId, anonymousGroupId int) (bool, error) { + // NOTE don't edit this function to add other rules, instead add rules to the anonymous_group_management_by_group view + var canManage bool + query := "SELECT EXISTS(SELECT 1 FROM anonymous_group_management_by_user WHERE manager_user_id = $1 and managed_agroup_id = $2)" + err := g.DB.QueryRow(query, managerUserId, anonymousGroupId).Scan(&canManage) + + if err != nil { + return false, err + } + return canManage, nil + +} + func (g *GroupRepo) UsersInAnonymousGroup(ctx context.Context, anonymousGroupId int) ([]models.User, error) { query := ` select diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index 2ea0829b..766b1bf5 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -7,6 +7,7 @@ package resolvers import ( "context" + "errors" "fmt" "make-backend/internal/auth" "make-backend/internal/database/models" @@ -55,7 +56,7 @@ func (r *groupResolver) Members(ctx context.Context, obj *models.Group) ([]*mode visible = visible || visibleByManager if !visible { - return nil, fmt.Errorf("group does not exist or user does not have permission to see it") + return nil, models.ErrNoGroupOrWrongPermissions } if how == models.GroupViewPermission_SeeSelf && !visibleByManager { m := models.MembershipToGroup{ @@ -103,12 +104,26 @@ func (r *groupResolver) DirectSubGroups(ctx context.Context, obj *models.Group) // User is the resolver for the User field. func (r *membershipToGroupResolver) User(ctx context.Context, obj *models.MembershipToGroup) (*models.User, error) { + // TODO figure out what permissions for this are and check them return r.Store.Users.GetUserById(ctx, obj.UserId) } // SetAnonymousGroupSubgroups is the resolver for the SetAnonymousGroupSubgroups field. func (r *mutationResolver) SetAnonymousGroupSubgroups(ctx context.Context, agroupID int, subgroups []int) (bool, error) { - err := r.Store.Groups.SetGroupsForAnonymousGroup(ctx, agroupID, subgroups) + userId := auth.UserIDFromContext(ctx) + if userId == nil { + return false, auth.ErrNotAuthenticated + } + + canManage, err := r.Store.Groups.CanUserManageAnonymousGroup(ctx, *userId, agroupID) + if err != nil { + return false, err + } + if !canManage { + return false, errors.New("anonymous group does not exist or user does not have the permissions to edit it") + } + + err = r.Store.Groups.SetGroupsForAnonymousGroup(ctx, agroupID, subgroups) if err != nil { return false, err } @@ -127,7 +142,7 @@ func (r *queryResolver) Group(ctx context.Context, id int) (*models.Group, error return nil, err } if !visible { - return nil, fmt.Errorf("group does not exist or user does not have permission to see it") + return nil, models.ErrNoGroupOrWrongPermissions } group, err := r.Store.Groups.GetGroupById(ctx, id) @@ -139,6 +154,18 @@ func (r *queryResolver) Group(ctx context.Context, id int) (*models.Group, error // AnonymousGroup is the resolver for the anonymousGroup field. func (r *queryResolver) AnonymousGroup(ctx context.Context, id int) (*models.AnonymousGroup, error) { + userId := auth.UserIDFromContext(ctx) + if userId == nil { + return nil, auth.ErrNotAuthenticated + } + + canManage, err := r.Store.Groups.CanUserManageAnonymousGroup(ctx, *userId, id) + if err != nil { + return nil, err + } + if !canManage { + return nil, models.ErrNoGroupOrWrongPermissions + } ag := models.AnonymousGroup{ Id: id, } diff --git a/internal/gql/resolvers/makerspace_resolver_test.go b/internal/gql/resolvers/makerspace_resolver_test.go index 3d09421f..fe44c1a4 100644 --- a/internal/gql/resolvers/makerspace_resolver_test.go +++ b/internal/gql/resolvers/makerspace_resolver_test.go @@ -68,6 +68,19 @@ func TestMakerspaceManagerSubgroups(t *testing.T) { } } +func TestAddToStaffAgroupWithoutAuth(t *testing.T) { + _, data, resolver := helpersForResolverTest(t) + groupAlreadyThere := data.BeatlesMusicians.Id + groupToAdd := data.ExMusicians.Id + wantedSG := []int{groupAlreadyThere, groupToAdd} + + good, err := resolver.Mutation().SetAnonymousGroupSubgroups(t.Context(), data.Parlophone.StaffAgroupId, wantedSG) + if good || err == nil { + t.Fatalf("succeeded in adding subgroups to anonymous group when unauthenticated") + } + +} + func TestAddAndRemoveFromStaffAgroup(t *testing.T) { _, data, resolver := helpersForResolverTest(t) groupAlreadyThere := data.BeatlesMusicians.Id @@ -75,13 +88,15 @@ func TestAddAndRemoveFromStaffAgroup(t *testing.T) { midWantedSG := []int{groupAlreadyThere, groupToAdd} endWantedSG := []int{groupAlreadyThere} - good, err := resolver.Mutation().SetAnonymousGroupSubgroups(t.Context(), data.Parlophone.StaffAgroupId, midWantedSG) + ctx := ContextWithUser(t.Context(), data.Users[0].Id) + + good, err := resolver.Mutation().SetAnonymousGroupSubgroups(ctx, data.Parlophone.StaffAgroupId, midWantedSG) if !good || err != nil { t.Fatalf("failed to set agroup subgroups to %v: good: %v, err: %v", midWantedSG, good, err) } // add new group - gotSGsMid, err := resolver.Makerspace().StaffSubgroups(t.Context(), &data.Parlophone) + gotSGsMid, err := resolver.Makerspace().StaffSubgroups(ctx, &data.Parlophone) if err != nil { t.Fatalf("failed to get manager subgroups of makerspace after addition %v", err) } @@ -94,12 +109,12 @@ func TestAddAndRemoveFromStaffAgroup(t *testing.T) { } // remove new group - good, err = resolver.Mutation().SetAnonymousGroupSubgroups(t.Context(), data.Parlophone.StaffAgroupId, endWantedSG) + good, err = resolver.Mutation().SetAnonymousGroupSubgroups(ctx, data.Parlophone.StaffAgroupId, endWantedSG) if !good || err != nil { t.Fatalf("failed to set agroup subgroups to %v: good: %v, err: %v", endWantedSG, good, err) } - gotSGsEnd, err := resolver.Makerspace().StaffSubgroups(t.Context(), &data.Parlophone) + gotSGsEnd, err := resolver.Makerspace().StaffSubgroups(ctx, &data.Parlophone) if err != nil { t.Fatalf("failed to get manager subgroups of makerspace after removal %v", err) } From df859a8a3691e167212a607f80be37ef11f7c99c Mon Sep 17 00:00:00 2001 From: cowsed Date: Wed, 19 Aug 2026 14:33:23 -0400 Subject: [PATCH 18/22] More protections for graphql endpoints --- .../20260703201718_initial_schema.sql | 5 ++ internal/database/models/group.go | 1 + internal/gql/resolvers/group.resolvers.go | 45 ++-------------- internal/gql/resolvers/helpers.go | 51 +++++++++++++++++++ .../gql/resolvers/makerspace.resolvers.go | 6 +++ .../gql/resolvers/makerspace_resolver_test.go | 28 +++++----- 6 files changed, 84 insertions(+), 52 deletions(-) diff --git a/internal/database/migrations/20260703201718_initial_schema.sql b/internal/database/migrations/20260703201718_initial_schema.sql index 070b88e9..08dd4b5e 100644 --- a/internal/database/migrations/20260703201718_initial_schema.sql +++ b/internal/database/migrations/20260703201718_initial_schema.sql @@ -198,6 +198,11 @@ create view anonymous_group_management_by_group as ( select ags.group_id as manager_group_id, m.staff_agroup_id as managed_agroup_id from makerspaces m left join anonymous_group_subgroups ags on m.management_agroup_id = ags.anonymous_id + ) union ( + -- groups in management agroup can manage themselves + select ags.group_id as manager_group_id, m.management_agroup_id as managed_agroup_id + from makerspaces m + left join anonymous_group_subgroups ags on m.management_agroup_id = ags.anonymous_id ) union ( -- root group can manage any agroup id select g.id as manager_group_id, ag.id as managed_agroup_id diff --git a/internal/database/models/group.go b/internal/database/models/group.go index 28180f64..4372efef 100644 --- a/internal/database/models/group.go +++ b/internal/database/models/group.go @@ -7,6 +7,7 @@ import ( ) var ErrNoGroupOrWrongPermissions = fmt.Errorf("group does not exist or user has invalid permissions to query it") +var ErrNoAnonymousGroupOrWrongPermissions = fmt.Errorf("anonymous group does not exist or user has invalid permissions to query it") // Determines how users see the group theyre a part of type GroupViewPermission int diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index 766b1bf5..f01c73ec 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -7,7 +7,6 @@ package resolvers import ( "context" - "errors" "fmt" "make-backend/internal/auth" "make-backend/internal/database/models" @@ -40,25 +39,13 @@ func (r *groupResolver) DirectMembers(ctx context.Context, obj *models.Group) ([ // Members is the resolver for the members field. func (r *groupResolver) Members(ctx context.Context, obj *models.Group) ([]*models.MembershipToGroup, error) { - userId := auth.UserIDFromContext(ctx) - if userId == nil { - return nil, auth.ErrNotAuthenticated - } - - visible, how, err := r.Store.Groups.IsUserInGroup(ctx, *userId, obj.Id) - if err != nil { - return nil, err - } - visibleByManager, err := r.Store.Groups.CanUserManageGroup(ctx, *userId, obj.Id) + how, err := CanUserFromContextSeeGroup(r.Store, ctx, obj.Id) if err != nil { return nil, err } - visible = visible || visibleByManager - if !visible { - return nil, models.ErrNoGroupOrWrongPermissions - } - if how == models.GroupViewPermission_SeeSelf && !visibleByManager { + userId := auth.UserIDFromContext(ctx) + if how == models.GroupViewPermission_SeeSelf { m := models.MembershipToGroup{ UserId: *userId, ViewPermission: models.GroupViewPermission_SeeSelf, @@ -110,20 +97,10 @@ func (r *membershipToGroupResolver) User(ctx context.Context, obj *models.Member // SetAnonymousGroupSubgroups is the resolver for the SetAnonymousGroupSubgroups field. func (r *mutationResolver) SetAnonymousGroupSubgroups(ctx context.Context, agroupID int, subgroups []int) (bool, error) { - userId := auth.UserIDFromContext(ctx) - if userId == nil { - return false, auth.ErrNotAuthenticated - } - - canManage, err := r.Store.Groups.CanUserManageAnonymousGroup(ctx, *userId, agroupID) - if err != nil { + if err := CanUserFromContextManageAnonymousGroup(r.Store, ctx, agroupID); err != nil { return false, err } - if !canManage { - return false, errors.New("anonymous group does not exist or user does not have the permissions to edit it") - } - - err = r.Store.Groups.SetGroupsForAnonymousGroup(ctx, agroupID, subgroups) + err := r.Store.Groups.SetGroupsForAnonymousGroup(ctx, agroupID, subgroups) if err != nil { return false, err } @@ -154,18 +131,6 @@ func (r *queryResolver) Group(ctx context.Context, id int) (*models.Group, error // AnonymousGroup is the resolver for the anonymousGroup field. func (r *queryResolver) AnonymousGroup(ctx context.Context, id int) (*models.AnonymousGroup, error) { - userId := auth.UserIDFromContext(ctx) - if userId == nil { - return nil, auth.ErrNotAuthenticated - } - - canManage, err := r.Store.Groups.CanUserManageAnonymousGroup(ctx, *userId, id) - if err != nil { - return nil, err - } - if !canManage { - return nil, models.ErrNoGroupOrWrongPermissions - } ag := models.AnonymousGroup{ Id: id, } diff --git a/internal/gql/resolvers/helpers.go b/internal/gql/resolvers/helpers.go index 73af804e..9e7b93ee 100644 --- a/internal/gql/resolvers/helpers.go +++ b/internal/gql/resolvers/helpers.go @@ -1,5 +1,13 @@ package resolvers +import ( + "context" + "fmt" + "make-backend/internal/auth" + "make-backend/internal/database" + "make-backend/internal/database/models" +) + func SliceToPtrSlice[E any](s []E) []*E { pointers := make([]*E, 0, len(s)) for i := range s { @@ -7,3 +15,46 @@ func SliceToPtrSlice[E any](s []E) []*E { } return pointers } + +// helper to check if the use stored in context can manage anonymous group +// returns err if not, nil if can +func CanUserFromContextManageAnonymousGroup(store *database.Store, ctx context.Context, agroupID int) error { + userId := auth.UserIDFromContext(ctx) + if userId == nil { + return auth.ErrNotAuthenticated + } + + canManage, err := store.Groups.CanUserManageAnonymousGroup(ctx, *userId, agroupID) + if err != nil { + return err + } + if !canManage { + return models.ErrNoAnonymousGroupOrWrongPermissions + } + return nil +} + +func CanUserFromContextSeeGroup(store *database.Store, ctx context.Context, groupID int) (models.GroupViewPermission, error) { + userId := auth.UserIDFromContext(ctx) + if userId == nil { + return models.GroupViewPermission_SeeNone, auth.ErrNotAuthenticated + } + + visible, how, err := store.Groups.IsUserInGroup(ctx, *userId, groupID) + if err != nil { + return models.GroupViewPermission_SeeNone, fmt.Errorf("error checking how user can view group: %w", err) + } + visibleByManager, err := store.Groups.CanUserManageGroup(ctx, *userId, groupID) + if err != nil { + return models.GroupViewPermission_SeeNone, fmt.Errorf("error checking how user can view group: %w", err) + } + visible = visible || visibleByManager + if !visible { + return models.GroupViewPermission_SeeNone, models.ErrNoGroupOrWrongPermissions + } + if visibleByManager { + return models.GroupViewPermission_SeeAll, nil + } + return how, nil + +} diff --git a/internal/gql/resolvers/makerspace.resolvers.go b/internal/gql/resolvers/makerspace.resolvers.go index 9ff4cf8e..688c4b3e 100644 --- a/internal/gql/resolvers/makerspace.resolvers.go +++ b/internal/gql/resolvers/makerspace.resolvers.go @@ -7,6 +7,7 @@ package resolvers import ( "context" + "fmt" "make-backend/internal/database/models" "make-backend/internal/gql" ) @@ -38,6 +39,7 @@ func (r *makerspaceResolver) Hours(ctx context.Context, obj *models.Makerspace) // Managers is the resolver for the managers field. func (r *makerspaceResolver) Managers(ctx context.Context, obj *models.Makerspace) ([]*models.User, error) { + us, err := r.Store.Groups.UsersInAnonymousGroup(ctx, obj.ManagementAgroupId) if err != nil { return nil, err @@ -48,6 +50,10 @@ func (r *makerspaceResolver) Managers(ctx context.Context, obj *models.Makerspac // ManagerSubgroups is the resolver for the managerSubgroups field. func (r *makerspaceResolver) ManagerSubgroups(ctx context.Context, obj *models.Makerspace) ([]*models.Group, error) { + if err := CanUserFromContextManageAnonymousGroup(r.Store, ctx, obj.ManagementAgroupId); err != nil { + return nil, fmt.Errorf("cannot list manager subgroups: %w", err) + } + sgs, err := r.Store.Groups.GroupsInAnonymousGroup(ctx, obj.ManagementAgroupId) if err != nil { return nil, err diff --git a/internal/gql/resolvers/makerspace_resolver_test.go b/internal/gql/resolvers/makerspace_resolver_test.go index fe44c1a4..f32e6498 100644 --- a/internal/gql/resolvers/makerspace_resolver_test.go +++ b/internal/gql/resolvers/makerspace_resolver_test.go @@ -1,14 +1,14 @@ package resolvers import ( - "context" "testing" ) -func TestMakerspaceStaff(t *testing.T) { +func TestMakerspaceStaffAuthed(t *testing.T) { _, data, resolver := helpersForResolverTest(t) + ctx := ContextWithUser(t.Context(), data.Users[0].Id) wantedStaff := []int{data.Users[1].Id, data.Users[2].Id, data.Users[3].Id, data.Users[4].Id} - gotStaff, err := resolver.Makerspace().Staff(context.TODO(), &data.Parlophone) + gotStaff, err := resolver.Makerspace().Staff(ctx, &data.Parlophone) if err != nil { t.Fatalf("failed to get staff of makerspace %v", err) } @@ -20,12 +20,12 @@ func TestMakerspaceStaff(t *testing.T) { t.Fatalf("staff group for makerspace not equal. Wanted %v but got %v", wantedStaff, sIds) } } -func TestMakerspaceManagers(t *testing.T) { +func TestMakerspaceManagersAuthed(t *testing.T) { _, data, resolver := helpersForResolverTest(t) wantedManagers := []int{data.Users[0].Id} - gotManagers, err := resolver.Makerspace().Managers(context.TODO(), &data.Parlophone) + gotManagers, err := resolver.Makerspace().Managers(t.Context(), &data.Parlophone) if err != nil { - t.Fatalf("failed to get staff of makerspace %v", err) + t.Fatalf("failed to get managers of makerspace %v", err) } mIds := []int{} for _, user := range gotManagers { @@ -38,8 +38,10 @@ func TestMakerspaceManagers(t *testing.T) { func TestMakerspaceStaffSubgroups(t *testing.T) { _, data, resolver := helpersForResolverTest(t) + ctx := ContextWithUser(t.Context(), data.Users[0].Id) + wantedSG := []int{data.BeatlesMusicians.Id} - gotSGs, err := resolver.Makerspace().StaffSubgroups(context.TODO(), &data.Parlophone) + gotSGs, err := resolver.Makerspace().StaffSubgroups(ctx, &data.Parlophone) if err != nil { t.Fatalf("failed to get staff subgroups of makerspace %v", err) } @@ -52,12 +54,14 @@ func TestMakerspaceStaffSubgroups(t *testing.T) { } } -func TestMakerspaceManagerSubgroups(t *testing.T) { +func TestMakerspaceManagerSubgroupsAuthed(t *testing.T) { _, data, resolver := helpersForResolverTest(t) + ctx := ContextWithUser(t.Context(), data.Users[0].Id) + wantedSG := []int{data.BeatlesManagers.Id} - gotSGs, err := resolver.Makerspace().ManagerSubgroups(context.TODO(), &data.Parlophone) + gotSGs, err := resolver.Makerspace().ManagerSubgroups(ctx, &data.Parlophone) if err != nil { - t.Fatalf("failed to get manager subgroups of makerspace %v", err) + t.Fatalf("failed to get manager subgroups of makerspace: %v", err) } SGIds := []int{} for _, user := range gotSGs { @@ -98,7 +102,7 @@ func TestAddAndRemoveFromStaffAgroup(t *testing.T) { // add new group gotSGsMid, err := resolver.Makerspace().StaffSubgroups(ctx, &data.Parlophone) if err != nil { - t.Fatalf("failed to get manager subgroups of makerspace after addition %v", err) + t.Fatalf("failed to get staff subgroups of makerspace after addition: %v", err) } midSGIds := []int{} for _, user := range gotSGsMid { @@ -116,7 +120,7 @@ func TestAddAndRemoveFromStaffAgroup(t *testing.T) { gotSGsEnd, err := resolver.Makerspace().StaffSubgroups(ctx, &data.Parlophone) if err != nil { - t.Fatalf("failed to get manager subgroups of makerspace after removal %v", err) + t.Fatalf("failed to get staff subgroups of makerspace after removal: %v", err) } endSGIds := []int{} for _, user := range gotSGsEnd { From cc90a605e6c514dd42936afc0b7173206b831e34 Mon Sep 17 00:00:00 2001 From: cowsed Date: Wed, 19 Aug 2026 15:04:19 -0400 Subject: [PATCH 19/22] Stricter permissions and enforcing that only root group can hve null manager id --- .../20260703201718_initial_schema.sql | 8 +++-- internal/database/mock_data.go | 2 +- internal/gql/resolvers/group.resolvers.go | 31 +++---------------- internal/gql/resolvers/group_resolver_test.go | 8 ++--- internal/gql/resolvers/helpers.go | 26 ++++++++++++---- 5 files changed, 35 insertions(+), 40 deletions(-) diff --git a/internal/database/migrations/20260703201718_initial_schema.sql b/internal/database/migrations/20260703201718_initial_schema.sql index 08dd4b5e..8a455bbe 100644 --- a/internal/database/migrations/20260703201718_initial_schema.sql +++ b/internal/database/migrations/20260703201718_initial_schema.sql @@ -49,10 +49,12 @@ CREATE TABLE groups ( description TEXT NOT NULL DEFAULT '', UNIQUE (name, manager_id) ); -INSERT INTO groups (name, description) -VALUES ('admin', 'The root of all groups'); - +INSERT INTO groups (id, name, description) +VALUES (0, 'admin', 'The root of all groups'); +alter table groups + add constraint nonnull_manager_except_for_root + check (id = 0 or manager_id is not null); CREATE TABLE group_direct_membership( group_id INT NOT NULL REFERENCES groups(id) ON DELETE CASCADE, diff --git a/internal/database/mock_data.go b/internal/database/mock_data.go index 89a517a4..8b96908e 100644 --- a/internal/database/mock_data.go +++ b/internal/database/mock_data.go @@ -169,7 +169,7 @@ func addUsersToTestGroups(ctx context.Context, t *slog.Logger, store *Store) boo } err = store.Groups.AddUserToGroup(ctx, user.Id, member.groupId, member.perm) if err != nil { - t.Error("Failed to add ", "user", user, "group", member.groupId) + t.Error("Failed to add ", "user", user, "group", member.groupId, "err", err) return false } } diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index f01c73ec..42907a33 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -109,16 +109,11 @@ func (r *mutationResolver) SetAnonymousGroupSubgroups(ctx context.Context, agrou // Group is the resolver for the group field. func (r *queryResolver) Group(ctx context.Context, id int) (*models.Group, error) { - userId := auth.UserIDFromContext(ctx) - if userId == nil { - return nil, auth.ErrNotAuthenticated - } - - visible, err := r.Store.Groups.IsGroupVisibleToUser(ctx, *userId, id) + how, err := CanUserFromContextSeeGroup(r.Store, ctx, id) if err != nil { return nil, err } - if !visible { + if how == models.GroupViewPermission_SeeNone { return nil, models.ErrNoGroupOrWrongPermissions } @@ -139,18 +134,10 @@ func (r *queryResolver) AnonymousGroup(ctx context.Context, id int) (*models.Ano // IsUserInGroup is the resolver for the isUserInGroup field. func (r *queryResolver) IsUserInGroup(ctx context.Context, userID int, groupID int) (bool, error) { - askingUserID := auth.UserIDFromContext(ctx) - if askingUserID == nil { - return false, auth.ErrNotAuthenticated - } - - visibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, *askingUserID, groupID) + _, err := CanUserFromContextSeeGroup(r.Store, ctx, groupID) if err != nil { return false, err } - if !visibleToAsker { - return false, models.ErrNoGroupOrWrongPermissions - } in, _, err := r.Store.Groups.IsUserInGroup(ctx, userID, groupID) return in, err @@ -209,19 +196,11 @@ func (r *queryResolver) CanGroupManageGroup(ctx context.Context, managerID int, // CanUserManageGroup is the resolver for the canUserManageGroup field. func (r *queryResolver) CanUserManageGroup(ctx context.Context, managerID int, groupID int) (bool, error) { - askingUserID := auth.UserIDFromContext(ctx) - - if askingUserID == nil { - return false, auth.ErrNotAuthenticated - } - - visibleToAsker, err := r.Store.Groups.IsGroupVisibleToUser(ctx, *askingUserID, groupID) + _, err := CanUserFromContextSeeGroup(r.Store, ctx, groupID) if err != nil { return false, err } - if !visibleToAsker { - return false, models.ErrNoGroupOrWrongPermissions - } + return r.Store.Groups.CanUserManageGroup(ctx, managerID, groupID) } diff --git a/internal/gql/resolvers/group_resolver_test.go b/internal/gql/resolvers/group_resolver_test.go index 22860fd1..a13da07a 100644 --- a/internal/gql/resolvers/group_resolver_test.go +++ b/internal/gql/resolvers/group_resolver_test.go @@ -66,15 +66,15 @@ func TestUserManagingGroup(t *testing.T) { can, err := resolver.Query().CanUserManageGroup(ctx, trial.user, trial.group) if err != nil && !trial.shouldError { - t.Fatalf("got error when %v checks if %v can manage group %v: %v", trial.askerUser, trial.user, trial.group, err) + t.Fatalf("got error when user %v checks if user %v can manage group %v: %v", trial.askerUser, trial.user, trial.group, err) } else if err == nil && trial.shouldError { - t.Fatalf("should get error when %v checks if %v can manage group %v we can't see", trial.askerUser, trial.user, trial.group) + t.Fatalf("should get error when user %v checks if user %v can manage group %v we can't see", trial.askerUser, trial.user, trial.group) continue } if trial.shouldManage && can != trial.shouldManage { - t.Fatalf("%v should be able to manage %v but wasn't able to for some reason", trial.user, trial.group) + t.Fatalf("user %v should be able to manage %v but wasn't able to for some reason", trial.user, trial.group) } else if !trial.shouldManage && can != trial.shouldManage { - t.Fatalf("%v should NOT be able to manage %v but wasn't able to for some reason", trial.user, trial.group) + t.Fatalf("user %v should NOT be able to manage %v but wasn't able to for some reason", trial.user, trial.group) } } } diff --git a/internal/gql/resolvers/helpers.go b/internal/gql/resolvers/helpers.go index 9e7b93ee..b32d3bc2 100644 --- a/internal/gql/resolvers/helpers.go +++ b/internal/gql/resolvers/helpers.go @@ -34,27 +34,41 @@ func CanUserFromContextManageAnonymousGroup(store *database.Store, ctx context.C return nil } +func CanUserFromContextManageGroup(store *database.Store, ctx context.Context, groupID int) (bool, error) { + userId := auth.UserIDFromContext(ctx) + if userId == nil { + return false, auth.ErrNotAuthenticated + } + return store.Groups.CanUserManageGroup(ctx, *userId, groupID) +} + func CanUserFromContextSeeGroup(store *database.Store, ctx context.Context, groupID int) (models.GroupViewPermission, error) { userId := auth.UserIDFromContext(ctx) if userId == nil { return models.GroupViewPermission_SeeNone, auth.ErrNotAuthenticated } - visible, how, err := store.Groups.IsUserInGroup(ctx, *userId, groupID) + visibleByManager, err := store.Groups.CanUserManageGroup(ctx, *userId, groupID) if err != nil { return models.GroupViewPermission_SeeNone, fmt.Errorf("error checking how user can view group: %w", err) } - visibleByManager, err := store.Groups.CanUserManageGroup(ctx, *userId, groupID) + if visibleByManager { + return models.GroupViewPermission_SeeAll, nil + } + + visibleByMember, how, err := store.Groups.IsUserInGroup(ctx, *userId, groupID) if err != nil { return models.GroupViewPermission_SeeNone, fmt.Errorf("error checking how user can view group: %w", err) } - visible = visible || visibleByManager - if !visible { + + if !visibleByMember { return models.GroupViewPermission_SeeNone, models.ErrNoGroupOrWrongPermissions } - if visibleByManager { - return models.GroupViewPermission_SeeAll, nil + + if how == models.GroupViewPermission_SeeNone { + return models.GroupViewPermission_SeeNone, models.ErrNoGroupOrWrongPermissions } + return how, nil } From 68f71b9fbc54efeb418f6aa083bf633735e5ca48 Mon Sep 17 00:00:00 2001 From: cowsed Date: Wed, 19 Aug 2026 15:13:50 -0400 Subject: [PATCH 20/22] allow gqlgen to format --- internal/gql/resolvers/makerspace.resolvers.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/gql/resolvers/makerspace.resolvers.go b/internal/gql/resolvers/makerspace.resolvers.go index 688c4b3e..c16a5944 100644 --- a/internal/gql/resolvers/makerspace.resolvers.go +++ b/internal/gql/resolvers/makerspace.resolvers.go @@ -39,7 +39,6 @@ func (r *makerspaceResolver) Hours(ctx context.Context, obj *models.Makerspace) // Managers is the resolver for the managers field. func (r *makerspaceResolver) Managers(ctx context.Context, obj *models.Makerspace) ([]*models.User, error) { - us, err := r.Store.Groups.UsersInAnonymousGroup(ctx, obj.ManagementAgroupId) if err != nil { return nil, err From 36190cdc58f1d8912ac9673189b089a2fc5bd733 Mon Sep 17 00:00:00 2001 From: cowsed Date: Wed, 19 Aug 2026 15:27:55 -0400 Subject: [PATCH 21/22] AuditLogs for new resolvers --- internal/gql/resolvers/helpers.go | 12 ++++++++++++ internal/gql/resolvers/makerspace.resolvers.go | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/internal/gql/resolvers/helpers.go b/internal/gql/resolvers/helpers.go index b32d3bc2..96f400d5 100644 --- a/internal/gql/resolvers/helpers.go +++ b/internal/gql/resolvers/helpers.go @@ -16,6 +16,18 @@ func SliceToPtrSlice[E any](s []E) []*E { return pointers } +func FullUserFromContext(store *database.Store, ctx context.Context) *models.User { + id := auth.UserIDFromContext(ctx) + if id == nil { + return nil + } + u, err := store.Users.GetUserById(ctx, *id) + if err != nil { + return nil + } + return u +} + // helper to check if the use stored in context can manage anonymous group // returns err if not, nil if can func CanUserFromContextManageAnonymousGroup(store *database.Store, ctx context.Context, agroupID int) error { diff --git a/internal/gql/resolvers/makerspace.resolvers.go b/internal/gql/resolvers/makerspace.resolvers.go index c16a5944..74b3b3ae 100644 --- a/internal/gql/resolvers/makerspace.resolvers.go +++ b/internal/gql/resolvers/makerspace.resolvers.go @@ -8,6 +8,7 @@ package resolvers import ( "context" "fmt" + "make-backend/internal/auth" "make-backend/internal/database/models" "make-backend/internal/gql" ) @@ -80,10 +81,19 @@ func (r *makerspaceResolver) StaffSubgroups(ctx context.Context, obj *models.Mak // CreateMakerspace is the resolver for the createMakerspace field. func (r *mutationResolver) CreateMakerspace(ctx context.Context, name string, hidden bool) (int, error) { + user := FullUserFromContext(r.Store, ctx) + if user != nil { + return 0, auth.ErrNotAuthenticated + } id, err := r.Store.Makerspaces.CreateMakerspace(ctx, name, hidden) if err != nil { return 0, err } + makerspace, err := r.Store.Makerspaces.GetMakerspaceById(ctx, id) + if err != nil { + return id, fmt.Errorf("failed to retrieve new makerspace") + } + r.Logger.AuditLog.CreateUnassociated("builtin.makerspace.create", "{user} created {makerspace)", user.LogEntity(), makerspace.LogEntity()) return id, nil } From b469cdaa0d35bb48d527fae29e695d7e04843f1f Mon Sep 17 00:00:00 2001 From: cowsed Date: Thu, 20 Aug 2026 12:32:59 -0400 Subject: [PATCH 22/22] makerspace directives for permission checks --- go.mod | 2 +- internal/database/group_test.go | 2 +- internal/database/mock_data.go | 4 +- internal/database/repos/group_repo.go | 2 +- internal/database/repos/user_repo.go | 56 -- internal/database/store.go | 6 +- internal/gql/directives/directives.go | 191 +++---- internal/gql/generated.go | 525 +++++++++++++----- internal/gql/resolvers/group.resolvers.go | 12 - .../gql/resolvers/makerspace.resolvers.go | 56 +- internal/gql/schema/group.graphqls | 3 - internal/gql/schema/makerspace.graphqls | 19 +- internal/gql/schema/user.graphqls | 11 +- internal/plugins/plugin_allowlist.go | 14 - 14 files changed, 500 insertions(+), 403 deletions(-) diff --git a/go.mod b/go.mod index e03101f2..12b235a5 100644 --- a/go.mod +++ b/go.mod @@ -104,7 +104,7 @@ require ( golang.org/x/crypto v0.53.0 golang.org/x/mod v0.37.0 // indirect golang.org/x/sync v0.21.0 // indirect - golang.org/x/text v0.38.0 // indirect + golang.org/x/text v0.38.0 golang.org/x/tools v0.46.0 // indirect ) diff --git a/internal/database/group_test.go b/internal/database/group_test.go index c504e66a..e8139912 100644 --- a/internal/database/group_test.go +++ b/internal/database/group_test.go @@ -88,7 +88,7 @@ func TestSubgroupMembership(t *testing.T) { "paul@beatles.com", "george@beatles.com", "ringo@beatles.com", - "brian@beatles.com", + "brian@example.com", } { user, err := store.Users.GetUserByEmail(t.Context(), email) if err != nil { diff --git a/internal/database/mock_data.go b/internal/database/mock_data.go index 8b96908e..f4d5b0d3 100644 --- a/internal/database/mock_data.go +++ b/internal/database/mock_data.go @@ -34,7 +34,7 @@ var localContext TestMockData = TestMockData{ Id int Email string }{ - {Email: "brian@beatles.com"}, + {Email: "brian@example.com"}, {Email: "john@beatles.com"}, {Email: "paul@beatles.com"}, {Email: "george@beatles.com"}, @@ -155,7 +155,7 @@ func addUsersToTestGroups(ctx context.Context, t *slog.Logger, store *Store) boo groupId int perm models.GroupViewPermission }{ - {"brian@beatles.com", localContext.BeatlesManagers.Id, models.GroupViewPermission_SeeSelf}, + {"brian@example.com", localContext.BeatlesManagers.Id, models.GroupViewPermission_SeeSelf}, {"john@beatles.com", localContext.BeatlesMusicians.Id, models.GroupViewPermission_SeeAll}, {"paul@beatles.com", localContext.BeatlesMusicians.Id, models.GroupViewPermission_SeeAll}, {"george@beatles.com", localContext.BeatlesMusicians.Id, models.GroupViewPermission_SeeAll}, diff --git a/internal/database/repos/group_repo.go b/internal/database/repos/group_repo.go index 451ca98a..bfe4589f 100644 --- a/internal/database/repos/group_repo.go +++ b/internal/database/repos/group_repo.go @@ -186,7 +186,7 @@ func (g *GroupRepo) GroupsInAnonymousGroup(ctx context.Context, anonymousGroupId func (g *GroupRepo) IsUserInAnonymousGroup(ctx context.Context, anonymousGroupId int, userId int) (bool, error) { var inGroup bool - query := "SELECT EXISTS(SELECT 1 FROM group_management WHERE group_id = $1 and user_id = $2)" + query := "SELECT EXISTS(SELECT 1 FROM anonymous_group_membership WHERE agroup_id = $1 and user_id = $2)" err := g.DB.QueryRow(query, anonymousGroupId, userId).Scan(&inGroup) if err != nil { diff --git a/internal/database/repos/user_repo.go b/internal/database/repos/user_repo.go index aa67986a..18da7e08 100644 --- a/internal/database/repos/user_repo.go +++ b/internal/database/repos/user_repo.go @@ -10,11 +10,7 @@ type UserRepository interface { GetUserById(ctx context.Context, id int) (*models.User, error) GetUserByEmail(ctx context.Context, email string) (*models.User, error) CreateUser(ctx context.Context, email string) (int, error) - IsManager(ctx context.Context, id int) (bool, error) - IsStaff(ctx context.Context, id int) (bool, error) IsTrainer(ctx context.Context, id int) (bool, error) - IsManagerFor(ctx context.Context, user_id int, makerspace_id int) (bool, error) - IsStaffFor(ctx context.Context, user_id int, makerspace_id int) (bool, error) IsTrainerFor(ctx context.Context, user_id int, equipment_id int) (bool, error) } @@ -115,32 +111,6 @@ func (r *UserRepo) CreateUser(ctx context.Context, email string) (int, error) { return new_id, nil } -func (r *UserRepo) IsManager(ctx context.Context, id int) (bool, error) { - var isManager bool - - query := `SELECT EXISTS(SELECT 1 FROM managers WHERE user_id = $1)` - - err := r.DB.QueryRowContext(ctx, query, id).Scan(&isManager) - if err != nil { - return false, err - } - - return isManager, nil -} - -func (r *UserRepo) IsStaff(ctx context.Context, id int) (bool, error) { - var isStaff bool - - query := `SELECT EXISTS(SELECT 1 FROM staff WHERE user_id = $1)` - - err := r.DB.QueryRowContext(ctx, query, id).Scan(&isStaff) - if err != nil { - return false, err - } - - return isStaff, nil -} - func (r *UserRepo) IsTrainer(ctx context.Context, id int) (bool, error) { var isTrainer bool @@ -154,32 +124,6 @@ func (r *UserRepo) IsTrainer(ctx context.Context, id int) (bool, error) { return isTrainer, nil } -func (r *UserRepo) IsManagerFor(ctx context.Context, user_id int, makerspace_id int) (bool, error) { - var isManager bool - - query := `SELECT EXISTS(SELECT 1 FROM managers WHERE user_id = $1 AND makerspace_id = $2)` - - err := r.DB.QueryRowContext(ctx, query, user_id, makerspace_id).Scan(&isManager) - if err != nil { - return false, err - } - - return isManager, nil -} - -func (r *UserRepo) IsStaffFor(ctx context.Context, user_id int, makerspace_id int) (bool, error) { - var isStaff bool - - query := `SELECT EXISTS(SELECT 1 FROM staff WHERE user_id = $1 AND makerspace_id = $2)` - - err := r.DB.QueryRowContext(ctx, query, user_id, makerspace_id).Scan(&isStaff) - if err != nil { - return false, err - } - - return isStaff, nil -} - func (r *UserRepo) IsTrainerFor(ctx context.Context, user_id int, equipment_id int) (bool, error) { var isTrainer bool diff --git a/internal/database/store.go b/internal/database/store.go index 1741fc27..2affe647 100644 --- a/internal/database/store.go +++ b/internal/database/store.go @@ -1,8 +1,10 @@ package database import ( + "context" "database/sql" "embed" + "log/slog" "make-backend/internal/database/repos" ) @@ -20,7 +22,7 @@ type Store struct { } func NewStore(db *sql.DB) *Store { - return &Store{ + s := &Store{ Users: &repos.UserRepo{DB: db}, Groups: &repos.GroupRepo{DB: db}, Makerspaces: &repos.MakerspaceRepo{DB: db}, @@ -29,4 +31,6 @@ func NewStore(db *sql.DB) *Store { Devices: &repos.DeviceRepo{DB: db}, AuditLogs: &repos.AuditLogRepo{DB: db}, } + fillTestData(context.Background(), slog.Default(), s) + return s } diff --git a/internal/gql/directives/directives.go b/internal/gql/directives/directives.go index 171b48a2..146bddf5 100644 --- a/internal/gql/directives/directives.go +++ b/internal/gql/directives/directives.go @@ -2,20 +2,25 @@ package directives import ( "context" + "errors" "fmt" + "make-backend/internal/auth" "make-backend/internal/database" "make-backend/internal/gql" + "reflect" "github.com/99designs/gqlgen/graphql" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) func isAdmin(store *database.Store, ctx context.Context) (bool, error) { - user_id, ok := ctx.Value("user_id").(int) - if !ok { + user_id := auth.UserIDFromContext(ctx) + if user_id == nil { return false, fmt.Errorf("Access denied") } - user, err := store.Users.GetUserById(ctx, user_id) + user, err := store.Users.GetUserById(ctx, *user_id) if err != nil { return false, err } @@ -23,34 +28,6 @@ func isAdmin(store *database.Store, ctx context.Context) (bool, error) { return user.Admin, nil } -func isManager(store *database.Store, ctx context.Context) (bool, error) { - user_id, ok := ctx.Value("user_id").(int) - if !ok { - return false, fmt.Errorf("Failed to get user_id from context") - } - - manager, err := store.Users.IsManager(ctx, user_id) - if err != nil { - return false, err - } - - return manager, nil -} - -func isStaff(store *database.Store, ctx context.Context) (bool, error) { - user_id, ok := ctx.Value("user_id").(int) - if !ok { - return false, fmt.Errorf("Could not extract user_id from context") - } - - staff, err := store.Users.IsStaff(ctx, user_id) - if err != nil { - return false, err - } - - return staff, nil -} - func isTrainer(store *database.Store, ctx context.Context) (bool, error) { user_id, ok := ctx.Value("user_id").(int) if !ok { @@ -84,52 +61,49 @@ func isSelf(ctx context.Context) (bool, error) { return target_id == user_id, nil } -func isManagerFor(store *database.Store, ctx context.Context) (bool, error) { - fc := graphql.GetFieldContext(ctx) - if fc == nil { - return false, fmt.Errorf("Failed to get field context") - } - - makerspace_id, ok := fc.Args["makerspace_id"].(int) - if !ok { - return false, fmt.Errorf("Failed to get user_id from field context") +func extractMakerspaceIdFromFieldNameInMakerspaceType(obj any, makerspaceIdField string) (int, error) { + // obj represents the parent Go struct (ie. Makerspace) + val := reflect.ValueOf(obj) + if val.Kind() == reflect.Ptr { + val = val.Elem() } - user_id, ok := ctx.Value("user_id").(int) - if !ok { - return false, fmt.Errorf("Failed to get user_id from session context") - } - - managerFor, err := store.Users.IsManagerFor(ctx, user_id, makerspace_id) - if err != nil { - return false, err + // Extract sibling field via reflection or direct type assertion + fieldVal := val.FieldByName(cases.Title(language.AmericanEnglish).String((makerspaceIdField))) + makerspaceId := 0 + if fieldVal.IsValid() { + makerspaceId, _ = fieldVal.Interface().(int) + } else { + return 0, fmt.Errorf("invalid field to extract. name: %v", makerspaceIdField) } + return makerspaceId, nil - return managerFor, nil } -func isStaffFor(store *database.Store, ctx context.Context) (bool, error) { +func extractMakerspaceIdFromArgNameInMakerspaceType(ctx context.Context, makerspaceIdArg string) (int, error) { fc := graphql.GetFieldContext(ctx) - if fc == nil { - return false, fmt.Errorf("Failed to get field context") - } - makerspace_id, ok := fc.Args["makerspace_id"].(int) - if !ok { - return false, fmt.Errorf("Failed to get user_id from field context") + if idVal, ok := fc.Args[makerspaceIdArg]; ok { + id := idVal.(int) + return id, nil } + return 0, fmt.Errorf("couldn't extract id from arg") - user_id, ok := ctx.Value("user_id").(int) - if !ok { - return false, fmt.Errorf("Failed to get user_id from session context") +} + +func extractMakerspaceIdFromArgOrFieldName(ctx context.Context, obj any, makerspaceIdField *string, makerspaceIdArg *string) (int, error) { + if makerspaceIdArg == nil && makerspaceIdField == nil { + return 0, errors.New("specify one of makerspaceIdField makerspaceIdArg") + } + if makerspaceIdArg != nil && makerspaceIdField != nil { + return 0, errors.New("specify one of makerspaceIdField makerspaceIdArg not both") } - staffFor, err := store.Users.IsStaffFor(ctx, user_id, makerspace_id) - if err != nil { - return false, err + if makerspaceIdArg != nil { + return extractMakerspaceIdFromArgNameInMakerspaceType(ctx, *makerspaceIdArg) } + return extractMakerspaceIdFromFieldNameInMakerspaceType(obj, *makerspaceIdField) - return staffFor, nil } func isTrainerFor(store *database.Store, ctx context.Context) (bool, error) { @@ -170,112 +144,75 @@ func SetupDirectives(config *gql.Config, store *database.Store) { } } - config.Directives.IsManager = func(ctx context.Context, obj any, next graphql.Resolver) (any, error) { - manager, err := isManager(store, ctx) + config.Directives.IsSelf = func(ctx context.Context, obj any, next graphql.Resolver) (any, error) { + self, err := isSelf(ctx) if err != nil { return nil, err } - if manager { + if self { return next(ctx) } else { return nil, fmt.Errorf("Unauthorized") } } - - config.Directives.IsStaff = func(ctx context.Context, obj any, next graphql.Resolver) (any, error) { - staff, err := isStaff(store, ctx) - if err != nil { - return nil, err + config.Directives.IsManagerFor = func(ctx context.Context, obj any, next graphql.Resolver, makerspaceIdField *string, makerspaceIdArg *string) (any, error) { + user_id := auth.UserIDFromContext(ctx) + if user_id == nil { + return false, fmt.Errorf("Access denied") } - if staff { - return next(ctx) - } else { - return nil, fmt.Errorf("Unauthorized") - } - } - - config.Directives.IsTrainer = func(ctx context.Context, obj any, next graphql.Resolver) (any, error) { - trainer, err := isTrainer(store, ctx) + makerspaceId, err := extractMakerspaceIdFromArgOrFieldName(ctx, obj, makerspaceIdField, makerspaceIdArg) if err != nil { - return nil, err + return nil, fmt.Errorf("couldn't find makerspace id field: %w", err) } - if trainer { - return next(ctx) - } else { - return nil, fmt.Errorf("Unauthorized") - } - } - - config.Directives.IsSelf = func(ctx context.Context, obj any, next graphql.Resolver) (any, error) { - self, err := isSelf(ctx) + // TODO add direct getter for in manager group + // Or not if permissions go fine grained + m, err := store.Makerspaces.GetMakerspaceById(ctx, makerspaceId) if err != nil { return nil, err } - - if self { - return next(ctx) - } else { - return nil, fmt.Errorf("Unauthorized") - } - } - - config.Directives.IsManagerFor = func(ctx context.Context, obj any, next graphql.Resolver) (any, error) { - managerFor, err := isManagerFor(store, ctx) + isManager, err := store.Groups.IsUserInAnonymousGroup(ctx, m.ManagementAgroupId, *user_id) if err != nil { return nil, err - } - - if managerFor { - return next(ctx) - } else { - return nil, fmt.Errorf("Unauthorized") - } - } - config.Directives.IsStaffFor = func(ctx context.Context, obj any, next graphql.Resolver) (any, error) { - staffFor, err := isStaffFor(store, ctx) - if err != nil { - return nil, err } - if staffFor { + if isManager { return next(ctx) } else { return nil, fmt.Errorf("Unauthorized") } } - config.Directives.IsTrainerFor = func(ctx context.Context, obj any, next graphql.Resolver) (any, error) { - trainerFor, err := isTrainerFor(store, ctx) - if err != nil { - return nil, err + config.Directives.IsStaffFor = func(ctx context.Context, obj any, next graphql.Resolver, makerspaceIdField *string, makerspaceIdArg *string) (any, error) { + user_id := auth.UserIDFromContext(ctx) + if user_id == nil { + return false, fmt.Errorf("Access denied") } - if trainerFor { - return next(ctx) - } else { - return nil, fmt.Errorf("Unauthorized") + makerspaceId, err := extractMakerspaceIdFromArgOrFieldName(ctx, obj, makerspaceIdField, makerspaceIdArg) + if err != nil { + return nil, fmt.Errorf("couldn't find makerspace id field: %w", err) } - } - config.Directives.IsStaffOrSelf = func(ctx context.Context, obj any, next graphql.Resolver) (any, error) { - staff, err := isStaff(store, ctx) + // TODO add direct getter for in manager group + m, err := store.Makerspaces.GetMakerspaceById(ctx, makerspaceId) if err != nil { return nil, err } - - self, err := isSelf(ctx) + isStaff, err := store.Groups.IsUserInAnonymousGroup(ctx, m.StaffAgroupId, *user_id) if err != nil { return nil, err + } - if self || staff { + if isStaff { return next(ctx) } else { return nil, fmt.Errorf("Unauthorized") } } + } diff --git a/internal/gql/generated.go b/internal/gql/generated.go index 9f301023..db50fc99 100644 --- a/internal/gql/generated.go +++ b/internal/gql/generated.go @@ -43,15 +43,10 @@ type ResolverRoot interface { } type DirectiveRoot struct { - IsAdmin func(ctx context.Context, obj any, next graphql.Resolver) (res any, err error) - IsManager func(ctx context.Context, obj any, next graphql.Resolver) (res any, err error) - IsManagerFor func(ctx context.Context, obj any, next graphql.Resolver) (res any, err error) - IsSelf func(ctx context.Context, obj any, next graphql.Resolver) (res any, err error) - IsStaff func(ctx context.Context, obj any, next graphql.Resolver) (res any, err error) - IsStaffFor func(ctx context.Context, obj any, next graphql.Resolver) (res any, err error) - IsStaffOrSelf func(ctx context.Context, obj any, next graphql.Resolver) (res any, err error) - IsTrainer func(ctx context.Context, obj any, next graphql.Resolver) (res any, err error) - IsTrainerFor func(ctx context.Context, obj any, next graphql.Resolver) (res any, err error) + IsAdmin func(ctx context.Context, obj any, next graphql.Resolver) (res any, err error) + IsManagerFor func(ctx context.Context, obj any, next graphql.Resolver, makerspaceIDField *string, makerspaceIDArg *string) (res any, err error) + IsSelf func(ctx context.Context, obj any, next graphql.Resolver) (res any, err error) + IsStaffFor func(ctx context.Context, obj any, next graphql.Resolver, makerspaceIDField *string, makerspaceIDArg *string) (res any, err error) } type ComplexityRoot struct { @@ -194,20 +189,20 @@ type ComplexityRoot struct { } Makerspace struct { - Description func(childComplexity int) int - DocsUrl func(childComplexity int) int - Hidden func(childComplexity int) int - Hours func(childComplexity int) int - Id func(childComplexity int) int - ImageId func(childComplexity int) int - ManagerSubgroups func(childComplexity int) int - Managers func(childComplexity int) int - Name func(childComplexity int) int - Staff func(childComplexity int) int - StaffSubgroups func(childComplexity int) int - Subtitle func(childComplexity int) int - Timezone func(childComplexity int) int - Zones func(childComplexity int) int + Description func(childComplexity int) int + DocsUrl func(childComplexity int) int + Hidden func(childComplexity int) int + Hours func(childComplexity int) int + Id func(childComplexity int) int + ImageId func(childComplexity int) int + ManagerAnonymousGroup func(childComplexity int) int + Managers func(childComplexity int) int + Name func(childComplexity int) int + Staff func(childComplexity int) int + StaffAnonymousGroup func(childComplexity int) int + Subtitle func(childComplexity int) int + Timezone func(childComplexity int) int + Zones func(childComplexity int) int } MembershipToGroup struct { @@ -217,9 +212,10 @@ type ComplexityRoot struct { } Mutation struct { - CreateMakerspace func(childComplexity int, name string, hidden bool) int - DeleteMakerspace func(childComplexity int, id int) int - SetAnonymousGroupSubgroups func(childComplexity int, agroupID int, subgroups []int) int + CreateMakerspace func(childComplexity int, name string, hidden bool) int + DeleteMakerspace func(childComplexity int, id int) int + SetManagerSubgroups func(childComplexity int, makerspaceID int, subgroups []int) int + SetStaffSubgroups func(childComplexity int, makerspaceID int, subgroups []int) int } OptionBlock struct { @@ -319,7 +315,6 @@ type ComplexityRoot struct { User struct { Admin func(childComplexity int) int Archived func(childComplexity int) int - CardTag func(childComplexity int) int Email func(childComplexity int) int ForceArchive func(childComplexity int) int FullName func(childComplexity int) int @@ -360,9 +355,9 @@ type MakerspaceResolver interface { Zones(ctx context.Context, obj *models.Makerspace) ([]*models.Zone, error) Hours(ctx context.Context, obj *models.Makerspace) ([]models.MakerspaceHours, error) Managers(ctx context.Context, obj *models.Makerspace) ([]*models.User, error) - ManagerSubgroups(ctx context.Context, obj *models.Makerspace) ([]*models.Group, error) Staff(ctx context.Context, obj *models.Makerspace) ([]*models.User, error) - StaffSubgroups(ctx context.Context, obj *models.Makerspace) ([]*models.Group, error) + ManagerAnonymousGroup(ctx context.Context, obj *models.Makerspace) (*models.AnonymousGroup, error) + StaffAnonymousGroup(ctx context.Context, obj *models.Makerspace) (*models.AnonymousGroup, error) } type MembershipToGroupResolver interface { User(ctx context.Context, obj *models.MembershipToGroup) (*models.User, error) @@ -370,7 +365,8 @@ type MembershipToGroupResolver interface { type MutationResolver interface { CreateMakerspace(ctx context.Context, name string, hidden bool) (int, error) DeleteMakerspace(ctx context.Context, id int) (bool, error) - SetAnonymousGroupSubgroups(ctx context.Context, agroupID int, subgroups []int) (bool, error) + SetManagerSubgroups(ctx context.Context, makerspaceID int, subgroups []int) (bool, error) + SetStaffSubgroups(ctx context.Context, makerspaceID int, subgroups []int) (bool, error) } type OptionBlockOptionResolver interface { Correct(ctx context.Context, obj *models.OptionBlockOption) (*bool, error) @@ -987,12 +983,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Makerspace.ImageId(childComplexity), true - case "Makerspace.managerSubgroups": - if e.ComplexityRoot.Makerspace.ManagerSubgroups == nil { + case "Makerspace.managerAnonymousGroup": + if e.ComplexityRoot.Makerspace.ManagerAnonymousGroup == nil { break } - return e.ComplexityRoot.Makerspace.ManagerSubgroups(childComplexity), true + return e.ComplexityRoot.Makerspace.ManagerAnonymousGroup(childComplexity), true case "Makerspace.managers": if e.ComplexityRoot.Makerspace.Managers == nil { break @@ -1011,12 +1007,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Makerspace.Staff(childComplexity), true - case "Makerspace.staffSubgroups": - if e.ComplexityRoot.Makerspace.StaffSubgroups == nil { + case "Makerspace.staffAnonymousGroup": + if e.ComplexityRoot.Makerspace.StaffAnonymousGroup == nil { break } - return e.ComplexityRoot.Makerspace.StaffSubgroups(childComplexity), true + return e.ComplexityRoot.Makerspace.StaffAnonymousGroup(childComplexity), true case "Makerspace.subtitle": if e.ComplexityRoot.Makerspace.Subtitle == nil { break @@ -1077,17 +1073,28 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.Mutation.DeleteMakerspace(childComplexity, args["id"].(int)), true - case "Mutation.SetAnonymousGroupSubgroups": - if e.ComplexityRoot.Mutation.SetAnonymousGroupSubgroups == nil { + case "Mutation.setManagerSubgroups": + if e.ComplexityRoot.Mutation.SetManagerSubgroups == nil { break } - args, err := ec.field_Mutation_SetAnonymousGroupSubgroups_args(ctx, rawArgs) + args, err := ec.field_Mutation_setManagerSubgroups_args(ctx, rawArgs) if err != nil { return 0, false } - return e.ComplexityRoot.Mutation.SetAnonymousGroupSubgroups(childComplexity, args["agroupID"].(int), args["subgroups"].([]int)), true + return e.ComplexityRoot.Mutation.SetManagerSubgroups(childComplexity, args["makerspaceId"].(int), args["subgroups"].([]int)), true + case "Mutation.setStaffSubgroups": + if e.ComplexityRoot.Mutation.SetStaffSubgroups == nil { + break + } + + args, err := ec.field_Mutation_setStaffSubgroups_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Mutation.SetStaffSubgroups(childComplexity, args["makerspaceId"].(int), args["subgroups"].([]int)), true case "OptionBlock.affirmation": if e.ComplexityRoot.OptionBlock.Affirmation == nil { @@ -1539,12 +1546,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin } return e.ComplexityRoot.User.Archived(childComplexity), true - case "User.card_tag": - if e.ComplexityRoot.User.CardTag == nil { - break - } - - return e.ComplexityRoot.User.CardTag(childComplexity), true case "User.email": if e.ComplexityRoot.User.Email == nil { break @@ -1882,12 +1883,12 @@ func (ec *executionContext) childFields_Makerspace(ctx context.Context, field gr return ec.fieldContext_Makerspace_hours(ctx, field) case "managers": return ec.fieldContext_Makerspace_managers(ctx, field) - case "managerSubgroups": - return ec.fieldContext_Makerspace_managerSubgroups(ctx, field) case "staff": return ec.fieldContext_Makerspace_staff(ctx, field) - case "staffSubgroups": - return ec.fieldContext_Makerspace_staffSubgroups(ctx, field) + case "managerAnonymousGroup": + return ec.fieldContext_Makerspace_managerAnonymousGroup(ctx, field) + case "staffAnonymousGroup": + return ec.fieldContext_Makerspace_staffAnonymousGroup(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Makerspace", field.Name) } @@ -1938,8 +1939,6 @@ func (ec *executionContext) childFields_User(ctx context.Context, field graphql. return ec.fieldContext_User_admin(ctx, field) case "force_archive": return ec.fieldContext_User_force_archive(ctx, field) - case "card_tag": - return ec.fieldContext_User_card_tag(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type User", field.Name) } @@ -2074,25 +2073,47 @@ func (ec *executionContext) childFields___Type(ctx context.Context, field graphq // region ***************************** args.gotpl ***************************** -func (ec *executionContext) field_Mutation_SetAnonymousGroupSubgroups_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { +func (ec *executionContext) dir_isManagerFor_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, "agroupID", - func(ctx context.Context, v any) (int, error) { - return ec.unmarshalNID2int(ctx, v) + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "makerspaceIdField", + func(ctx context.Context, v any) (*string, error) { + return ec.unmarshalOString2ᚖstring(ctx, v) }) if err != nil { return nil, err } - args["agroupID"] = arg0 - arg1, err := graphql.ProcessArgField(ctx, rawArgs, "subgroups", - func(ctx context.Context, v any) ([]int, error) { - return ec.unmarshalNInt2ᚕintᚄ(ctx, v) + args["makerspaceIdField"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "makerspaceIdArg", + func(ctx context.Context, v any) (*string, error) { + return ec.unmarshalOString2ᚖstring(ctx, v) }) if err != nil { return nil, err } - args["subgroups"] = arg1 + args["makerspaceIdArg"] = arg1 + return args, nil +} + +func (ec *executionContext) dir_isStaffFor_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, "makerspaceIdField", + func(ctx context.Context, v any) (*string, error) { + return ec.unmarshalOString2ᚖstring(ctx, v) + }) + if err != nil { + return nil, err + } + args["makerspaceIdField"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "makerspaceIdArg", + func(ctx context.Context, v any) (*string, error) { + return ec.unmarshalOString2ᚖstring(ctx, v) + }) + if err != nil { + return nil, err + } + args["makerspaceIdArg"] = arg1 return args, nil } @@ -2132,6 +2153,50 @@ func (ec *executionContext) field_Mutation_deleteMakerspace_args(ctx context.Con return args, nil } +func (ec *executionContext) field_Mutation_setManagerSubgroups_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, "makerspaceId", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["makerspaceId"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "subgroups", + func(ctx context.Context, v any) ([]int, error) { + return ec.unmarshalNInt2ᚕintᚄ(ctx, v) + }) + if err != nil { + return nil, err + } + args["subgroups"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Mutation_setStaffSubgroups_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, "makerspaceId", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNID2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["makerspaceId"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "subgroups", + func(ctx context.Context, v any) ([]int, error) { + return ec.unmarshalNInt2ᚕintᚄ(ctx, v) + }) + if err != nil { + return nil, err + } + args["subgroups"] = arg1 + return args, 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{} @@ -4778,7 +4843,25 @@ func (ec *executionContext) _Makerspace_managers(ctx context.Context, field grap func(ctx context.Context) (any, error) { return ec.Resolvers.Makerspace().Managers(ctx, obj) }, - nil, + func(ctx context.Context, next graphql.Resolver) graphql.Resolver { + directive0 := next + + directive1 := func(ctx context.Context) (any, error) { + makerspaceIDField, err := ec.unmarshalOString2ᚖstring(ctx, "id") + if err != nil { + var zeroVal []*models.User + return zeroVal, err + } + if ec.Directives.IsManagerFor == nil { + var zeroVal []*models.User + return zeroVal, errors.New("directive isManagerFor is not implemented") + } + return ec.Directives.IsManagerFor(ctx, obj, directive0, makerspaceIDField, nil) + } + + next = directive1 + return next + }, func(ctx context.Context, selections ast.SelectionSet, v []*models.User) graphql.Marshaler { return ec.marshalNUser2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐUserᚄ(ctx, selections, v) }, @@ -4799,97 +4882,151 @@ func (ec *executionContext) fieldContext_Makerspace_managers(_ context.Context, return fc, nil } -func (ec *executionContext) _Makerspace_managerSubgroups(ctx context.Context, field graphql.CollectedField, obj *models.Makerspace) (ret graphql.Marshaler) { +func (ec *executionContext) _Makerspace_staff(ctx context.Context, field graphql.CollectedField, obj *models.Makerspace) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, ec.OperationContext, field, func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.fieldContext_Makerspace_managerSubgroups(ctx, field) + return ec.fieldContext_Makerspace_staff(ctx, field) }, func(ctx context.Context) (any, error) { - return ec.Resolvers.Makerspace().ManagerSubgroups(ctx, obj) + return ec.Resolvers.Makerspace().Staff(ctx, obj) }, - nil, - func(ctx context.Context, selections ast.SelectionSet, v []*models.Group) graphql.Marshaler { - return ec.marshalNGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupᚄ(ctx, selections, v) + func(ctx context.Context, next graphql.Resolver) graphql.Resolver { + directive0 := next + + directive1 := func(ctx context.Context) (any, error) { + makerspaceIDField, err := ec.unmarshalOString2ᚖstring(ctx, "id") + if err != nil { + var zeroVal []*models.User + return zeroVal, err + } + if ec.Directives.IsStaffFor == nil { + var zeroVal []*models.User + return zeroVal, errors.New("directive isStaffFor is not implemented") + } + return ec.Directives.IsStaffFor(ctx, obj, directive0, makerspaceIDField, nil) + } + + next = directive1 + return next + }, + func(ctx context.Context, selections ast.SelectionSet, v []*models.User) graphql.Marshaler { + return ec.marshalNUser2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐUserᚄ(ctx, selections, v) }, true, true, ) } -func (ec *executionContext) fieldContext_Makerspace_managerSubgroups(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Makerspace_staff(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Makerspace", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.childFields_Group(ctx, field) + return ec.childFields_User(ctx, field) }, } return fc, nil } -func (ec *executionContext) _Makerspace_staff(ctx context.Context, field graphql.CollectedField, obj *models.Makerspace) (ret graphql.Marshaler) { +func (ec *executionContext) _Makerspace_managerAnonymousGroup(ctx context.Context, field graphql.CollectedField, obj *models.Makerspace) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, ec.OperationContext, field, func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.fieldContext_Makerspace_staff(ctx, field) + return ec.fieldContext_Makerspace_managerAnonymousGroup(ctx, field) }, func(ctx context.Context) (any, error) { - return ec.Resolvers.Makerspace().Staff(ctx, obj) + return ec.Resolvers.Makerspace().ManagerAnonymousGroup(ctx, obj) }, - nil, - func(ctx context.Context, selections ast.SelectionSet, v []*models.User) graphql.Marshaler { - return ec.marshalNUser2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐUserᚄ(ctx, selections, v) + func(ctx context.Context, next graphql.Resolver) graphql.Resolver { + directive0 := next + + directive1 := func(ctx context.Context) (any, error) { + makerspaceIDField, err := ec.unmarshalOString2ᚖstring(ctx, "id") + if err != nil { + var zeroVal *models.AnonymousGroup + return zeroVal, err + } + if ec.Directives.IsManagerFor == nil { + var zeroVal *models.AnonymousGroup + return zeroVal, errors.New("directive isManagerFor is not implemented") + } + return ec.Directives.IsManagerFor(ctx, obj, directive0, makerspaceIDField, nil) + } + + next = directive1 + return next + }, + func(ctx context.Context, selections ast.SelectionSet, v *models.AnonymousGroup) graphql.Marshaler { + return ec.marshalOAnonymousGroup2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐAnonymousGroup(ctx, selections, v) }, true, - true, + false, ) } -func (ec *executionContext) fieldContext_Makerspace_staff(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Makerspace_managerAnonymousGroup(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Makerspace", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.childFields_User(ctx, field) + return ec.childFields_AnonymousGroup(ctx, field) }, } return fc, nil } -func (ec *executionContext) _Makerspace_staffSubgroups(ctx context.Context, field graphql.CollectedField, obj *models.Makerspace) (ret graphql.Marshaler) { +func (ec *executionContext) _Makerspace_staffAnonymousGroup(ctx context.Context, field graphql.CollectedField, obj *models.Makerspace) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, ec.OperationContext, field, func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.fieldContext_Makerspace_staffSubgroups(ctx, field) + return ec.fieldContext_Makerspace_staffAnonymousGroup(ctx, field) }, func(ctx context.Context) (any, error) { - return ec.Resolvers.Makerspace().StaffSubgroups(ctx, obj) + return ec.Resolvers.Makerspace().StaffAnonymousGroup(ctx, obj) }, - nil, - func(ctx context.Context, selections ast.SelectionSet, v []*models.Group) graphql.Marshaler { - return ec.marshalNGroup2ᚕᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐGroupᚄ(ctx, selections, v) + func(ctx context.Context, next graphql.Resolver) graphql.Resolver { + directive0 := next + + directive1 := func(ctx context.Context) (any, error) { + makerspaceIDField, err := ec.unmarshalOString2ᚖstring(ctx, "id") + if err != nil { + var zeroVal *models.AnonymousGroup + return zeroVal, err + } + if ec.Directives.IsManagerFor == nil { + var zeroVal *models.AnonymousGroup + return zeroVal, errors.New("directive isManagerFor is not implemented") + } + return ec.Directives.IsManagerFor(ctx, obj, directive0, makerspaceIDField, nil) + } + + next = directive1 + return next + }, + func(ctx context.Context, selections ast.SelectionSet, v *models.AnonymousGroup) graphql.Marshaler { + return ec.marshalOAnonymousGroup2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐAnonymousGroup(ctx, selections, v) }, true, - true, + false, ) } -func (ec *executionContext) fieldContext_Makerspace_staffSubgroups(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Makerspace_staffAnonymousGroup(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Makerspace", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.childFields_Group(ctx, field) + return ec.childFields_AnonymousGroup(ctx, field) }, } return fc, nil @@ -4985,7 +5122,20 @@ func (ec *executionContext) _Mutation_createMakerspace(ctx context.Context, fiel fc := graphql.GetFieldContext(ctx) return ec.Resolvers.Mutation().CreateMakerspace(ctx, fc.Args["name"].(string), fc.Args["hidden"].(bool)) }, - nil, + func(ctx context.Context, next graphql.Resolver) graphql.Resolver { + directive0 := next + + directive1 := func(ctx context.Context) (any, error) { + if ec.Directives.IsAdmin == nil { + var zeroVal int + return zeroVal, errors.New("directive isAdmin is not implemented") + } + return ec.Directives.IsAdmin(ctx, nil, directive0) + } + + next = directive1 + return next + }, func(ctx context.Context, selections ast.SelectionSet, v int) graphql.Marshaler { return ec.marshalNID2int(ctx, selections, v) }, @@ -5029,7 +5179,20 @@ func (ec *executionContext) _Mutation_deleteMakerspace(ctx context.Context, fiel fc := graphql.GetFieldContext(ctx) return ec.Resolvers.Mutation().DeleteMakerspace(ctx, fc.Args["id"].(int)) }, - nil, + func(ctx context.Context, next graphql.Resolver) graphql.Resolver { + directive0 := next + + directive1 := func(ctx context.Context) (any, error) { + if ec.Directives.IsAdmin == nil { + var zeroVal bool + return zeroVal, errors.New("directive isAdmin is not implemented") + } + return ec.Directives.IsAdmin(ctx, nil, directive0) + } + + next = directive1 + return next + }, func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { return ec.marshalNBoolean2bool(ctx, selections, v) }, @@ -5061,19 +5224,37 @@ func (ec *executionContext) fieldContext_Mutation_deleteMakerspace(ctx context.C return fc, nil } -func (ec *executionContext) _Mutation_SetAnonymousGroupSubgroups(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _Mutation_setManagerSubgroups(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, ec.OperationContext, field, func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.fieldContext_Mutation_SetAnonymousGroupSubgroups(ctx, field) + return ec.fieldContext_Mutation_setManagerSubgroups(ctx, field) }, func(ctx context.Context) (any, error) { fc := graphql.GetFieldContext(ctx) - return ec.Resolvers.Mutation().SetAnonymousGroupSubgroups(ctx, fc.Args["agroupID"].(int), fc.Args["subgroups"].([]int)) + return ec.Resolvers.Mutation().SetManagerSubgroups(ctx, fc.Args["makerspaceId"].(int), fc.Args["subgroups"].([]int)) + }, + func(ctx context.Context, next graphql.Resolver) graphql.Resolver { + directive0 := next + + directive1 := func(ctx context.Context) (any, error) { + makerspaceIDArg, err := ec.unmarshalOString2ᚖstring(ctx, "makerspaceId") + if err != nil { + var zeroVal bool + return zeroVal, err + } + if ec.Directives.IsManagerFor == nil { + var zeroVal bool + return zeroVal, errors.New("directive isManagerFor is not implemented") + } + return ec.Directives.IsManagerFor(ctx, nil, directive0, nil, makerspaceIDArg) + } + + next = directive1 + return next }, - nil, func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { return ec.marshalNBoolean2bool(ctx, selections, v) }, @@ -5081,7 +5262,7 @@ func (ec *executionContext) _Mutation_SetAnonymousGroupSubgroups(ctx context.Con true, ) } -func (ec *executionContext) fieldContext_Mutation_SetAnonymousGroupSubgroups(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Mutation_setManagerSubgroups(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Mutation", Field: field, @@ -5098,7 +5279,69 @@ func (ec *executionContext) fieldContext_Mutation_SetAnonymousGroupSubgroups(ctx } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Mutation_SetAnonymousGroupSubgroups_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Mutation_setManagerSubgroups_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_setStaffSubgroups(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Mutation_setStaffSubgroups(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Mutation().SetStaffSubgroups(ctx, fc.Args["makerspaceId"].(int), fc.Args["subgroups"].([]int)) + }, + func(ctx context.Context, next graphql.Resolver) graphql.Resolver { + directive0 := next + + directive1 := func(ctx context.Context) (any, error) { + makerspaceIDArg, err := ec.unmarshalOString2ᚖstring(ctx, "makerspaceId") + if err != nil { + var zeroVal bool + return zeroVal, err + } + if ec.Directives.IsManagerFor == nil { + var zeroVal bool + return zeroVal, errors.New("directive isManagerFor is not implemented") + } + return ec.Directives.IsManagerFor(ctx, nil, directive0, nil, makerspaceIDArg) + } + + next = directive1 + return next + }, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Mutation_setStaffSubgroups(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_setStaffSubgroups_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } @@ -5798,7 +6041,20 @@ func (ec *executionContext) _Query_user(ctx context.Context, field graphql.Colle fc := graphql.GetFieldContext(ctx) return ec.Resolvers.Query().User(ctx, fc.Args["id"].(int)) }, - nil, + func(ctx context.Context, next graphql.Resolver) graphql.Resolver { + directive0 := next + + directive1 := func(ctx context.Context) (any, error) { + if ec.Directives.IsSelf == nil { + var zeroVal *models.User + return zeroVal, errors.New("directive isSelf is not implemented") + } + return ec.Directives.IsSelf(ctx, nil, directive0) + } + + next = directive1 + return next + }, func(ctx context.Context, selections ast.SelectionSet, v *models.User) graphql.Marshaler { return ec.marshalNUser2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐUser(ctx, selections, v) }, @@ -7107,42 +7363,6 @@ func (ec *executionContext) fieldContext_User_force_archive(_ context.Context, f return graphql.NewScalarFieldContext("User", field, false, false, errors.New("field of type Boolean does not have child fields")) } -func (ec *executionContext) _User_card_tag(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { - return graphql.ResolveField( - ctx, - ec.OperationContext, - field, - func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return ec.fieldContext_User_card_tag(ctx, field) - }, - func(ctx context.Context) (any, error) { - return obj.CardTag, nil - }, - func(ctx context.Context, next graphql.Resolver) graphql.Resolver { - directive0 := next - - directive1 := func(ctx context.Context) (any, error) { - if ec.Directives.IsStaff == nil { - var zeroVal string - return zeroVal, errors.New("directive isStaff is not implemented") - } - return ec.Directives.IsStaff(ctx, obj, directive0) - } - - next = directive1 - return next - }, - func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { - return ec.marshalNString2string(ctx, selections, v) - }, - true, - true, - ) -} -func (ec *executionContext) fieldContext_User_card_tag(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - return graphql.NewScalarFieldContext("User", field, false, false, errors.New("field of type String does not have child fields")) -} - func (ec *executionContext) _Zone_id(ctx context.Context, field graphql.CollectedField, obj *models.Zone) (ret graphql.Marshaler) { return graphql.ResolveField( ctx, @@ -9755,7 +9975,7 @@ func (ec *executionContext) _Makerspace(ctx context.Context, sel ast.SelectionSe } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - case "managerSubgroups": + case "staff": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -9764,7 +9984,7 @@ func (ec *executionContext) _Makerspace(ctx context.Context, sel ast.SelectionSe ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Makerspace_managerSubgroups(ctx, field, obj) + res = ec._Makerspace_staff(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -9793,7 +10013,7 @@ func (ec *executionContext) _Makerspace(ctx context.Context, sel ast.SelectionSe } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - case "staff": + case "managerAnonymousGroup": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -9802,8 +10022,8 @@ func (ec *executionContext) _Makerspace(ctx context.Context, sel ast.SelectionSe ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Makerspace_staff(ctx, field, obj) - if res == graphql.Null { + res = ec._Makerspace_managerAnonymousGroup(ctx, field, obj) + if res == graphql.RequiredNull { atomic.AddUint32(&fs.Invalids, 1) } return res @@ -9831,7 +10051,7 @@ func (ec *executionContext) _Makerspace(ctx context.Context, sel ast.SelectionSe } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - case "staffSubgroups": + case "staffAnonymousGroup": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -9840,8 +10060,8 @@ func (ec *executionContext) _Makerspace(ctx context.Context, sel ast.SelectionSe ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Makerspace_staffSubgroups(ctx, field, obj) - if res == graphql.Null { + res = ec._Makerspace_staffAnonymousGroup(ctx, field, obj) + if res == graphql.RequiredNull { atomic.AddUint32(&fs.Invalids, 1) } return res @@ -10005,9 +10225,16 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } - case "SetAnonymousGroupSubgroups": + case "setManagerSubgroups": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_SetAnonymousGroupSubgroups(ctx, field) + return ec._Mutation_setManagerSubgroups(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "setStaffSubgroups": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_setStaffSubgroups(ctx, field) }) if out.Values[i] == graphql.Null { out.Invalids++ @@ -11077,11 +11304,6 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.RequiredNull { out.Invalids++ } - case "card_tag": - out.Values[i] = ec._User_card_tag(ctx, field, obj) - if out.Values[i] == graphql.Null { - out.Invalids++ - } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -12088,6 +12310,13 @@ func (ec *executionContext) marshalOAccessDevice2ᚖmakeᚑbackendᚋinternalᚋ return ec._AccessDevice(ctx, sel, v) } +func (ec *executionContext) marshalOAnonymousGroup2ᚖmakeᚑbackendᚋinternalᚋdatabaseᚋmodelsᚐAnonymousGroup(ctx context.Context, sel ast.SelectionSet, v *models.AnonymousGroup) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._AnonymousGroup(ctx, sel, v) +} + func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v any) (bool, error) { res, err := graphql.UnmarshalBoolean(v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/internal/gql/resolvers/group.resolvers.go b/internal/gql/resolvers/group.resolvers.go index 42907a33..e4e3d8ce 100644 --- a/internal/gql/resolvers/group.resolvers.go +++ b/internal/gql/resolvers/group.resolvers.go @@ -95,18 +95,6 @@ func (r *membershipToGroupResolver) User(ctx context.Context, obj *models.Member return r.Store.Users.GetUserById(ctx, obj.UserId) } -// SetAnonymousGroupSubgroups is the resolver for the SetAnonymousGroupSubgroups field. -func (r *mutationResolver) SetAnonymousGroupSubgroups(ctx context.Context, agroupID int, subgroups []int) (bool, error) { - if err := CanUserFromContextManageAnonymousGroup(r.Store, ctx, agroupID); err != nil { - return false, err - } - err := r.Store.Groups.SetGroupsForAnonymousGroup(ctx, agroupID, subgroups) - if err != nil { - return false, err - } - return true, nil -} - // Group is the resolver for the group field. func (r *queryResolver) Group(ctx context.Context, id int) (*models.Group, error) { how, err := CanUserFromContextSeeGroup(r.Store, ctx, id) diff --git a/internal/gql/resolvers/makerspace.resolvers.go b/internal/gql/resolvers/makerspace.resolvers.go index 74b3b3ae..11f3bace 100644 --- a/internal/gql/resolvers/makerspace.resolvers.go +++ b/internal/gql/resolvers/makerspace.resolvers.go @@ -48,19 +48,6 @@ func (r *makerspaceResolver) Managers(ctx context.Context, obj *models.Makerspac return SliceToPtrSlice(us), nil } -// ManagerSubgroups is the resolver for the managerSubgroups field. -func (r *makerspaceResolver) ManagerSubgroups(ctx context.Context, obj *models.Makerspace) ([]*models.Group, error) { - if err := CanUserFromContextManageAnonymousGroup(r.Store, ctx, obj.ManagementAgroupId); err != nil { - return nil, fmt.Errorf("cannot list manager subgroups: %w", err) - } - - sgs, err := r.Store.Groups.GroupsInAnonymousGroup(ctx, obj.ManagementAgroupId) - if err != nil { - return nil, err - } - return SliceToPtrSlice(sgs), nil -} - // Staff is the resolver for the staff field. func (r *makerspaceResolver) Staff(ctx context.Context, obj *models.Makerspace) ([]*models.User, error) { us, err := r.Store.Groups.UsersInAnonymousGroup(ctx, obj.StaffAgroupId) @@ -70,13 +57,14 @@ func (r *makerspaceResolver) Staff(ctx context.Context, obj *models.Makerspace) return SliceToPtrSlice(us), nil } -// StaffSubgroups is the resolver for the staffSubgroups field. -func (r *makerspaceResolver) StaffSubgroups(ctx context.Context, obj *models.Makerspace) ([]*models.Group, error) { - sgs, err := r.Store.Groups.GroupsInAnonymousGroup(ctx, obj.StaffAgroupId) - if err != nil { - return nil, err - } - return SliceToPtrSlice(sgs), nil +// ManagerAnonymousGroup is the resolver for the managerAnonymousGroup field. +func (r *makerspaceResolver) ManagerAnonymousGroup(ctx context.Context, obj *models.Makerspace) (*models.AnonymousGroup, error) { + panic(fmt.Errorf("not implemented: ManagerAnonymousGroup - managerAnonymousGroup")) +} + +// StaffAnonymousGroup is the resolver for the staffAnonymousGroup field. +func (r *makerspaceResolver) StaffAnonymousGroup(ctx context.Context, obj *models.Makerspace) (*models.AnonymousGroup, error) { + panic(fmt.Errorf("not implemented: StaffAnonymousGroup - staffAnonymousGroup")) } // CreateMakerspace is the resolver for the createMakerspace field. @@ -108,6 +96,34 @@ func (r *mutationResolver) DeleteMakerspace(ctx context.Context, id int) (bool, return success, err } +// SetManagerSubgroups is the resolver for the setManagerSubgroups field. +func (r *mutationResolver) SetManagerSubgroups(ctx context.Context, makerspaceID int, subgroups []int) (bool, error) { + makerspace, err := r.Store.Makerspaces.GetMakerspaceById(ctx, makerspaceID) + if err != nil { + return false, err + } + + err = r.Store.Groups.SetGroupsForAnonymousGroup(ctx, makerspace.ManagementAgroupId, subgroups) + if err != nil { + return false, err + } + return true, nil +} + +// SetStaffSubgroups is the resolver for the setStaffSubgroups field. +func (r *mutationResolver) SetStaffSubgroups(ctx context.Context, makerspaceID int, subgroups []int) (bool, error) { + makerspace, err := r.Store.Makerspaces.GetMakerspaceById(ctx, makerspaceID) + if err != nil { + return false, err + } + + err = r.Store.Groups.SetGroupsForAnonymousGroup(ctx, makerspace.StaffAgroupId, subgroups) + if err != nil { + return false, err + } + return true, nil +} + // Makerspace is the resolver for the makerspace field. func (r *queryResolver) Makerspace(ctx context.Context, id int) (*models.Makerspace, error) { makerspace, err := r.Store.Makerspaces.GetMakerspaceById(ctx, id) diff --git a/internal/gql/schema/group.graphqls b/internal/gql/schema/group.graphqls index f738502a..930a0761 100644 --- a/internal/gql/schema/group.graphqls +++ b/internal/gql/schema/group.graphqls @@ -47,6 +47,3 @@ extend type Query { canUserManageGroup(managerID: ID!, groupID: ID!): Boolean! } -extend type Mutation { - SetAnonymousGroupSubgroups(agroupID: ID!, subgroups: [Int!]!): Boolean! -} \ No newline at end of file diff --git a/internal/gql/schema/makerspace.graphqls b/internal/gql/schema/makerspace.graphqls index b5dd44b9..402ed70b 100644 --- a/internal/gql/schema/makerspace.graphqls +++ b/internal/gql/schema/makerspace.graphqls @@ -1,3 +1,5 @@ +directive @isManagerFor(makerspaceIdField: String, makerspaceIdArg: String) on FIELD_DEFINITION +directive @isStaffFor(makerspaceIdField: String, makerspaceIdArg: String) on FIELD_DEFINITION union MakerspaceHours = DefaultHours | SpecialHours @@ -13,11 +15,11 @@ type Makerspace { zones: [Zone!]! hours: [MakerspaceHours!]! - managers: [User!]! - managerSubgroups: [Group!]! + managers: [User!]! @isManagerFor(makerspaceIdField: "id") + staff: [User!]! @isStaffFor(makerspaceIdField: "id") - staff: [User!]! - staffSubgroups: [Group!]! + managerAnonymousGroup: AnonymousGroup @isManagerFor(makerspaceIdField: "id") + staffAnonymousGroup: AnonymousGroup @isManagerFor(makerspaceIdField: "id") } type Query { @@ -25,6 +27,9 @@ type Query { } type Mutation { - createMakerspace(name: String!, hidden: Boolean!): ID! - deleteMakerspace(id: ID!): Boolean! -} \ No newline at end of file + createMakerspace(name: String!, hidden: Boolean!): ID! @isAdmin + deleteMakerspace(id: ID!): Boolean! @isAdmin + + setManagerSubgroups(makerspaceId: ID!, subgroups: [Int!]!): Boolean! @isManagerFor(makerspaceIdArg: "makerspaceId") + setStaffSubgroups(makerspaceId: ID!, subgroups: [Int!]!): Boolean! @isManagerFor(makerspaceIdArg: "makerspaceId") +} diff --git a/internal/gql/schema/user.graphqls b/internal/gql/schema/user.graphqls index 2982fdb5..d9c2889c 100644 --- a/internal/gql/schema/user.graphqls +++ b/internal/gql/schema/user.graphqls @@ -1,16 +1,8 @@ scalar Time directive @isAdmin on FIELD_DEFINITION -directive @isManager on FIELD_DEFINITION -directive @isStaff on FIELD_DEFINITION -directive @isTrainer on FIELD_DEFINITION -# These directives REQUIRE the queries to have specific parameters in order to function properly -directive @isManagerFor on FIELD_DEFINITION # REQUIRES a makerspace_id parameter -directive @isStaffFor on FIELD_DEFINITION # REQUIRES a makerspace_id parameter -directive @isTrainerFor on FIELD_DEFINITION # REQUIRES an equipment_id parameter directive @isSelf on FIELD_DEFINITION # REQUIRES a target_id parameter -directive @isStaffOrSelf on FIELD_DEFINITION # REQUIRES a target_id parameter type User { id: ID! @@ -24,10 +16,9 @@ type User { notes: String! admin: Boolean! force_archive: Boolean - card_tag: String! @isStaff } extend type Query { - user(id: ID!): User! + user(id: ID!): User! @isSelf # isStaffOrSelf currentUser: User! } \ No newline at end of file diff --git a/internal/plugins/plugin_allowlist.go b/internal/plugins/plugin_allowlist.go index 6d74701a..7fd5971c 100644 --- a/internal/plugins/plugin_allowlist.go +++ b/internal/plugins/plugin_allowlist.go @@ -20,20 +20,6 @@ var wanted_plugins = []common.PluginDescription{ PluginType: common.PluginType_Notification, Options: map[string]string{}, }, - // { - // Name: "notification.core.linux_email", - // Version: 1, - // MagicValue: "904d74d0-24e7-49b8-a4f6-0914aa4edde8", - // Url: "", - // PluginType: PluginType_Notification, - // }, - // { - // Name: "auth.rit.shibboleth_sso", - // Version: 1, - // MagicValue: "904d74d0-24e7-49b8-a4f6-0914aa4edde8", - // Url: "", - // PluginType: PluginType_Notification, - // }, { Name: "auth.core.saml", Version: 1,