From 4d4c44f03d0c437fc57b4431f3615130366b9830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Egelund-M=C3=BCller?= Date: Mon, 26 Oct 2020 20:14:33 +0100 Subject: [PATCH] refactor backend project layout --- .gitignore | 2 +- .gitlab-ci.yml | 48 +- build/README.md | 2 +- build/{pipeline => backend}/Dockerfile | 2 +- build/control/Dockerfile | 15 - build/gateway/Dockerfile | 16 - build/taskqueue/Dockerfile | 14 - bus/README.md | 18 + bus/bus.go | 331 + clients/python/beneath/proto/gateway.proto | 2 +- cmd/README.md | 9 +- cmd/beneath/cli/cli.go | 50 + cmd/beneath/cli/config.go | 72 + cmd/beneath/cli/registry.go | 95 + cmd/beneath/cli/start.go | 65 + cmd/beneath/dependencies/control_migrate.go | 25 + cmd/beneath/dependencies/control_server.go | 71 + cmd/beneath/dependencies/control_worker.go | 43 + cmd/beneath/dependencies/data_server.go | 37 + cmd/beneath/dependencies/data_worker.go | 41 + cmd/beneath/dependencies/db.go | 37 + cmd/beneath/dependencies/engine.go | 47 + cmd/beneath/dependencies/hub.go | 19 + cmd/beneath/dependencies/mq.go | 24 + cmd/beneath/dependencies/redis.go | 22 + cmd/beneath/dependencies/services.go | 85 + cmd/beneath/main.go | 12 + cmd/control/main.go | 71 - cmd/dump/main.go | 36 - cmd/gateway/main.go | 107 - cmd/pipeline/main.go | 46 - cmd/taskqueue/main.go | 48 - {configs => config}/README.md | 0 config/config.yaml | 58 + configs/example.env | 36 - control/auth/goth.go | 61 - control/auth/router.go | 112 - control/entity/cleanup_instance_task.go | 39 - control/entity/cleanup_stream_task.go | 30 - control/entity/memberships.go | 91 - control/entity/organization.go | 439 - control/entity/organization_invite.go | 65 - control/entity/permissions.go | 228 - control/entity/permissions_cache.go | 188 - control/entity/project.go | 255 - control/entity/secret.go | 132 - control/entity/secret_anonymous.go | 102 - control/entity/secret_service.go | 125 - control/entity/secret_test.go | 47 - control/entity/secret_user.go | 145 - control/entity/service.go | 176 - control/entity/stream.go | 722 -- control/entity/stream_cache.go | 514 - .../entity/stream_current_instance_cache.go | 114 - control/entity/stream_index.go | 37 - control/entity/stream_instance.go | 83 - control/entity/user.go | 416 - control/entity/user_test.go | 30 - control/gql/gqlgen.yml | 57 - control/resolver/stream.go | 218 - control/server.go | 146 - control/taskqueue/taskqueue.go | 17 - control/taskqueue/types.go | 78 - control/taskqueue/worker/worker.go | 43 - ee/.gitignore | 1 + ee/config/config.yaml | 5 + {deployments => ee/deployments}/README.md | 0 .../deployments}/gitlab/README.md | 0 .../gitlab/admin-service-account.yaml | 0 .../deployments}/helm/README.md | 0 .../deployments}/helm/control/Chart.yaml | 0 .../helm/control/templates/_helpers.tpl | 0 .../helm/control/templates/deployment.yaml | 0 .../helm/control/templates/ingress.yaml | 0 .../helm/control/templates/service.yaml | 0 .../deployments}/helm/control/values.yaml | 0 .../deployments}/helm/gateway/Chart.yaml | 0 .../helm/gateway/templates/_helpers.tpl | 0 .../helm/gateway/templates/deployment.yaml | 0 .../helm/gateway/templates/ingress.yaml | 0 .../helm/gateway/templates/service.yaml | 0 .../deployments}/helm/gateway/values.yaml | 0 .../deployments}/helm/pipeline/Chart.yaml | 0 .../helm/pipeline/templates/_helpers.tpl | 0 .../helm/pipeline/templates/deployment.yaml | 0 .../deployments}/helm/pipeline/values.yaml | 0 .../deployments}/helm/taskqueue/Chart.yaml | 0 .../helm/taskqueue/templates/_helpers.tpl | 0 .../helm/taskqueue/templates/deployment.yaml | 0 .../deployments}/helm/taskqueue/values.yaml | 0 .../deployments}/helm/web/Chart.yaml | 0 .../helm/web/templates/_helpers.tpl | 0 .../helm/web/templates/deployment.yaml | 0 .../helm/web/templates/ingress.yaml | 0 .../helm/web/templates/service.yaml | 0 .../deployments}/helm/web/values.yaml | 0 .../deployments}/kube/README.md | 0 .../cert-manager/cluster-issuer-prod.yaml | 0 .../cert-manager/cluster-issuer-staging.yaml | 0 .../deployments}/kube/jupyterhub/Dockerfile | 0 .../deployments}/kube/jupyterhub/deploy.sh | 0 .../kube/jupyterhub/helm/config.yaml | 0 .../kube/jupyterhub/jupyter/Dockerfile | 0 .../jupyter/jupyter_notebook_config.py | 0 .../kube/test/test-resources.yaml | 0 .../deployments}/metabase/README.md | 0 .../deployments}/metabase/values.yaml | 0 .../payments/driver/anarchism/anarchism.go | 2 +- .../infrastructure}/payments/driver/driver.go | 0 .../payments/driver/stripecard/stripecard.go | 4 +- .../payments/driver/stripeutil/stripeutil.go | 2 +- .../payments/driver/stripewire/stripewire.go | 4 +- .../infrastructure}/payments/payments.go | 8 +- {pkg => ee/pkg}/paymentsutil/paymentsutil.go | 0 ee/server/control/gql/gqlgen.yml | 25 + .../control}/resolver/billed_resource.go | 6 +- .../server/control}/resolver/billing_info.go | 8 +- .../control}/resolver/billing_method.go | 6 +- .../server/control}/resolver/billing_plan.go | 2 +- ee/server/control/schema/base.graphql | 10 + .../control}/schema/billed_resources.graphql | 0 .../control}/schema/billing_info.graphql | 0 .../control}/schema/billing_method.graphql | 0 .../control}/schema/billing_plans.graphql | 0 ee/server/control/server.go | 9 + ee/services/bi/bi.go | 37 + ee/services/billing/billing.go | 117 + {control => ee/services}/entity/base.go | 0 .../services}/entity/billed_resources.go | 0 .../services}/entity/billing_info.go | 5 +- .../services}/entity/billing_method.go | 0 .../services}/entity/billing_plan.go | 0 .../services}/entity/billing_task_a_run.go | 9 +- .../billing_task_b_compute_bill_resources.go | 11 +- .../entity/billing_task_c_send_invoice.go | 8 +- {control => ee/services}/entity/util.go | 0 {control => ee/services}/entity/validate.go | 0 engine/control_events.go | 54 - engine/driver/bigquery/bigquery.go | 65 - engine/driver/mock/mock.go | 13 - engine/driver/mock/service.go | 52 - engine/driver/postgres/postgres.go | 41 - engine/driver/postgres/service.go | 52 - engine/driver/pubsub/pubsub.go | 64 - engine/engine.go | 160 - engine/proto/taskqueue.pb.go | 105 - engine/proto/taskqueue.proto | 10 - engine/service.go | 90 - engine/tasks.go | 39 - gateway/gateway.go | 27 - gateway/grpc/subscription.go | 71 - gateway/http/server.go | 107 - gateway/http/subscription.go | 183 - gateway/subscriptions/broker.go | 124 - go.mod | 32 +- go.sum | 490 + hub/hub.go | 55 - hub/pg.go | 34 - hub/redis.go | 15 - infrastructure/db/db.go | 82 + infrastructure/db/util.go | 18 + {engine => infrastructure/engine}/README.md | 0 .../engine}/driver/README.md | 0 .../engine/driver/bigquery/bigquery.go | 66 + .../driver/bigquery/proto/bigquery.pb.go | 31 +- .../driver/bigquery/proto/bigquery.proto | 0 .../engine}/driver/bigquery/query.go | 4 +- .../engine}/driver/bigquery/service.go | 26 +- .../engine}/driver/bigquery/util.go | 0 .../engine}/driver/bigquery/warehouse.go | 2 +- .../engine}/driver/bigtable/bigtable.go | 86 +- .../engine}/driver/bigtable/bigtable_test.go | 0 .../engine}/driver/bigtable/loading.go | 2 +- .../engine}/driver/bigtable/lookup.go | 6 +- .../driver/bigtable/proto/cursor.pb.go | 54 +- .../driver/bigtable/proto/cursor.proto | 0 .../engine}/driver/bigtable/schema.go | 0 .../driver/bigtable/sequencer/sequencer.go | 0 .../bigtable/sequencer/sequencer_test.go | 0 .../engine}/driver/bigtable/service.go | 21 +- .../engine}/driver/bigtable/usage.go | 2 +- .../engine}/driver/bigtable/util.go | 2 +- .../engine}/driver/bigtable/util_test.go | 0 .../engine}/driver/driver.go | 208 +- infrastructure/engine/driver/mock/mock.go | 27 + infrastructure/engine/driver/mock/service.go | 37 + .../engine}/driver/mock/util.go | 4 +- .../engine}/driver/mock/warehouse.go | 2 +- .../engine}/driver/postgres/lookup.go | 2 +- .../engine/driver/postgres/postgres.go | 41 + .../engine/driver/postgres/service.go | 37 + .../engine}/driver/postgres/usage.go | 2 +- .../engine}/driver/postgres/warehouse.go | 2 +- infrastructure/engine/engine.go | 148 + {engine => infrastructure/engine}/metrics.go | 2 +- .../engine}/proto/engine.pb.go | 47 +- .../engine}/proto/engine.proto | 4 +- .../engine}/proto/quota.pb.go | 45 +- .../engine}/proto/quota.proto | 2 +- infrastructure/engine/proto/taskqueue.pb.go | 108 + infrastructure/engine/proto/taskqueue.proto | 10 + {engine => infrastructure/engine}/query.go | 2 +- .../engine}/query_test.go | 4 +- infrastructure/engine/service.go | 43 + .../mq}/driver/pubsub/mq.go | 19 +- infrastructure/mq/driver/pubsub/pubsub.go | 59 + infrastructure/mq/mq.go | 54 + infrastructure/mq/write.go | 67 + infrastructure/redis/redis.go | 21 + internal/README.md | 3 - internal/metrics/reader.go | 65 - .../001_organization.go | 0 .../migrations => migrations}/002_project.go | 0 .../migrations => migrations}/003_user.go | 0 .../migrations => migrations}/004_stream.go | 0 .../migrations => migrations}/005_service.go | 0 .../migrations => migrations}/006_secret.go | 0 .../migrations => migrations}/007_model.go | 0 .../008_service_dates.go | 0 .../009_organization_unique.go | 0 .../010_project_display_name.go | 0 .../011_service_unique.go | 0 .../012_stream_instances_counts.go | 0 .../013_better_secrets.go | 0 .../migrations => migrations}/014_billing.go | 0 .../015_stream_retention.go | 0 .../016_stream_index.go | 0 .../017_project_index.go | 0 .../018_two_organizations.go | 0 .../019_billing_method.go | 0 .../migrations => migrations}/020_tax_info.go | 0 .../021_master_users.go | 0 .../022_nullable_billing_method.go | 0 .../023_organization_invite.go | 0 .../024_user_org_perms_create.go | 0 .../025_organization_quotas.go | 0 .../026_user_details_to_organization.go | 0 .../027_billing_plan_quotas.go | 0 .../028_rm_entity_name.go | 0 .../029_prepaid_quotas.go | 0 .../030_billing_floats.go | 0 .../031_billing_plan_base_price.go | 0 .../032_streams_tidy_up.go | 0 .../033_billing_plan_multiple_users.go | 0 .../034_user_consent.go | 0 .../035_streams_options.go | 0 .../036_drop_models.go | 0 .../037_services_to_projects.go | 0 .../038_instance_versions.go | 0 .../039_scan_quotas.go | 0 .../040_different_stream_schema_types.go | 0 .../041_featured_projects.go | 0 .../migrations => migrations}/migrations.go | 0 models/README.md | 7 + models/organization.go | 178 + models/permission.go | 67 + models/project.go | 98 + models/secret.go | 265 + models/service.go | 59 + models/stream.go | 371 + models/user.go | 47 + models/validate.go | 6 + pkg/envutil/config.go | 27 - pkg/grpcutil/grpcutil.go | 32 + pkg/httputil/httputil.go | 27 + scripts/gqlgen-control.sh | 2 +- scripts/proto-build.sh | 8 +- {control => server/control}/README.md | 0 server/control/auth.go | 142 + server/control/gql/gqlgen.yml | 48 + {control => server/control}/gql/models_gen.go | 12 +- {control => server/control}/gql/schema_gen.go | 10643 ++++++---------- {control => server/control}/gql/uuid.go | 0 .../control}/resolver/memberships.go | 12 +- .../control}/resolver/metrics.go | 40 +- .../control}/resolver/metrics_test.go | 2 +- .../control}/resolver/organization.go | 128 +- .../control}/resolver/project.go | 84 +- .../control}/resolver/resolver.go | 21 +- .../control}/resolver/secret.go | 44 +- .../control}/resolver/service.go | 57 +- server/control/resolver/stream.go | 268 + .../control}/resolver/stream_index.go | 6 +- .../control}/resolver/stream_instance.go | 6 +- {control => server/control}/resolver/user.go | 46 +- {control => server/control}/resolver/util.go | 2 +- .../control}/schema/base.graphql | 0 .../control}/schema/metrics.graphql | 0 .../control}/schema/organizations.graphql | 0 .../control}/schema/projects.graphql | 0 .../control}/schema/secrets.graphql | 0 .../control}/schema/services.graphql | 0 .../control}/schema/streams.graphql | 0 .../control}/schema/users.graphql | 0 server/control/server.go | 204 + {gateway => server/data}/README.md | 0 {gateway => server/data}/grpc/ping.go | 6 +- .../data}/grpc/proto/gateway.pb.go | 186 +- .../data}/grpc/proto/gateway.proto | 2 +- {gateway => server/data}/grpc/query.go | 8 +- {gateway => server/data}/grpc/read.go | 6 +- {gateway => server/data}/grpc/server.go | 17 +- server/data/grpc/subscription.go | 45 + {gateway => server/data}/grpc/warehouse.go | 12 +- {gateway => server/data}/grpc/write.go | 10 +- {gateway => server/data}/http/ping.go | 6 +- {gateway => server/data}/http/query.go | 25 +- {gateway => server/data}/http/read.go | 10 +- server/data/http/server.go | 122 + server/data/http/subscription.go | 153 + {gateway => server/data}/http/warehouse.go | 14 +- {gateway => server/data}/http/write.go | 21 +- server/data/server.go | 65 + .../data}/clientversion/clientversion.go | 0 {gateway/util => services/data}/cursor.go | 19 +- services/data/data.go | 44 + .../index.go => services/data/handle_index.go | 20 +- .../api/log.go => services/data/handle_log.go | 26 +- .../ping.go => services/data/handle_ping.go | 8 +- .../read.go => services/data/handle_read.go | 34 +- services/data/handle_subscribe.go | 71 + .../data/handle_warehouse.go | 36 +- .../write.go => services/data/handle_write.go | 44 +- engine/writes.go => services/data/mq.go | 30 +- services/data/subscriptions.go | 119 + {gateway/util => services/data}/usage.go | 49 +- {gateway/api => services/data}/util.go | 19 +- .../pipeline.go => services/data/worker.go | 31 +- services/metrics/broker.go | 53 + services/metrics/reading.go | 109 + .../broker.go => services/metrics/writing.go | 104 +- {internal => services}/middleware/auth.go | 28 +- .../middleware/ipratelimiting.go | 77 +- {internal => services}/middleware/logger.go | 10 +- services/middleware/middleware.go | 25 + .../middleware/recoverer.go | 10 +- {internal => services}/middleware/tags.go | 52 +- services/organization/crud.go | 149 + services/organization/invites.go | 59 + services/organization/organization.go | 116 + services/organization/transfer.go | 87 + services/permissions/cache.go | 149 + services/permissions/permissions.go | 205 + services/permissions/secrets.go | 91 + services/project/project.go | 224 + services/project/starter.go | 30 + .../secret/cache.go | 105 +- services/secret/crud.go | 89 + services/secret/events.go | 27 + services/secret/secret.go | 83 + services/service/service.go | 161 + services/stream/cached_stream.go | 159 + services/stream/compile.go | 121 + services/stream/events.go | 87 + services/stream/instance_cache.go | 202 + services/stream/instances.go | 239 + services/stream/name_cache.go | 108 + services/stream/stream.go | 40 + services/stream/streams.go | 244 + services/stream/util.go | 8 + services/user/create.go | 234 + services/user/update.go | 76 + services/user/user.go | 37 + services/user/username_seeds.go | 71 + test/integration/integration_test.go | 12 +- .../stream_create_read_write_test.go | 2 +- 366 files changed, 13034 insertions(+), 14811 deletions(-) rename build/{pipeline => backend}/Dockerfile (78%) delete mode 100644 build/control/Dockerfile delete mode 100644 build/gateway/Dockerfile delete mode 100644 build/taskqueue/Dockerfile create mode 100644 bus/README.md create mode 100644 bus/bus.go create mode 100644 cmd/beneath/cli/cli.go create mode 100644 cmd/beneath/cli/config.go create mode 100644 cmd/beneath/cli/registry.go create mode 100644 cmd/beneath/cli/start.go create mode 100644 cmd/beneath/dependencies/control_migrate.go create mode 100644 cmd/beneath/dependencies/control_server.go create mode 100644 cmd/beneath/dependencies/control_worker.go create mode 100644 cmd/beneath/dependencies/data_server.go create mode 100644 cmd/beneath/dependencies/data_worker.go create mode 100644 cmd/beneath/dependencies/db.go create mode 100644 cmd/beneath/dependencies/engine.go create mode 100644 cmd/beneath/dependencies/hub.go create mode 100644 cmd/beneath/dependencies/mq.go create mode 100644 cmd/beneath/dependencies/redis.go create mode 100644 cmd/beneath/dependencies/services.go create mode 100644 cmd/beneath/main.go delete mode 100644 cmd/control/main.go delete mode 100644 cmd/dump/main.go delete mode 100644 cmd/gateway/main.go delete mode 100644 cmd/pipeline/main.go delete mode 100644 cmd/taskqueue/main.go rename {configs => config}/README.md (100%) create mode 100644 config/config.yaml delete mode 100644 configs/example.env delete mode 100644 control/auth/goth.go delete mode 100644 control/auth/router.go delete mode 100644 control/entity/cleanup_instance_task.go delete mode 100644 control/entity/cleanup_stream_task.go delete mode 100644 control/entity/memberships.go delete mode 100644 control/entity/organization.go delete mode 100644 control/entity/organization_invite.go delete mode 100644 control/entity/permissions.go delete mode 100644 control/entity/permissions_cache.go delete mode 100644 control/entity/project.go delete mode 100644 control/entity/secret.go delete mode 100644 control/entity/secret_anonymous.go delete mode 100644 control/entity/secret_service.go delete mode 100644 control/entity/secret_test.go delete mode 100644 control/entity/secret_user.go delete mode 100644 control/entity/service.go delete mode 100644 control/entity/stream.go delete mode 100644 control/entity/stream_cache.go delete mode 100644 control/entity/stream_current_instance_cache.go delete mode 100644 control/entity/stream_index.go delete mode 100644 control/entity/stream_instance.go delete mode 100644 control/entity/user.go delete mode 100644 control/entity/user_test.go delete mode 100644 control/gql/gqlgen.yml delete mode 100644 control/resolver/stream.go delete mode 100644 control/server.go delete mode 100644 control/taskqueue/taskqueue.go delete mode 100644 control/taskqueue/types.go delete mode 100644 control/taskqueue/worker/worker.go create mode 100644 ee/.gitignore create mode 100644 ee/config/config.yaml rename {deployments => ee/deployments}/README.md (100%) rename {deployments => ee/deployments}/gitlab/README.md (100%) rename {deployments => ee/deployments}/gitlab/admin-service-account.yaml (100%) rename {deployments => ee/deployments}/helm/README.md (100%) rename {deployments => ee/deployments}/helm/control/Chart.yaml (100%) rename {deployments => ee/deployments}/helm/control/templates/_helpers.tpl (100%) rename {deployments => ee/deployments}/helm/control/templates/deployment.yaml (100%) rename {deployments => ee/deployments}/helm/control/templates/ingress.yaml (100%) rename {deployments => ee/deployments}/helm/control/templates/service.yaml (100%) rename {deployments => ee/deployments}/helm/control/values.yaml (100%) rename {deployments => ee/deployments}/helm/gateway/Chart.yaml (100%) rename {deployments => ee/deployments}/helm/gateway/templates/_helpers.tpl (100%) rename {deployments => ee/deployments}/helm/gateway/templates/deployment.yaml (100%) rename {deployments => ee/deployments}/helm/gateway/templates/ingress.yaml (100%) rename {deployments => ee/deployments}/helm/gateway/templates/service.yaml (100%) rename {deployments => ee/deployments}/helm/gateway/values.yaml (100%) rename {deployments => ee/deployments}/helm/pipeline/Chart.yaml (100%) rename {deployments => ee/deployments}/helm/pipeline/templates/_helpers.tpl (100%) rename {deployments => ee/deployments}/helm/pipeline/templates/deployment.yaml (100%) rename {deployments => ee/deployments}/helm/pipeline/values.yaml (100%) rename {deployments => ee/deployments}/helm/taskqueue/Chart.yaml (100%) rename {deployments => ee/deployments}/helm/taskqueue/templates/_helpers.tpl (100%) rename {deployments => ee/deployments}/helm/taskqueue/templates/deployment.yaml (100%) rename {deployments => ee/deployments}/helm/taskqueue/values.yaml (100%) rename {deployments => ee/deployments}/helm/web/Chart.yaml (100%) rename {deployments => ee/deployments}/helm/web/templates/_helpers.tpl (100%) rename {deployments => ee/deployments}/helm/web/templates/deployment.yaml (100%) rename {deployments => ee/deployments}/helm/web/templates/ingress.yaml (100%) rename {deployments => ee/deployments}/helm/web/templates/service.yaml (100%) rename {deployments => ee/deployments}/helm/web/values.yaml (100%) rename {deployments => ee/deployments}/kube/README.md (100%) rename {deployments => ee/deployments}/kube/cert-manager/cluster-issuer-prod.yaml (100%) rename {deployments => ee/deployments}/kube/cert-manager/cluster-issuer-staging.yaml (100%) rename {deployments => ee/deployments}/kube/jupyterhub/Dockerfile (100%) rename {deployments => ee/deployments}/kube/jupyterhub/deploy.sh (100%) rename {deployments => ee/deployments}/kube/jupyterhub/helm/config.yaml (100%) rename {deployments => ee/deployments}/kube/jupyterhub/jupyter/Dockerfile (100%) rename {deployments => ee/deployments}/kube/jupyterhub/jupyter/jupyter_notebook_config.py (100%) rename {deployments => ee/deployments}/kube/test/test-resources.yaml (100%) rename {deployments => ee/deployments}/metabase/README.md (100%) rename {deployments => ee/deployments}/metabase/values.yaml (100%) rename {control => ee/infrastructure}/payments/driver/anarchism/anarchism.go (92%) rename {control => ee/infrastructure}/payments/driver/driver.go (100%) rename {control => ee/infrastructure}/payments/driver/stripecard/stripecard.go (98%) rename {control => ee/infrastructure}/payments/driver/stripeutil/stripeutil.go (99%) rename {control => ee/infrastructure}/payments/driver/stripewire/stripewire.go (96%) rename {control => ee/infrastructure}/payments/payments.go (64%) rename {pkg => ee/pkg}/paymentsutil/paymentsutil.go (100%) create mode 100644 ee/server/control/gql/gqlgen.yml rename {control => ee/server/control}/resolver/billed_resource.go (89%) rename {control => ee/server/control}/resolver/billing_info.go (90%) rename {control => ee/server/control}/resolver/billing_method.go (86%) rename {control => ee/server/control}/resolver/billing_plan.go (95%) create mode 100644 ee/server/control/schema/base.graphql rename {control/gql => ee/server/control}/schema/billed_resources.graphql (100%) rename {control/gql => ee/server/control}/schema/billing_info.graphql (100%) rename {control/gql => ee/server/control}/schema/billing_method.graphql (100%) rename {control/gql => ee/server/control}/schema/billing_plans.graphql (100%) create mode 100644 ee/server/control/server.go create mode 100644 ee/services/bi/bi.go create mode 100644 ee/services/billing/billing.go rename {control => ee/services}/entity/base.go (100%) rename {control => ee/services}/entity/billed_resources.go (100%) rename {control => ee/services}/entity/billing_info.go (97%) rename {control => ee/services}/entity/billing_method.go (100%) rename {control => ee/services}/entity/billing_plan.go (100%) rename {control => ee/services}/entity/billing_task_a_run.go (81%) rename {control => ee/services}/entity/billing_task_b_compute_bill_resources.go (96%) rename {control => ee/services}/entity/billing_task_c_send_invoice.go (89%) rename {control => ee/services}/entity/util.go (100%) rename {control => ee/services}/entity/validate.go (100%) delete mode 100644 engine/control_events.go delete mode 100644 engine/driver/bigquery/bigquery.go delete mode 100644 engine/driver/mock/mock.go delete mode 100644 engine/driver/mock/service.go delete mode 100644 engine/driver/postgres/postgres.go delete mode 100644 engine/driver/postgres/service.go delete mode 100644 engine/driver/pubsub/pubsub.go delete mode 100644 engine/engine.go delete mode 100644 engine/proto/taskqueue.pb.go delete mode 100644 engine/proto/taskqueue.proto delete mode 100644 engine/service.go delete mode 100644 engine/tasks.go delete mode 100644 gateway/gateway.go delete mode 100644 gateway/grpc/subscription.go delete mode 100644 gateway/http/server.go delete mode 100644 gateway/http/subscription.go delete mode 100644 gateway/subscriptions/broker.go delete mode 100644 hub/hub.go delete mode 100644 hub/pg.go delete mode 100644 hub/redis.go create mode 100644 infrastructure/db/db.go create mode 100644 infrastructure/db/util.go rename {engine => infrastructure/engine}/README.md (100%) rename {engine => infrastructure/engine}/driver/README.md (100%) create mode 100644 infrastructure/engine/driver/bigquery/bigquery.go rename {engine => infrastructure/engine}/driver/bigquery/proto/bigquery.pb.go (63%) rename {engine => infrastructure/engine}/driver/bigquery/proto/bigquery.proto (100%) rename {engine => infrastructure/engine}/driver/bigquery/query.go (98%) rename {engine => infrastructure/engine}/driver/bigquery/service.go (67%) rename {engine => infrastructure/engine}/driver/bigquery/util.go (100%) rename {engine => infrastructure/engine}/driver/bigquery/warehouse.go (97%) rename {engine => infrastructure/engine}/driver/bigtable/bigtable.go (72%) rename {engine => infrastructure/engine}/driver/bigtable/bigtable_test.go (100%) rename {engine => infrastructure/engine}/driver/bigtable/loading.go (99%) rename {engine => infrastructure/engine}/driver/bigtable/lookup.go (98%) rename {engine => infrastructure/engine}/driver/bigtable/proto/cursor.pb.go (68%) rename {engine => infrastructure/engine}/driver/bigtable/proto/cursor.proto (100%) rename {engine => infrastructure/engine}/driver/bigtable/schema.go (100%) rename {engine => infrastructure/engine}/driver/bigtable/sequencer/sequencer.go (100%) rename {engine => infrastructure/engine}/driver/bigtable/sequencer/sequencer_test.go (100%) rename {engine => infrastructure/engine}/driver/bigtable/service.go (72%) rename {engine => infrastructure/engine}/driver/bigtable/usage.go (98%) rename {engine => infrastructure/engine}/driver/bigtable/util.go (97%) rename {engine => infrastructure/engine}/driver/bigtable/util_test.go (100%) rename {engine => infrastructure/engine}/driver/driver.go (85%) create mode 100644 infrastructure/engine/driver/mock/mock.go create mode 100644 infrastructure/engine/driver/mock/service.go rename {engine => infrastructure/engine}/driver/mock/util.go (83%) rename {engine => infrastructure/engine}/driver/mock/warehouse.go (95%) rename {engine => infrastructure/engine}/driver/postgres/lookup.go (95%) create mode 100644 infrastructure/engine/driver/postgres/postgres.go create mode 100644 infrastructure/engine/driver/postgres/service.go rename {engine => infrastructure/engine}/driver/postgres/usage.go (93%) rename {engine => infrastructure/engine}/driver/postgres/warehouse.go (95%) create mode 100644 infrastructure/engine/engine.go rename {engine => infrastructure/engine}/metrics.go (94%) rename {engine => infrastructure/engine}/proto/engine.pb.go (68%) rename {engine => infrastructure/engine}/proto/engine.proto (67%) rename {engine => infrastructure/engine}/proto/quota.pb.go (65%) rename {engine => infrastructure/engine}/proto/quota.proto (75%) create mode 100644 infrastructure/engine/proto/taskqueue.pb.go create mode 100644 infrastructure/engine/proto/taskqueue.proto rename {engine => infrastructure/engine}/query.go (97%) rename {engine => infrastructure/engine}/query_test.go (94%) create mode 100644 infrastructure/engine/service.go rename {engine => infrastructure/mq}/driver/pubsub/mq.go (91%) create mode 100644 infrastructure/mq/driver/pubsub/pubsub.go create mode 100644 infrastructure/mq/mq.go create mode 100644 infrastructure/mq/write.go create mode 100644 infrastructure/redis/redis.go delete mode 100644 internal/README.md delete mode 100644 internal/metrics/reader.go rename {control/migrations => migrations}/001_organization.go (100%) rename {control/migrations => migrations}/002_project.go (100%) rename {control/migrations => migrations}/003_user.go (100%) rename {control/migrations => migrations}/004_stream.go (100%) rename {control/migrations => migrations}/005_service.go (100%) rename {control/migrations => migrations}/006_secret.go (100%) rename {control/migrations => migrations}/007_model.go (100%) rename {control/migrations => migrations}/008_service_dates.go (100%) rename {control/migrations => migrations}/009_organization_unique.go (100%) rename {control/migrations => migrations}/010_project_display_name.go (100%) rename {control/migrations => migrations}/011_service_unique.go (100%) rename {control/migrations => migrations}/012_stream_instances_counts.go (100%) rename {control/migrations => migrations}/013_better_secrets.go (100%) rename {control/migrations => migrations}/014_billing.go (100%) rename {control/migrations => migrations}/015_stream_retention.go (100%) rename {control/migrations => migrations}/016_stream_index.go (100%) rename {control/migrations => migrations}/017_project_index.go (100%) rename {control/migrations => migrations}/018_two_organizations.go (100%) rename {control/migrations => migrations}/019_billing_method.go (100%) rename {control/migrations => migrations}/020_tax_info.go (100%) rename {control/migrations => migrations}/021_master_users.go (100%) rename {control/migrations => migrations}/022_nullable_billing_method.go (100%) rename {control/migrations => migrations}/023_organization_invite.go (100%) rename {control/migrations => migrations}/024_user_org_perms_create.go (100%) rename {control/migrations => migrations}/025_organization_quotas.go (100%) rename {control/migrations => migrations}/026_user_details_to_organization.go (100%) rename {control/migrations => migrations}/027_billing_plan_quotas.go (100%) rename {control/migrations => migrations}/028_rm_entity_name.go (100%) rename {control/migrations => migrations}/029_prepaid_quotas.go (100%) rename {control/migrations => migrations}/030_billing_floats.go (100%) rename {control/migrations => migrations}/031_billing_plan_base_price.go (100%) rename {control/migrations => migrations}/032_streams_tidy_up.go (100%) rename {control/migrations => migrations}/033_billing_plan_multiple_users.go (100%) rename {control/migrations => migrations}/034_user_consent.go (100%) rename {control/migrations => migrations}/035_streams_options.go (100%) rename {control/migrations => migrations}/036_drop_models.go (100%) rename {control/migrations => migrations}/037_services_to_projects.go (100%) rename {control/migrations => migrations}/038_instance_versions.go (100%) rename {control/migrations => migrations}/039_scan_quotas.go (100%) rename {control/migrations => migrations}/040_different_stream_schema_types.go (100%) rename {control/migrations => migrations}/041_featured_projects.go (100%) rename {control/migrations => migrations}/migrations.go (100%) create mode 100644 models/README.md create mode 100644 models/organization.go create mode 100644 models/permission.go create mode 100644 models/project.go create mode 100644 models/secret.go create mode 100644 models/service.go create mode 100644 models/stream.go create mode 100644 models/user.go create mode 100644 models/validate.go create mode 100644 pkg/grpcutil/grpcutil.go rename {control => server/control}/README.md (100%) create mode 100644 server/control/auth.go create mode 100644 server/control/gql/gqlgen.yml rename {control => server/control}/gql/models_gen.go (90%) rename {control => server/control}/gql/schema_gen.go (62%) rename {control => server/control}/gql/uuid.go (100%) rename {control => server/control}/resolver/memberships.go (75%) rename {control => server/control}/resolver/metrics.go (77%) rename {control => server/control}/resolver/metrics_test.go (97%) rename {control => server/control}/resolver/organization.go (66%) rename {control => server/control}/resolver/project.go (61%) rename {control => server/control}/resolver/resolver.go (61%) rename {control => server/control}/resolver/secret.go (70%) rename {control => server/control}/resolver/service.go (59%) create mode 100644 server/control/resolver/stream.go rename {control => server/control}/resolver/stream_index.go (72%) rename {control => server/control}/resolver/stream_instance.go (71%) rename {control => server/control}/resolver/user.go (62%) rename {control => server/control}/resolver/util.go (95%) rename {control/gql => server/control}/schema/base.graphql (100%) rename {control/gql => server/control}/schema/metrics.graphql (100%) rename {control/gql => server/control}/schema/organizations.graphql (100%) rename {control/gql => server/control}/schema/projects.graphql (100%) rename {control/gql => server/control}/schema/secrets.graphql (100%) rename {control/gql => server/control}/schema/services.graphql (100%) rename {control/gql => server/control}/schema/streams.graphql (100%) rename {control/gql => server/control}/schema/users.graphql (100%) create mode 100644 server/control/server.go rename {gateway => server/data}/README.md (100%) rename {gateway => server/data}/grpc/ping.go (71%) rename {gateway => server/data}/grpc/proto/gateway.pb.go (85%) rename {gateway => server/data}/grpc/proto/gateway.proto (96%) rename {gateway => server/data}/grpc/query.go (83%) rename {gateway => server/data}/grpc/read.go (67%) rename {gateway => server/data}/grpc/server.go (72%) create mode 100644 server/data/grpc/subscription.go rename {gateway => server/data}/grpc/warehouse.go (83%) rename {gateway => server/data}/grpc/write.go (70%) rename {gateway => server/data}/http/ping.go (81%) rename {gateway => server/data}/http/query.go (80%) rename {gateway => server/data}/http/read.go (83%) create mode 100644 server/data/http/server.go create mode 100644 server/data/http/subscription.go rename {gateway => server/data}/http/warehouse.go (84%) rename {gateway => server/data}/http/write.go (67%) create mode 100644 server/data/server.go rename {gateway => services/data}/clientversion/clientversion.go (100%) rename {gateway/util => services/data}/cursor.go (78%) create mode 100644 services/data/data.go rename gateway/api/index.go => services/data/handle_index.go (66%) rename gateway/api/log.go => services/data/handle_log.go (60%) rename gateway/api/ping.go => services/data/handle_ping.go (85%) rename gateway/api/read.go => services/data/handle_read.go (76%) create mode 100644 services/data/handle_subscribe.go rename gateway/api/warehouse.go => services/data/handle_warehouse.go (80%) rename gateway/api/write.go => services/data/handle_write.go (81%) rename engine/writes.go => services/data/mq.go (60%) create mode 100644 services/data/subscriptions.go rename {gateway/util => services/data}/usage.go (59%) rename {gateway/api => services/data}/util.go (64%) rename gateway/pipeline/pipeline.go => services/data/worker.go (76%) create mode 100644 services/metrics/broker.go create mode 100644 services/metrics/reading.go rename internal/metrics/broker.go => services/metrics/writing.go (52%) rename {internal => services}/middleware/auth.go (72%) rename {internal => services}/middleware/ipratelimiting.go (55%) rename {internal => services}/middleware/logger.go (86%) create mode 100644 services/middleware/middleware.go rename {internal => services}/middleware/recoverer.go (80%) rename {internal => services}/middleware/tags.go (82%) create mode 100644 services/organization/crud.go create mode 100644 services/organization/invites.go create mode 100644 services/organization/organization.go create mode 100644 services/organization/transfer.go create mode 100644 services/permissions/cache.go create mode 100644 services/permissions/permissions.go create mode 100644 services/permissions/secrets.go create mode 100644 services/project/project.go create mode 100644 services/project/starter.go rename control/entity/secret_cache.go => services/secret/cache.go (67%) create mode 100644 services/secret/crud.go create mode 100644 services/secret/events.go create mode 100644 services/secret/secret.go create mode 100644 services/service/service.go create mode 100644 services/stream/cached_stream.go create mode 100644 services/stream/compile.go create mode 100644 services/stream/events.go create mode 100644 services/stream/instance_cache.go create mode 100644 services/stream/instances.go create mode 100644 services/stream/name_cache.go create mode 100644 services/stream/stream.go create mode 100644 services/stream/streams.go create mode 100644 services/stream/util.go create mode 100644 services/user/create.go create mode 100644 services/user/update.go create mode 100644 services/user/user.go create mode 100644 services/user/username_seeds.go diff --git a/.gitignore b/.gitignore index f8551eae..6f365784 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ __pycache__ .cache .DS_Store -configs/.*.env +config/.* .history .idea .ipynb_checkpoints diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 505233b9..7d0c9366 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,47 +23,17 @@ build:web: - docker push ${IMAGE}:${CI_COMMIT_SHORT_SHA} - docker push ${IMAGE}:latest -.build:go: +build:backend: + variables: + IMAGE: gcr.io/beneath/backend script: - docker pull ${IMAGE}:builder || true - - docker build -f ./build/${CMD_NAME}/Dockerfile --target builder -t ${IMAGE}:builder --cache-from ${IMAGE}:builder . - - docker build -f ./build/${CMD_NAME}/Dockerfile -t ${IMAGE}:latest -t ${IMAGE}:${CI_COMMIT_SHORT_SHA} --cache-from ${IMAGE}:builder . + - docker build -f ./build/backend/Dockerfile --target builder -t ${IMAGE}:builder --cache-from ${IMAGE}:builder . + - docker build -f ./build/backend/Dockerfile -t ${IMAGE}:latest -t ${IMAGE}:${CI_COMMIT_SHORT_SHA} --cache-from ${IMAGE}:builder . - docker push ${IMAGE}:${CI_COMMIT_SHORT_SHA} - docker push ${IMAGE}:latest - docker push ${IMAGE}:builder -build:control: - extends: - - .build - - .build:go - variables: - CMD_NAME: control - IMAGE: gcr.io/beneath/${CMD_NAME} - -build:gateway: - extends: - - .build - - .build:go - variables: - CMD_NAME: gateway - IMAGE: gcr.io/beneath/${CMD_NAME} - -build:pipeline: - extends: - - .build - - .build:go - variables: - CMD_NAME: pipeline - IMAGE: gcr.io/beneath/${CMD_NAME} - -build:taskqueue: - extends: - - .build - - .build:go - variables: - CMD_NAME: taskqueue - IMAGE: gcr.io/beneath/${CMD_NAME} - .deploy: stage: deploy image: dtzar/helm-kubectl:3.2.1 @@ -93,7 +63,7 @@ deploy:control: extends: - .deploy - .deploy:prod - needs: ["build:control"] + needs: ["build:backend"] variables: CMD_NAME: control REPLICAS: ${REPLICAS_CONTROL} @@ -103,7 +73,7 @@ deploy:gateway: extends: - .deploy - .deploy:prod - needs: ["build:gateway"] + needs: ["build:backend"] variables: CMD_NAME: gateway REPLICAS: ${REPLICAS_GATEWAY} @@ -113,7 +83,7 @@ deploy:pipeline: extends: - .deploy - .deploy:prod - needs: ["build:pipeline"] + needs: ["build:backend"] variables: CMD_NAME: pipeline REPLICAS: ${REPLICAS_PIPELINE} @@ -123,7 +93,7 @@ deploy:taskqueue: extends: - .deploy - .deploy:prod - needs: ["build:taskqueue"] + needs: ["build:backend"] variables: CMD_NAME: taskqueue REPLICAS: ${REPLICAS_TASKQUEUE} diff --git a/build/README.md b/build/README.md index a9c6741f..eaec236e 100644 --- a/build/README.md +++ b/build/README.md @@ -1,3 +1,3 @@ # `build/` -This directory contains build manifests (currently only Dockerfiles) for each executable in `cmd/` that is deployed in production. +This directory contains build manifests (Dockerfiles) for the web frontend in `web/` and backend executable in `cmd/beneath/`. diff --git a/build/pipeline/Dockerfile b/build/backend/Dockerfile similarity index 78% rename from build/pipeline/Dockerfile rename to build/backend/Dockerfile index a81f37c3..bf86cb78 100644 --- a/build/pipeline/Dockerfile +++ b/build/backend/Dockerfile @@ -4,7 +4,7 @@ WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . -RUN CGO_ENABLED=0 GOOS=linux go build -a -o main cmd/pipeline/main.go +RUN CGO_ENABLED=0 GOOS=linux go build -a -o main cmd/beneath/main.go # Create run image FROM alpine:latest diff --git a/build/control/Dockerfile b/build/control/Dockerfile deleted file mode 100644 index 823f83a3..00000000 --- a/build/control/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -# Create builder image -FROM golang:alpine as builder -WORKDIR /app -COPY go.mod go.sum ./ -RUN go mod download -COPY . . -RUN CGO_ENABLED=0 GOOS=linux go build -a -o main cmd/control/main.go - -# Create run image -FROM alpine:latest -RUN apk --no-cache add ca-certificates -WORKDIR /root -COPY --from=builder /app/main . -EXPOSE 8080 -CMD ["./main"] diff --git a/build/gateway/Dockerfile b/build/gateway/Dockerfile deleted file mode 100644 index d8725740..00000000 --- a/build/gateway/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -# Create builder image -FROM golang:alpine as builder -WORKDIR /app -COPY go.mod go.sum ./ -RUN go mod download -COPY . . -RUN CGO_ENABLED=0 GOOS=linux go build -a -o main cmd/gateway/main.go - -# Create run image -FROM alpine:latest -RUN apk --no-cache add ca-certificates -WORKDIR /root -COPY --from=builder /app/main . -EXPOSE 8080 -EXPOSE 9090 -CMD ["./main"] diff --git a/build/taskqueue/Dockerfile b/build/taskqueue/Dockerfile deleted file mode 100644 index 63dc310f..00000000 --- a/build/taskqueue/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -# Create builder image -FROM golang:alpine as builder -WORKDIR /app -COPY go.mod go.sum ./ -RUN go mod download -COPY . . -RUN CGO_ENABLED=0 GOOS=linux go build -a -o main cmd/taskqueue/main.go - -# Create run image -FROM alpine:latest -RUN apk --no-cache add ca-certificates -WORKDIR /root -COPY --from=builder /app/main . -CMD ["./main"] diff --git a/bus/README.md b/bus/README.md new file mode 100644 index 00000000..2a12aaef --- /dev/null +++ b/bus/README.md @@ -0,0 +1,18 @@ +# `bus/` + +The bus facilitates sync (in-process) and async (background worker) event dispatch and handling. Services (in `services/`) send and subscribe to events messages, which are defined in `models/`. + +The bus was inspired by the [communication model in Grafana](https://github.com/grafana/grafana/blob/master/contribute/architecture/communication.md). + +## Sync and async handlers + +- *Sync event handlers* are called sequentially in-process when an event is published, and causes the event publisher to fail on error. If an event is sent in a DB transaction, subscribed handlers will also run inside that transaction! +- *Async event handlers* are called in a background worker. They retry on error. Event messages are serializes with msgpack and passed through the MQ (`infrastructure/mq/`). + +Use sync event handlers for light operations or operations that require the publisher to fail on error. Use async event handlers for everything else. + +## Background worker + +The background worker calls `bus.Run` to start processing async events dispatched from other processes. It's started with the `control-worker` startable (see `cmd/beneath/`). + +**It's critical that every service that handles async events is initialized in the worker process** before bus.Run is called! (See `cmd/beneath/dependencies/services.go`.) diff --git a/bus/bus.go b/bus/bus.go new file mode 100644 index 00000000..769b7760 --- /dev/null +++ b/bus/bus.go @@ -0,0 +1,331 @@ +package bus + +import ( + "context" + "encoding/json" + "fmt" + "reflect" + "time" + + "github.com/golang/protobuf/proto" + uuid "github.com/satori/go.uuid" + "github.com/vmihailenco/msgpack" + + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" + "gitlab.com/beneath-hq/beneath/infrastructure/mq" + "gitlab.com/beneath-hq/beneath/pkg/log" + "gitlab.com/beneath-hq/beneath/pkg/timeutil" +) + +// Msg represents an event handled by Bus +type Msg interface{} + +// HandlerFunc represents an event handler. +// It's signature must be (func(context.Context, Msg) error). +type HandlerFunc interface{} + +// Bus dispatches events to listener. Published events are processed +// immediately by sync listeners (and will use any DB transactions in ctx), +// and in a background worker by async listeners (passed over MQ). +type Bus struct { + MQ mq.MessageQueue + + msgTypes map[string]reflect.Type + syncListeners map[string][]HandlerFunc + asyncListeners map[string][]HandlerFunc +} + +const ( + asyncTopic = "bus" + asyncSubscription = "bus-worker" +) + +// asyncMsg wraps a pb.BusMsg +type asyncMsg struct { + ID uuid.UUID + Name string + Timestamp time.Time + Payload Msg +} + +// NewBus creates a new Bus +func NewBus(mq mq.MessageQueue) (*Bus, error) { + err := mq.RegisterTopic(asyncTopic) + if err != nil { + return nil, err + } + + err = mq.RegisterTopic(controlEventsTopic) + if err != nil { + return nil, err + } + + return &Bus{ + MQ: mq, + msgTypes: make(map[string]reflect.Type), + syncListeners: make(map[string][]HandlerFunc), + asyncListeners: make(map[string][]HandlerFunc), + }, nil +} + +// AddSyncListener registers a synchronous msg handler. +// Calls to Publish do not return until every sync listener +// has processed the msg. If any listener returns an error, +// subsequent listeners are *not* called, and the error is +// returned to the publisher. +func (b *Bus) AddSyncListener(handler HandlerFunc) { + b.addListener(b.syncListeners, handler) +} + +// AddAsyncListener registers an async msg handler, which +// handles published messages (passed through MQ) in a background +// worker. +func (b *Bus) AddAsyncListener(handler HandlerFunc) { + b.addListener(b.asyncListeners, handler) +} + +func (b *Bus) addListener(listeners map[string][]HandlerFunc, handler HandlerFunc) { + // check handler takes two args and returns one + handlerType := reflect.TypeOf(handler) + if handlerType.NumIn() != 2 { + panic(fmt.Errorf("expected handler <%v> to take two args, a context and a msg", handler)) + } + if handlerType.NumOut() != 1 { + panic(fmt.Errorf("expected handler <%v> to return one arg, an error", handler)) + } + + // check handler returns an error + errorType := reflect.TypeOf((*error)(nil)).Elem() + if !handlerType.Out(0).Implements(errorType) { + panic(fmt.Errorf("expected handler <%v> to return one arg, an error", handler)) + } + + // check first arg is a context.Context + ctxType := reflect.TypeOf((*context.Context)(nil)).Elem() + if !handlerType.In(0).Implements(ctxType) { + panic(fmt.Errorf("expected handler <%v> to take two args, a context and a msg", handler)) + } + + // check second arg is a struct pointer + msgType := handlerType.In(1) + if msgType.Kind() != reflect.Ptr || msgType.Elem().Kind() != reflect.Struct { + panic(fmt.Errorf("expected handler <%v> to take two args, a context and a msg", handler)) + } + + // get msg type and name + msgName := msgType.Name() + + // track msg type if it doesn't exist + _, exists := b.msgTypes[msgName] + if !exists { + b.msgTypes[msgName] = msgType + } + + // add handler to listeners + _, exists = listeners[msgName] + if !exists { + listeners[msgName] = make([]HandlerFunc, 0) + } + listeners[msgName] = append(listeners[msgName], handler) +} + +// Publish publishes a message to sync and async listeners. +// If a sync listener fails, its error is returned and async +// listeners will not be called. Async listeners run in a background +// worker, so msg will be serialized with msgpack. +func (b *Bus) Publish(ctx context.Context, msg Msg) error { + msgName := reflect.TypeOf(msg).Elem().Name() + + err := b.callListeners(ctx, b.syncListeners[msgName], msg) + if err != nil { + return err + } + + err = b.publishAsync(ctx, msgName, msg) + if err != nil { + return err + } + + return nil +} + +// PublishDelayed will schedule a message for delayed handling. +// It's not currently implemented. +func (b *Bus) PublishDelayed(ctx context.Context, d time.Duration, msg Msg) error { + panic("not implemented") +} + +// PublishScheduled will schedule a message for delayed handling at a specific time. +// It's not currently implemented. +func (b *Bus) PublishScheduled(ctx context.Context, t time.Time, msg Msg) error { + panic("not implemented") +} + +func (b *Bus) callListeners(ctx context.Context, listeners []HandlerFunc, msg Msg) error { + if len(listeners) == 0 { + return nil + } + + params := make([]reflect.Value, 2) + params[0] = reflect.ValueOf(ctx) + params[1] = reflect.ValueOf(msg) + + for _, handler := range listeners { + ret := reflect.ValueOf(handler).Call(params) + err := ret[0].Interface() + if err != nil { + return err.(error) + } + } + + return nil +} + +func (b *Bus) publishAsync(ctx context.Context, msgName string, msg Msg) error { + listeners := b.asyncListeners[msgName] + if len(listeners) == 0 { + return nil + } + + amsg := &asyncMsg{ + ID: uuid.NewV4(), + Name: msgName, + Timestamp: time.Now(), + Payload: msg, + } + + data, err := b.marshalAsyncMsg(ctx, amsg) + if err != nil { + return err + } + + err = b.MQ.Publish(ctx, asyncTopic, data) + if err != nil { + return err + } + + log.S.Infow("bus_async_publish", "id", amsg.ID.String(), "name", msgName, "bytes", len(data)) + return nil +} + +func (b *Bus) marshalAsyncMsg(ctx context.Context, amsg *asyncMsg) ([]byte, error) { + payload, err := msgpack.Marshal(amsg.Payload) + if err != nil { + return nil, fmt.Errorf("error marshalling msg %s with msgpack: %s", amsg.Name, err.Error()) + } + + pbmsg := &pb.BusMsg{ + Id: amsg.ID.Bytes(), + Name: amsg.Name, + Timestamp: timeutil.UnixMilli(amsg.Timestamp), + Payload: payload, + } + + return proto.Marshal(pbmsg) +} + +func (b *Bus) unmarshalAsyncMsg(ctx context.Context, data []byte) (*asyncMsg, error) { + pbmsg := &pb.BusMsg{} + err := proto.Unmarshal(data, pbmsg) + if err != nil { + return nil, err + } + + msgType, ok := b.msgTypes[pbmsg.Name] + if !ok { + return nil, fmt.Errorf("cannot find msg type with name '%s'", pbmsg.Name) + } + + payload := reflect.New(msgType).Interface().(Msg) // pointer to struct + err = msgpack.Unmarshal(pbmsg.Payload, payload) + if err != nil { + return nil, err + } + + amsg := &asyncMsg{ + ID: uuid.FromBytesOrNil(pbmsg.Id), + Name: pbmsg.Name, + Timestamp: timeutil.FromUnixMilli(pbmsg.Timestamp), + Payload: payload, + } + + return amsg, nil +} + +// Run subscribes to MQ for published async messages and calls the relevant +// async listeners. +// It's suitable for running in a worker process, but care should be taken to +// make sure all the correct listeners have been instantiated in the process. +func (b *Bus) Run(ctx context.Context) error { + return b.MQ.Subscribe(ctx, asyncTopic, asyncSubscription, true, func(ctx context.Context, data []byte) error { + startTime := time.Now() + + amsg, err := b.unmarshalAsyncMsg(ctx, data) + if err != nil { + log.S.Errorf("bus async worker got unmarshal err, nacking...: %s", err) + return err + } + + listeners := b.asyncListeners[amsg.Name] + if len(listeners) == 0 { + log.S.Errorf("bus async worker got msg with no listeners, the correct services are likely not created in this process, acking...: %x", data) + return nil + } + + err = b.callListeners(ctx, listeners, amsg.Payload) + if err != nil { + log.S.Errorf("bus async worker got err when calling listeners, nacking...: %s", err) + return err + } + + log.S.Infow("bus_async_processed", "id", amsg.ID.String(), "name", amsg.Name, "time", amsg.Timestamp, "elapsed", time.Since(startTime)) + + return nil + }) +} + +// TODO: Remove this, but not right now + +const ( + controlEventsTopic = "control-events" + controlEventsSubscription = "control-events-worker" +) + +// ControlEvent describes a control-plane event +type ControlEvent struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + Timestamp time.Time `json:"timestamp"` + Data map[string]interface{} `json:"data"` +} + +// PublishControlEvent publishes a control-plane event to controlEventsTopic +// for external consumption (e.g. for BI purposes) +func (b *Bus) PublishControlEvent(ctx context.Context, name string, data map[string]interface{}) error { + msg := ControlEvent{ + ID: uuid.NewV4(), + Name: name, + Timestamp: time.Now(), + Data: data, + } + json, err := json.Marshal(msg) + if err != nil { + return err + } + if len(json) > b.MQ.MaxMessageSize() { + return fmt.Errorf("control event message %v has invalid size", json) + } + return b.MQ.Publish(ctx, controlEventsTopic, json) +} + +// SubscribeControlEvents subscribes to all control events +func (b *Bus) SubscribeControlEvents(ctx context.Context, fn func(context.Context, *ControlEvent) error) error { + return b.MQ.Subscribe(ctx, controlEventsTopic, controlEventsSubscription, true, func(ctx context.Context, msg []byte) error { + t := &ControlEvent{} + err := json.Unmarshal(msg, t) + if err != nil { + return err + } + return fn(ctx, t) + }) +} diff --git a/clients/python/beneath/proto/gateway.proto b/clients/python/beneath/proto/gateway.proto index 8d69a167..aa677950 100644 --- a/clients/python/beneath/proto/gateway.proto +++ b/clients/python/beneath/proto/gateway.proto @@ -1,5 +1,5 @@ syntax = "proto3"; -option go_package = "gitlab.com/beneath-hq/beneath/gateway/grpc/proto"; +option go_package = "gitlab.com/beneath-hq/beneath/server/data/grpc/proto"; package gateway.v1; message Record { diff --git a/cmd/README.md b/cmd/README.md index fd2da425..ee90f101 100644 --- a/cmd/README.md +++ b/cmd/README.md @@ -1,10 +1,5 @@ # `cmd/` -Beneath is not just a single executable -- it's several different "micro"services. This directory contains a subdirectory for each executable service. +The Beneath backend is comprised of a handful different services that can all be started with the same executable. See `cmd/beneath/` for more. -## Creating an executable - -- Create a directory named for the executable -- Add a `main.go` file to it -- All configuration should be loaded within the `main.go` and passed down from there (using environment variables, see existing executables for examples) -- The `main.go` file should call logic stored outside of `cmd/` (this is just the entry point, not the place to store the entire codebase) +The Beneath frontend is found and started in `web/`. diff --git a/cmd/beneath/cli/cli.go b/cmd/beneath/cli/cli.go new file mode 100644 index 00000000..2e6db205 --- /dev/null +++ b/cmd/beneath/cli/cli.go @@ -0,0 +1,50 @@ +package cli + +import ( + "os" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// CLI builds and serves the CLI for *launching* the Beneath backend (*not* the Python-based CLI +// for local authentication, creating streams, etc.) +type CLI struct { + rootCmd *cobra.Command + v *viper.Viper +} + +// NewCLI creates a new CLI instance +func NewCLI() *CLI { + c := &CLI{} + c.v = viper.New() + c.rootCmd = c.newRootCmd() + return c +} + +// Run parses and runs commands +func (c *CLI) Run() { + // add subcommands + c.rootCmd.AddCommand(c.newStartCmd()) + + // run + if err := c.rootCmd.Execute(); err != nil { + os.Exit(1) + } +} + +func (c *CLI) newRootCmd() *cobra.Command { + var configFile string + cmd := &cobra.Command{ + Use: "beneath", + Short: "Open source data systems meta-layer", + Long: "Beneath is the management layer for all your data systems.\nSee https://beneath.dev for details.", + // Called before every command AND subcommand. + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + // Loads config file into c.v + return c.loadConfig(configFile) + }, + } + cmd.PersistentFlags().StringVar(&configFile, "config", "", "config file (default is ./config/.env)") + return cmd +} diff --git a/cmd/beneath/cli/config.go b/cmd/beneath/cli/config.go new file mode 100644 index 00000000..404c6151 --- /dev/null +++ b/cmd/beneath/cli/config.go @@ -0,0 +1,72 @@ +package cli + +import ( + "fmt" + "strings" + + "github.com/spf13/viper" + "gitlab.com/beneath-hq/beneath/pkg/envutil" +) + +// prefix for environment variables that override config keys +const envVarPrefix = "BENEATH" + +// loads config based on the given file, or if it's not set, the current environment +func (c *CLI) loadConfig(configFileOrEmpty string) error { + // load config file + if configFileOrEmpty != "" { + c.loadConfigFile(configFileOrEmpty) + } else { + c.searchLoadAndMergeConfigName(".default") // always loads config/.default + c.searchLoadAndMergeConfigName(fmt.Sprintf(".%s", envutil.GetEnv())) // if env=DEV, then loads config/.development.yaml + } + + // Not using v.AutomaticEnv() and v.SetEnvPrefix() to directly handle + // conversion of key names to env variable names. + + // register every config key + for _, configKey := range configKeys { // configKeys set in registry.go + // set default + c.v.SetDefault(configKey.Key, configKey.Default) + + // bind to env variable name (eg. "mq_driver" -> "BENEATH_MQ_DRIVER") + envVarSuffix := strings.ToUpper(strings.ReplaceAll(configKey.Key, ".", "_")) + envVarName := fmt.Sprintf("%s_%s", envVarPrefix, envVarSuffix) + c.v.BindEnv(configKey.Key, envVarName) + } + + return nil +} + +// loads config file (errors if file doesn't exist) +func (c *CLI) loadConfigFile(file string) error { + c.v.SetConfigFile(file) + if err := c.v.ReadInConfig(); err != nil { + return err + } + return nil +} + +// searches for a config file with the given name, and merges it +// into c.v if found +func (c *CLI) searchLoadAndMergeConfigName(name string) error { + // create new viper instance + v := viper.New() + + // configure to look for file with name + v.SetConfigName(name) + v.AddConfigPath(".") + v.AddConfigPath("./config") + + // search for config file (don't error if not found) + if err := v.ReadInConfig(); err != nil { + if _, ok := err.(viper.ConfigFileNotFoundError); !ok { + return err + } + return nil + } + + // merge into c.v (main viper object) + c.v.MergeConfigMap(v.AllSettings()) + return nil +} diff --git a/cmd/beneath/cli/registry.go b/cmd/beneath/cli/registry.go new file mode 100644 index 00000000..ff129e20 --- /dev/null +++ b/cmd/beneath/cli/registry.go @@ -0,0 +1,95 @@ +package cli + +import ( + "context" + "os" + + "gitlab.com/beneath-hq/beneath/pkg/ctxutil" + "gitlab.com/beneath-hq/beneath/pkg/log" + "golang.org/x/sync/errgroup" +) + +// the registered dependencies +var dependencies []interface{} + +// AddDependency registers a dependency to provide to fx. +// A dependency is a constructor, i.e. a "New..." function +func AddDependency(constructor interface{}) { + dependencies = append(dependencies, constructor) +} + +// Startable is a service that can be started with the start command +type Startable struct { + Name string + Register interface{} // func (lc *Lifecycle, s *Startable) { lc.Add(s.Run) } +} + +// the registered startables +var startables []*Startable + +// AddStartable registers a startable +func AddStartable(s *Startable) { + startables = append(startables, s) +} + +// ConfigKey represents a config key and optionally a default value +type ConfigKey struct { + Key string + Description string + Default interface{} +} + +// the registered config keys +var configKeys []*ConfigKey + +// AddConfigKey registers a new config key to be loaded from config files +// with Viper and/or overriden via the CLI +func AddConfigKey(key *ConfigKey) { + configKeys = append(configKeys, key) +} + +// Runable should implement a Run function that returns nil on success, +// an error on failure, and stops gracefully if the ctx is cancelled. +type Runable interface { + Run(ctx context.Context) error +} + +// Lifecycle runs one or more Runables. It is inspired by fx.Lifecycle, +// but we prefer a ctx-based Run function to start/stop hooks. +type Lifecycle struct { + Runners []Runable +} + +// Add registers a new Runable in the lifecycle +func (l *Lifecycle) Add(runner Runable) { + l.Runners = append(l.Runners, runner) +} + +// Run is where the magic happens! It runs every Runner registered in the lifecycle. +// If any runner returns an error, it cancels every other runner and stops the application. +// It also cancels runners if it receives a termination signal (ie. SIGINT or SIGTERM). +func (l *Lifecycle) Run() { + // A ctx that we can cancel, and that also cancels on sigint, etc. + ctx, cancel := context.WithCancel(ctxutil.WithCancelOnTerminate(context.Background())) + + // Run every runner in an error group + group := new(errgroup.Group) + for _, runner := range l.Runners { + runner := runner + group.Go(func() error { + log.S.Infof("running %T", runner) + err := runner.Run(ctx) + log.S.Infof("%T stopped", runner) + if err != nil { + cancel() + } + return err + }) + } + + err := group.Wait() + if err != nil { + log.S.Fatal(err) + } + os.Exit(0) +} diff --git a/cmd/beneath/cli/start.go b/cmd/beneath/cli/start.go new file mode 100644 index 00000000..46abb357 --- /dev/null +++ b/cmd/beneath/cli/start.go @@ -0,0 +1,65 @@ +package cli + +import ( + "github.com/spf13/cobra" + "github.com/spf13/viper" + "go.uber.org/fx" + + "gitlab.com/beneath-hq/beneath/pkg/log" +) + +// registers start command, which runs services registered with AddStartable +func (c *CLI) newStartCmd() *cobra.Command { + startCmd := &cobra.Command{ + Use: "start", + Short: "Start backend service", + Long: `Starts backend servers or workers`, + } + + for _, service := range startables { + serviceCopy := service + cmd := &cobra.Command{ + Use: service.Name, + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + c.runStartableServices([]*Startable{serviceCopy}) + }, + } + startCmd.AddCommand(cmd) + } + + allCmd := &cobra.Command{ + Use: "all", + Short: "Starts every backend service", + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + c.runStartableServices(startables) + }, + } + startCmd.AddCommand(allCmd) + + return startCmd +} + +// runs the given startable services (with dependencies injected through fx) +func (c *CLI) runStartableServices(services []*Startable) { + log.InitLogger() + + var invokers []interface{} + for _, service := range services { + invokers = append(invokers, service.Register) + } + + var lc *Lifecycle + fx.New( + fx.NopLogger, + fx.Provide(func() *Lifecycle { return &Lifecycle{} }), // provides Lifecycle object (see registry.go for more) + fx.Provide(func() *viper.Viper { return c.v }), // provides viper config for other dependencies to consume + fx.Provide(dependencies...), // all dependencies registered with AddDependency + fx.Invoke(invokers...), // registers every startable + fx.Populate(&lc), // extract lifecycle + ) + + // migrations.MustRunUp(hub.DB) + lc.Run() +} diff --git a/cmd/beneath/dependencies/control_migrate.go b/cmd/beneath/dependencies/control_migrate.go new file mode 100644 index 00000000..04febbbd --- /dev/null +++ b/cmd/beneath/dependencies/control_migrate.go @@ -0,0 +1,25 @@ +package dependencies + +func init() { + +} + +// import ( +// "fmt" + +// "github.com/spf13/cobra" +// ) + +// func (c *CLI) newMigrateCmd() *cobra.Command { +// cmd := &cobra.Command{ +// Use: "migrate", +// Short: "Runs control-plane db migrations", +// Long: "Runs control-plane db migrations", +// Args: cobra.NoArgs, +// Run: func(cmd *cobra.Command, args []string) { +// fmt.Printf("Migrate! %v\n", args) +// }, +// } + +// return cmd +// } diff --git a/cmd/beneath/dependencies/control_server.go b/cmd/beneath/dependencies/control_server.go new file mode 100644 index 00000000..2d825247 --- /dev/null +++ b/cmd/beneath/dependencies/control_server.go @@ -0,0 +1,71 @@ +package dependencies + +import ( + "github.com/spf13/viper" + "gitlab.com/beneath-hq/beneath/cmd/beneath/cli" + "gitlab.com/beneath-hq/beneath/server/control" +) + +func init() { + cli.AddStartable(&cli.Startable{ + Name: "control-server", + Register: func(lc *cli.Lifecycle, server *control.Server) { + lc.Add(server) + }, + }) + + cli.AddDependency(control.NewServer) + + cli.AddDependency(func(v *viper.Viper) (*control.ServerOptions, error) { + var opts control.ServerOptions + return &opts, v.UnmarshalKey("control", &opts) + }) + + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.port", + Default: "4000", + Description: "control server port", + }) + + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.host", + Default: "http://localhost:4000", + Description: "control server host (with protocol) (for redirects)", + }) + + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.frontend_host", + Default: "http://localhost:3000", + Description: "host (with protocol) of the web frontend (for redirects)", + }) + + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.session_secret", + Default: "", + Description: "secret to use for signing session tokens", + }) + + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.auth.github.id", + Default: "", + Description: "id for authentication with Github", + }) + + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.auth.github.secret", + Default: "", + Description: "secret for authentication with Github", + }) + + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.auth.google.id", + Default: "", + Description: "id for authentication with Google", + }) + + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.auth.google.secret", + Default: "", + Description: "secret for authentication with Google", + }) +} diff --git a/cmd/beneath/dependencies/control_worker.go b/cmd/beneath/dependencies/control_worker.go new file mode 100644 index 00000000..197ad203 --- /dev/null +++ b/cmd/beneath/dependencies/control_worker.go @@ -0,0 +1,43 @@ +package dependencies + +import ( + "context" + + "gitlab.com/beneath-hq/beneath/bus" + "gitlab.com/beneath-hq/beneath/cmd/beneath/cli" +) + +func init() { + // The control worker is so lean, it's defined below in this file. + // It basically just ensures all services are created in the process (to register + // their events handlers with the bus, and then calls bus.Run) + + cli.AddDependency(NewControlWorker) + + cli.AddStartable(&cli.Startable{ + Name: "control-worker", + Register: func(lc *cli.Lifecycle, worker *ControlWorker) { + lc.Add(worker) + }, + }) + +} + +// ControlWorker is the background worker for async events (i.e. it runs bus.Run) +type ControlWorker struct { + Bus *bus.Bus + Services *AllServices // Ensures all services are created and registers event handlers with Bus +} + +// NewControlWorker initializes a new ControlWorker +func NewControlWorker(bus *bus.Bus, services *AllServices) *ControlWorker { + return &ControlWorker{ + Bus: bus, + Services: services, + } +} + +// Run starts the worker +func (s *ControlWorker) Run(ctx context.Context) error { + return s.Bus.Run(ctx) +} diff --git a/cmd/beneath/dependencies/data_server.go b/cmd/beneath/dependencies/data_server.go new file mode 100644 index 00000000..cb4afc41 --- /dev/null +++ b/cmd/beneath/dependencies/data_server.go @@ -0,0 +1,37 @@ +package dependencies + +import ( + "github.com/spf13/viper" + "gitlab.com/beneath-hq/beneath/cmd/beneath/cli" + "gitlab.com/beneath-hq/beneath/server/data" + "gitlab.com/beneath-hq/beneath/services/metrics" +) + +func init() { + cli.AddStartable(&cli.Startable{ + Name: "data-server", + Register: func(lc *cli.Lifecycle, server *data.Server, metrics *metrics.Broker) { + lc.Add(server) + lc.Add(metrics) + }, + }) + + cli.AddDependency(data.NewServer) + + cli.AddDependency(func(v *viper.Viper) (*data.ServerOptions, error) { + var opts data.ServerOptions + return &opts, v.UnmarshalKey("data", &opts) + }) + + cli.AddConfigKey(&cli.ConfigKey{ + Key: "data.http_port", + Default: "5000", + Description: "data server port for HTTP", + }) + + cli.AddConfigKey(&cli.ConfigKey{ + Key: "data.grpc_port", + Default: "50051", + Description: "data server port for GRPC", + }) +} diff --git a/cmd/beneath/dependencies/data_worker.go b/cmd/beneath/dependencies/data_worker.go new file mode 100644 index 00000000..ef040a78 --- /dev/null +++ b/cmd/beneath/dependencies/data_worker.go @@ -0,0 +1,41 @@ +package dependencies + +import ( + "context" + + "gitlab.com/beneath-hq/beneath/bus" + "gitlab.com/beneath-hq/beneath/cmd/beneath/cli" + "gitlab.com/beneath-hq/beneath/services/data" +) + +func init() { + // Like the control worker, the data worker is so lean it's defined below in this file. + // It basically just calls RunWorker on a *data.Service. + + cli.AddDependency(NewDataWorker) + + cli.AddStartable(&cli.Startable{ + Name: "data-worker", + Register: func(lc *cli.Lifecycle, worker *DataWorker) { + lc.Add(worker) + }, + }) + +} + +// DataWorker is the data background worker (that writes data to the engine) +type DataWorker struct { + DataService *data.Service +} + +// NewDataWorker initializes a new DataWorker +func NewDataWorker(bus *bus.Bus, data *data.Service) *DataWorker { + return &DataWorker{ + DataService: data, + } +} + +// Run starts the worker +func (s *DataWorker) Run(ctx context.Context) error { + return s.DataService.RunWorker(ctx) +} diff --git a/cmd/beneath/dependencies/db.go b/cmd/beneath/dependencies/db.go new file mode 100644 index 00000000..03ad0ddc --- /dev/null +++ b/cmd/beneath/dependencies/db.go @@ -0,0 +1,37 @@ +package dependencies + +import ( + "github.com/spf13/viper" + + "gitlab.com/beneath-hq/beneath/cmd/beneath/cli" + "gitlab.com/beneath-hq/beneath/infrastructure/db" +) + +func init() { + cli.AddDependency(db.NewDB) + cli.AddDependency(func(v *viper.Viper) (*db.Options, error) { + var opts db.Options + return &opts, v.UnmarshalKey("control.postgres", &opts) + }) + + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.postgres.host", + Default: "localhost", + Description: "Postgres host for control-plane db", + }) + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.postgres.db", + Default: "postgres", + Description: "Postgres database for control-plane db", + }) + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.postgres.user", + Default: "postgres", + Description: "Postgres user for control-plane db", + }) + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.postgres.password", + Default: "", + Description: "Postgres password for control-plane db", + }) +} diff --git a/cmd/beneath/dependencies/engine.go b/cmd/beneath/dependencies/engine.go new file mode 100644 index 00000000..caec33a4 --- /dev/null +++ b/cmd/beneath/dependencies/engine.go @@ -0,0 +1,47 @@ +package dependencies + +import ( + "github.com/spf13/viper" + + "gitlab.com/beneath-hq/beneath/cmd/beneath/cli" + "gitlab.com/beneath-hq/beneath/infrastructure/engine" + + // registers all engine drivers + _ "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver/bigquery" + _ "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver/bigtable" + _ "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver/mock" + _ "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver/postgres" +) + +func init() { + cli.AddDependency(engine.NewEngine) + cli.AddDependency(func(v *viper.Viper) (*engine.IndexOptions, error) { + var indexOpts engine.IndexOptions + err := v.UnmarshalKey("data.index", &indexOpts) + if err != nil { + return nil, err + } + return &indexOpts, nil + }) + cli.AddDependency(func(v *viper.Viper) (*engine.WarehouseOptions, error) { + var warehouseOpts engine.WarehouseOptions + err := v.UnmarshalKey("data.warehouse", &warehouseOpts) + if err != nil { + return nil, err + } + return &warehouseOpts, nil + }) + cli.AddConfigKey(&cli.ConfigKey{ + Key: "data.index.driver", + Default: "", + Description: "driver to use for (indexed) operational serving of stream records", + }) + cli.AddConfigKey(&cli.ConfigKey{ + Key: "data.warehouse.driver", + Default: "", + Description: "driver to use for OLAP queries of stream records", + }) + // Key: "data.log.driver", + // Default: "", + // Description: "driver to use for log storage of stream records", +} diff --git a/cmd/beneath/dependencies/hub.go b/cmd/beneath/dependencies/hub.go new file mode 100644 index 00000000..458bf50c --- /dev/null +++ b/cmd/beneath/dependencies/hub.go @@ -0,0 +1,19 @@ +package dependencies + +import ( + "context" + + "github.com/go-pg/pg/v9" + + "gitlab.com/beneath-hq/beneath/bus" + "gitlab.com/beneath-hq/beneath/cmd/beneath/cli" + "gitlab.com/beneath-hq/beneath/infrastructure/db" +) + +func init() { + cli.AddDependency(bus.NewBus) + + cli.AddDependency(func(db db.DB) *pg.DB { + return db.GetDB(context.Background()).(*pg.DB) + }) +} diff --git a/cmd/beneath/dependencies/mq.go b/cmd/beneath/dependencies/mq.go new file mode 100644 index 00000000..1c72eab3 --- /dev/null +++ b/cmd/beneath/dependencies/mq.go @@ -0,0 +1,24 @@ +package dependencies + +import ( + "github.com/spf13/viper" + "gitlab.com/beneath-hq/beneath/cmd/beneath/cli" + "gitlab.com/beneath-hq/beneath/infrastructure/mq" + + // registers all mq drivers + _ "gitlab.com/beneath-hq/beneath/infrastructure/mq/driver/pubsub" +) + +func init() { + cli.AddDependency(mq.NewMessageQueue) + cli.AddDependency(func(v *viper.Viper) (*mq.Options, error) { + var opts mq.Options + return &opts, v.UnmarshalKey("mq", &opts) + }) + + cli.AddConfigKey(&cli.ConfigKey{ + Key: "mq.driver", + Default: "", + Description: "driver to use for message queue", + }) +} diff --git a/cmd/beneath/dependencies/redis.go b/cmd/beneath/dependencies/redis.go new file mode 100644 index 00000000..c7869d89 --- /dev/null +++ b/cmd/beneath/dependencies/redis.go @@ -0,0 +1,22 @@ +package dependencies + +import ( + "github.com/spf13/viper" + + "gitlab.com/beneath-hq/beneath/cmd/beneath/cli" + "gitlab.com/beneath-hq/beneath/infrastructure/redis" +) + +func init() { + cli.AddDependency(redis.NewRedis) + cli.AddDependency(func(v *viper.Viper) (*redis.Options, error) { + var opts redis.Options + return &opts, v.UnmarshalKey("control.redis", &opts) + }) + cli.AddConfigKey(&cli.ConfigKey{ + Key: "control.redis.url", + Default: "redis://localhost/", + Description: "Redis connection URL for control-plane caching", + }) + +} diff --git a/cmd/beneath/dependencies/services.go b/cmd/beneath/dependencies/services.go new file mode 100644 index 00000000..b70818b4 --- /dev/null +++ b/cmd/beneath/dependencies/services.go @@ -0,0 +1,85 @@ +package dependencies + +import ( + "time" + + "gitlab.com/beneath-hq/beneath/cmd/beneath/cli" + "gitlab.com/beneath-hq/beneath/services/data" + "gitlab.com/beneath-hq/beneath/services/metrics" + "gitlab.com/beneath-hq/beneath/services/middleware" + "gitlab.com/beneath-hq/beneath/services/organization" + "gitlab.com/beneath-hq/beneath/services/permissions" + "gitlab.com/beneath-hq/beneath/services/project" + "gitlab.com/beneath-hq/beneath/services/secret" + "gitlab.com/beneath-hq/beneath/services/service" + "gitlab.com/beneath-hq/beneath/services/stream" + "gitlab.com/beneath-hq/beneath/services/user" +) + +// TO ADD A NEW SERVICE: +// 1. Add it as a member to AllServices +// 2. Add it to NewAllServices (two places!) +// 3. Add it as a dependency in init() + +// AllServices is a convenience wrapper that initializes all services +type AllServices struct { + Data *data.Service + Metrics *metrics.Broker + Middleware *middleware.Service + Organization *organization.Service + Permissions *permissions.Service + Project *project.Service + Secret *secret.Service + Service *service.Service + Stream *stream.Service + User *user.Service +} + +// NewAllServices creates a new AllServices +func NewAllServices( + data *data.Service, + metrics *metrics.Broker, + middleware *middleware.Service, + organization *organization.Service, + permissions *permissions.Service, + project *project.Service, + secret *secret.Service, + service *service.Service, + stream *stream.Service, + user *user.Service, +) *AllServices { + return &AllServices{ + Data: data, + Metrics: metrics, + Middleware: middleware, + Organization: organization, + Permissions: permissions, + Project: project, + Secret: secret, + Service: service, + Stream: stream, + User: user, + } +} + +func init() { + cli.AddDependency(NewAllServices) + cli.AddDependency(data.New) + cli.AddDependency(metrics.New) + cli.AddDependency(middleware.New) + cli.AddDependency(organization.New) + cli.AddDependency(permissions.New) + cli.AddDependency(project.New) + cli.AddDependency(secret.New) + cli.AddDependency(service.New) + cli.AddDependency(stream.New) + cli.AddDependency(user.New) + + // the metrics service takes some extra options + cli.AddDependency(func() *metrics.Options { + return &metrics.Options{ + CacheSize: 2500, + CommitInterval: 30 * time.Second, + } + }) +} diff --git a/cmd/beneath/main.go b/cmd/beneath/main.go new file mode 100644 index 00000000..afa000ab --- /dev/null +++ b/cmd/beneath/main.go @@ -0,0 +1,12 @@ +package main + +import ( + "gitlab.com/beneath-hq/beneath/cmd/beneath/cli" + + // registers everything all dependencies with the CLI + _ "gitlab.com/beneath-hq/beneath/cmd/beneath/dependencies" +) + +func main() { + cli.NewCLI().Run() +} diff --git a/cmd/control/main.go b/cmd/control/main.go deleted file mode 100644 index 2ecc5111..00000000 --- a/cmd/control/main.go +++ /dev/null @@ -1,71 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - - "gitlab.com/beneath-hq/beneath/control" - "gitlab.com/beneath-hq/beneath/control/auth" - "gitlab.com/beneath-hq/beneath/control/migrations" - "gitlab.com/beneath-hq/beneath/control/payments" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/envutil" - "gitlab.com/beneath-hq/beneath/pkg/log" -) - -type configSpecification struct { - ControlPort int `envconfig:"CONTROL_PORT" required:"true" default:"8080"` - ControlHost string `envconfig:"CONTROL_HOST" required:"true"` - FrontendHost string `envconfig:"FRONTEND_HOST" required:"true"` - - RedisURL string `envconfig:"CONTROL_REDIS_URL" required:"true"` - PostgresHost string `envconfig:"CONTROL_POSTGRES_HOST" required:"true"` - PostgresDB string `envconfig:"CONTROL_POSTGRES_DB" required:"true"` - PostgresUser string `envconfig:"CONTROL_POSTGRES_USER" required:"true"` - PostgresPassword string `envconfig:"CONTROL_POSTGRES_PASSWORD" required:"true"` - - MQDriver string `envconfig:"ENGINE_MQ_DRIVER" required:"true"` - LookupDriver string `envconfig:"ENGINE_LOOKUP_DRIVER" required:"true"` - WarehouseDriver string `envconfig:"ENGINE_WAREHOUSE_DRIVER" required:"true"` - - PaymentsDrivers []string `envconfig:"CONTROL_PAYMENTS_DRIVERS" required:"true"` - SessionSecret string `envconfig:"CONTROL_SESSION_SECRET" required:"true"` - GithubAuthID string `envconfig:"CONTROL_GITHUB_AUTH_ID" required:"true"` - GithubAuthSecret string `envconfig:"CONTROL_GITHUB_AUTH_SECRET" required:"true"` - GoogleAuthID string `envconfig:"CONTROL_GOOGLE_AUTH_ID" required:"true"` - GoogleAuthSecret string `envconfig:"CONTROL_GOOGLE_AUTH_SECRET" required:"true"` -} - -func main() { - // load config - var config configSpecification - envutil.LoadConfig("beneath", &config) - - // Init logging - log.InitLogger() - - // connect postgres, redis, engine, and payment drivers - hub.InitPostgres(config.PostgresHost, config.PostgresDB, config.PostgresUser, config.PostgresPassword) - hub.InitRedis(config.RedisURL) - hub.InitEngine(config.MQDriver, config.LookupDriver, config.WarehouseDriver) - hub.SetPaymentDrivers(payments.InitDrivers(config.PaymentsDrivers)) - - // run migrations - migrations.MustRunUp(hub.DB) - - // configure auth - auth.InitGoth(&auth.GothConfig{ - ClientHost: config.FrontendHost, - SessionSecret: config.SessionSecret, - BackendHost: config.ControlHost, - GithubAuthID: config.GithubAuthID, - GithubAuthSecret: config.GithubAuthSecret, - GoogleAuthID: config.GoogleAuthID, - GoogleAuthSecret: config.GoogleAuthSecret, - }) - - // run handler - handler := control.Handler(config.ControlHost, config.FrontendHost) - log.S.Infow("control http started", "port", config.ControlPort) - log.S.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", config.ControlPort), handler)) -} diff --git a/cmd/dump/main.go b/cmd/dump/main.go deleted file mode 100644 index fcfe5a3d..00000000 --- a/cmd/dump/main.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "context" - "encoding/hex" - "log" - "os" - - "cloud.google.com/go/bigtable" -) - -func main() { - os.Setenv("BIGTABLE_PROJECT_ID", "") - os.Setenv("BIGTABLE_EMULATOR_HOST", "localhost:8086") - - // prepare BigTable client - ctx := context.Background() - client, err := bigtable.NewClient(ctx, "", "") - if err != nil { - log.Fatalf("Could not create bigtable client: %v", err) - } - - // create table - table := client.Open("metrics") - - // dump all rows - rr := bigtable.PrefixRange("") - err = table.ReadRows(context.Background(), rr, func(row bigtable.Row) bool { - item := row["cf0"][0] - log.Printf("\tKey: %s; Value: %s; Timestamp: %v\n", hex.EncodeToString([]byte(item.Row)), hex.EncodeToString(item.Value), item.Timestamp) - return true - }) - if err != nil { - log.Fatalf("Could not create dump rows: %v", err) - } -} diff --git a/cmd/gateway/main.go b/cmd/gateway/main.go deleted file mode 100644 index 6dc93e18..00000000 --- a/cmd/gateway/main.go +++ /dev/null @@ -1,107 +0,0 @@ -package main - -import ( - "context" - "fmt" - "net" - "net/http" - "os" - "time" - - "golang.org/x/sync/errgroup" - - gw "gitlab.com/beneath-hq/beneath/gateway" - gwgrpc "gitlab.com/beneath-hq/beneath/gateway/grpc" - gwhttp "gitlab.com/beneath-hq/beneath/gateway/http" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/ctxutil" - "gitlab.com/beneath-hq/beneath/pkg/envutil" - "gitlab.com/beneath-hq/beneath/pkg/log" -) - -type configSpecification struct { - HTTPPort int `envconfig:"GATEWAY_PORT" default:"8080"` - GRPCPort int `envconfig:"GATEWAY_PORT_GRPC" default:"9090"` - MQDriver string `envconfig:"ENGINE_MQ_DRIVER" required:"true"` - LookupDriver string `envconfig:"ENGINE_LOOKUP_DRIVER" required:"true"` - WarehouseDriver string `envconfig:"ENGINE_WAREHOUSE_DRIVER" required:"true"` - RedisURL string `envconfig:"CONTROL_REDIS_URL" required:"true"` - PostgresHost string `envconfig:"CONTROL_POSTGRES_HOST" required:"true"` - PostgresDB string `envconfig:"CONTROL_POSTGRES_DB" required:"true"` - PostgresUser string `envconfig:"CONTROL_POSTGRES_USER" required:"true"` - PostgresPassword string `envconfig:"CONTROL_POSTGRES_PASSWORD" required:"true"` -} - -const ( - metricsCacheSize = 2500 - metricsCommitInterval = 30 * time.Second -) - -func main() { - // Config for gateway - var config configSpecification - envutil.LoadConfig("beneath", &config) - - // Init logging - log.InitLogger() - - // Init connections - hub.InitPostgres(config.PostgresHost, config.PostgresDB, config.PostgresUser, config.PostgresPassword) - hub.InitRedis(config.RedisURL) - hub.InitEngine(config.MQDriver, config.LookupDriver, config.WarehouseDriver) - - // Init gateway globals - gw.InitMetrics(metricsCacheSize, metricsCommitInterval) - gw.InitSubscriptions(hub.Engine) - - // A ctx that we can cancel, and that also cancels on sigint, etc. - ctx, cancel := context.WithCancel(ctxutil.WithCancelOnTerminate(context.Background())) - - // Run listenAndServeHTTP and listenAndServeGRPC in the background, cancel if any of them fails - go func() { - err := listenAndServeHTTP(config.HTTPPort) - log.S.Errorw("http serve failed", "error", err) - cancel() - }() - - go func() { - err := listenAndServeGRPC(config.GRPCPort) - log.S.Errorw("grpc serve failed", "error", err) - cancel() - }() - - // Run metrics and subscriptions in the background, exit when ctx is cancelled and they've finished cleaning up - group := new(errgroup.Group) - - group.Go(func() error { - gw.Metrics.RunForever(ctx) - return nil - }) - - group.Go(func() error { - gw.Subscriptions.RunForever(ctx) - return nil - }) - - // run - err := group.Wait() - if err != nil { - log.S.Fatal(err) - } - os.Exit(0) -} - -func listenAndServeHTTP(port int) error { - log.S.Infow("gateway http started", "port", port) - return http.ListenAndServe(fmt.Sprintf(":%d", port), gwhttp.Handler()) -} - -func listenAndServeGRPC(port int) error { - lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) - if err != nil { - return err - } - - log.S.Infow("gateway grpc started", "port", port) - return gwgrpc.Server().Serve(lis) -} diff --git a/cmd/pipeline/main.go b/cmd/pipeline/main.go deleted file mode 100644 index 2f009683..00000000 --- a/cmd/pipeline/main.go +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - "context" - "os" - - "gitlab.com/beneath-hq/beneath/gateway/pipeline" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/ctxutil" - "gitlab.com/beneath-hq/beneath/pkg/envutil" - "gitlab.com/beneath-hq/beneath/pkg/log" -) - -type configSpecification struct { - MQDriver string `envconfig:"ENGINE_MQ_DRIVER" required:"true"` - LookupDriver string `envconfig:"ENGINE_LOOKUP_DRIVER" required:"true"` - WarehouseDriver string `envconfig:"ENGINE_WAREHOUSE_DRIVER" required:"true"` - RedisURL string `envconfig:"CONTROL_REDIS_URL" required:"true"` - PostgresHost string `envconfig:"CONTROL_POSTGRES_HOST" required:"true"` - PostgresDB string `envconfig:"CONTROL_POSTGRES_DB" required:"true"` - PostgresUser string `envconfig:"CONTROL_POSTGRES_USER" required:"true"` - PostgresPassword string `envconfig:"CONTROL_POSTGRES_PASSWORD" required:"true"` -} - -func main() { - // Load config - var config configSpecification - envutil.LoadConfig("beneath", &config) - - // Init logging - log.InitLogger() - - // Init data stores - hub.InitPostgres(config.PostgresHost, config.PostgresDB, config.PostgresUser, config.PostgresPassword) - hub.InitRedis(config.RedisURL) - hub.InitEngine(config.MQDriver, config.LookupDriver, config.WarehouseDriver) - - // Run forever (until failure) - ctx := ctxutil.WithCancelOnTerminate(context.Background()) - log.S.Info("pipeline started") - err := pipeline.Run(ctx) - if err != nil { - log.S.Fatal(err) - } - os.Exit(0) -} diff --git a/cmd/taskqueue/main.go b/cmd/taskqueue/main.go deleted file mode 100644 index e92244e2..00000000 --- a/cmd/taskqueue/main.go +++ /dev/null @@ -1,48 +0,0 @@ -package main - -import ( - "context" - "os" - - "gitlab.com/beneath-hq/beneath/control/payments" - "gitlab.com/beneath-hq/beneath/control/taskqueue/worker" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/ctxutil" - "gitlab.com/beneath-hq/beneath/pkg/envutil" - "gitlab.com/beneath-hq/beneath/pkg/log" - - // import modules that register tasks in taskqueue - _ "gitlab.com/beneath-hq/beneath/control/entity" -) - -type configSpecification struct { - MQDriver string `envconfig:"ENGINE_MQ_DRIVER" required:"true"` - LookupDriver string `envconfig:"ENGINE_LOOKUP_DRIVER" required:"true"` - WarehouseDriver string `envconfig:"ENGINE_WAREHOUSE_DRIVER" required:"true"` - RedisURL string `envconfig:"CONTROL_REDIS_URL" required:"true"` - PostgresHost string `envconfig:"CONTROL_POSTGRES_HOST" required:"true"` - PostgresDB string `envconfig:"CONTROL_POSTGRES_DB" required:"true"` - PostgresUser string `envconfig:"CONTROL_POSTGRES_USER" required:"true"` - PostgresPassword string `envconfig:"CONTROL_POSTGRES_PASSWORD" required:"true"` - PaymentsDrivers []string `envconfig:"CONTROL_PAYMENTS_DRIVERS" required:"true"` -} - -func main() { - var config configSpecification - envutil.LoadConfig("beneath", &config) - - log.InitLogger() - - hub.InitPostgres(config.PostgresHost, config.PostgresDB, config.PostgresUser, config.PostgresPassword) - hub.InitRedis(config.RedisURL) - hub.InitEngine(config.MQDriver, config.LookupDriver, config.WarehouseDriver) - - hub.SetPaymentDrivers(payments.InitDrivers(config.PaymentsDrivers)) - - ctx := ctxutil.WithCancelOnTerminate(context.Background()) - err := worker.Work(ctx) - if err != nil { - log.S.Fatal(err) - } - os.Exit(0) -} diff --git a/configs/README.md b/config/README.md similarity index 100% rename from configs/README.md rename to config/README.md diff --git a/config/config.yaml b/config/config.yaml new file mode 100644 index 00000000..4b450a9f --- /dev/null +++ b/config/config.yaml @@ -0,0 +1,58 @@ +mq: + driver: "" # env: BENEATH_MQ_DRIVER, flag: --mq-driver + +control: + port: 4000 # env: BENEATH_CONTROL_PORT, flag: --control-port + host: "http://localhost:4000" # env: BENEATH_CONTROL_HOST, flag: --control-host + frontend_host: "http://localhost:3000" # env: BENEATH_CONTROL_FRONTEND_HOST, flag: --control-frontend-host + + redis: + url: "redis://localhost/" # env: BENEATH_CONTROL_REDIS_URL, flag: --control-redis-url + + postgres: + host: "localhost" # env: BENEATH_CONTROL_POSTGRES_HOST, flag: --control-postgres-host + db: "postgres" # env: BENEATH_CONTROL_POSTGRES_DB, flag: --control-postgres-db + user: "postgres" # env: BENEATH_CONTROL_POSTGRES_USER, flag: --control-postgres-user + password: "" # env: BENEATH_CONTROL_POSTGRES_PASSWORD, flag: --control-postgres-password + + session_secret: "" # env: BENEATH_CONTROL_SESSION_SECRET, flag: --control-session-secret + auth: + github: + id: "" # env: BENEATH_CONTROL_AUTH_GITHUB_ID, flag: --control-auth-github-id + secret: "" # env: BENEATH_CONTROL_AUTH_GITHUB_SECRET, flag: --control-auth-github-secret + google: + id: "" # env: BENEATH_CONTROL_AUTH_GOOGLE_ID, flag: --control-auth-google-id + secret: "" # env: BENEATH_CONTROL_AUTH_GOOGLE_SECRET, flag: --control-auth-google-secret + +data: + http_port: 5000 # env: BENEATH_DATA_HTTP_PORT, flag: --data-port-http + grpc_port: 50051 # env: BENEATH_DATA_GRPC_PORT, flag: --data-port-grpc + + log: + driver: "" # env: BENEATH_DATA_LOG_DRIVER, flag: --data-log-driver + # driver-specific settings... + + index: + driver: "" # env: BENEATH_DATA_INDEX_DRIVER, flag: --data-index-driver + # driver-specific settings... + + warehouse: + driver: "" # env: BENEATH_DATA_WAREHOUSE_DRIVER, flag: --data-warehouse-driver + # driver-specific settings... + +# MQ driver settings: +# - pubsub: +# project_id: "" +# subscriber_id: "" +# emulator_host: "" +# topic_prefix: "" +# subscription_prefix: "" +# +# Data driver settings: +# - bigtable: +# project_id: "" +# instance_id: "" +# emulator_host: "" +# - bigquery: +# project_id: "" +# instances_dataset_id: "" diff --git a/configs/example.env b/configs/example.env deleted file mode 100644 index 2169778e..00000000 --- a/configs/example.env +++ /dev/null @@ -1,36 +0,0 @@ -BENEATH_FRONTEND_PORT= -BENEATH_FRONTEND_HOST= - -BENEATH_CONTROL_PORT= -BENEATH_CONTROL_HOST= -BENEATH_CONTROL_REDIS_URL= -BENEATH_CONTROL_POSTGRES_HOST= -BENEATH_CONTROL_POSTGRES_USER= -BENEATH_CONTROL_POSTGRES_PASSWORD= -BENEATH_CONTROL_SESSION_SECRET= -BENEATH_CONTROL_GITHUB_AUTH_ID= -BENEATH_CONTROL_GITHUB_AUTH_SECRET= -BENEATH_CONTROL_GOOGLE_AUTH_ID= -BENEATH_CONTROL_GOOGLE_AUTH_SECRET= -BENEATH_CONTROL_PAYMENTS_DRIVERS= - -BENEATH_GATEWAY_PORT= -BENEATH_GATEWAY_PORT_GRPC= -BENEATH_GATEWAY_HOST= - -BENEATH_ENGINE_MQ_DRIVER= -BENEATH_ENGINE_LOOKUP_DRIVER= -BENEATH_ENGINE_WAREHOUSE_DRIVER= - -BENEATH_ENGINE_PUBSUB_PROJECT_ID= -BENEATH_ENGINE_PUBSUB_SUBSCRIBER_ID= -BENEATH_ENGINE_PUBSUB_EMULATOR_HOST= -BENEATH_ENGINE_PUBSUB_TOPIC_PREFIX= -BENEATH_ENGINE_PUBSUB_SUBSCRIPTION_PREFIX= - -BENEATH_ENGINE_BIGTABLE_PROJECT_ID= -BENEATH_ENGINE_BIGTABLE_INSTANCE_ID= -BENEATH_ENGINE_BIGTABLE_EMULATOR_HOST= - -BENEATH_ENGINE_BIGQUERY_PROJECT_ID= -BENEATH_ENGINE_BIGQUERY_INSTANCES_DATASET_ID= diff --git a/control/auth/goth.go b/control/auth/goth.go deleted file mode 100644 index 1bb50b9f..00000000 --- a/control/auth/goth.go +++ /dev/null @@ -1,61 +0,0 @@ -package auth - -import ( - "fmt" - "strings" - - "github.com/gorilla/sessions" - "github.com/markbates/goth" - "github.com/markbates/goth/gothic" - "github.com/markbates/goth/providers/github" - "github.com/markbates/goth/providers/google" -) - -// GothConfig used to setup https://github.com/markbates/goth -type GothConfig struct { - ClientHost string - BackendHost string - SessionSecret string - GithubAuthID string - GithubAuthSecret string - GoogleAuthID string - GoogleAuthSecret string -} - -var ( - gothConfig *GothConfig -) - -// InitGoth configures goth -func InitGoth(config *GothConfig) { - if config == nil { - panic(fmt.Errorf("GothConfig cannot be nil")) - } - - if gothConfig != nil { - panic(fmt.Errorf("InitGoth called twice")) - } - - gothConfig = config - - goth.UseProviders( - google.New( - config.GoogleAuthID, config.GoogleAuthSecret, callbackURL("google"), - "https://www.googleapis.com/auth/plus.login", "email", - ), - github.New( - config.GithubAuthID, config.GithubAuthSecret, callbackURL("github"), - "user:email", - ), - ) - - // set store for oauth state - store := sessions.NewCookieStore([]byte(config.SessionSecret)) - store.Options.HttpOnly = true - store.Options.Secure = strings.HasPrefix(config.BackendHost, "https") - gothic.Store = store -} - -func callbackURL(provider string) string { - return fmt.Sprintf("%s/auth/%s/callback", gothConfig.BackendHost, provider) -} diff --git a/control/auth/router.go b/control/auth/router.go deleted file mode 100644 index 7fc7fa7b..00000000 --- a/control/auth/router.go +++ /dev/null @@ -1,112 +0,0 @@ -package auth - -import ( - "context" - "fmt" - "net/http" - "net/url" - - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/internal/middleware" - "gitlab.com/beneath-hq/beneath/pkg/httputil" - "gitlab.com/beneath-hq/beneath/pkg/log" - - "github.com/go-chi/chi" - "github.com/markbates/goth/gothic" -) - -// Router adds /github and /google login endpoints and /logout logout endpoint -func Router() http.Handler { - // check config set - if gothConfig == nil { - panic(fmt.Errorf("Call InitGoth before AuthHandler")) - } - - // prepare router - router := chi.NewRouter() - - // social auth handlers - router.With(providerParamToContext).MethodFunc("GET", "/{provider}", gothic.BeginAuthHandler) - router.With(providerParamToContext).Method("GET", "/{provider}/callback", httputil.AppHandler(authCallbackHandler)) - - // logout handler - router.Method("GET", "/logout", httputil.AppHandler(logoutHandler)) - - // done - return router -} - -// providerParamToContext is a middleware that reads the url param "provider" and -// saves it in the request context -- necessary because goth reads the provider name -// from the key "provider" in the request context -func providerParamToContext(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - provider := chi.URLParam(r, "provider") - ctx := context.WithValue(r.Context(), interface{}("provider"), provider) - next.ServeHTTP(w, r.WithContext(ctx)) - }) -} - -// authCallbackHandler gets called after social authentication -func authCallbackHandler(w http.ResponseWriter, r *http.Request) error { - // handle with gothic - info, err := gothic.CompleteUserAuth(w, r) - if err != nil { - return err - } - - // we're not using gothic for auth management, so end the user session immediately - gothic.Logout(w, r) - - // get googleID or githubID - var googleID string - var githubID string - if info.Provider == "google" { - googleID = info.UserID - } else if info.Provider == "github" { - githubID = info.UserID - } else { - return httputil.NewError(500, "expected provider to be 'google' or 'github'") - } - - // we only want to use Github's nicknames - var nickname string - if githubID != "" { - nickname = info.NickName - } - - // upsert user - user, err := entity.CreateOrUpdateUser(r.Context(), githubID, googleID, info.Email, nickname, info.Name, info.AvatarURL) - if err != nil { - return err - } - - // create session secret - secret, err := entity.CreateUserSecret(r.Context(), user.UserID, "Browser session", false, false) - if err != nil { - return err - } - - // redirect to client, setting token - url := fmt.Sprintf("%s/-/redirects/auth/login/callback?token=%s", gothConfig.ClientHost, url.QueryEscape(secret.Token.String())) - http.Redirect(w, r, url, http.StatusSeeOther) - - // done - return nil -} - -// logoutHandler revokes the current auth secret -func logoutHandler(w http.ResponseWriter, r *http.Request) error { - secret := middleware.GetSecret(r.Context()) - if secret != nil { - if secret.IsUser() { - secret.Revoke(r.Context()) - log.S.Infow( - "control user logout", - "user_id", secret.GetOwnerID(), - "secret_id", secret.GetSecretID(), - ) - } - } - return nil -} diff --git a/control/entity/cleanup_instance_task.go b/control/entity/cleanup_instance_task.go deleted file mode 100644 index 022decd1..00000000 --- a/control/entity/cleanup_instance_task.go +++ /dev/null @@ -1,39 +0,0 @@ -package entity - -import ( - "context" - "time" - - uuid "github.com/satori/go.uuid" - - "gitlab.com/beneath-hq/beneath/control/taskqueue" - "gitlab.com/beneath-hq/beneath/hub" -) - -// CleanupInstanceTask is a task that removes all data and tables related to an instance -type CleanupInstanceTask struct { - InstanceID uuid.UUID - CachedStream *CachedStream -} - -// register task -func init() { - taskqueue.RegisterTask(&CleanupInstanceTask{}) -} - -// Run triggers the task -func (t *CleanupInstanceTask) Run(ctx context.Context) error { - time.Sleep(getStreamCache().cacheLRUTime()) - - err := hub.Engine.RemoveInstance(ctx, t.CachedStream, t.CachedStream, EfficientStreamInstance(t.InstanceID)) - if err != nil { - return err - } - - err = hub.Engine.ClearUsage(ctx, t.InstanceID) - if err != nil { - return err - } - - return nil -} diff --git a/control/entity/cleanup_stream_task.go b/control/entity/cleanup_stream_task.go deleted file mode 100644 index acd918c9..00000000 --- a/control/entity/cleanup_stream_task.go +++ /dev/null @@ -1,30 +0,0 @@ -package entity - -import ( - "context" - - uuid "github.com/satori/go.uuid" - - "gitlab.com/beneath-hq/beneath/control/taskqueue" - "gitlab.com/beneath-hq/beneath/hub" -) - -// CleanupStreamTask is a task triggered after a stream is deleted -type CleanupStreamTask struct { - StreamID uuid.UUID -} - -// register task -func init() { - taskqueue.RegisterTask(&CleanupStreamTask{}) -} - -// Run triggers the task -func (t *CleanupStreamTask) Run(ctx context.Context) error { - err := hub.Engine.ClearUsage(ctx, t.StreamID) - if err != nil { - return err - } - - return nil -} diff --git a/control/entity/memberships.go b/control/entity/memberships.go deleted file mode 100644 index fe10c61a..00000000 --- a/control/entity/memberships.go +++ /dev/null @@ -1,91 +0,0 @@ -package entity - -import ( - "context" - - "github.com/go-pg/pg/v9" - uuid "github.com/satori/go.uuid" - - "gitlab.com/beneath-hq/beneath/hub" -) - -// ProjectMember is a convenience representation of project membership -type ProjectMember struct { - ProjectID uuid.UUID - UserID uuid.UUID - Name string - DisplayName string - PhotoURL string - View bool - Create bool - Admin bool -} - -// OrganizationMember is a convenience representation of organization membership -type OrganizationMember struct { - OrganizationID uuid.UUID - UserID uuid.UUID - BillingOrganizationID uuid.UUID - Name string - DisplayName string - PhotoURL string - View bool - Create bool - Admin bool - ReadQuota *int - WriteQuota *int - ScanQuota *int -} - -// FindProjectMembers finds useful information about the project's members, represented in -// the structure of ProjectMember -func FindProjectMembers(ctx context.Context, projectID uuid.UUID) ([]*ProjectMember, error) { - var result []*ProjectMember - _, err := hub.DB.QueryContext(ctx, &result, ` - select - p.project_id, - p.user_id, - o.name, - o.display_name, - o.photo_url, - p.view, - p."create", - p.admin - from permissions_users_projects p - join organizations o on p.user_id = o.user_id - where p.project_id = ? - `, projectID) - if err != nil && err != pg.ErrNoRows { - return nil, err - } - return result, nil -} - -// FindOrganizationMembers finds useful information about the organization's members, represented in -// the structure of OrganizationMember (includes both people with and without billing affiliation) -func FindOrganizationMembers(ctx context.Context, organizationID uuid.UUID) ([]*OrganizationMember, error) { - var result []*OrganizationMember - _, err := hub.DB.QueryContext(ctx, &result, ` - select - p.organization_id, - p.user_id, - u.billing_organization_id, - o.name, - o.display_name, - o.photo_url, - p.view, - p."create", - p.admin, - u.read_quota, - u.write_quota, - u.scan_quota - from permissions_users_organizations p - join organizations o on p.user_id = o.user_id - join users u on p.user_id = u.user_id - where p.organization_id = ? - `, organizationID) - if err != nil && err != pg.ErrNoRows { - return nil, err - } - return result, nil -} diff --git a/control/entity/organization.go b/control/entity/organization.go deleted file mode 100644 index 413a1092..00000000 --- a/control/entity/organization.go +++ /dev/null @@ -1,439 +0,0 @@ -package entity - -import ( - "context" - "fmt" - "regexp" - "time" - - "github.com/go-pg/pg/v9" - uuid "github.com/satori/go.uuid" - "gopkg.in/go-playground/validator.v9" - - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/log" - "gitlab.com/beneath-hq/beneath/pkg/timeutil" -) - -// Organization represents the entity that manages billing on behalf of its users -type Organization struct { - OrganizationID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` - Name string `sql:",unique,notnull",validate:"required,gte=3,lte=40"` // NOTE: when updating, clear stream cache - DisplayName string `sql:",notnull",validate:"required,gte=1,lte=50"` - Description string `validate:"omitempty,lte=255"` - PhotoURL string `validate:"omitempty,url,lte=400"` - UserID *uuid.UUID `sql:",on_delete:restrict,type:uuid"` - User *User - CreatedOn time.Time `sql:",default:now()"` - UpdatedOn time.Time `sql:",default:now()"` - PrepaidReadQuota *int64 // bytes - PrepaidWriteQuota *int64 // bytes - PrepaidScanQuota *int64 // bytes - ReadQuota *int64 // bytes // NOTE: when updating value, clear secret cache - WriteQuota *int64 // bytes // NOTE: when updating value, clear secret cache - ScanQuota *int64 // bytes // NOTE: when updating value, clear secret cache - Projects []*Project - Users []*User `pg:"fk:billing_organization_id"` - - // used to indicate requestor's permissions in resolvers - Permissions *PermissionsUsersOrganizations `sql:"-"` -} - -var ( - // used for validation - organizationNameRegex = regexp.MustCompile("^[_a-z][_a-z0-9]*$") - organizationNameBlacklist = []string{ - "auth", - "billing", - "console", - "docs", - "documentation", - "explore", - "health", - "healthz", - "instance", - "instances", - "organization", - "organizations", - "permissions", - "project", - "projects", - "redirects", - "secret", - "secrets", - "stream", - "streams", - "terminal", - "user", - "username", - "users", - } -) - -func init() { - // configure validation - GetValidator().RegisterStructValidation(organizationValidation, Organization{}) -} - -// custom stream validation -func organizationValidation(sl validator.StructLevel) { - s := sl.Current().Interface().(Organization) - - if !organizationNameRegex.MatchString(s.Name) { - sl.ReportError(s.Name, "Name", "", "alphanumericorunderscore", "") - } - - for _, blacklisted := range organizationNameBlacklist { - if s.Name == blacklisted { - sl.ReportError(s.Name, "Name", "", "blacklisted", "") - break - } - } -} - -// FindOrganization finds a organization by ID -func FindOrganization(ctx context.Context, organizationID uuid.UUID) *Organization { - organization := &Organization{ - OrganizationID: organizationID, - } - err := hub.DB.ModelContext(ctx, organization).WherePK(). - Column( - "organization.*", - "User", - "Projects", - ).Select() - if !AssertFoundOne(err) { - return nil - } - return organization -} - -// FindOrganizationByName finds a organization by name -func FindOrganizationByName(ctx context.Context, name string) *Organization { - organization := &Organization{} - err := hub.DB.ModelContext(ctx, organization). - Where("lower(organization.name) = lower(?)", name). - Column( - "organization.*", - "User", - "User.BillingOrganization", - "Projects", - ).Select() - if !AssertFoundOne(err) { - return nil - } - return organization -} - -// FindOrganizationByUserID finds an organization by its personal user ID (if set) -func FindOrganizationByUserID(ctx context.Context, userID uuid.UUID) *Organization { - organization := &Organization{} - err := hub.DB.ModelContext(ctx, organization). - Where("organization.user_id = ?", userID). - Column( - "organization.*", - "User", - "User.BillingOrganization", - "Projects", - ).Select() - if !AssertFoundOne(err) { - return nil - } - return organization -} - -// FindAllOrganizations returns all active organizations -func FindAllOrganizations(ctx context.Context) []*Organization { - var organizations []*Organization - err := hub.DB.ModelContext(ctx, &organizations). - Column("organization.*"). - Select() - if err != nil { - panic(err) - } - return organizations -} - -// IsOrganization implements gql.Organization -func (o *Organization) IsOrganization() {} - -// IsMulti returns true if o is a multi-user organization -func (o *Organization) IsMulti() bool { - return o.UserID == nil -} - -// IsBillingOrganizationForUser returns true if o is also the billing org for the user it represents. -// It panics if called on a non-personal organization -func (o *Organization) IsBillingOrganizationForUser() bool { - if o.UserID == nil { - panic(fmt.Errorf("Called IsBillingOrganizationForUser on non-personal organization")) - } - return o.User.BillingOrganizationID == o.OrganizationID -} - -// StripPrivateProjects removes private projects from o.Projects (no changes in database, just the loaded object) -func (o *Organization) StripPrivateProjects() { - for i, p := range o.Projects { - if !p.Public { - n := len(o.Projects) - o.Projects[n-1], o.Projects[i] = o.Projects[i], o.Projects[n-1] - o.Projects = o.Projects[:n-1] - } - } -} - -// CreateWithUser creates an organization and makes user a member -func (o *Organization) CreateWithUser(ctx context.Context, userID uuid.UUID, view bool, create bool, admin bool) error { - defaultBillingPlan := FindDefaultBillingPlan(ctx) - - o.PrepaidReadQuota = &defaultBillingPlan.ReadQuota - o.PrepaidWriteQuota = &defaultBillingPlan.WriteQuota - o.ReadQuota = &defaultBillingPlan.ReadQuota - o.WriteQuota = &defaultBillingPlan.WriteQuota - - // validate - err := GetValidator().Struct(o) - if err != nil { - return err - } - - // create organization and PermissionsUsersOrganizations in one transaction - err = hub.DB.WithContext(ctx).RunInTransaction(func(tx *pg.Tx) error { - // insert org - _, err := tx.Model(o).Insert() - if err != nil { - return err - } - - // connect org to userID - err = tx.Insert(&PermissionsUsersOrganizations{ - UserID: userID, - OrganizationID: o.OrganizationID, - View: view, - Create: create, - Admin: admin, - }) - if err != nil { - return err - } - - // create billing info - bi := &BillingInfo{ - OrganizationID: o.OrganizationID, - BillingPlanID: defaultBillingPlan.BillingPlanID, - } - _, err = tx.Model(bi).Insert() - if err != nil { - return err - } - - return nil - }) - if err != nil { - return err - } - - // log new organization - log.S.Infow( - "control created non-personal organization", - "organization_id", o.OrganizationID, - ) - - return nil -} - -// UpdateDetails updates the organization's name, display name, description and/or photo -func (o *Organization) UpdateDetails(ctx context.Context, name *string, displayName *string, description *string, photoURL *string) error { - if name != nil { - o.Name = *name - } - if displayName != nil { - o.DisplayName = *displayName - } - if description != nil { - o.Description = *description - } - if photoURL != nil { - o.PhotoURL = *photoURL - } - - // validate - err := GetValidator().Struct(o) - if err != nil { - return err - } - - o.UpdatedOn = time.Now() - _, err = hub.DB.ModelContext(ctx, o). - Column( - "name", - "display_name", - "description", - "photo_url", - "updated_on", - ).WherePK().Update() - if err != nil { - return err - } - - // flush all cached streams if name changed - if name != nil { - getStreamCache().ClearForOrganization(ctx, o.OrganizationID) - } - - return nil -} - -// UpdateQuotas updates the quotas enforced upon the organization -func (o *Organization) UpdateQuotas(ctx context.Context, readQuota *int64, writeQuota *int64, scanQuota *int64) error { - // set fields - o.ReadQuota = readQuota - o.WriteQuota = writeQuota - o.ScanQuota = scanQuota - - // validate - err := GetValidator().Struct(o) - if err != nil { - return err - } - - // update - o.UpdatedOn = time.Now() - _, err = hub.DB.ModelContext(ctx, o).Column("read_quota", "write_quota", "scan_quota", "updated_on").WherePK().Update() - - // clear cache for the organization's users' secrets - getSecretCache().ClearForOrganization(ctx, o.OrganizationID) - - return err -} - -// UpdatePrepaidQuotas updates the organization's prepaid quotas -func (o *Organization) UpdatePrepaidQuotas(ctx context.Context, billingPlan *BillingPlan) error { - numSeats := int64(len(o.Users)) - prepaidReadQuota := billingPlan.BaseReadQuota + billingPlan.SeatReadQuota*numSeats - prepaidWriteQuota := billingPlan.BaseWriteQuota + billingPlan.SeatWriteQuota*numSeats - prepaidScanQuota := billingPlan.BaseScanQuota + billingPlan.SeatScanQuota*numSeats - - // set fields - o.PrepaidReadQuota = &prepaidReadQuota - o.PrepaidWriteQuota = &prepaidWriteQuota - o.PrepaidScanQuota = &prepaidScanQuota - o.UpdatedOn = time.Now() - - // update - _, err := hub.DB.WithContext(ctx).Model(o). - Column("prepaid_read_quota", "prepaid_write_quota", "prepaid_scan_quota", "updated_on"). - WherePK(). - Update() - if err != nil { - return err - } - - return err -} - -// Delete deletes the organization -// this will fail if there are any users, services, or projects that are still tied to the organization -func (o *Organization) Delete(ctx context.Context) error { - // NOTE: effectively, this resolver doesn't work, as there will always be one admin member - // TODO: check it's empty and has just one admin user, trigger bill, make the admin leave, delete org - - err := hub.DB.WithContext(ctx).Delete(o) - if err != nil { - return err - } - - return nil -} - -// TransferUser transfers a user in o to another organization -func (o *Organization) TransferUser(ctx context.Context, user *User, targetOrg *Organization) error { - // can be from personal to multi, multi to personal, multi to multi - - // Ensure the last admin member isn't leaving a multi-user org - if o.IsMulti() { - foundRemainingAdmin := false - members, err := FindOrganizationMembers(ctx, o.OrganizationID) - if err != nil { - return err - } - for _, member := range members { - if member.Admin && member.UserID != user.UserID { - foundRemainingAdmin = true - break - } - } - if !foundRemainingAdmin { - return fmt.Errorf("Cannot transfer user because it would leave the organization without an admin") - } - } - - // update user - user.BillingOrganization = targetOrg - user.BillingOrganizationID = targetOrg.OrganizationID - user.ReadQuota = nil - user.WriteQuota = nil - user.ScanQuota = nil - user.UpdatedOn = time.Now() - _, err := hub.DB.WithContext(ctx).Model(user). - Column("billing_organization_id", "read_quota", "write_quota", "scan_quota", "updated_on"). - WherePK(). - Update() - if err != nil { - return err - } - getSecretCache().ClearForUser(ctx, user.UserID) - - // find target billing info - targetBillingInfo := FindBillingInfo(ctx, targetOrg.OrganizationID) - if targetBillingInfo == nil { - return fmt.Errorf("Couldn't find billing info for target organization") - } - - // add prorated seat to the target organization's next month's bill - billingTime := timeutil.Next(time.Now(), targetBillingInfo.BillingPlan.Period) - err = commitProratedSeatsToBill(ctx, targetBillingInfo, billingTime, []*User{user}) - if err != nil { - panic("unable to commit prorated seat to bill") - } - - // increment the target organization's prepaid quota by the seat quota - // we do this now because we want to show the new usage capacity in the UI as soon as possible - if targetBillingInfo.BillingPlan.SeatReadQuota > 0 || targetBillingInfo.BillingPlan.SeatWriteQuota > 0 || targetBillingInfo.BillingPlan.SeatScanQuota > 0 { - newPrepaidReadQuota := *targetOrg.PrepaidReadQuota + targetBillingInfo.BillingPlan.SeatReadQuota - newPrepaidWriteQuota := *targetOrg.PrepaidWriteQuota + targetBillingInfo.BillingPlan.SeatWriteQuota - newPrepaidScanQuota := *targetOrg.PrepaidScanQuota + targetBillingInfo.BillingPlan.SeatScanQuota - - targetOrg.PrepaidReadQuota = &newPrepaidReadQuota - targetOrg.PrepaidWriteQuota = &newPrepaidWriteQuota - targetOrg.PrepaidScanQuota = &newPrepaidScanQuota - - targetOrg.UpdatedOn = time.Now() - - _, err = hub.DB.WithContext(ctx).Model(targetOrg). - Column("prepaid_read_quota", "prepaid_write_quota", "prepaid_scan_quota", "updated_on"). - WherePK(). - Update() - if err != nil { - return err - } - } - - return nil -} - -// TransferProject transfers a project in o to another organization -func (o *Organization) TransferProject(ctx context.Context, project *Project, targetOrg *Organization) error { - project.Organization = targetOrg - project.OrganizationID = targetOrg.OrganizationID - project.UpdatedOn = time.Now() - _, err := hub.DB.ModelContext(ctx, project).Column("organization_id", "updated_on").WherePK().Update() - if err != nil { - return err - } - - // stream cache includes organization name, so invalidate cache - getStreamCache().ClearForProject(ctx, project.ProjectID) - - return nil -} diff --git a/control/entity/organization_invite.go b/control/entity/organization_invite.go deleted file mode 100644 index a286a31a..00000000 --- a/control/entity/organization_invite.go +++ /dev/null @@ -1,65 +0,0 @@ -package entity - -import ( - "context" - "time" - - uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/hub" -) - -// OrganizationInvite represents invites to use an organization as your billing organization. -// An invite procedure is required since there's mutual costs and benefits: a) The inviter -// proposes to cover the invitees bills, but b) the invitee is subjected to quotas set by -// from the inviter (as well as more intrusive oversight). -// Don't confuse changing billing organizations with simply granted organization permissions to someone, -// which doesn't imply a change in billing or quotas. -type OrganizationInvite struct { - OrganizationInviteID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` - OrganizationID uuid.UUID `sql:"on_delete:CASCADE,type:uuid"` - Organization *Organization - UserID uuid.UUID `sql:"on_delete:CASCADE,type:uuid"` - User *User - CreatedOn time.Time `sql:",default:now()"` - UpdatedOn time.Time `sql:",default:now()"` - View bool `sql:",notnull"` - Create bool `sql:",notnull"` - Admin bool `sql:",notnull"` -} - -// FindOrganizationInvite finds an existing invitation -func FindOrganizationInvite(ctx context.Context, organizationID uuid.UUID, userID uuid.UUID) *OrganizationInvite { - invite := &OrganizationInvite{} - err := hub.DB.ModelContext(ctx, invite). - Column("organization_invite.*", "Organization", "User", "User.BillingOrganization"). - Where("organization_invite.organization_id = ?", organizationID). - Where("organization_invite.user_id = ?", userID). - Select() - if !AssertFoundOne(err) { - return nil - } - return invite -} - -// Upsert creates or updates the organization invite -func (i *OrganizationInvite) Upsert(ctx context.Context) error { - // validate - err := GetValidator().Struct(i) - if err != nil { - return err - } - - // build upsert - q := hub.DB.ModelContext(ctx, i).OnConflict("(organization_id, user_id) DO UPDATE") - q.Set("view = EXCLUDED.view") - q.Set(`"create" = EXCLUDED."create"`) - q.Set("admin = EXCLUDED.admin") - - // run upsert - _, err = q.Insert() - if err != nil { - return err - } - - return nil -} diff --git a/control/entity/permissions.go b/control/entity/permissions.go deleted file mode 100644 index d1018fc6..00000000 --- a/control/entity/permissions.go +++ /dev/null @@ -1,228 +0,0 @@ -package entity - -import ( - "context" - - "github.com/go-pg/pg/v9/orm" - uuid "github.com/satori/go.uuid" - - "gitlab.com/beneath-hq/beneath/hub" -) - -// PermissionsUsersProjects represents the many-to-many relationship between users and projects -type PermissionsUsersProjects struct { - tableName struct{} `sql:"permissions_users_projects"` - UserID uuid.UUID `sql:"on_delete:CASCADE,pk,type:uuid"` - User *User - ProjectID uuid.UUID `sql:"on_delete:CASCADE,pk,type:uuid"` - Project *Project - View bool `sql:",notnull"` - Create bool `sql:",notnull"` - Admin bool `sql:",notnull"` -} - -// PermissionsUsersOrganizations represents the many-to-one relationship between users and organizations -type PermissionsUsersOrganizations struct { - tableName struct{} `sql:"permissions_users_organizations"` - UserID uuid.UUID `sql:"on_delete:CASCADE,pk,type:uuid"` - User *User - OrganizationID uuid.UUID `sql:"on_delete:CASCADE,pk,type:uuid"` - Organization *Organization - View bool `sql:",notnull"` - Create bool `sql:",notnull"` - Admin bool `sql:",notnull"` -} - -// PermissionsServicesStreams represnts the many-to-many relationship between services and projects -type PermissionsServicesStreams struct { - tableName struct{} `sql:"permissions_services_streams"` - ServiceID uuid.UUID `sql:"on_delete:CASCADE,pk,type:uuid"` - Service *Service - StreamID uuid.UUID `sql:"on_delete:CASCADE,pk,type:uuid"` - Stream *Stream - Read bool `sql:",notnull"` - Write bool `sql:",notnull"` -} - -func init() { - orm.RegisterTable((*PermissionsUsersProjects)(nil)) - orm.RegisterTable((*PermissionsUsersOrganizations)(nil)) - orm.RegisterTable((*PermissionsServicesStreams)(nil)) -} - -// FindPermissionsUsersProjects finds a user's permissions for a project -func FindPermissionsUsersProjects(ctx context.Context, userID uuid.UUID, projectID uuid.UUID) *PermissionsUsersProjects { - permissions := &PermissionsUsersProjects{ - UserID: userID, - ProjectID: projectID, - } - err := hub.DB.ModelContext(ctx, permissions). - WherePK(). - Select() - - if !AssertFoundOne(err) { - return nil - } - - return permissions -} - -// FindPermissionsUsersOrganizations finds a user's permissions for an organization -func FindPermissionsUsersOrganizations(ctx context.Context, userID uuid.UUID, organizationID uuid.UUID) *PermissionsUsersOrganizations { - permissions := &PermissionsUsersOrganizations{ - UserID: userID, - OrganizationID: organizationID, - } - err := hub.DB.ModelContext(ctx, permissions). - WherePK(). - Select() - - if !AssertFoundOne(err) { - return nil - } - - return permissions -} - -// FindPermissionsServicesStreams finds a service's permissions for a stream -func FindPermissionsServicesStreams(ctx context.Context, serviceID uuid.UUID, streamID uuid.UUID) *PermissionsServicesStreams { - permissions := &PermissionsServicesStreams{ - ServiceID: serviceID, - StreamID: streamID, - } - err := hub.DB.ModelContext(ctx, permissions). - WherePK(). - Select() - - if !AssertFoundOne(err) { - return nil - } - - return permissions -} - -// Update upserts permissions (or deletes them if all are falsy) -func (p *PermissionsUsersProjects) Update(ctx context.Context, view *bool, create *bool, admin *bool) error { - if view != nil { - p.View = *view - } - if create != nil { - p.Create = *create - } - if admin != nil { - p.Admin = *admin - } - - // if all are falsy, delete the permiission (if it exists), else update - if !p.View && !p.Create && !p.Admin { - _, err := hub.DB.ModelContext(ctx, p).WherePK().Delete() - if err != nil { - return err - } - } else { - // build upsert - q := hub.DB.ModelContext(ctx, p).OnConflict("(user_id, project_id) DO UPDATE") - if view != nil { - q = q.Set("view = EXCLUDED.view") - } - if create != nil { - q = q.Set(`"create" = EXCLUDED."create"`) - } - if admin != nil { - q = q.Set("admin = EXCLUDED.admin") - } - - // run upsert - _, err := q.Insert() - if err != nil { - return err - } - } - - // clear cache - getUserProjectPermissionsCache().Clear(ctx, p.UserID, p.ProjectID) - - return nil -} - -// Update upserts permissions (or deletes them if all are falsy) -func (p *PermissionsUsersOrganizations) Update(ctx context.Context, view *bool, create *bool, admin *bool) error { - if view != nil { - p.View = *view - } - if create != nil { - p.Create = *create - } - if admin != nil { - p.Admin = *admin - } - - // if all are falsy, delete the permiission (if it exists), else update - if !p.View && !p.Create && !p.Admin { - _, err := hub.DB.ModelContext(ctx, p).WherePK().Delete() - if err != nil { - return err - } - } else { - // build upsert - q := hub.DB.ModelContext(ctx, p).OnConflict("(user_id, organization_id) DO UPDATE") - if view != nil { - q = q.Set("view = EXCLUDED.view") - } - if create != nil { - q = q.Set(`"create" = EXCLUDED."create"`) - } - if admin != nil { - q = q.Set("admin = EXCLUDED.admin") - } - - // run upsert - _, err := q.Insert() - if err != nil { - return err - } - } - - // clear cache - getUserOrganizationPermissionsCache().Clear(ctx, p.UserID, p.OrganizationID) - - return nil -} - -// Update upserts permissions (or deletes them if all are falsy) -func (p *PermissionsServicesStreams) Update(ctx context.Context, read *bool, write *bool) error { - if read != nil { - p.Read = *read - } - if write != nil { - p.Write = *write - } - - // if all are falsy, delete the permiission (if it exists), else update - if !p.Read && !p.Write { - _, err := hub.DB.ModelContext(ctx, p).WherePK().Delete() - if err != nil { - return err - } - } else { - // build upsert - q := hub.DB.ModelContext(ctx, p).OnConflict("(service_id, stream_id) DO UPDATE") - if read != nil { - q = q.Set("read = EXCLUDED.read") - } - if write != nil { - q = q.Set("write = EXCLUDED.write") - } - - // run upsert - _, err := q.Insert() - if err != nil { - return err - } - } - - // clear cache - getServiceStreamPermissionsCache().Clear(ctx, p.ServiceID, p.StreamID) - - return nil -} diff --git a/control/entity/permissions_cache.go b/control/entity/permissions_cache.go deleted file mode 100644 index 3a21239a..00000000 --- a/control/entity/permissions_cache.go +++ /dev/null @@ -1,188 +0,0 @@ -package entity - -import ( - "bytes" - "context" - "encoding/gob" - "reflect" - "time" - - "github.com/go-pg/pg/v9" - "github.com/go-redis/cache/v7" - uuid "github.com/satori/go.uuid" - - "gitlab.com/beneath-hq/beneath/hub" -) - -// ProjectPermissions represents permissions that a user has for a given project -type ProjectPermissions struct { - View bool - Create bool - Admin bool -} - -// StreamPermissions represents permissions that a service has for a given stream -type StreamPermissions struct { - Read bool - Write bool -} - -// OrganizationPermissions represents permissions that a user has for a given organization -type OrganizationPermissions struct { - View bool - Create bool - Admin bool -} - -// PermissionsCache caches an owner's permissions for a resource for fast access -type PermissionsCache struct { - codec *cache.Codec - prototype reflect.Type - query string -} - -var ( - userOrganizationPermissions *PermissionsCache - userProjectPermissions *PermissionsCache - serviceStreamPermissions *PermissionsCache -) - -var permsCacheConfig = struct { - cacheTime time.Duration - cacheLRUTime time.Duration - cacheLRUSize int - redisKeyFn func(ownerID uuid.UUID, resourceID uuid.UUID) string -}{ - cacheTime: time.Hour, - cacheLRUTime: 10 * time.Second, - cacheLRUSize: 20000, - redisKeyFn: func(ownerID uuid.UUID, resourceID uuid.UUID) string { - res := append([]byte("perm:"), ownerID.Bytes()...) - res = append(res, resourceID.Bytes()...) - return string(res) - }, -} - -func getUserOrganizationPermissionsCache() *PermissionsCache { - if userOrganizationPermissions == nil { - userOrganizationPermissions = NewPermissionsCache(OrganizationPermissions{}, ` - select p.view, p.create, p.admin - from permissions_users_organizations p - where p.user_id = ? and p.organization_id = ? - `) - } - - return userOrganizationPermissions -} - -func getUserProjectPermissionsCache() *PermissionsCache { - if userProjectPermissions == nil { - userProjectPermissions = NewPermissionsCache(ProjectPermissions{}, ` - select p.view, p.create, p.admin - from permissions_users_projects p - where p.user_id = ? and p.project_id = ? - `) - } - - return userProjectPermissions -} - -func getServiceStreamPermissionsCache() *PermissionsCache { - if serviceStreamPermissions == nil { - serviceStreamPermissions = NewPermissionsCache(StreamPermissions{}, ` - select p.read, p.write - from permissions_services_streams p - where p.service_id = ? and p.stream_id = ? - `) - } - - return serviceStreamPermissions -} - -// CachedUserOrganizationPermissions returns organization permissions for a given owner-resource combo -func CachedUserOrganizationPermissions(ctx context.Context, userID uuid.UUID, organizationID uuid.UUID) OrganizationPermissions { - return getUserOrganizationPermissionsCache().Get(ctx, userID, organizationID).(OrganizationPermissions) -} - -// CachedUserProjectPermissions returns project permissions for a given owner-resource combo -func CachedUserProjectPermissions(ctx context.Context, userID uuid.UUID, projectID uuid.UUID) ProjectPermissions { - return getUserProjectPermissionsCache().Get(ctx, userID, projectID).(ProjectPermissions) -} - -// CachedServiceStreamPermissions returns stream permissions for a given owner-resource combo -func CachedServiceStreamPermissions(ctx context.Context, serviceID uuid.UUID, streamID uuid.UUID) StreamPermissions { - return getServiceStreamPermissionsCache().Get(ctx, serviceID, streamID).(StreamPermissions) -} - -// NewPermissionsCache initializes a PermissionCache object for a given prototype (organization/project/stream) -func NewPermissionsCache(prototype interface{}, query string) *PermissionsCache { - pm := &PermissionsCache{} - pm.prototype = reflect.TypeOf(prototype) - pm.query = query - pm.codec = &cache.Codec{ - Redis: hub.Redis, - Marshal: pm.marshal, - Unmarshal: pm.unmarshal, - } - pm.codec.UseLocalCache(permsCacheConfig.cacheLRUSize, permsCacheConfig.cacheLRUTime) - return pm -} - -// Get fetches permissions by applying the cached query to the given parameters -func (c *PermissionsCache) Get(ctx context.Context, ownerID uuid.UUID, resourceID uuid.UUID) interface{} { - res := reflect.New(c.prototype) - err := c.codec.Once(&cache.Item{ - Key: permsCacheConfig.redisKeyFn(ownerID, resourceID), - Object: res.Interface(), - Expiration: permsCacheConfig.cacheTime, - Func: c.getterFunc(ctx, ownerID, resourceID), - }) - if err != nil { - if ctx.Err() == context.Canceled { - return res.Elem().Interface() - } - panic(err) - } - return res.Elem().Interface() -} - -// Clear removes a key from the cache -func (c *PermissionsCache) Clear(ctx context.Context, ownerID uuid.UUID, resourceID uuid.UUID) { - err := c.codec.Delete(permsCacheConfig.redisKeyFn(ownerID, resourceID)) - if err != nil && err != cache.ErrCacheMiss { - panic(err) - } -} - -func (c PermissionsCache) marshal(v interface{}) ([]byte, error) { - var buf bytes.Buffer - enc := gob.NewEncoder(&buf) - err := enc.Encode(v) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -func (c PermissionsCache) unmarshal(b []byte, v interface{}) (err error) { - dec := gob.NewDecoder(bytes.NewReader(b)) - err = dec.Decode(v) - if err != nil { - return err - } - return nil -} - -func (c PermissionsCache) getterFunc(ctx context.Context, ownerID uuid.UUID, resourceID uuid.UUID) func() (interface{}, error) { - return func() (interface{}, error) { - res := reflect.New(c.prototype) - _, err := hub.DB.QueryContext(ctx, res.Interface(), c.query, ownerID, resourceID) - if err != nil && err != pg.ErrNoRows { - if ctx.Err() == context.Canceled { - return res.Elem().Interface(), nil - } - panic(err) - } - return res.Elem().Interface(), nil - } -} diff --git a/control/entity/project.go b/control/entity/project.go deleted file mode 100644 index 8eefb5ff..00000000 --- a/control/entity/project.go +++ /dev/null @@ -1,255 +0,0 @@ -package entity - -import ( - "context" - "regexp" - "time" - - "github.com/go-pg/pg/v9" - "github.com/go-pg/pg/v9/orm" - uuid "github.com/satori/go.uuid" - "gopkg.in/go-playground/validator.v9" - - "gitlab.com/beneath-hq/beneath/hub" -) - -// Project represents a Beneath project -type Project struct { - ProjectID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` - Name string `sql:",notnull",validate:"required,gte=3,lte=16"` - DisplayName string `validate:"omitempty,lte=40"` - Site string `validate:"omitempty,url,lte=255"` - Description string `validate:"omitempty,lte=255"` - PhotoURL string `validate:"omitempty,url,lte=255"` - Public bool `sql:",notnull,default:true"` - Locked bool `sql:",notnull,default:false"` - ExploreRank int - OrganizationID uuid.UUID `sql:",on_delete:restrict,notnull,type:uuid"` - Organization *Organization - CreatedOn time.Time `sql:",default:now()"` - UpdatedOn time.Time `sql:",default:now()"` - Streams []*Stream - Services []*Service - Users []*User `pg:"many2many:permissions_users_projects,fk:project_id,joinFK:user_id"` - - // used to indicate requestor's permissions in resolvers - Permissions *PermissionsUsersProjects `sql:"-"` -} - -var ( - // regex used in validation - projectNameRegex *regexp.Regexp -) - -func init() { - projectNameRegex = regexp.MustCompile("^[_a-z][_a-z0-9]*$") - GetValidator().RegisterStructValidation(validateProject, Project{}) -} - -// custom project validation -func validateProject(sl validator.StructLevel) { - p := sl.Current().Interface().(Project) - - if !projectNameRegex.MatchString(p.Name) { - sl.ReportError(p.Name, "Name", "", "alphanumericorunderscore", "") - } -} - -// FindProject finds a project by ID -func FindProject(ctx context.Context, projectID uuid.UUID) *Project { - project := &Project{ - ProjectID: projectID, - } - err := hub.DB.ModelContext(ctx, project).WherePK().Column("project.*", "Streams", "Services", "Organization").Select() - if !AssertFoundOne(err) { - return nil - } - return project -} - -// ExploreProjects returns a sample of projects -func ExploreProjects(ctx context.Context) []*Project { - var projects []*Project - err := hub.DB.ModelContext(ctx, &projects). - Where("project.explore_rank IS NOT NULL"). - Limit(200). - Order("explore_rank"). - Relation("Organization"). - Select() - if err != nil { - panic(err) - } - return projects -} - -// FindProjectsForUser finds the projects that the user has been granted access to -func FindProjectsForUser(ctx context.Context, userID uuid.UUID) []*Project { - var projects []*Project - err := hub.DB.ModelContext(ctx, &projects). - Relation("Organization"). - Join("JOIN permissions_users_projects AS pup ON pup.project_id = project.project_id"). - Where("pup.user_id = ?", userID). - Order("project.name"). - Limit(200). - Select() - if err != nil { - panic(err) - } - return projects -} - -// FindProjectByOrganizationAndName finds a project by organization name and project name -func FindProjectByOrganizationAndName(ctx context.Context, organizationName string, projectName string) *Project { - project := &Project{} - err := hub.DB.ModelContext(ctx, project). - Relation("Organization", func(q *orm.Query) (*orm.Query, error) { - return q.Where("lower(organization.name) = lower(?)", organizationName), nil - }). - Where("lower(project.name) = lower(?)", projectName). - Column("project.*", "Streams", "Services"). - Select() - if !AssertFoundOne(err) { - return nil - } - return project -} - -// GetProjectID implements engine/driver.Project -func (p *Project) GetProjectID() uuid.UUID { - return p.ProjectID -} - -// GetOrganizationName implements engine/driver.Project -func (p *Project) GetOrganizationName() string { - return p.Organization.Name -} - -// GetProjectName implements engine/driver.Project -func (p *Project) GetProjectName() string { - return p.Name -} - -// GetPublic implements engine/driver.Project -func (p *Project) GetPublic() bool { - return p.Public -} - -// StageWithUser updates the project if it already exists or creates it with the given user as a member -func (p *Project) StageWithUser(ctx context.Context, displayName *string, public *bool, description *string, site *string, photoURL *string, userID uuid.UUID, perms ProjectPermissions) error { - // determine whether to insert or update - update := (p.ProjectID != uuid.Nil) - - // tracks whether a save is necessary - save := !update - - if displayName != nil && p.DisplayName != *displayName { - p.DisplayName = *displayName - save = true - } - - if public != nil && p.Public != *public { - p.Public = *public - save = true - } - - if description != nil && p.Description != *description { - p.Description = *description - save = true - } - - if site != nil && p.Site != *site { - p.Site = *site - save = true - } - - if photoURL != nil && p.PhotoURL != *photoURL { - p.PhotoURL = *photoURL - save = true - } - - // quit if no changes - if !save { - return nil - } - - // validate - err := GetValidator().Struct(p) - if err != nil { - return err - } - - // note: if we ever support renaming projects, must invalidate stream cache for all instances in project - - return hub.DB.WithContext(ctx).RunInTransaction(func(tx *pg.Tx) error { - if update { - // update - p.UpdatedOn = time.Now() - _, err = tx.Model(p). - Column("display_name", "public", "description", "site", "photo_url", "updated_on"). - WherePK(). - Update() - if err != nil { - return err - } - } else { - // insert - _, err := tx.Model(p).Insert() - if err != nil { - return err - } - - // connect project to userID - err = tx.Insert(&PermissionsUsersProjects{ - UserID: userID, - ProjectID: p.ProjectID, - View: perms.View, - Create: perms.Create, - Admin: perms.Admin, - }) - if err != nil { - return err - } - } - - // update in warehouse - err = hub.Engine.RegisterProject(ctx, p) - if err != nil { - return err - } - - return nil - }) -} - -// SetLock sets a project's "locked" status -func (p *Project) SetLock(ctx context.Context, isLocked bool) error { - p.Locked = isLocked - p.UpdatedOn = time.Now() - - _, err := hub.DB.ModelContext(ctx, p). - Column("locked", "updated_on"). - WherePK(). - Update() - if err != nil { - return err - } - - return nil -} - -// Delete safely deletes the project (fails if the project still has content) -func (p *Project) Delete(ctx context.Context) error { - return hub.DB.WithContext(ctx).RunInTransaction(func(tx *pg.Tx) error { - err := hub.DB.WithContext(ctx).Delete(p) - if err != nil { - return err - } - - err = hub.Engine.RemoveProject(ctx, p) - if err != nil { - return err - } - - return nil - }) -} diff --git a/control/entity/secret.go b/control/entity/secret.go deleted file mode 100644 index c9ef54a7..00000000 --- a/control/entity/secret.go +++ /dev/null @@ -1,132 +0,0 @@ -package entity - -import ( - "context" - "time" - - "gitlab.com/beneath-hq/beneath/pkg/secrettoken" - - uuid "github.com/satori/go.uuid" -) - -const ( - // TokenFlagsService is used as flags byte for service secret tokens - TokenFlagsService = byte(0x80) - - // TokenFlagsUser is used as flags byte for user secret tokens - TokenFlagsUser = byte(0x81) -) - -// Secret represents an access token to Beneath -type Secret interface { - // GetSecretID returns a unique identifier of the secret - GetSecretID() uuid.UUID - - // GetOwnerID returns the ID of the secret's owner, i.e. a user or service (or uuid.Nil for anonymous) - GetOwnerID() uuid.UUID - - // GetBillingOrganizationID returns the ID of the organization responsible for the secret's billing - GetBillingOrganizationID() uuid.UUID - - // IsAnonymous is true iff the secret is anonymous - IsAnonymous() bool - - // IsUser is true iff the secret is a user - IsUser() bool - - // IsService is true iff the secret is a service - IsService() bool - - // IsMaster is true iff the secret is a master secret - IsMaster() bool - - // GetBillingReadQuota returns the billing organization's read quota (or nil if unlimited) - GetBillingReadQuota() *int64 - - // GetBillingWriteQuota returns the billing organization's write quota (or nil if unlimited) - GetBillingWriteQuota() *int64 - - // GetBillingScanQuota returns the billing organization's scan quota (or nil if unlimited) - GetBillingScanQuota() *int64 - - // GetOwnerReadQuota returns the owner's read quota (or nil if unlimited) - GetOwnerReadQuota() *int64 - - // GetOwnerWriteQuota returns the owner's write quota (or nil if unlimited) - GetOwnerWriteQuota() *int64 - - // GetOwnerScanQuota returns the owner's scan quota (or nil if unlimited) - GetOwnerScanQuota() *int64 - - // StreamPermissions returns the secret's permissions for a given stream - StreamPermissions(ctx context.Context, streamID uuid.UUID, projectID uuid.UUID, public bool) StreamPermissions - - // ProjectPermissions returns the secret's permissions for a given project - ProjectPermissions(ctx context.Context, projectID uuid.UUID, public bool) ProjectPermissions - - // OrganizationPermissions returns the secret's permissions for a given organization - OrganizationPermissions(ctx context.Context, organizationID uuid.UUID) OrganizationPermissions - - // Revokes the secret - Revoke(ctx context.Context) -} - -// BaseSecret is the "abstract" base of structs that implement the Secret interface -type BaseSecret struct { - _msgpack struct{} `msgpack:",omitempty"` - Prefix string `sql:",notnull",validate:"required,len=4"` - HashedToken []byte `sql:",unique,notnull",validate:"required,lte=64"` - Description string `validate:"omitempty,lte=40"` - CreatedOn time.Time `sql:",notnull,default:now()"` - UpdatedOn time.Time `sql:",notnull,default:now()"` - - Token secrettoken.Token `sql:"-"` - Master bool `sql:"-"` - BillingOrganizationID uuid.UUID `sql:"-"` - BillingReadQuota *int64 `sql:"-"` - BillingWriteQuota *int64 `sql:"-"` - BillingScanQuota *int64 `sql:"-"` - OwnerReadQuota *int64 `sql:"-"` - OwnerWriteQuota *int64 `sql:"-"` - OwnerScanQuota *int64 `sql:"-"` -} - -// GetBillingOrganizationID implements Secret -func (s *BaseSecret) GetBillingOrganizationID() uuid.UUID { - return s.BillingOrganizationID -} - -// IsMaster implements Secret -func (s *BaseSecret) IsMaster() bool { - return s.Master -} - -// GetBillingReadQuota implements Secret -func (s *BaseSecret) GetBillingReadQuota() *int64 { - return s.BillingReadQuota -} - -// GetBillingWriteQuota implements Secret -func (s *BaseSecret) GetBillingWriteQuota() *int64 { - return s.BillingWriteQuota -} - -// GetBillingScanQuota implements Secret -func (s *BaseSecret) GetBillingScanQuota() *int64 { - return s.BillingScanQuota -} - -// GetOwnerReadQuota implements Secret -func (s *BaseSecret) GetOwnerReadQuota() *int64 { - return s.OwnerReadQuota -} - -// GetOwnerWriteQuota implements Secret -func (s *BaseSecret) GetOwnerWriteQuota() *int64 { - return s.OwnerWriteQuota -} - -// GetOwnerScanQuota implements Secret -func (s *BaseSecret) GetOwnerScanQuota() *int64 { - return s.OwnerScanQuota -} diff --git a/control/entity/secret_anonymous.go b/control/entity/secret_anonymous.go deleted file mode 100644 index be80fa61..00000000 --- a/control/entity/secret_anonymous.go +++ /dev/null @@ -1,102 +0,0 @@ -package entity - -import ( - "context" - "fmt" - - "gitlab.com/beneath-hq/beneath/pkg/log" - - uuid "github.com/satori/go.uuid" -) - -// AnonymousSecret implements Secret for anonymous requests -type AnonymousSecret struct{} - -// GetSecretID implements the Secret interface -func (s *AnonymousSecret) GetSecretID() uuid.UUID { - return uuid.Nil -} - -// GetOwnerID implements the Secret interface -func (s *AnonymousSecret) GetOwnerID() uuid.UUID { - return uuid.Nil -} - -// GetBillingOrganizationID implements the Secret interface -func (s *AnonymousSecret) GetBillingOrganizationID() uuid.UUID { - return uuid.Nil -} - -// IsAnonymous implements the Secret interface -func (s *AnonymousSecret) IsAnonymous() bool { - return true -} - -// IsUser implements the Secret interface -func (s *AnonymousSecret) IsUser() bool { - return false -} - -// IsService implements the Secret interface -func (s *AnonymousSecret) IsService() bool { - return false -} - -// IsMaster implements the Secret interface -func (s *AnonymousSecret) IsMaster() bool { - return false -} - -// GetBillingReadQuota implements Secret -func (s *AnonymousSecret) GetBillingReadQuota() *int64 { - panic(fmt.Errorf("Called GetBillingReadQuota on an anonymous secret")) -} - -// GetBillingWriteQuota implements Secret -func (s *AnonymousSecret) GetBillingWriteQuota() *int64 { - panic(fmt.Errorf("Called GetBillingWriteQuota on an anonymous secret")) -} - -// GetBillingScanQuota implements Secret -func (s *AnonymousSecret) GetBillingScanQuota() *int64 { - panic(fmt.Errorf("Called GetBillingScanQuota on an anonymous secret")) -} - -// GetOwnerReadQuota implements Secret -func (s *AnonymousSecret) GetOwnerReadQuota() *int64 { - panic(fmt.Errorf("Called GetOwnerReadQuota on an anonymous secret")) -} - -// GetOwnerWriteQuota implements Secret -func (s *AnonymousSecret) GetOwnerWriteQuota() *int64 { - panic(fmt.Errorf("Called GetOwnerWriteQuota on an anonymous secret")) -} - -// GetOwnerScanQuota implements Secret -func (s *AnonymousSecret) GetOwnerScanQuota() *int64 { - panic(fmt.Errorf("Called GetOwnerScanQuota on an anonymous secret")) -} - -// StreamPermissions implements the Secret interface -func (s *AnonymousSecret) StreamPermissions(ctx context.Context, streamID uuid.UUID, projectID uuid.UUID, public bool) StreamPermissions { - return StreamPermissions{ - Read: public, - } -} - -// ProjectPermissions implements the Secret interface -func (s *AnonymousSecret) ProjectPermissions(ctx context.Context, projectID uuid.UUID, public bool) ProjectPermissions { - return ProjectPermissions{ - View: public, - } -} - -// OrganizationPermissions implements the Secret interface -func (s *AnonymousSecret) OrganizationPermissions(ctx context.Context, organizationID uuid.UUID) OrganizationPermissions { - return OrganizationPermissions{} -} - -// Revoke implements the Secret interface -func (s *AnonymousSecret) Revoke(ctx context.Context) { - log.S.Warnf("called Revoke on AnonymousSecret") -} diff --git a/control/entity/secret_service.go b/control/entity/secret_service.go deleted file mode 100644 index 027f7fb9..00000000 --- a/control/entity/secret_service.go +++ /dev/null @@ -1,125 +0,0 @@ -package entity - -import ( - "context" - - "gitlab.com/beneath-hq/beneath/pkg/secrettoken" - - "github.com/go-pg/pg/v9" - uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/hub" -) - -// ServiceSecret implements Secret for Token entities -type ServiceSecret struct { - _msgpack struct{} `msgpack:",omitempty"` - ServiceSecretID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` - BaseSecret - ServiceID uuid.UUID `sql:"on_delete:CASCADE,type:uuid"` - Service *Service -} - -// CreateServiceSecret creates a new secret to manage a service -func CreateServiceSecret(ctx context.Context, serviceID uuid.UUID, description string) (*ServiceSecret, error) { - // create - secret := &ServiceSecret{} - secret.Token = secrettoken.New(TokenFlagsService) - secret.Prefix = secret.Token.Prefix() - secret.HashedToken = secret.Token.Hashed() - secret.Description = description - secret.ServiceID = serviceID - - // validate - err := GetValidator().Struct(secret) - if err != nil { - return nil, err - } - - // insert - err = hub.DB.WithContext(ctx).Insert(secret) - if err != nil { - return nil, err - } - - // done - return secret, nil -} - -// FindServiceSecret finds a secret -func FindServiceSecret(ctx context.Context, secretID uuid.UUID) *ServiceSecret { - secret := &ServiceSecret{ - ServiceSecretID: secretID, - } - err := hub.DB.ModelContext(ctx, secret).WherePK().Select() - if !AssertFoundOne(err) { - return nil - } - return secret -} - -// FindServiceSecrets finds all the service's secrets -func FindServiceSecrets(ctx context.Context, serviceID uuid.UUID) []*ServiceSecret { - var secrets []*ServiceSecret - err := hub.DB.ModelContext(ctx, &secrets).Where("service_id = ?", serviceID).Limit(1000).Select() - if err != nil { - panic(err) - } - return secrets -} - -// GetSecretID implements the Secret interface -func (s *ServiceSecret) GetSecretID() uuid.UUID { - return s.ServiceSecretID -} - -// GetOwnerID implements the Secret interface -func (s *ServiceSecret) GetOwnerID() uuid.UUID { - return s.ServiceID -} - -// IsAnonymous implements the Secret interface -func (s *ServiceSecret) IsAnonymous() bool { - return false -} - -// IsUser implements the Secret interface -func (s *ServiceSecret) IsUser() bool { - return false -} - -// IsService implements the Secret interface -func (s *ServiceSecret) IsService() bool { - return true -} - -// IsMaster implements the Secret interface -func (s *ServiceSecret) IsMaster() bool { - return false -} - -// StreamPermissions implements the Secret interface -func (s *ServiceSecret) StreamPermissions(ctx context.Context, streamID uuid.UUID, projectID uuid.UUID, public bool) StreamPermissions { - return CachedServiceStreamPermissions(ctx, s.ServiceID, streamID) -} - -// ProjectPermissions implements the Secret interface -func (s *ServiceSecret) ProjectPermissions(ctx context.Context, projectID uuid.UUID, public bool) ProjectPermissions { - return ProjectPermissions{} -} - -// OrganizationPermissions implements the Secret interface -func (s *ServiceSecret) OrganizationPermissions(ctx context.Context, organizationID uuid.UUID) OrganizationPermissions { - return OrganizationPermissions{} -} - -// Revoke implements the Secret interface -func (s *ServiceSecret) Revoke(ctx context.Context) { - // delete from db - err := hub.DB.WithContext(ctx).Delete(s) - if err != nil && err != pg.ErrNoRows { - panic(err) - } - - // remove from redis (ignore error) - getSecretCache().Clear(ctx, s.HashedToken) -} diff --git a/control/entity/secret_test.go b/control/entity/secret_test.go deleted file mode 100644 index abbb0009..00000000 --- a/control/entity/secret_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package entity - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/secrettoken" -) - -func init() { - hub.InitPostgres("localhost", "", "postgres", "") - hub.InitRedis("redis://localhost/") -} - -func TestSecretIntegration(t *testing.T) { - ctx := context.Background() - - // create a user - user, err := CreateOrUpdateUser(ctx, "tmp", "", "test@example.org", "test", "Test Test", "") - assert.Nil(t, err) - assert.NotNil(t, user) - - secret1, err := CreateUserSecret(ctx, user.UserID, "Test secret", false, false) - assert.Nil(t, err) - assert.NotNil(t, secret1) - assert.NotEqual(t, secret1.Token, secrettoken.Nil) - - secret2 := AuthenticateWithToken(ctx, secret1.Token) - assert.NotNil(t, secret2) - assert.Equal(t, secret1.UserID, secret2.GetOwnerID()) - - secret3 := AuthenticateWithToken(ctx, secrettoken.FromStringOrNil("")) - assert.Nil(t, secret3) - - secret4 := AuthenticateWithToken(ctx, secrettoken.FromStringOrNil("GBJApvATiuhoxTXksicC6ePzhVu9VDy7hWnWLvpzayhY")) - assert.Nil(t, secret4) - - secret1.Revoke(ctx) - secret2 = AuthenticateWithToken(ctx, secret1.Token) - assert.Nil(t, secret2) - - // cleanup - secretCache = nil - hub.Redis.FlushAll() -} diff --git a/control/entity/secret_user.go b/control/entity/secret_user.go deleted file mode 100644 index 660000b4..00000000 --- a/control/entity/secret_user.go +++ /dev/null @@ -1,145 +0,0 @@ -package entity - -import ( - "context" - - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/secrettoken" - - "github.com/go-pg/pg/v9" - uuid "github.com/satori/go.uuid" -) - -// UserSecret implements Secret for User entities -type UserSecret struct { - _msgpack struct{} `msgpack:",omitempty"` - UserSecretID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` - BaseSecret - UserID uuid.UUID `sql:"on_delete:CASCADE,notnull,type:uuid"` - User *User - ReadOnly bool `sql:",notnull"` - PublicOnly bool `sql:",notnull"` -} - -// CreateUserSecret creates a new secret to manage a user -func CreateUserSecret(ctx context.Context, userID uuid.UUID, description string, publicOnly, readOnly bool) (*UserSecret, error) { - // create - secret := &UserSecret{} - secret.Token = secrettoken.New(TokenFlagsUser) - secret.Prefix = secret.Token.Prefix() - secret.HashedToken = secret.Token.Hashed() - secret.Description = description - secret.UserID = userID - secret.ReadOnly = readOnly - secret.PublicOnly = publicOnly - - // validate - err := GetValidator().Struct(secret) - if err != nil { - return nil, err - } - - // insert - err = hub.DB.WithContext(ctx).Insert(secret) - if err != nil { - return nil, err - } - - // done - return secret, nil -} - -// FindUserSecret finds a secret -func FindUserSecret(ctx context.Context, secretID uuid.UUID) *UserSecret { - secret := &UserSecret{ - UserSecretID: secretID, - } - err := hub.DB.ModelContext(ctx, secret).WherePK().Select() - if !AssertFoundOne(err) { - return nil - } - return secret -} - -// FindUserSecrets finds all the user's secrets -func FindUserSecrets(ctx context.Context, userID uuid.UUID) []*UserSecret { - var secrets []*UserSecret - err := hub.DB.ModelContext(ctx, &secrets).Where("user_id = ?", userID).Limit(1000).Order("created_on DESC").Select() - if err != nil { - panic(err) - } - return secrets -} - -// GetSecretID implements the Secret interface -func (s *UserSecret) GetSecretID() uuid.UUID { - return s.UserSecretID -} - -// GetOwnerID implements the Secret interface -func (s *UserSecret) GetOwnerID() uuid.UUID { - return s.UserID -} - -// IsAnonymous implements the Secret interface -func (s *UserSecret) IsAnonymous() bool { - return false -} - -// IsUser implements the Secret interface -func (s *UserSecret) IsUser() bool { - return true -} - -// IsService implements the Secret interface -func (s *UserSecret) IsService() bool { - return false -} - -// StreamPermissions implements the Secret interface -func (s *UserSecret) StreamPermissions(ctx context.Context, streamID uuid.UUID, projectID uuid.UUID, public bool) StreamPermissions { - projectPerms := CachedUserProjectPermissions(ctx, s.UserID, projectID) - return StreamPermissions{ - Read: (projectPerms.View && !s.PublicOnly) || public, - Write: projectPerms.Create && !s.ReadOnly && (!s.PublicOnly || public), - } -} - -// ProjectPermissions implements the Secret interface -func (s *UserSecret) ProjectPermissions(ctx context.Context, projectID uuid.UUID, public bool) ProjectPermissions { - if s.PublicOnly && !public { - return ProjectPermissions{} - } - if s.ReadOnly && public { - return ProjectPermissions{View: true} - } - perms := CachedUserProjectPermissions(ctx, s.UserID, projectID) - if public { - perms.View = true - } - if s.ReadOnly { - perms.Admin = false - perms.Create = false - } - return perms -} - -// OrganizationPermissions implements the Secret interface -func (s *UserSecret) OrganizationPermissions(ctx context.Context, organizationID uuid.UUID) OrganizationPermissions { - if s.ReadOnly || s.PublicOnly { - return OrganizationPermissions{} - } - return CachedUserOrganizationPermissions(ctx, s.UserID, organizationID) -} - -// Revoke implements the Secret interface -func (s *UserSecret) Revoke(ctx context.Context) { - // delete from db - err := hub.DB.WithContext(ctx).Delete(s) - if err != nil && err != pg.ErrNoRows { - panic(err) - } - - // remove from redis (ignore error) - getSecretCache().Clear(ctx, s.HashedToken) -} diff --git a/control/entity/service.go b/control/entity/service.go deleted file mode 100644 index ef8ea5bd..00000000 --- a/control/entity/service.go +++ /dev/null @@ -1,176 +0,0 @@ -package entity - -import ( - "context" - "regexp" - "time" - - uuid "github.com/satori/go.uuid" - "gopkg.in/go-playground/validator.v9" - - "gitlab.com/beneath-hq/beneath/hub" -) - -// Service represents external service keys, models, and, in the future, charts, all of which need OrganizationIDs for billing -type Service struct { - ServiceID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` - Name string `sql:",notnull",validate:"required,gte=1,lte=40"` // not unique because of (organization_id, service_id) index - Description string `validate:"omitempty,lte=255"` - SourceURL string `validate:"omitempty,url,lte=255"` - ProjectID uuid.UUID `sql:"on_delete:restrict,notnull,type:uuid"` - Project *Project - ReadQuota *int64 // NOTE: when updating value, clear secret cache - WriteQuota *int64 // NOTE: when updating value, clear secret cache - ScanQuota *int64 // NOTE: when updating value, clear secret cache - CreatedOn time.Time `sql:",notnull,default:now()"` - UpdatedOn time.Time `sql:",notnull,default:now()"` - Secrets []*ServiceSecret -} - -var ( - // used for validation - serviceNameRegex *regexp.Regexp -) - -func init() { - // configure validation - serviceNameRegex = regexp.MustCompile("^[_a-z][_a-z0-9]*$") - GetValidator().RegisterStructValidation(serviceValidation, Service{}) -} - -// custom service validation -func serviceValidation(sl validator.StructLevel) { - s := sl.Current().Interface().(Service) - - if !serviceNameRegex.MatchString(s.Name) { - sl.ReportError(s.Name, "Name", "", "alphanumericorunderscore", "") - } -} - -// FindService returns the matching service or nil -func FindService(ctx context.Context, serviceID uuid.UUID) *Service { - service := &Service{ - ServiceID: serviceID, - } - err := hub.DB.ModelContext(ctx, service). - Column( - "service.*", - "Project", - "Project.Organization", - ). - WherePK(). - Select() - if !AssertFoundOne(err) { - return nil - } - - return service -} - -// FindServiceByOrganizationProjectAndName returns the matching service or nil -func FindServiceByOrganizationProjectAndName(ctx context.Context, organizationName, projectName, serviceName string) *Service { - service := &Service{} - err := hub.DB.ModelContext(ctx, service). - Column( - "service.*", - "Project", - "Project.Organization", - ). - Where("lower(project__organization.name) = lower(?)", organizationName). - Where("lower(project.name) = lower(?)", projectName). - Where("lower(service.name) = lower(?)", serviceName). - Select() - if !AssertFoundOne(err) { - return nil - } - return service -} - -// Stage creates or updates the service -func (s *Service) Stage(ctx context.Context, description *string, sourceURL *string, readQuota *int64, writeQuota *int64, scanQuota *int64) error { - // determine whether to insert or update - update := (s.ServiceID != uuid.Nil) - - // tracks whether a save is necessary - save := !update - - if description != nil { - if s.Description != *description { - s.Description = *description - save = true - } - } - - if sourceURL != nil { - if s.SourceURL != *sourceURL { - s.SourceURL = *sourceURL - save = true - } - } - - if readQuota != nil { - if *readQuota == 0 { - s.ReadQuota = nil - } else { - s.ReadQuota = readQuota - } - save = true - } - - if writeQuota != nil { - if *writeQuota == 0 { - s.WriteQuota = nil - } else { - s.WriteQuota = writeQuota - } - save = true - } - - if scanQuota != nil { - if *scanQuota == 0 { - s.ScanQuota = nil - } else { - s.ScanQuota = scanQuota - } - save = true - } - - // quit if no changes - if !save { - return nil - } - - // validate - err := GetValidator().Struct(s) - if err != nil { - return err - } - - // populate s.Project and s.Project.Organization if not set (i.e. due to inserting new stream) - if s.Project == nil { - s.Project = FindProject(ctx, s.ProjectID) - } - - if update { - s.UpdatedOn = time.Now() - _, err := hub.DB.ModelContext(ctx, s).WherePK().Update() - if err != nil { - return err - } - - getSecretCache().ClearForService(ctx, s.ServiceID) - } else { - _, err := hub.DB.ModelContext(ctx, s).Insert() - if err != nil { - return err - } - } - - return nil -} - -// Delete removes a service from the database -func (s *Service) Delete(ctx context.Context) error { - _, err := hub.DB.ModelContext(ctx, s).WherePK().Delete() - return err -} diff --git a/control/entity/stream.go b/control/entity/stream.go deleted file mode 100644 index 37553114..00000000 --- a/control/entity/stream.go +++ /dev/null @@ -1,722 +0,0 @@ -package entity - -import ( - "bytes" - "context" - "crypto/md5" - "encoding/json" - "fmt" - "regexp" - "time" - - "github.com/go-pg/pg/v9" - uuid "github.com/satori/go.uuid" - "github.com/vektah/gqlparser/gqlerror" - "gopkg.in/go-playground/validator.v9" - - "gitlab.com/beneath-hq/beneath/control/taskqueue" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/codec" - "gitlab.com/beneath-hq/beneath/pkg/schemalang" - "gitlab.com/beneath-hq/beneath/pkg/schemalang/transpilers" -) - -// Stream represents a collection of data -type Stream struct { - // Descriptive fields - StreamID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` - Name string `sql:",notnull",validate:"required,gte=1,lte=40"` // not unique because of (project_id, lower(name)) index // note: used in stream cache - Description string `validate:"omitempty,lte=255"` - CreatedOn time.Time `sql:",default:now()"` - UpdatedOn time.Time `sql:",default:now()"` - ProjectID uuid.UUID `sql:"on_delete:RESTRICT,notnull,type:uuid"` - Project *Project - AllowManualWrites bool `sql:",notnull"` - - // Schema-related fields (note: some are used in stream cache) - SchemaKind StreamSchemaKind `sql:",notnull",validate:"required"` - Schema string `sql:",notnull",validate:"required"` - SchemaMD5 []byte `sql:"schema_md5,notnull",validate:"required"` - AvroSchema string `sql:",type:json,notnull",validate:"required"` - CanonicalAvroSchema string `sql:",type:json,notnull",validate:"required"` - CanonicalIndexes string `sql:",type:json,notnull",validate:"required"` - StreamIndexes []*StreamIndex - - // Behaviour-related fields (note: used in stream cache) - UseLog bool `sql:",notnull"` - UseIndex bool `sql:",notnull"` - UseWarehouse bool `sql:",notnull"` - LogRetentionSeconds int32 `sql:",notnull,default:0"` - IndexRetentionSeconds int32 `sql:",notnull,default:0"` - WarehouseRetentionSeconds int32 `sql:",notnull,default:0"` - - // Instances-related fields - StreamInstances []*StreamInstance - PrimaryStreamInstanceID *uuid.UUID `sql:"on_delete:SET NULL,type:uuid"` - PrimaryStreamInstance *StreamInstance - InstancesCreatedCount int32 `sql:",notnull,default:0"` - InstancesDeletedCount int32 `sql:",notnull,default:0"` - InstancesMadeFinalCount int32 `sql:",notnull,default:0"` - InstancesMadePrimaryCount int32 `sql:",notnull,default:0"` -} - -// StreamSchemaKind indicates the SDL of a stream's schema -type StreamSchemaKind string - -// Constants for StreamSchemaKind -const ( - StreamSchemaKindGraphQL StreamSchemaKind = "GraphQL" - StreamSchemaKindAvro StreamSchemaKind = "Avro" -) - -// MaxInstancesPerStream sets a limit for the number of instances for a stream at any given time -const MaxInstancesPerStream = 25 - -var ( - // used for validation - streamNameRegex *regexp.Regexp -) - -func init() { - // configure validation - streamNameRegex = regexp.MustCompile("^[_a-z][_a-z0-9]*$") - GetValidator().RegisterStructValidation(streamValidation, Stream{}) -} - -// custom stream validation -func streamValidation(sl validator.StructLevel) { - s := sl.Current().Interface().(Stream) - - if !streamNameRegex.MatchString(s.Name) { - sl.ReportError(s.Name, "Name", "", "alphanumericorunderscore", "") - } -} - -// FindStream finds a stream -func FindStream(ctx context.Context, streamID uuid.UUID) *Stream { - stream := &Stream{ - StreamID: streamID, - } - err := hub.DB.ModelContext(ctx, stream). - WherePK(). - Column( - "stream.*", - "Project", - "Project.Organization", - "PrimaryStreamInstance", - "StreamIndexes", - ). - Select() - if !AssertFoundOne(err) { - return nil - } - return stream -} - -// FindStreamByOrganizationProjectAndName finds a stream -func FindStreamByOrganizationProjectAndName(ctx context.Context, organizationName string, projectName string, streamName string) *Stream { - stream := &Stream{} - err := hub.DB.ModelContext(ctx, stream). - Column( - "stream.*", - "Project", - "Project.Organization", - "PrimaryStreamInstance", - "StreamIndexes", - ). - Where("lower(project__organization.name) = lower(?)", organizationName). - Where("lower(project.name) = lower(?)", projectName). - Where("lower(stream.name) = lower(?)", streamName). - Select() - if !AssertFoundOne(err) { - return nil - } - return stream -} - -// GetStreamID implements engine/driver.Stream -func (s *Stream) GetStreamID() uuid.UUID { - return s.StreamID -} - -// GetStreamName implements engine/driver.Stream -func (s *Stream) GetStreamName() string { - return s.Name -} - -// GetUseLog implements engine/driver.Stream -func (s *Stream) GetUseLog() bool { - return s.UseLog -} - -// GetUseIndex implements engine/driver.Stream -func (s *Stream) GetUseIndex() bool { - return s.UseIndex -} - -// GetUseWarehouse implements engine/driver.Stream -func (s *Stream) GetUseWarehouse() bool { - return s.UseWarehouse -} - -// GetLogRetention implements engine/driver.Stream -func (s *Stream) GetLogRetention() time.Duration { - return time.Duration(s.LogRetentionSeconds) * time.Second -} - -// GetIndexRetention implements engine/driver.Stream -func (s *Stream) GetIndexRetention() time.Duration { - return time.Duration(s.IndexRetentionSeconds) * time.Second -} - -// GetWarehouseRetention implements engine/driver.Stream -func (s *Stream) GetWarehouseRetention() time.Duration { - return time.Duration(s.WarehouseRetentionSeconds) * time.Second -} - -// GetCodec implements engine/driver.Stream -func (s *Stream) GetCodec() *codec.Codec { - if len(s.StreamIndexes) == 0 { - panic(fmt.Errorf("GetCodec must not be called without StreamIndexes loaded")) - } - - var primaryIndex codec.Index - var secondaryIndexes []codec.Index - for _, index := range s.StreamIndexes { - if index.Primary { - primaryIndex = index - } else { - secondaryIndexes = append(secondaryIndexes, index) - } - } - - c, err := codec.New(s.CanonicalAvroSchema, primaryIndex, secondaryIndexes) - if err != nil { - panic(err) - } - - return c -} - -// Compile compiles the given schema and sets relevant fields -func (s *Stream) Compile(ctx context.Context, schemaKind StreamSchemaKind, newSchema string, newIndexes *string, description *string, update bool) error { - // get schema - var schema schemalang.Schema - var indexes schemalang.Indexes - var err error - switch schemaKind { - case StreamSchemaKindAvro: - schema, err = transpilers.FromAvro(newSchema) - case StreamSchemaKindGraphQL: - schema, indexes, err = transpilers.FromGraphQL(newSchema) - default: - err = fmt.Errorf("Unsupported stream schema definition language '%s'", schemaKind) - } - if err != nil { - return err - } - - // parse newIndexes if set (overrides output from transpiler) - if newIndexes != nil { - err = json.Unmarshal([]byte(*newIndexes), &indexes) - if err != nil { - return fmt.Errorf("error parsing indexes: '%s'", err.Error()) - } - } - - // check schema - err = schemalang.Check(schema) - if err != nil { - return err - } - - // check indexes - err = indexes.Check(schema) - if err != nil { - return err - } - - // normalize indexes - canonicalIndexes := indexes.CanonicalJSON() - - // get avro schemas - canonicalAvro := transpilers.ToAvro(schema, false) - avro := transpilers.ToAvro(schema, true) - - // if update, check canonical avro is the same - if update { - if canonicalAvro != s.CanonicalAvroSchema { - return fmt.Errorf("Unfortunately we do not currently support updating a stream's data structure; you can only edit its documentation") - } - if canonicalIndexes != s.CanonicalIndexes { - return fmt.Errorf("Unfortunately we do not currently support updating a stream's indexes") - } - } - - // TEMPORARY: disable secondary indexes - if len(indexes) != 1 { - return fmt.Errorf("Cannot add secondary indexes to stream (a stream must have exactly one key index)") - } - - // set indexes - if !update { - s.assignIndexes(indexes) - } - - // set missing stream fields - s.SchemaKind = schemaKind - s.Schema = newSchema - s.AvroSchema = avro - s.CanonicalAvroSchema = canonicalAvro - s.CanonicalIndexes = canonicalIndexes - if description == nil { - s.Description = schema.(*schemalang.Record).Doc - } else { - s.Description = *description - } - - return nil -} - -// Sets StreamIndexes to new StreamIndex objects based on def. -// Doesn't execute any DB actions, so doesn't set any IDs. -func (s *Stream) assignIndexes(indexes schemalang.Indexes) { - indexes.Sort() - s.StreamIndexes = make([]*StreamIndex, len(indexes)) - for idx, index := range indexes { - s.StreamIndexes[idx] = &StreamIndex{ - ShortID: idx, - Fields: index.Fields, - Primary: index.Key, - Normalize: index.Normalize, - } - } -} - -// Stage creates or updates the stream so that it adheres to the params (or does nothing if everything already conforms). -// If s is a new stream object, Name and ProjectID must be set before calling Stage. -func (s *Stream) Stage(ctx context.Context, schemaKind StreamSchemaKind, schema string, indexes *string, description *string, allowManualWrites *bool, useLog *bool, useIndex *bool, useWarehouse *bool, logRetentionSeconds *int, indexRetentionSeconds *int, warehouseRetentionSeconds *int) error { - // determine whether to insert or update - update := (s.StreamID != uuid.Nil) - - // tracks whether a save is necessary - save := !update - - // compile if necessary - md5Input := []byte(schema) - if indexes != nil { - md5Input = append(md5Input, []byte(*indexes)...) - } - schemaMD5 := md5.Sum(md5Input) - if schemaKind != s.SchemaKind || !bytes.Equal(schemaMD5[:], s.SchemaMD5) { - err := s.Compile(ctx, schemaKind, schema, indexes, description, update) - if err != nil { - return err - } - s.SchemaMD5 = schemaMD5[:] - save = true - } - - // update fields if necessary - - if allowManualWrites != nil && *allowManualWrites != s.AllowManualWrites { - s.AllowManualWrites = *allowManualWrites - save = true - } - - if update { - // on updates, don't allow changes to used services and retention - - if useLog != nil && *useLog != s.UseLog { - return fmt.Errorf("Cannot change useLog after a stream is created") - } - - if useIndex != nil && *useIndex != s.UseIndex { - return fmt.Errorf("Cannot change useIndex after a stream is created") - } - - if useWarehouse != nil && *useWarehouse != s.UseWarehouse { - return fmt.Errorf("Cannot change useWarehouse after a stream is created") - } - - if logRetentionSeconds != nil && int32(*logRetentionSeconds) != s.LogRetentionSeconds { - return fmt.Errorf("Cannot change logRetentionSeconds after a stream is created") - } - - if indexRetentionSeconds != nil && int32(*indexRetentionSeconds) != s.IndexRetentionSeconds { - return fmt.Errorf("Cannot change indexRetentionSeconds after a stream is created") - } - - if warehouseRetentionSeconds != nil && int32(*warehouseRetentionSeconds) != s.WarehouseRetentionSeconds { - return fmt.Errorf("Cannot change warehouseRetentionSeconds after a stream is created") - } - } else { - save = true - - s.UseLog = true - if useLog != nil { - s.UseLog = *useLog - } - - s.UseIndex = true - if useIndex != nil { - s.UseIndex = *useIndex - } - - s.UseWarehouse = true - if useWarehouse != nil { - s.UseWarehouse = *useWarehouse - } - - if logRetentionSeconds != nil { - if !s.UseLog { - return fmt.Errorf("Cannot set logRetentionSeconds on stream that doesn't have useLog=true") - } - s.LogRetentionSeconds = int32(*logRetentionSeconds) - } - - if indexRetentionSeconds != nil { - if !s.UseIndex { - return fmt.Errorf("Cannot set indexRetentionSeconds on stream that doesn't have useIndex=true") - } - s.IndexRetentionSeconds = int32(*indexRetentionSeconds) - } - - if warehouseRetentionSeconds != nil { - if !s.UseWarehouse { - return fmt.Errorf("Cannot set warehouseRetentionSeconds on stream that doesn't have useWarehouse=true") - } - s.WarehouseRetentionSeconds = int32(*warehouseRetentionSeconds) - } - - // if there's a normalized index, make sure we use a non-expiring log - for _, index := range s.StreamIndexes { - if index.Normalize && (!s.UseLog || s.LogRetentionSeconds != 0) { - return fmt.Errorf("Cannot use normalized indexes when useLog=false or logRetentionSeconds is set") - } - } - } - - // temporarily, we're going to enforce UseLog - if !s.UseLog { - return fmt.Errorf("Currently doesn't support streams with useLog=false") - } - - // quit if no changes - if !save { - return nil - } - - // validate - err := GetValidator().Struct(s) - if err != nil { - return err - } - - // populate s.Project and s.Project.Organization if not set (i.e. due to inserting new stream) - if s.Project == nil { - s.Project = FindProject(ctx, s.ProjectID) - } - - // insert or update - return hub.DB.WithContext(ctx).RunInTransaction(func(tx *pg.Tx) error { - if update { - // update - s.UpdatedOn = time.Now() - _, err := tx.Model(s).WherePK().Update() - if err != nil { - return err - } - - // update instances in engine and clear cached instances - instances := FindStreamInstances(tx.Context(), s.StreamID, nil, nil) - for _, instance := range instances { - getStreamCache().Clear(tx.Context(), instance.StreamInstanceID) - err := hub.Engine.RegisterInstance(tx.Context(), s.Project, s, instance) - if err != nil { - return err - } - } - - // done with updates - return nil - } - - // IT'S AN INSERT (NOT UPDATE) - - // insert - _, err := tx.Model(s).Insert() - if err != nil { - return err - } - - // create indexes - for _, index := range s.StreamIndexes { - index.StreamID = s.StreamID - _, err := tx.Model(index).Insert() - if err != nil { - return err - } - } - - return nil - }) -} - -// Delete deletes a stream and all its related instances -func (s *Stream) Delete(ctx context.Context) error { - // delete instances - instances := FindStreamInstances(ctx, s.StreamID, nil, nil) - for _, inst := range instances { - err := s.DeleteStreamInstance(ctx, inst) - if err != nil { - return err - } - } - - // delete stream - err := hub.DB.WithContext(ctx).Delete(s) - if err != nil { - return err - } - - // background cleanup - err = taskqueue.Submit(ctx, &CleanupStreamTask{ - StreamID: s.StreamID, - }) - if err != nil { - return err - } - - return nil -} - -// StageStreamInstance creates or finds an instance with version in the stream -func (s *Stream) StageStreamInstance(ctx context.Context, version int, makeFinal bool, makePrimary bool) (*StreamInstance, error) { - if version < 0 { - return nil, fmt.Errorf("Cannot create stream instance with negative version (got %d)", version) - } - - // find existing instance - instances := FindStreamInstances(ctx, s.StreamID, &version, nil) - maxVersion := 0 - for _, si := range instances { - // return if version matches - if si.Version == version { - // update if makeFinal or makePrimary - if (makeFinal && si.MadeFinalOn == nil) || (makePrimary && si.MadePrimaryOn == nil) { - err := s.UpdateStreamInstance(ctx, si, makeFinal, makePrimary) - if err != nil { - return nil, err - } - } - - // return - return si, nil - } - - // track for maxVersion - if si.Version > maxVersion { - maxVersion = si.Version - } - } - - // don't create if there's an instance with a higher version - if len(instances) > 0 { - return nil, fmt.Errorf("One or more instances already exist with a higher version for stream (highest currently has version %d)", maxVersion) - } - - // check not too many instances - if s.InstancesCreatedCount-s.InstancesDeletedCount >= MaxInstancesPerStream { - return nil, gqlerror.Errorf("You cannot have more than %d instances per stream. Delete an existing instance to make room for more.", MaxInstancesPerStream) - } - - // create instance - si := &StreamInstance{ - StreamID: s.StreamID, - Stream: s, - Version: version, - } - - err := hub.DB.WithContext(ctx).RunInTransaction(func(tx *pg.Tx) error { - _, err := tx.Model(si).Insert() - if err != nil { - return err - } - - // increment count - s.InstancesCreatedCount++ - _, err = tx.Model(s).Set("instances_created_count = instances_created_count + 1").WherePK().Update() - if err != nil { - return err - } - - // register instance - err = hub.Engine.RegisterInstance(tx.Context(), s.Project, s, si) - if err != nil { - return err - } - - // update if makeFinal or makePrimary - if makeFinal || makePrimary { - err = s.UpdateStreamInstanceWithTx(tx, si, makeFinal, makePrimary) - if err != nil { - return err - } - } - - return nil - }) - if err != nil { - return nil, err - } - - return si, nil -} - -// UpdateStreamInstance updates the state of a stream instance -func (s *Stream) UpdateStreamInstance(ctx context.Context, instance *StreamInstance, makeFinal bool, makePrimary bool) error { - return hub.DB.WithContext(ctx).RunInTransaction(func(tx *pg.Tx) error { - return s.UpdateStreamInstanceWithTx(tx, instance, makeFinal, makePrimary) - }) -} - -// UpdateStreamInstanceWithTx is like UpdateStreamInstance, but runs in a transaction -func (s *Stream) UpdateStreamInstanceWithTx(tx *pg.Tx, instance *StreamInstance, makeFinal bool, makePrimary bool) error { - // check relationship - if instance.StreamID != s.StreamID { - return fmt.Errorf("Cannot update instance '%s' because it doesn't belong to stream '%s'", instance.StreamInstanceID.String(), s.StreamID.String()) - } - - // bail if there's nothing to do - if (!makeFinal || instance.MadeFinalOn != nil) && !makePrimary { - return nil - } - - // we know there's something to do - - // prepare models to update - sm := tx.Model(s) - im := tx.Model(instance) - - // values needed later - now := time.Now() - - // handle makeFinal - if makeFinal && instance.MadeFinalOn == nil { - s.InstancesMadeFinalCount++ - sm = sm.Set("instances_made_final_count = instances_made_final_count + 1") - instance.MadeFinalOn = &now - im = im.Set("made_final_on = now()") - } - - // handle makePrimary - if makePrimary { - s.PrimaryStreamInstanceID = &instance.StreamInstanceID - sm = sm.Set("primary_stream_instance_id = ?", instance.StreamInstanceID) - if instance.MadePrimaryOn == nil { - s.InstancesMadePrimaryCount++ - sm = sm.Set("instances_made_primary_count = instances_made_primary_count + 1") - instance.MadePrimaryOn = &now - im = im.Set("made_primary_on = now()") - } - } - - // updated on timestamps - s.UpdatedOn = now - sm = sm.Set("updated_on = now()") - instance.UpdatedOn = now - im = im.Set("updated_on = now()") - - // update - _, err := sm.WherePK().Update() - if err != nil { - return err - } - _, err = im.WherePK().Update() - if err != nil { - return err - } - - // update in warehouse - if makePrimary { - err = hub.Engine.PromoteInstance(tx.Context(), s.Project, s, instance) - if err != nil { - return err - } - } - - // delete earlier versions - if makePrimary { - instances := FindStreamInstances(tx.Context(), s.StreamID, nil, &instance.Version) - for _, si := range instances { - err := s.DeleteStreamInstanceWithTx(tx, si) - if err != nil { - return err - } - getStreamCache().Clear(tx.Context(), si.StreamInstanceID) - } - } - - // clear caches - getStreamCache().Clear(tx.Context(), instance.StreamInstanceID) - if makePrimary { - getInstanceCache().clear(tx.Context(), s.Project.Organization.Name, s.Project.Name, s.Name) - } - - return nil -} - -// DeleteStreamInstance deletes and deregisters a stream instance -func (s *Stream) DeleteStreamInstance(ctx context.Context, si *StreamInstance) error { - return hub.DB.WithContext(ctx).RunInTransaction(func(tx *pg.Tx) error { - return s.DeleteStreamInstanceWithTx(tx, si) - }) -} - -// DeleteStreamInstanceWithTx is like DeleteStreamInstance in a tx -func (s *Stream) DeleteStreamInstanceWithTx(tx *pg.Tx, instance *StreamInstance) error { - // check relationship - if instance.StreamID != s.StreamID { - return fmt.Errorf("Cannot delete instance '%s' because it doesn't belong to stream '%s'", instance.StreamInstanceID.String(), s.StreamID.String()) - } - - // delete instance - err := tx.Delete(instance) - if err != nil { - return err - } - - // clear cache - getStreamCache().Clear(tx.Context(), instance.StreamInstanceID) - - // if we deleted the primary instance, clear it (not part of stream update because of SET NULL constraint) - if s.PrimaryStreamInstanceID != nil && *s.PrimaryStreamInstanceID == instance.StreamInstanceID { - s.PrimaryStreamInstanceID = nil - s.PrimaryStreamInstance = nil - getInstanceCache().clear(tx.Context(), s.Project.Organization.Name, s.Project.Name, s.Name) - } - - // update stream - s.UpdatedOn = time.Now() - s.InstancesDeletedCount++ - _, err = tx.Model(s). - Set("updated_on = ?", s.UpdatedOn). - Set("instances_deleted_count = instances_deleted_count + 1"). - WherePK(). - Update() - if err != nil { - return err - } - - // deregister instance - err = taskqueue.Submit(tx.Context(), &CleanupInstanceTask{ - InstanceID: instance.StreamInstanceID, - CachedStream: NewCachedStream(s, instance), - }) - if err != nil { - return err - } - - return nil -} diff --git a/control/entity/stream_cache.go b/control/entity/stream_cache.go deleted file mode 100644 index e846bbae..00000000 --- a/control/entity/stream_cache.go +++ /dev/null @@ -1,514 +0,0 @@ -package entity - -import ( - "bytes" - "context" - "encoding/gob" - "sync" - "time" - - "github.com/bluele/gcache" - "github.com/go-pg/pg/v9" - "github.com/go-redis/cache/v7" - uuid "github.com/satori/go.uuid" - "github.com/vmihailenco/msgpack" - - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/codec" -) - -// FindCachedStreamByCurrentInstanceID returns select info about the instance's stream -func FindCachedStreamByCurrentInstanceID(ctx context.Context, instanceID uuid.UUID) *CachedStream { - return getStreamCache().Get(ctx, instanceID) -} - -// CachedStream keeps key information about a stream for rapid lookup -type CachedStream struct { - StreamID uuid.UUID - Public bool - Final bool - UseLog bool - UseIndex bool - UseWarehouse bool - LogRetentionSeconds int32 - IndexRetentionSeconds int32 - WarehouseRetentionSeconds int32 - OrganizationID uuid.UUID - OrganizationName string - ProjectID uuid.UUID - ProjectName string - StreamName string - Codec *codec.Codec -} - -// EfficientStreamIndex represents indexes in EfficientStream -type EfficientStreamIndex struct { - StreamIndexID uuid.UUID - ShortID int - Fields []string - Primary bool - Normalize bool -} - -// GetIndexID implements codec.Index -func (e EfficientStreamIndex) GetIndexID() uuid.UUID { - return e.StreamIndexID -} - -// GetShortID implements codec.Index -func (e EfficientStreamIndex) GetShortID() int { - return e.ShortID -} - -// GetFields implements codec.Index -func (e EfficientStreamIndex) GetFields() []string { - return e.Fields -} - -// GetNormalize implements codec.Index -func (e EfficientStreamIndex) GetNormalize() bool { - return e.Normalize -} - -type internalCachedStream struct { - StreamID uuid.UUID - Public bool - Final bool - UseLog bool - UseIndex bool - UseWarehouse bool - LogRetentionSeconds int32 - IndexRetentionSeconds int32 - WarehouseRetentionSeconds int32 - OrganizationID uuid.UUID - OrganizationName string - ProjectID uuid.UUID - ProjectName string - StreamName string - CanonicalAvroSchema string - Indexes []EfficientStreamIndex -} - -// NewCachedStream creates a CachedStream from a regular Stream object -func NewCachedStream(s *Stream, instance *StreamInstance) *CachedStream { - if s.Project == nil { - panic("Stream project must be loaded") - } - - if s.Project.Organization == nil { - panic("Stream organization must be loaded") - } - - indexes := make([]EfficientStreamIndex, len(s.StreamIndexes)) - for idx, index := range s.StreamIndexes { - indexes[idx] = EfficientStreamIndex{ - StreamIndexID: index.StreamIndexID, - ShortID: index.ShortID, - Fields: index.Fields, - Primary: index.Primary, - Normalize: index.Normalize, - } - } - - internal := &internalCachedStream{ - StreamID: s.StreamID, - Public: s.Project.Public, - Final: instance.MadeFinalOn != nil, - UseLog: s.UseLog, - UseIndex: s.UseIndex, - UseWarehouse: s.UseWarehouse, - LogRetentionSeconds: s.LogRetentionSeconds, - IndexRetentionSeconds: s.IndexRetentionSeconds, - WarehouseRetentionSeconds: s.WarehouseRetentionSeconds, - OrganizationID: s.Project.Organization.OrganizationID, - OrganizationName: s.Project.Organization.Name, - ProjectID: s.Project.ProjectID, - ProjectName: s.Project.Name, - StreamName: s.Name, - CanonicalAvroSchema: s.CanonicalAvroSchema, - Indexes: indexes, - } - - result := &CachedStream{} - - err := unwrapInternalCachedStream(internal, result) - if err != nil { - panic(err) - } - - return result -} - -// MarshalBinary serializes for storage in cache -func (c CachedStream) MarshalBinary() ([]byte, error) { - wrapped := internalCachedStream{ - StreamID: c.StreamID, - Public: c.Public, - Final: c.Final, - UseLog: c.UseLog, - UseIndex: c.UseIndex, - UseWarehouse: c.UseWarehouse, - LogRetentionSeconds: c.LogRetentionSeconds, - IndexRetentionSeconds: c.IndexRetentionSeconds, - WarehouseRetentionSeconds: c.WarehouseRetentionSeconds, - OrganizationID: c.OrganizationID, - OrganizationName: c.OrganizationName, - ProjectID: c.ProjectID, - ProjectName: c.ProjectName, - StreamName: c.StreamName, - } - - // necessary because we allow empty CachedStream objects - if c.Codec != nil { - wrapped.CanonicalAvroSchema = c.Codec.AvroSchema - wrapped.Indexes = []EfficientStreamIndex{c.Codec.PrimaryIndex.(EfficientStreamIndex)} - for _, index := range c.Codec.SecondaryIndexes { - wrapped.Indexes = append(wrapped.Indexes, index.(EfficientStreamIndex)) - } - } - - var buf bytes.Buffer - enc := gob.NewEncoder(&buf) - err := enc.Encode(wrapped) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// UnmarshalBinary deserializes back from storage in cache -func (c *CachedStream) UnmarshalBinary(data []byte) error { - wrapped := internalCachedStream{} - dec := gob.NewDecoder(bytes.NewReader(data)) - err := dec.Decode(&wrapped) - if err != nil { - return err - } - - return unwrapInternalCachedStream(&wrapped, c) -} - -// Add support for msgpack -var _ msgpack.CustomEncoder = (*CachedStream)(nil) -var _ msgpack.CustomDecoder = (*CachedStream)(nil) - -// EncodeMsgpack adds support for encoding CachedStream with msgpack -func (c *CachedStream) EncodeMsgpack(enc *msgpack.Encoder) error { - bin, err := c.MarshalBinary() - if err != nil { - return err - } - return enc.EncodeBytes(bin) -} - -// DecodeMsgpack adds support for decoding CachedStream with msgpack -func (c *CachedStream) DecodeMsgpack(dec *msgpack.Decoder) error { - bin, err := dec.DecodeBytes() - if err != nil { - return err - } - return c.UnmarshalBinary(bin) -} - -// CachedStream implements engine/driver.Organization, engine/driver.Project, engine/driver.StreamInstance, and engine/driver.Stream - -// GetOrganizationID implements engine/driver.Organization -func (c *CachedStream) GetOrganizationID() uuid.UUID { - return c.OrganizationID -} - -// GetOrganizationName implements engine/driver.Project -func (c *CachedStream) GetOrganizationName() string { - return c.OrganizationName -} - -// GetProjectID implements engine/driver.Project -func (c *CachedStream) GetProjectID() uuid.UUID { - return c.ProjectID -} - -// GetProjectName implements engine/driver.Project -func (c *CachedStream) GetProjectName() string { - return c.ProjectName -} - -// GetPublic implements engine/driver.Project -func (c *CachedStream) GetPublic() bool { - return c.Public -} - -// GetStreamID implements engine/driver.Stream -func (c *CachedStream) GetStreamID() uuid.UUID { - return c.StreamID -} - -// GetStreamName implements engine/driver.Stream -func (c *CachedStream) GetStreamName() string { - return c.StreamName -} - -// GetUseLog implements engine/driver.Stream -func (c *CachedStream) GetUseLog() bool { - return c.UseLog -} - -// GetUseIndex implements engine/driver.Stream -func (c *CachedStream) GetUseIndex() bool { - return c.UseIndex -} - -// GetUseWarehouse implements engine/driver.Stream -func (c *CachedStream) GetUseWarehouse() bool { - return c.UseWarehouse -} - -// GetLogRetention implements engine/driver.Stream -func (c *CachedStream) GetLogRetention() time.Duration { - return time.Duration(c.LogRetentionSeconds) * time.Second -} - -// GetIndexRetention implements engine/driver.Stream -func (c *CachedStream) GetIndexRetention() time.Duration { - return time.Duration(c.IndexRetentionSeconds) * time.Second -} - -// GetWarehouseRetention implements engine/driver.Stream -func (c *CachedStream) GetWarehouseRetention() time.Duration { - return time.Duration(c.WarehouseRetentionSeconds) * time.Second -} - -// GetCodec implements engine/driver.Stream -func (c *CachedStream) GetCodec() *codec.Codec { - return c.Codec -} - -// StreamCache is a Redis and LRU based cache mapping an instance ID to a CachedStream -type StreamCache struct { - codec *cache.Codec - lru gcache.Cache -} - -var ( - _streamCacheLock sync.Mutex - _streamCache *StreamCache -) - -// getStreamCache returns a global streamCache -func getStreamCache() *StreamCache { - _streamCacheLock.Lock() - if _streamCache == nil { - _streamCache = &StreamCache{ - codec: &cache.Codec{ - Redis: hub.Redis, - Marshal: _streamCache.marshal, - Unmarshal: _streamCache.unmarshal, - }, - lru: gcache.New(_streamCache.cacheLRUSize()).LRU().Build(), - } - } - _streamCacheLock.Unlock() - return _streamCache -} - -// Get returns the CachedStream for the given instanceID -func (c *StreamCache) Get(ctx context.Context, instanceID uuid.UUID) *CachedStream { - key := c.redisKey(instanceID) - - // lookup in lru first - value, err := c.lru.Get(key) - if err == nil { - cachedStream := value.(*CachedStream) - return cachedStream - } - - // lookup in redis or db - cachedStream := &CachedStream{} - err = c.codec.Once(&cache.Item{ - Key: key, - Object: cachedStream, - Expiration: c.cacheTime(), - Func: c.getterFunc(ctx, instanceID), - }) - - if err != nil { - if ctx.Err() == context.Canceled { - return nil - } - panic(err) - } - - if cachedStream.ProjectID == uuid.Nil { - cachedStream = nil - } - - // set in lru - c.lru.SetWithExpire(key, cachedStream, c.cacheLRUTime()) - - return cachedStream -} - -// Clear removes any CachedStream cached for the given instanceID -func (c *StreamCache) Clear(ctx context.Context, instanceID uuid.UUID) { - key := c.redisKey(instanceID) - c.lru.Remove(key) - err := c.codec.Delete(key) - if err != nil && err != cache.ErrCacheMiss { - panic(err) - } -} - -// ClearForOrganization clears all streams in the organization -func (c *StreamCache) ClearForOrganization(ctx context.Context, organizationID uuid.UUID) { - c.clearQuery(ctx, ` - select si.stream_instance_id - from stream_instances si - join streams s on si.stream_id = s.stream_id - join projects p on s.project_id = p.project_id - where p.organization_id = ? - `, organizationID) -} - -// ClearForProject clears all streams in the project -func (c *StreamCache) ClearForProject(ctx context.Context, projectID uuid.UUID) { - c.clearQuery(ctx, ` - select si.stream_instance_id - from stream_instances si - join streams s on si.stream_id = s.stream_id - where s.project_id = ? - `, projectID) -} - -// clearQuery clears instance IDs returned by the given query and params -func (c *StreamCache) clearQuery(ctx context.Context, query string, params ...interface{}) { - var instanceIDs []uuid.UUID - _, err := hub.DB.QueryContext(ctx, &instanceIDs, query, params...) - if err != nil { - panic(err) - } - for _, instanceID := range instanceIDs { - c.Clear(ctx, instanceID) - } -} - -func (c *StreamCache) cacheTime() time.Duration { - return time.Hour -} - -func (c *StreamCache) cacheLRUSize() int { - return 10000 -} - -func (c *StreamCache) cacheLRUTime() time.Duration { - return 10 * time.Second -} - -func (c *StreamCache) redisKey(instanceID uuid.UUID) string { - return string(append([]byte("strm:"), instanceID.Bytes()...)) -} - -func (c *StreamCache) marshal(v interface{}) ([]byte, error) { - cachedStream := v.(*CachedStream) - return cachedStream.MarshalBinary() -} - -func (c *StreamCache) unmarshal(b []byte, v interface{}) (err error) { - cachedStream := v.(*CachedStream) - return cachedStream.UnmarshalBinary(b) -} - -func (c *StreamCache) getterFunc(ctx context.Context, instanceID uuid.UUID) func() (interface{}, error) { - return func() (interface{}, error) { - internalResult := &internalCachedStream{} - _, err := hub.DB.QueryContext(ctx, internalResult, ` - select - s.stream_id, - p.public, - si.made_final_on is not null as final, - s.use_log, - s.use_index, - s.use_warehouse, - s.log_retention_seconds, - s.index_retention_seconds, - s.warehouse_retention_seconds, - p.organization_id, - o.name as organization_name, - s.project_id, - p.name as project_name, - s.name as stream_name, - s.canonical_avro_schema - from stream_instances si - join streams s on si.stream_id = s.stream_id - join projects p on s.project_id = p.project_id - join organizations o on p.organization_id = o.organization_id - where si.stream_instance_id = ? - `, instanceID) - - result := &CachedStream{} - if err == pg.ErrNoRows { - return result, nil - } else if err != nil { - return nil, err - } - - _, err = hub.DB.QueryContext(ctx, &internalResult.Indexes, ` - select - stream_index_id, - short_id, - fields, - "primary", - normalize - from stream_indexes - where stream_id = ? - `, internalResult.StreamID) - if err == pg.ErrNoRows { - return result, nil - } else if err != nil { - return nil, err - } - - err = unwrapInternalCachedStream(internalResult, result) - if err != nil { - return nil, err - } - - return result, nil - } -} - -func unwrapInternalCachedStream(source *internalCachedStream, target *CachedStream) (err error) { - target.StreamID = source.StreamID - target.Public = source.Public - target.Final = source.Final - target.UseLog = source.UseLog - target.UseIndex = source.UseIndex - target.UseWarehouse = source.UseWarehouse - target.LogRetentionSeconds = source.LogRetentionSeconds - target.IndexRetentionSeconds = source.IndexRetentionSeconds - target.WarehouseRetentionSeconds = source.WarehouseRetentionSeconds - target.OrganizationID = source.OrganizationID - target.OrganizationName = source.OrganizationName - target.ProjectID = source.ProjectID - target.ProjectName = source.ProjectName - target.StreamName = source.StreamName - - // nil checks necessary because we allow empty CachedStream objects - - if source.CanonicalAvroSchema != "" { - var primaryIndex codec.Index - var secondaryIndexes []codec.Index - for _, index := range source.Indexes { - if index.Primary { - primaryIndex = index - } else { - secondaryIndexes = append(secondaryIndexes, index) - } - } - - target.Codec, err = codec.New(source.CanonicalAvroSchema, primaryIndex, secondaryIndexes) - if err != nil { - return err - } - } - - return nil -} diff --git a/control/entity/stream_current_instance_cache.go b/control/entity/stream_current_instance_cache.go deleted file mode 100644 index d2e3581e..00000000 --- a/control/entity/stream_current_instance_cache.go +++ /dev/null @@ -1,114 +0,0 @@ -package entity - -import ( - "context" - "fmt" - "time" - - "github.com/go-pg/pg/v9" - "github.com/go-redis/cache/v7" - uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/hub" -) - -// FindInstanceIDByOrganizationProjectAndName returns the current instance ID of the stream -func FindInstanceIDByOrganizationProjectAndName(ctx context.Context, organizationName string, projectName string, streamName string) uuid.UUID { - return getInstanceCache().get(ctx, organizationName, projectName, streamName) -} - -// instanceCache is a Redis and LRU based cache mapping (projectName, streamName) pairs to -// the current instance ID for that stream (table `streams`, column `current_stream_instance_id`) -type instanceCache struct { - codec *cache.Codec -} - -var ( - _instanceCache instanceCache -) - -// getInstanceCache returns a global instanceCache -func getInstanceCache() instanceCache { - if _instanceCache.codec == nil { - _instanceCache.codec = &cache.Codec{ - Redis: hub.Redis, - Marshal: _instanceCache.marshal, - Unmarshal: _instanceCache.unmarshal, - } - _instanceCache.codec.UseLocalCache(_instanceCache.cacheLRUSize(), _instanceCache.cacheLRUTime()) - } - - return _instanceCache -} - -func (c instanceCache) get(ctx context.Context, organizationName string, projectName string, streamName string) uuid.UUID { - var instanceID uuid.UUID - err := c.codec.Once(&cache.Item{ - Key: c.redisKey(organizationName, projectName, streamName), - Object: &instanceID, - Expiration: c.cacheTime(), - Func: c.getterFunc(ctx, organizationName, projectName, streamName), - }) - - if err != nil { - if ctx.Err() == context.Canceled { - return uuid.Nil - } - panic(err) - } - - return instanceID -} - -func (c instanceCache) clear(ctx context.Context, organizationName string, projectName string, streamName string) { - err := c.codec.Delete(c.redisKey(organizationName, projectName, streamName)) - if err != nil && err != cache.ErrCacheMiss { - panic(err) - } -} - -func (c instanceCache) cacheTime() time.Duration { - return time.Hour -} - -func (c instanceCache) cacheLRUSize() int { - return 10000 -} - -func (c instanceCache) cacheLRUTime() time.Duration { - return 10 * time.Second -} - -func (c instanceCache) redisKey(organizationName string, projectName string, streamName string) string { - return fmt.Sprintf("inst:%s:%s:%s", organizationName, projectName, streamName) -} - -func (c instanceCache) marshal(v interface{}) ([]byte, error) { - instanceID := v.(uuid.UUID) - return instanceID.Bytes(), nil -} - -func (c instanceCache) unmarshal(b []byte, v interface{}) (err error) { - instanceID := v.(*uuid.UUID) - *instanceID, err = uuid.FromBytes(b) - return err -} - -func (c instanceCache) getterFunc(ctx context.Context, organizationName string, projectName string, streamName string) func() (interface{}, error) { - return func() (interface{}, error) { - res := uuid.Nil - _, err := hub.DB.QueryContext(ctx, pg.Scan(&res), ` - select s.primary_stream_instance_id - from streams s - join projects p on s.project_id = p.project_id - join organizations o on p.organization_id = o.organization_id - where lower(s.name) = lower(?) - and lower(p.name) = lower(?) - and lower(o.name) = lower(?) - and primary_stream_instance_id is not null - `, streamName, projectName, organizationName) - if err == pg.ErrNoRows { - return res, nil - } - return res, err - } -} diff --git a/control/entity/stream_index.go b/control/entity/stream_index.go deleted file mode 100644 index 5a536530..00000000 --- a/control/entity/stream_index.go +++ /dev/null @@ -1,37 +0,0 @@ -package entity - -import ( - uuid "github.com/satori/go.uuid" -) - -// StreamIndex represents an index on a stream -type StreamIndex struct { - tableName struct{} `sql:"stream_indexes"` - StreamIndexID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` - StreamID uuid.UUID `sql:"on_delete:CASCADE,notnull,type:uuid"` - Stream *Stream - ShortID int `sql:",notnull",validate:"required"` - Fields []string `sql:",notnull",validate:"required,gte=1"` - Primary bool `sql:",notnull"` - Normalize bool `sql:",notnull"` -} - -// GetIndexID implements codec.Index -func (i *StreamIndex) GetIndexID() uuid.UUID { - return i.StreamIndexID -} - -// GetShortID implements codec.Index -func (i *StreamIndex) GetShortID() int { - return i.ShortID -} - -// GetFields implements codec.Index -func (i *StreamIndex) GetFields() []string { - return i.Fields -} - -// GetNormalize implements codec.Index -func (i *StreamIndex) GetNormalize() bool { - return i.Normalize -} diff --git a/control/entity/stream_instance.go b/control/entity/stream_instance.go deleted file mode 100644 index 52f4d5d9..00000000 --- a/control/entity/stream_instance.go +++ /dev/null @@ -1,83 +0,0 @@ -package entity - -import ( - "context" - "fmt" - "time" - - "gitlab.com/beneath-hq/beneath/hub" - - uuid "github.com/satori/go.uuid" -) - -// StreamInstance represents a single version of a stream (for a streaming stream, -// there will only be one instance; but for a batch stream, each update represents -// a new instance) -type StreamInstance struct { - StreamInstanceID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` - StreamID uuid.UUID `sql:"on_delete:RESTRICT,notnull,type:uuid"` - Stream *Stream - CreatedOn time.Time `sql:",default:now()"` - UpdatedOn time.Time `sql:",default:now()"` - MadePrimaryOn *time.Time - MadeFinalOn *time.Time - Version int `sql:",notnull,default:0"` -} - -// EfficientStreamInstance can be used to efficiently make a UUID conform to engine/driver.StreamInstance -type EfficientStreamInstance uuid.UUID - -// GetStreamInstanceID implements engine/driver.StreamInstance -func (si EfficientStreamInstance) GetStreamInstanceID() uuid.UUID { - return uuid.UUID(si) -} - -// GetStreamInstanceID implements engine/driver.StreamInstance -func (si *StreamInstance) GetStreamInstanceID() uuid.UUID { - return si.StreamInstanceID -} - -// FindStreamInstances finds the instances associated with the given stream -func FindStreamInstances(ctx context.Context, streamID uuid.UUID, fromVersion *int, toVersion *int) []*StreamInstance { - var res []*StreamInstance - - // optimization - if fromVersion != nil && toVersion != nil && *fromVersion == *toVersion { - return res - } - - // build query - query := hub.DB.ModelContext(ctx, &res).Where("stream_id = ?", streamID) - if fromVersion != nil { - query = query.Where("version >= ?", *fromVersion) - } - if toVersion != nil { - query = query.Where("version < ?", *toVersion) - } - - // select - err := query.Select() - if err != nil { - panic(fmt.Errorf("error fetching stream instances: %s", err.Error())) - } - - return res -} - -// FindStreamInstance finds an instance and related stream details -func FindStreamInstance(ctx context.Context, instanceID uuid.UUID) *StreamInstance { - si := &StreamInstance{ - StreamInstanceID: instanceID, - } - err := hub.DB.ModelContext(ctx, si).Column( - "stream_instance.*", - "Stream", - "Stream.StreamIndexes", - "Stream.Project", - "Stream.Project.Organization", - ).WherePK().Select() - if !AssertFoundOne(err) { - return nil - } - return si -} diff --git a/control/entity/user.go b/control/entity/user.go deleted file mode 100644 index 8bcfe04c..00000000 --- a/control/entity/user.go +++ /dev/null @@ -1,416 +0,0 @@ -package entity - -import ( - "context" - "fmt" - "regexp" - "strings" - "time" - "unicode" - - "github.com/go-pg/pg/v9/orm" - uuid "github.com/satori/go.uuid" - - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/log" -) - -// User represents a Beneath user -type User struct { - UserID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` - Email string `sql:",notnull",validate:"required,email"` - GoogleID string `sql:",unique",validate:"omitempty,lte=255"` - GithubID string `sql:",unique",validate:"omitempty,lte=255"` - CreatedOn time.Time `sql:",default:now()"` - UpdatedOn time.Time `sql:",default:now()"` - Master bool `sql:",notnull,default:false"` // NOTE: when updating value, clear secret cache - ConsentTerms bool `sql:",notnull,default:false"` - ConsentNewsletter bool `sql:",notnull,default:false"` - ReadQuota *int64 // NOTE: when updating value, clear secret cache - WriteQuota *int64 // NOTE: when updating value, clear secret cache - ScanQuota *int64 // NOTE: when updating value, clear secret cache - BillingOrganizationID uuid.UUID `sql:",on_delete:restrict,notnull,type:uuid"` // NOTE: when updating value, clear secret cache - BillingOrganization *Organization - Projects []*Project `pg:"many2many:permissions_users_projects,fk:user_id,joinFK:project_id"` - Organizations []*Organization `pg:"many2many:permissions_users_organizations,fk:user_id,joinFK:organization_id"` - Secrets []*UserSecret -} - -var ( - nonAlphanumericRegex *regexp.Regexp -) - -const ( - // used for generating username seeds - usernameMinLength = 3 - usernameMaxLength = 50 -) - -func init() { - nonAlphanumericRegex = regexp.MustCompile("[^a-zA-Z0-9]+") -} - -// FindUser returns the matching user or nil -func FindUser(ctx context.Context, userID uuid.UUID) *User { - user := &User{ - UserID: userID, - } - err := hub.DB.ModelContext(ctx, user).WherePK().Column("user.*").Select() - if !AssertFoundOne(err) { - return nil - } - return user -} - -// CreateOrUpdateUser consolidates and returns the user matching the args -func CreateOrUpdateUser(ctx context.Context, githubID, googleID, email, nickname, name, photoURL string) (*User, error) { - defaultBillingPlan := FindDefaultBillingPlan(ctx) - - user := &User{} - org := &Organization{} - create := false - - tx, err := hub.DB.Begin() - if err != nil { - return nil, err - } - defer tx.Rollback() // defer rollback on error - - // find user by ID (and lock for update) - var userQuery *orm.Query - if githubID != "" { - userQuery = tx.Model(user).Where("github_id = ?", githubID) - } else if googleID != "" { - userQuery = tx.Model(user).Where("google_id = ?", googleID) - } else { - panic(fmt.Errorf("CreateOrUpdateUser neither githubID nor googleID set")) - } - - err = userQuery.For("UPDATE").Select() - if !AssertFoundOne(err) { - // find user by email - err = tx.Model(user).Where("lower(email) = lower(?)", email).For("UPDATE").Select() - if !AssertFoundOne(err) { - create = true - } - } - - // if not create, select personal org for update - if !create { - err = tx.Model(org).Where("user_id = ?", user.UserID).For("UPDATE").Select() - if err != nil { - panic(fmt.Errorf("Couldn't find personal organization for user: %s", err.Error())) - } - } - - // set fields - if githubID != "" { - user.GithubID = githubID - } - if googleID != "" { - user.GoogleID = googleID - } - if email != "" { - user.Email = email - } - if org.DisplayName == "" { - org.DisplayName = name - } - if org.PhotoURL == "" { - org.PhotoURL = photoURL - } - - // if updating, finalize and return - if !create { - // validate and save user - user.UpdatedOn = time.Now() - err = GetValidator().Struct(user) - if err != nil { - return nil, err - } - err = tx.Update(user) - if err != nil { - return nil, err - } - - // validate and save org - org.UpdatedOn = time.Now() - err = GetValidator().Struct(org) - if err != nil { - return nil, err - } - err = tx.Update(org) - if err != nil { - return nil, err - } - - // log - log.S.Infow( - "control updated user", - "user_id", user.UserID, - ) - - // commit - err = tx.Commit() - if err != nil { - return nil, err - } - - return user, nil - } - - // we're creating a new user - - // not a platform admin - user.Master = false - - // set the organization's default quotas - org.PrepaidReadQuota = &defaultBillingPlan.ReadQuota - org.PrepaidWriteQuota = &defaultBillingPlan.WriteQuota - org.PrepaidScanQuota = &defaultBillingPlan.ScanQuota - org.ReadQuota = &defaultBillingPlan.ReadQuota - org.WriteQuota = &defaultBillingPlan.WriteQuota - org.ScanQuota = &defaultBillingPlan.ScanQuota - - // try out all possible usernames - created := false - usernameSeeds := usernameSeeds(email, name, nickname) - for _, username := range usernameSeeds { - // update org and user - org.Name = username - if org.DisplayName == "" { - org.DisplayName = username - } - - // validate org - err = GetValidator().Struct(org) - if err != nil { - // continue (probably username is blacklisted) - continue - } - - // savepoint in case name is taken - _, err = tx.Exec("SAVEPOINT bi") - if err != nil { - return nil, err - } - - // insert org - err = tx.Insert(org) - if err == nil { - // insert user (with org as billing) - user.BillingOrganizationID = org.OrganizationID - err = tx.Insert(user) - if err != nil { - return nil, err - } - - // update org with user ID - org.UserID = &user.UserID - _, err = tx.Model(org).Column("user_id").WherePK().Update() - if err != nil { - return nil, err - } - - // success - created = true - break - } - - // failure, err != nil - - // rollback on name error - if isUniqueError(err) { - // rollback to before error, then try next username - _, err = tx.Exec("ROLLBACK TO SAVEPOINT bi") - if err != nil { - return nil, err - } - continue - } - - // unexpected error - return nil, err - } - - // if not created, error - if !created { - return nil, fmt.Errorf("couldn't create user for any username seeds") - } - - // add user to user-organization permissions table - err = tx.Insert(&PermissionsUsersOrganizations{ - UserID: user.UserID, - OrganizationID: org.OrganizationID, - View: true, - Create: true, - Admin: true, - }) - if err != nil { - return nil, err - } - - // create billing info - bi := &BillingInfo{ - OrganizationID: org.OrganizationID, - BillingPlanID: defaultBillingPlan.BillingPlanID, - } - _, err = tx.Model(bi).Insert() - if err != nil { - return nil, err - } - - // commit it all - err = tx.Commit() - if err != nil { - return nil, err - } - - // stage initial project - starterProject := &Project{ - Name: "starter_project", - DisplayName: "Starter project", - Description: "We automatically created this project for you to help you get started", - Public: true, - OrganizationID: user.BillingOrganizationID, - } - err = starterProject.StageWithUser(ctx, nil, nil, nil, nil, nil, user.UserID, ProjectPermissions{ - View: true, - Create: true, - Admin: true, - }) - if err != nil { - return nil, err - } - - // log new user - log.S.Infow( - "control created user", - "user_id", user.UserID, - ) - - // send event about user create - err = hub.Engine.PublishControlEvent(ctx, "user_create", map[string]interface{}{ - "organization_id": org.OrganizationID, - "user_id": user.UserID, - }) - if err != nil { - return nil, err - } - - return user, nil -} - -// RegisterConsent updates the user's consent preferences -func (u *User) RegisterConsent(ctx context.Context, terms *bool, newsletter *bool) error { - if !u.ConsentTerms && (terms == nil || !*terms) { - return fmt.Errorf("Cannot continue without consent to the terms of service") - } - - if terms != nil { - if !*terms { - return fmt.Errorf("You cannot withdraw consent to the terms of service; instead, delete your user") - } - u.ConsentTerms = *terms - } - - if newsletter != nil { - u.ConsentNewsletter = *newsletter - } - - // validate and save - u.UpdatedOn = time.Now() - err := GetValidator().Struct(u) - if err != nil { - return err - } - _, err = hub.DB.ModelContext(ctx, u).Column("consent_terms", "consent_newsletter", "updated_on").WherePK().Update() - if err != nil { - return err - } - - return nil -} - -// UpdateQuotas change the user's quotas -func (u *User) UpdateQuotas(ctx context.Context, readQuota *int64, writeQuota *int64, scanQuota *int64) error { - u.ReadQuota = readQuota - u.WriteQuota = writeQuota - u.ScanQuota = scanQuota - - // validate and save - u.UpdatedOn = time.Now() - err := GetValidator().Struct(u) - if err != nil { - return err - } - _, err = hub.DB.ModelContext(ctx, u).Column("read_quota", "write_quota", "scan_quota", "updated_on").WherePK().Update() - if err != nil { - return err - } - - getSecretCache().ClearForUser(ctx, u.UserID) - return nil -} - -func usernameSeeds(email string, name string, nickname string) []string { - // gather candidates - var seeds []string - var shortest string - - // base on nickname - username := nonAlphanumericRegex.ReplaceAllString(nickname, "") - if len(username) >= usernameMinLength { - seeds = append(seeds, finalizeUsernameSeed(username)) - shortest = username - } - if len(username) < len(shortest) { - shortest = username - } - - // base on email - username = strings.Split(email, "@")[0] - username = nonAlphanumericRegex.ReplaceAllString(username, "") - if len(username) >= usernameMinLength { - seeds = append(seeds, finalizeUsernameSeed(username)) - } - if len(username) < len(shortest) { - shortest = username - } - - // base on name - username = nonAlphanumericRegex.ReplaceAllString(name, "") - if len(username) >= usernameMinLength { - seeds = append(seeds, finalizeUsernameSeed(username)) - } - if len(username) < len(shortest) { - shortest = username - } - - // final fallback -- a uuid - username = shortest + uuid.NewV4().String()[0:8] - seeds = append(seeds, finalizeUsernameSeed(username)) - - return seeds -} - -func finalizeUsernameSeed(seed string) string { - seed = strings.ToLower(seed) - if len(seed) == (usernameMinLength-1) && seed[0] != '_' { - seed = "_" + seed - } - if unicode.IsDigit(rune(seed[0])) { - seed = "b" + seed - } - if len(seed) > usernameMaxLength { - seed = seed[0:usernameMaxLength] - } - return seed -} - -func isUniqueError(err error) bool { - if err == nil { - return false - } - return strings.Contains(strings.ToLower(err.Error()), "violates unique constraint") -} diff --git a/control/entity/user_test.go b/control/entity/user_test.go deleted file mode 100644 index cc74a469..00000000 --- a/control/entity/user_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package entity - -import ( - "testing" - - "gitlab.com/beneath-hq/beneath/hub" -) - -func init() { - hub.InitPostgres("localhost", "", "postgres", "") - hub.InitRedis("redis://localhost/") -} - -func TestUserCreate(t *testing.T) { - // ctx := context.Background() - - // user10, err := CreateOrUpdateUser(ctx, "10", "", "benjamin@example10.org", "bem8", "1", "") - // assert.Nil(t, err) - // t.Logf("%v", user10) - - // user20, err := CreateOrUpdateUser(ctx, "20", "", "benjamin@example20.org", "", "Egelund", "") - // assert.Nil(t, err) - // t.Logf("%v", user20) - - // assert.Nil(t, user10.Delete(ctx)) - // assert.Nil(t, user20.Delete(ctx)) - - // // cleanup - // hub.Redis.FlushAll() -} diff --git a/control/gql/gqlgen.yml b/control/gql/gqlgen.yml deleted file mode 100644 index d4a0fd43..00000000 --- a/control/gql/gqlgen.yml +++ /dev/null @@ -1,57 +0,0 @@ -# Configures gqlgen – docs at https://gqlgen.com/config/ -schema: -- "control/gql/schema/**/*.graphql" -exec: - filename: control/gql/schema_gen.go - package: gql -model: - filename: control/gql/models_gen.go - package: gql -resolver: - filename: control/resolver/generated.go - package: resolver - type: Resolver -autobind: [] -models: - UUID: - model: gitlab.com/beneath-hq/beneath/control/gql.UUID - UserSecret: - model: gitlab.com/beneath-hq/beneath/control/entity.UserSecret - ServiceSecret: - model: gitlab.com/beneath-hq/beneath/control/entity.ServiceSecret - Project: - model: gitlab.com/beneath-hq/beneath/control/entity.Project - Stream: - model: gitlab.com/beneath-hq/beneath/control/entity.Stream - StreamInstance: - model: gitlab.com/beneath-hq/beneath/control/entity.StreamInstance - StreamIndex: - model: gitlab.com/beneath-hq/beneath/control/entity.StreamIndex - PrivateUser: - model: gitlab.com/beneath-hq/beneath/control/entity.User - PublicOrganization: - model: gitlab.com/beneath-hq/beneath/control/entity.Organization - ProjectMember: - model: gitlab.com/beneath-hq/beneath/control/entity.ProjectMember - OrganizationMember: - model: gitlab.com/beneath-hq/beneath/control/entity.OrganizationMember - Service: - model: gitlab.com/beneath-hq/beneath/control/entity.Service - PermissionsUsersProjects: - model: gitlab.com/beneath-hq/beneath/control/entity.PermissionsUsersProjects - PermissionsUsersOrganizations: - model: gitlab.com/beneath-hq/beneath/control/entity.PermissionsUsersOrganizations - PermissionsServicesStreams: - model: gitlab.com/beneath-hq/beneath/control/entity.PermissionsServicesStreams - BillingPlan: - model: gitlab.com/beneath-hq/beneath/control/entity.BillingPlan - BilledResource: - model: gitlab.com/beneath-hq/beneath/control/entity.BilledResource - BillingMethod: - model: gitlab.com/beneath-hq/beneath/control/entity.BillingMethod - BillingInfo: - model: gitlab.com/beneath-hq/beneath/control/entity.BillingInfo - PaymentMethod: - model: gitlab.com/beneath-hq/beneath/control/entity.PaymentMethod - StreamSchemaKind: - model: gitlab.com/beneath-hq/beneath/control/entity.StreamSchemaKind diff --git a/control/resolver/stream.go b/control/resolver/stream.go deleted file mode 100644 index fb70bec2..00000000 --- a/control/resolver/stream.go +++ /dev/null @@ -1,218 +0,0 @@ -package resolver - -import ( - "context" - - uuid "github.com/satori/go.uuid" - "github.com/vektah/gqlparser/gqlerror" - - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/control/gql" - "gitlab.com/beneath-hq/beneath/internal/middleware" -) - -// Stream returns the gql.StreamResolver -func (r *Resolver) Stream() gql.StreamResolver { - return &streamResolver{r} -} - -type streamResolver struct{ *Resolver } - -func (r *streamResolver) StreamID(ctx context.Context, obj *entity.Stream) (string, error) { - return obj.StreamID.String(), nil -} - -func (r *queryResolver) StreamByID(ctx context.Context, streamID uuid.UUID) (*entity.Stream, error) { - stream := entity.FindStream(ctx, streamID) - if stream == nil { - return nil, gqlerror.Errorf("Stream with ID %s not found", streamID.String()) - } - - secret := middleware.GetSecret(ctx) - perms := secret.StreamPermissions(ctx, stream.StreamID, stream.ProjectID, stream.Project.Public) - if !perms.Read { - return nil, gqlerror.Errorf("Not allowed to read stream with ID %s", streamID.String()) - } - - return stream, nil -} - -func (r *queryResolver) StreamByOrganizationProjectAndName(ctx context.Context, organizationName string, projectName string, streamName string) (*entity.Stream, error) { - stream := entity.FindStreamByOrganizationProjectAndName(ctx, organizationName, projectName, streamName) - if stream == nil { - return nil, gqlerror.Errorf("Stream %s/%s/%s not found", organizationName, projectName, streamName) - } - - secret := middleware.GetSecret(ctx) - perms := secret.StreamPermissions(ctx, stream.StreamID, stream.ProjectID, stream.Project.Public) - if !perms.Read && !perms.Write { - return nil, gqlerror.Errorf("Not allowed to find stream %s/%s/%s", organizationName, projectName, streamName) - } - - return stream, nil -} - -func (r *queryResolver) StreamInstancesForStream(ctx context.Context, streamID uuid.UUID) ([]*entity.StreamInstance, error) { - stream := entity.FindStream(ctx, streamID) - if stream == nil { - return nil, gqlerror.Errorf("Stream with ID %s not found", streamID.String()) - } - - secret := middleware.GetSecret(ctx) - perms := secret.StreamPermissions(ctx, stream.StreamID, stream.ProjectID, stream.Project.Public) - if !perms.Read { - return nil, gqlerror.Errorf("Not allowed to read stream with ID %s", streamID.String()) - } - - instances := entity.FindStreamInstances(ctx, streamID, nil, nil) - return instances, nil -} - -func (r *queryResolver) StreamInstancesByOrganizationProjectAndStreamName(ctx context.Context, organizationName string, projectName string, streamName string) ([]*entity.StreamInstance, error) { - stream := entity.FindStreamByOrganizationProjectAndName(ctx, organizationName, projectName, streamName) - if stream == nil { - return nil, gqlerror.Errorf("Stream %s/%s/%s not found", organizationName, projectName, streamName) - } - - secret := middleware.GetSecret(ctx) - perms := secret.StreamPermissions(ctx, stream.StreamID, stream.ProjectID, stream.Project.Public) - if !perms.Read { - return nil, gqlerror.Errorf("Not allowed to read stream with ID %s", stream.StreamID.String()) - } - - instances := entity.FindStreamInstances(ctx, stream.StreamID, nil, nil) - return instances, nil -} - -func (r *mutationResolver) StageStream(ctx context.Context, organizationName string, projectName string, streamName string, schemaKind entity.StreamSchemaKind, schema string, indexes *string, description *string, allowManualWrites *bool, useLog *bool, useIndex *bool, useWarehouse *bool, logRetentionSeconds *int, indexRetentionSeconds *int, warehouseRetentionSeconds *int) (*entity.Stream, error) { - var project *entity.Project - var stream *entity.Stream - - stream = entity.FindStreamByOrganizationProjectAndName(ctx, organizationName, projectName, streamName) - if stream == nil { - project = entity.FindProjectByOrganizationAndName(ctx, organizationName, projectName) - if project == nil { - return nil, gqlerror.Errorf("Project %s/%s not found", organizationName, projectName) - } - stream = &entity.Stream{ - Name: streamName, - ProjectID: project.ProjectID, - } - } else { - project = stream.Project - } - - secret := middleware.GetSecret(ctx) - perms := secret.ProjectPermissions(ctx, project.ProjectID, project.Public) - if !perms.Create { - return nil, gqlerror.Errorf("Not allowed to create or modify resources in project %s/%s", organizationName, projectName) - } - - err := stream.Stage(ctx, schemaKind, schema, indexes, description, allowManualWrites, useLog, useIndex, useWarehouse, logRetentionSeconds, indexRetentionSeconds, warehouseRetentionSeconds) - if err != nil { - return nil, gqlerror.Errorf("Error staging stream: %s", err.Error()) - } - - _, err = stream.StageStreamInstance(ctx, 0, false, true) - if err != nil { - return nil, gqlerror.Errorf("Error creating first instance: %s", err.Error()) - } - - return stream, nil -} - -func (r *mutationResolver) DeleteStream(ctx context.Context, streamID uuid.UUID) (bool, error) { - stream := entity.FindStream(ctx, streamID) - if stream == nil { - return false, gqlerror.Errorf("Stream %s not found", streamID.String()) - } - - secret := middleware.GetSecret(ctx) - perms := secret.ProjectPermissions(ctx, stream.ProjectID, false) - if !perms.Create { - return false, gqlerror.Errorf("Not allowed to perform admin functions in project %s", stream.Project.Name) - } - - err := stream.Delete(ctx) - if err != nil { - return false, gqlerror.Errorf("%s", err.Error()) - } - - return true, nil -} - -func (r *mutationResolver) StageStreamInstance(ctx context.Context, streamID uuid.UUID, version int, makeFinal *bool, makePrimary *bool) (*entity.StreamInstance, error) { - stream := entity.FindStream(ctx, streamID) - if stream == nil { - return nil, gqlerror.Errorf("Stream %s not found", streamID.String()) - } - - secret := middleware.GetSecret(ctx) - perms := secret.StreamPermissions(ctx, stream.StreamID, stream.ProjectID, stream.Project.Public) - if !perms.Write { - return nil, gqlerror.Errorf("Not allowed to write to stream %s/%s", stream.Name, stream.Project.Name) - } - - falseVal := false - if makeFinal == nil { - makeFinal = &falseVal - } - if makePrimary == nil { - makePrimary = &falseVal - } - - si, err := stream.StageStreamInstance(ctx, version, *makeFinal, *makePrimary) - if err != nil { - return nil, err - } - - return si, nil -} - -func (r *mutationResolver) UpdateStreamInstance(ctx context.Context, instanceID uuid.UUID, makeFinal *bool, makePrimary *bool) (*entity.StreamInstance, error) { - instance := entity.FindStreamInstance(ctx, instanceID) - if instance == nil { - return nil, gqlerror.Errorf("Stream instance '%s' not found", instanceID.String()) - } - - secret := middleware.GetSecret(ctx) - perms := secret.StreamPermissions(ctx, instance.Stream.StreamID, instance.Stream.ProjectID, false) - if !perms.Write { - return nil, gqlerror.Errorf("Not allowed to write to instance %s", instanceID.String()) - } - - falseVal := false - if makeFinal == nil { - makeFinal = &falseVal - } - if makePrimary == nil { - makePrimary = &falseVal - } - - err := instance.Stream.UpdateStreamInstance(ctx, instance, *makeFinal, *makePrimary) - if err != nil { - return nil, gqlerror.Errorf("Error updating stream instance: %s", err.Error()) - } - - return instance, nil -} - -func (r *mutationResolver) DeleteStreamInstance(ctx context.Context, instanceID uuid.UUID) (bool, error) { - instance := entity.FindStreamInstance(ctx, instanceID) - if instance == nil { - return false, gqlerror.Errorf("Stream instance '%s' not found", instanceID.String()) - } - - secret := middleware.GetSecret(ctx) - perms := secret.StreamPermissions(ctx, instance.Stream.StreamID, instance.Stream.ProjectID, false) - if !perms.Write { - return false, gqlerror.Errorf("Not allowed to write to instance %s", instanceID.String()) - } - - err := instance.Stream.DeleteStreamInstance(ctx, instance) - if err != nil { - return false, gqlerror.Errorf("Couldn't delete stream instance: %s", err.Error()) - } - - return true, nil -} diff --git a/control/server.go b/control/server.go deleted file mode 100644 index 08f08631..00000000 --- a/control/server.go +++ /dev/null @@ -1,146 +0,0 @@ -package control - -import ( - "context" - "fmt" - "net/http" - "time" - - "gitlab.com/beneath-hq/beneath/control/auth" - "gitlab.com/beneath-hq/beneath/control/gql" - "gitlab.com/beneath-hq/beneath/control/resolver" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/internal/middleware" - "gitlab.com/beneath-hq/beneath/pkg/httputil" - "gitlab.com/beneath-hq/beneath/pkg/log" - - "github.com/99designs/gqlgen/graphql" - "github.com/99designs/gqlgen/handler" - "github.com/go-chi/chi" - chimiddleware "github.com/go-chi/chi/middleware" - "github.com/rs/cors" - "github.com/vektah/gqlparser/ast" - "github.com/vektah/gqlparser/gqlerror" -) - -// Handler serves the GraphQL API on HTTP -func Handler(host string, frontendHost string) http.Handler { - router := chi.NewRouter() - - corsOptions := cors.Options{ - AllowedOrigins: []string{ - host, - frontendHost, - }, - AllowedHeaders: []string{"*"}, - AllowCredentials: true, - Debug: false, - } - - router.Use(chimiddleware.RealIP) - router.Use(chimiddleware.DefaultCompress) - router.Use(cors.New(corsOptions).Handler) - router.Use(middleware.InjectTags) - router.Use(middleware.Logger) - router.Use(middleware.Recoverer) - router.Use(middleware.Auth) - router.Use(middleware.IPRateLimit()) - - // Authentication endpoints - router.Mount("/auth", auth.Router()) - - // Add health check - router.Get("/", healthCheck) - router.Get("/healthz", healthCheck) - - // Add error testing - router.Get("/error", func(w http.ResponseWriter, r *http.Request) { - panic(fmt.Errorf("Testing error at %v", time.Now())) - }) - - // Add playground - router.Handle("/playground", handler.Playground("Beneath", "/graphql")) - - // Add graphql server - router.Handle("/graphql", handler.GraphQL( - makeExecutableSchema(), - makeQueryLoggingMiddleware(), - makeGraphQLErrorPresenter(), - handler.RecoverFunc(func(ctx context.Context, err interface{}) error { - panic(err) - }), - )) - - // Add payments handlers - for name, driver := range hub.PaymentDrivers { - for subpath, handler := range driver.GetHTTPHandlers() { - path := fmt.Sprintf("/billing/%s/%s", name, subpath) - router.Handle(path, httputil.AppHandler(handler)) - } - } - - return router -} - -func healthCheck(w http.ResponseWriter, r *http.Request) { - if hub.Healthy() { - w.WriteHeader(http.StatusOK) - w.Write([]byte(http.StatusText(http.StatusOK))) - } else { - log.S.Errorf("Control database health check failed") - http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - } -} - -func makeExecutableSchema() graphql.ExecutableSchema { - return gql.NewExecutableSchema(gql.Config{Resolvers: &resolver.Resolver{}}) -} - -type gqlLog struct { - Op string `json:"op"` - Name string `json:"name,omitempty"` - Field string `json:"field"` - Error error `json:"error,omitempty"` - Vars map[string]interface{} `json:"vars,omitempty"` -} - -func makeQueryLoggingMiddleware() handler.Option { - return handler.RequestMiddleware(func(ctx context.Context, next func(ctx context.Context) []byte) []byte { - reqCtx := graphql.GetRequestContext(ctx) - middleware.SetTagsPayload(ctx, logInfoFromRequestContext(reqCtx)) - return next(ctx) - }) -} - -func logInfoFromRequestContext(ctx *graphql.RequestContext) interface{} { - var queries []gqlLog - for _, op := range ctx.Doc.Operations { - for _, sel := range op.SelectionSet { - if field, ok := sel.(*ast.Field); ok { - name := op.Name - if name == "" { - name = "Unnamed" - } - queries = append(queries, gqlLog{ - Op: string(op.Operation), - Name: name, - Field: field.Name, - Vars: ctx.Variables, - }) - } - } - } - return queries -} - -func makeGraphQLErrorPresenter() handler.Option { - return handler.ErrorPresenter(func(ctx context.Context, err error) *gqlerror.Error { - tags := middleware.GetTags(ctx) - if q, ok := tags.Payload.(gqlLog); ok { - q.Error = err - } - // Uncomment this line to print resolver error details in the console - // fmt.Printf("Error in GraphQL Resolver: %s", err.Error()) - return graphql.DefaultErrorPresenter(ctx, err) - }) -} diff --git a/control/taskqueue/taskqueue.go b/control/taskqueue/taskqueue.go deleted file mode 100644 index 681ca411..00000000 --- a/control/taskqueue/taskqueue.go +++ /dev/null @@ -1,17 +0,0 @@ -package taskqueue - -import ( - "context" - - "gitlab.com/beneath-hq/beneath/hub" -) - -// Submit queues a task for proocessing -func Submit(ctx context.Context, t Task) error { - qt, err := EncodeTask(t) - if err != nil { - return err - } - - return hub.Engine.QueueTask(ctx, qt) -} diff --git a/control/taskqueue/types.go b/control/taskqueue/types.go deleted file mode 100644 index 43f79557..00000000 --- a/control/taskqueue/types.go +++ /dev/null @@ -1,78 +0,0 @@ -package taskqueue - -import ( - "context" - "fmt" - "reflect" - "time" - - "gitlab.com/beneath-hq/beneath/pkg/timeutil" - uuid "github.com/satori/go.uuid" - "github.com/vmihailenco/msgpack" - - pb "gitlab.com/beneath-hq/beneath/engine/proto" -) - -// Task is the abstract interface for a worker task -type Task interface { - Run(ctx context.Context) error -} - -var ( - taskRegistry map[string]reflect.Type -) - -// RegisterTask registers a task struct for processing -func RegisterTask(task Task) { - if taskRegistry == nil { - taskRegistry = make(map[string]reflect.Type) - } - - t := reflect.TypeOf(task) - if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct { - panic(fmt.Errorf("task is not a pointer to a struct")) - } - - taskRegistry[t.Elem().Name()] = t.Elem() -} - -// EncodeTask converts a task to a protobuf (the task struct must have been registered with RegisterTask) -func EncodeTask(task Task) (*pb.QueuedTask, error) { - t := reflect.TypeOf(task) - if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct { - panic(fmt.Errorf("task is not a pointer to a struct")) - } - - data, err := msgpack.Marshal(task) - if err != nil { - return nil, err - } - - return &pb.QueuedTask{ - UniqueId: uuid.NewV4().String(), - Name: t.Elem().Name(), - Timestamp: timeutil.UnixMilli(time.Now()), - Data: data, - }, nil -} - -// DecodeTask converts a pb.QueuedTask to a task registered with RegisterTask -func DecodeTask(qt *pb.QueuedTask) (Task, error) { - t, ok := taskRegistry[qt.Name] - if !ok { - return nil, fmt.Errorf("cannot find task with name '%s'", qt.Name) - } - - tval := reflect.New(t) // pointer to underlying; underlying is raw struct - task, ok := tval.Interface().(Task) // pointer to struct - if !ok { - return nil, fmt.Errorf("cannot cast type '%s' to Task", qt.Name) - } - - err := msgpack.Unmarshal(qt.Data, task) - if err != nil { - return nil, err - } - - return task, nil -} diff --git a/control/taskqueue/worker/worker.go b/control/taskqueue/worker/worker.go deleted file mode 100644 index c47c212b..00000000 --- a/control/taskqueue/worker/worker.go +++ /dev/null @@ -1,43 +0,0 @@ -package worker - -import ( - "context" - "time" - - "gitlab.com/beneath-hq/beneath/control/taskqueue" - pb "gitlab.com/beneath-hq/beneath/engine/proto" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/log" - "gitlab.com/beneath-hq/beneath/pkg/timeutil" -) - -// Work runs a worker -func Work(ctx context.Context) error { - log.S.Info("taskqueue worker started") - return hub.Engine.ReadTasks(ctx, processTask) -} - -// processWriteRequest is called (approximately once) for each task -func processTask(ctx context.Context, t *pb.QueuedTask) error { - // metrics to track - startTime := time.Now() - - // decode and run - task, err := taskqueue.DecodeTask(t) - if err == nil { - err = task.Run(ctx) - } - - // log - log.S.Infow( - "task processed", - "uuid", t.UniqueId, - "time", timeutil.FromUnixMilli(t.Timestamp), - "name", t.Name, - "err", err, - "elapsed", time.Since(startTime), - ) - - // done - return err -} diff --git a/ee/.gitignore b/ee/.gitignore new file mode 100644 index 00000000..96616538 --- /dev/null +++ b/ee/.gitignore @@ -0,0 +1 @@ +config/.* \ No newline at end of file diff --git a/ee/config/config.yaml b/ee/config/config.yaml new file mode 100644 index 00000000..76a6cd6d --- /dev/null +++ b/ee/config/config.yaml @@ -0,0 +1,5 @@ +payments: + drivers: + - anarchism + stripe: + secret: "" diff --git a/deployments/README.md b/ee/deployments/README.md similarity index 100% rename from deployments/README.md rename to ee/deployments/README.md diff --git a/deployments/gitlab/README.md b/ee/deployments/gitlab/README.md similarity index 100% rename from deployments/gitlab/README.md rename to ee/deployments/gitlab/README.md diff --git a/deployments/gitlab/admin-service-account.yaml b/ee/deployments/gitlab/admin-service-account.yaml similarity index 100% rename from deployments/gitlab/admin-service-account.yaml rename to ee/deployments/gitlab/admin-service-account.yaml diff --git a/deployments/helm/README.md b/ee/deployments/helm/README.md similarity index 100% rename from deployments/helm/README.md rename to ee/deployments/helm/README.md diff --git a/deployments/helm/control/Chart.yaml b/ee/deployments/helm/control/Chart.yaml similarity index 100% rename from deployments/helm/control/Chart.yaml rename to ee/deployments/helm/control/Chart.yaml diff --git a/deployments/helm/control/templates/_helpers.tpl b/ee/deployments/helm/control/templates/_helpers.tpl similarity index 100% rename from deployments/helm/control/templates/_helpers.tpl rename to ee/deployments/helm/control/templates/_helpers.tpl diff --git a/deployments/helm/control/templates/deployment.yaml b/ee/deployments/helm/control/templates/deployment.yaml similarity index 100% rename from deployments/helm/control/templates/deployment.yaml rename to ee/deployments/helm/control/templates/deployment.yaml diff --git a/deployments/helm/control/templates/ingress.yaml b/ee/deployments/helm/control/templates/ingress.yaml similarity index 100% rename from deployments/helm/control/templates/ingress.yaml rename to ee/deployments/helm/control/templates/ingress.yaml diff --git a/deployments/helm/control/templates/service.yaml b/ee/deployments/helm/control/templates/service.yaml similarity index 100% rename from deployments/helm/control/templates/service.yaml rename to ee/deployments/helm/control/templates/service.yaml diff --git a/deployments/helm/control/values.yaml b/ee/deployments/helm/control/values.yaml similarity index 100% rename from deployments/helm/control/values.yaml rename to ee/deployments/helm/control/values.yaml diff --git a/deployments/helm/gateway/Chart.yaml b/ee/deployments/helm/gateway/Chart.yaml similarity index 100% rename from deployments/helm/gateway/Chart.yaml rename to ee/deployments/helm/gateway/Chart.yaml diff --git a/deployments/helm/gateway/templates/_helpers.tpl b/ee/deployments/helm/gateway/templates/_helpers.tpl similarity index 100% rename from deployments/helm/gateway/templates/_helpers.tpl rename to ee/deployments/helm/gateway/templates/_helpers.tpl diff --git a/deployments/helm/gateway/templates/deployment.yaml b/ee/deployments/helm/gateway/templates/deployment.yaml similarity index 100% rename from deployments/helm/gateway/templates/deployment.yaml rename to ee/deployments/helm/gateway/templates/deployment.yaml diff --git a/deployments/helm/gateway/templates/ingress.yaml b/ee/deployments/helm/gateway/templates/ingress.yaml similarity index 100% rename from deployments/helm/gateway/templates/ingress.yaml rename to ee/deployments/helm/gateway/templates/ingress.yaml diff --git a/deployments/helm/gateway/templates/service.yaml b/ee/deployments/helm/gateway/templates/service.yaml similarity index 100% rename from deployments/helm/gateway/templates/service.yaml rename to ee/deployments/helm/gateway/templates/service.yaml diff --git a/deployments/helm/gateway/values.yaml b/ee/deployments/helm/gateway/values.yaml similarity index 100% rename from deployments/helm/gateway/values.yaml rename to ee/deployments/helm/gateway/values.yaml diff --git a/deployments/helm/pipeline/Chart.yaml b/ee/deployments/helm/pipeline/Chart.yaml similarity index 100% rename from deployments/helm/pipeline/Chart.yaml rename to ee/deployments/helm/pipeline/Chart.yaml diff --git a/deployments/helm/pipeline/templates/_helpers.tpl b/ee/deployments/helm/pipeline/templates/_helpers.tpl similarity index 100% rename from deployments/helm/pipeline/templates/_helpers.tpl rename to ee/deployments/helm/pipeline/templates/_helpers.tpl diff --git a/deployments/helm/pipeline/templates/deployment.yaml b/ee/deployments/helm/pipeline/templates/deployment.yaml similarity index 100% rename from deployments/helm/pipeline/templates/deployment.yaml rename to ee/deployments/helm/pipeline/templates/deployment.yaml diff --git a/deployments/helm/pipeline/values.yaml b/ee/deployments/helm/pipeline/values.yaml similarity index 100% rename from deployments/helm/pipeline/values.yaml rename to ee/deployments/helm/pipeline/values.yaml diff --git a/deployments/helm/taskqueue/Chart.yaml b/ee/deployments/helm/taskqueue/Chart.yaml similarity index 100% rename from deployments/helm/taskqueue/Chart.yaml rename to ee/deployments/helm/taskqueue/Chart.yaml diff --git a/deployments/helm/taskqueue/templates/_helpers.tpl b/ee/deployments/helm/taskqueue/templates/_helpers.tpl similarity index 100% rename from deployments/helm/taskqueue/templates/_helpers.tpl rename to ee/deployments/helm/taskqueue/templates/_helpers.tpl diff --git a/deployments/helm/taskqueue/templates/deployment.yaml b/ee/deployments/helm/taskqueue/templates/deployment.yaml similarity index 100% rename from deployments/helm/taskqueue/templates/deployment.yaml rename to ee/deployments/helm/taskqueue/templates/deployment.yaml diff --git a/deployments/helm/taskqueue/values.yaml b/ee/deployments/helm/taskqueue/values.yaml similarity index 100% rename from deployments/helm/taskqueue/values.yaml rename to ee/deployments/helm/taskqueue/values.yaml diff --git a/deployments/helm/web/Chart.yaml b/ee/deployments/helm/web/Chart.yaml similarity index 100% rename from deployments/helm/web/Chart.yaml rename to ee/deployments/helm/web/Chart.yaml diff --git a/deployments/helm/web/templates/_helpers.tpl b/ee/deployments/helm/web/templates/_helpers.tpl similarity index 100% rename from deployments/helm/web/templates/_helpers.tpl rename to ee/deployments/helm/web/templates/_helpers.tpl diff --git a/deployments/helm/web/templates/deployment.yaml b/ee/deployments/helm/web/templates/deployment.yaml similarity index 100% rename from deployments/helm/web/templates/deployment.yaml rename to ee/deployments/helm/web/templates/deployment.yaml diff --git a/deployments/helm/web/templates/ingress.yaml b/ee/deployments/helm/web/templates/ingress.yaml similarity index 100% rename from deployments/helm/web/templates/ingress.yaml rename to ee/deployments/helm/web/templates/ingress.yaml diff --git a/deployments/helm/web/templates/service.yaml b/ee/deployments/helm/web/templates/service.yaml similarity index 100% rename from deployments/helm/web/templates/service.yaml rename to ee/deployments/helm/web/templates/service.yaml diff --git a/deployments/helm/web/values.yaml b/ee/deployments/helm/web/values.yaml similarity index 100% rename from deployments/helm/web/values.yaml rename to ee/deployments/helm/web/values.yaml diff --git a/deployments/kube/README.md b/ee/deployments/kube/README.md similarity index 100% rename from deployments/kube/README.md rename to ee/deployments/kube/README.md diff --git a/deployments/kube/cert-manager/cluster-issuer-prod.yaml b/ee/deployments/kube/cert-manager/cluster-issuer-prod.yaml similarity index 100% rename from deployments/kube/cert-manager/cluster-issuer-prod.yaml rename to ee/deployments/kube/cert-manager/cluster-issuer-prod.yaml diff --git a/deployments/kube/cert-manager/cluster-issuer-staging.yaml b/ee/deployments/kube/cert-manager/cluster-issuer-staging.yaml similarity index 100% rename from deployments/kube/cert-manager/cluster-issuer-staging.yaml rename to ee/deployments/kube/cert-manager/cluster-issuer-staging.yaml diff --git a/deployments/kube/jupyterhub/Dockerfile b/ee/deployments/kube/jupyterhub/Dockerfile similarity index 100% rename from deployments/kube/jupyterhub/Dockerfile rename to ee/deployments/kube/jupyterhub/Dockerfile diff --git a/deployments/kube/jupyterhub/deploy.sh b/ee/deployments/kube/jupyterhub/deploy.sh similarity index 100% rename from deployments/kube/jupyterhub/deploy.sh rename to ee/deployments/kube/jupyterhub/deploy.sh diff --git a/deployments/kube/jupyterhub/helm/config.yaml b/ee/deployments/kube/jupyterhub/helm/config.yaml similarity index 100% rename from deployments/kube/jupyterhub/helm/config.yaml rename to ee/deployments/kube/jupyterhub/helm/config.yaml diff --git a/deployments/kube/jupyterhub/jupyter/Dockerfile b/ee/deployments/kube/jupyterhub/jupyter/Dockerfile similarity index 100% rename from deployments/kube/jupyterhub/jupyter/Dockerfile rename to ee/deployments/kube/jupyterhub/jupyter/Dockerfile diff --git a/deployments/kube/jupyterhub/jupyter/jupyter_notebook_config.py b/ee/deployments/kube/jupyterhub/jupyter/jupyter_notebook_config.py similarity index 100% rename from deployments/kube/jupyterhub/jupyter/jupyter_notebook_config.py rename to ee/deployments/kube/jupyterhub/jupyter/jupyter_notebook_config.py diff --git a/deployments/kube/test/test-resources.yaml b/ee/deployments/kube/test/test-resources.yaml similarity index 100% rename from deployments/kube/test/test-resources.yaml rename to ee/deployments/kube/test/test-resources.yaml diff --git a/deployments/metabase/README.md b/ee/deployments/metabase/README.md similarity index 100% rename from deployments/metabase/README.md rename to ee/deployments/metabase/README.md diff --git a/deployments/metabase/values.yaml b/ee/deployments/metabase/values.yaml similarity index 100% rename from deployments/metabase/values.yaml rename to ee/deployments/metabase/values.yaml diff --git a/control/payments/driver/anarchism/anarchism.go b/ee/infrastructure/payments/driver/anarchism/anarchism.go similarity index 92% rename from control/payments/driver/anarchism/anarchism.go rename to ee/infrastructure/payments/driver/anarchism/anarchism.go index 60d6b042..8536833b 100644 --- a/control/payments/driver/anarchism/anarchism.go +++ b/ee/infrastructure/payments/driver/anarchism/anarchism.go @@ -1,7 +1,7 @@ package anarchism import ( - "gitlab.com/beneath-hq/beneath/control/payments/driver" + "gitlab.com/beneath-hq/beneath/ee/infrastructure/payments/driver" "gitlab.com/beneath-hq/beneath/pkg/httputil" "gitlab.com/beneath-hq/beneath/pkg/log" ) diff --git a/control/payments/driver/driver.go b/ee/infrastructure/payments/driver/driver.go similarity index 100% rename from control/payments/driver/driver.go rename to ee/infrastructure/payments/driver/driver.go diff --git a/control/payments/driver/stripecard/stripecard.go b/ee/infrastructure/payments/driver/stripecard/stripecard.go similarity index 98% rename from control/payments/driver/stripecard/stripecard.go rename to ee/infrastructure/payments/driver/stripecard/stripecard.go index b857d328..a5c4b171 100644 --- a/control/payments/driver/stripecard/stripecard.go +++ b/ee/infrastructure/payments/driver/stripecard/stripecard.go @@ -9,9 +9,9 @@ import ( uuid "github.com/satori/go.uuid" stripe "github.com/stripe/stripe-go" "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/control/payments/driver" + "gitlab.com/beneath-hq/beneath/ee/infrastructure/payments/driver" "gitlab.com/beneath-hq/beneath/control/payments/driver/stripeutil" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/services/middleware" "gitlab.com/beneath-hq/beneath/pkg/envutil" "gitlab.com/beneath-hq/beneath/pkg/httputil" "gitlab.com/beneath-hq/beneath/pkg/jsonutil" diff --git a/control/payments/driver/stripeutil/stripeutil.go b/ee/infrastructure/payments/driver/stripeutil/stripeutil.go similarity index 99% rename from control/payments/driver/stripeutil/stripeutil.go rename to ee/infrastructure/payments/driver/stripeutil/stripeutil.go index 10624b5a..4b585773 100644 --- a/control/payments/driver/stripeutil/stripeutil.go +++ b/ee/infrastructure/payments/driver/stripeutil/stripeutil.go @@ -12,7 +12,7 @@ import ( "github.com/stripe/stripe-go/setupintent" "github.com/stripe/stripe-go/taxrate" "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/control/payments/driver" + "gitlab.com/beneath-hq/beneath/ee/infrastructure/payments/driver" "gitlab.com/beneath-hq/beneath/pkg/log" "gitlab.com/beneath-hq/beneath/pkg/paymentsutil" ) diff --git a/control/payments/driver/stripewire/stripewire.go b/ee/infrastructure/payments/driver/stripewire/stripewire.go similarity index 96% rename from control/payments/driver/stripewire/stripewire.go rename to ee/infrastructure/payments/driver/stripewire/stripewire.go index 8d0549bb..af860f4e 100644 --- a/control/payments/driver/stripewire/stripewire.go +++ b/ee/infrastructure/payments/driver/stripewire/stripewire.go @@ -7,12 +7,12 @@ import ( uuid "github.com/satori/go.uuid" stripe "github.com/stripe/stripe-go" "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/control/payments/driver" "gitlab.com/beneath-hq/beneath/control/payments/driver/stripeutil" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/ee/infrastructure/payments/driver" "gitlab.com/beneath-hq/beneath/pkg/envutil" "gitlab.com/beneath-hq/beneath/pkg/httputil" "gitlab.com/beneath-hq/beneath/pkg/log" + "gitlab.com/beneath-hq/beneath/services/middleware" ) // StripeWire implements beneath.PaymentsDriver diff --git a/control/payments/payments.go b/ee/infrastructure/payments/payments.go similarity index 64% rename from control/payments/payments.go rename to ee/infrastructure/payments/payments.go index 0f149173..f7396c22 100644 --- a/control/payments/payments.go +++ b/ee/infrastructure/payments/payments.go @@ -1,10 +1,10 @@ package payments import ( - "gitlab.com/beneath-hq/beneath/control/payments/driver" - "gitlab.com/beneath-hq/beneath/control/payments/driver/anarchism" - "gitlab.com/beneath-hq/beneath/control/payments/driver/stripecard" - "gitlab.com/beneath-hq/beneath/control/payments/driver/stripewire" + "gitlab.com/beneath-hq/beneath/ee/infrastructure/payments/driver" + "gitlab.com/beneath-hq/beneath/ee/infrastructure/payments/driver/anarchism" + "gitlab.com/beneath-hq/beneath/ee/infrastructure/payments/driver/stripecard" + "gitlab.com/beneath-hq/beneath/ee/infrastructure/payments/driver/stripewire" ) // InitDrivers initializes all of the payments drivers diff --git a/pkg/paymentsutil/paymentsutil.go b/ee/pkg/paymentsutil/paymentsutil.go similarity index 100% rename from pkg/paymentsutil/paymentsutil.go rename to ee/pkg/paymentsutil/paymentsutil.go diff --git a/ee/server/control/gql/gqlgen.yml b/ee/server/control/gql/gqlgen.yml new file mode 100644 index 00000000..afff9f51 --- /dev/null +++ b/ee/server/control/gql/gqlgen.yml @@ -0,0 +1,25 @@ +# Configures gqlgen – docs at https://gqlgen.com/config/ +schema: +- "ee/server/control/schema/**/*.graphql" +exec: + filename: ee/server/control/gql/schema_gen.go + package: gql +model: + filename: ee/server/control/gql/models_gen.go + package: gql +resolver: + filename: ee/server/control/resolver/generated.go + package: resolver + type: Resolver +autobind: [] +models: + BillingPlan: + model: gitlab.com/beneath-hq/beneath/ee/models.BillingPlan + BilledResource: + model: gitlab.com/beneath-hq/beneath/ee/models.BilledResource + BillingMethod: + model: gitlab.com/beneath-hq/beneath/ee/models.BillingMethod + BillingInfo: + model: gitlab.com/beneath-hq/beneath/ee/models.BillingInfo + PaymentMethod: + model: gitlab.com/beneath-hq/beneath/ee/models.PaymentMethod diff --git a/control/resolver/billed_resource.go b/ee/server/control/resolver/billed_resource.go similarity index 89% rename from control/resolver/billed_resource.go rename to ee/server/control/resolver/billed_resource.go index cdd4741e..548692b2 100644 --- a/control/resolver/billed_resource.go +++ b/ee/server/control/resolver/billed_resource.go @@ -5,10 +5,10 @@ import ( "time" uuid "github.com/satori/go.uuid" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/gqlerror" "gitlab.com/beneath-hq/beneath/control/entity" "gitlab.com/beneath-hq/beneath/control/gql" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/services/middleware" ) // BilledResource returns the gql.BilledResourceResolver @@ -36,7 +36,7 @@ func (r *billedResourceResolver) Currency(ctx context.Context, obj *entity.Bille func (r *queryResolver) BilledResources(ctx context.Context, organizationID uuid.UUID, billingTime time.Time) ([]*entity.BilledResource, error) { secret := middleware.GetSecret(ctx) - perms := secret.OrganizationPermissions(ctx, organizationID) + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, organizationID) if !perms.Admin { return nil, gqlerror.Errorf("Not allowed to perform admin functions on organization %s", organizationID.String()) } diff --git a/control/resolver/billing_info.go b/ee/server/control/resolver/billing_info.go similarity index 90% rename from control/resolver/billing_info.go rename to ee/server/control/resolver/billing_info.go index 6b63a01c..47f02638 100644 --- a/control/resolver/billing_info.go +++ b/ee/server/control/resolver/billing_info.go @@ -4,17 +4,17 @@ import ( "context" uuid "github.com/satori/go.uuid" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/gqlerror" "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/services/middleware" "gitlab.com/beneath-hq/beneath/pkg/paymentsutil" ) func (r *queryResolver) BillingInfo(ctx context.Context, organizationID uuid.UUID) (*entity.BillingInfo, error) { secret := middleware.GetSecret(ctx) - perms := secret.OrganizationPermissions(ctx, organizationID) + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, organizationID) if !perms.Admin { return nil, gqlerror.Errorf("Not allowed to perform admin functions in organization %s", organizationID.String()) } @@ -30,7 +30,7 @@ func (r *queryResolver) BillingInfo(ctx context.Context, organizationID uuid.UUI func (r *mutationResolver) UpdateBillingInfo(ctx context.Context, organizationID uuid.UUID, billingMethodID *uuid.UUID, billingPlanID uuid.UUID, country string, region *string, companyName *string, taxNumber *string) (*entity.BillingInfo, error) { secret := middleware.GetSecret(ctx) - perms := secret.OrganizationPermissions(ctx, organizationID) + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, organizationID) if !perms.Admin { return nil, gqlerror.Errorf("Not allowed to perform admin functions on organization %s", organizationID.String()) } diff --git a/control/resolver/billing_method.go b/ee/server/control/resolver/billing_method.go similarity index 86% rename from control/resolver/billing_method.go rename to ee/server/control/resolver/billing_method.go index d52e3f19..3632cbed 100644 --- a/control/resolver/billing_method.go +++ b/ee/server/control/resolver/billing_method.go @@ -4,8 +4,8 @@ import ( "context" uuid "github.com/satori/go.uuid" - "github.com/vektah/gqlparser/gqlerror" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "github.com/vektah/gqlparser/v2/gqlerror" + "gitlab.com/beneath-hq/beneath/services/middleware" "gitlab.com/beneath-hq/beneath/pkg/jsonutil" "gitlab.com/beneath-hq/beneath/control/entity" @@ -31,7 +31,7 @@ func (r *billingMethodResolver) DriverPayload(ctx context.Context, obj *entity.B func (r *queryResolver) BillingMethods(ctx context.Context, organizationID uuid.UUID) ([]*entity.BillingMethod, error) { secret := middleware.GetSecret(ctx) - perms := secret.OrganizationPermissions(ctx, organizationID) + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, organizationID) if !perms.Admin { return nil, gqlerror.Errorf("Not allowed to perform admin functions on organization %s", organizationID.String()) } diff --git a/control/resolver/billing_plan.go b/ee/server/control/resolver/billing_plan.go similarity index 95% rename from control/resolver/billing_plan.go rename to ee/server/control/resolver/billing_plan.go index 49be5daa..55892f3b 100644 --- a/control/resolver/billing_plan.go +++ b/ee/server/control/resolver/billing_plan.go @@ -3,7 +3,7 @@ package resolver import ( "context" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/gqlerror" "gitlab.com/beneath-hq/beneath/control/entity" "gitlab.com/beneath-hq/beneath/control/gql" ) diff --git a/ee/server/control/schema/base.graphql b/ee/server/control/schema/base.graphql new file mode 100644 index 00000000..a7d2dc65 --- /dev/null +++ b/ee/server/control/schema/base.graphql @@ -0,0 +1,10 @@ +scalar Time +scalar UUID + +type Query { + empty: String +} + +type Mutation { + empty: String +} diff --git a/control/gql/schema/billed_resources.graphql b/ee/server/control/schema/billed_resources.graphql similarity index 100% rename from control/gql/schema/billed_resources.graphql rename to ee/server/control/schema/billed_resources.graphql diff --git a/control/gql/schema/billing_info.graphql b/ee/server/control/schema/billing_info.graphql similarity index 100% rename from control/gql/schema/billing_info.graphql rename to ee/server/control/schema/billing_info.graphql diff --git a/control/gql/schema/billing_method.graphql b/ee/server/control/schema/billing_method.graphql similarity index 100% rename from control/gql/schema/billing_method.graphql rename to ee/server/control/schema/billing_method.graphql diff --git a/control/gql/schema/billing_plans.graphql b/ee/server/control/schema/billing_plans.graphql similarity index 100% rename from control/gql/schema/billing_plans.graphql rename to ee/server/control/schema/billing_plans.graphql diff --git a/ee/server/control/server.go b/ee/server/control/server.go new file mode 100644 index 00000000..25bc2edc --- /dev/null +++ b/ee/server/control/server.go @@ -0,0 +1,9 @@ +package control + +// // Add payments handlers +// for name, driver := range hub.PaymentDrivers { +// for subpath, handler := range driver.GetHTTPHandlers() { +// path := fmt.Sprintf("/billing/%s/%s", name, subpath) +// router.Handle(path, httputil.AppHandler(handler)) +// } +// } diff --git a/ee/services/bi/bi.go b/ee/services/bi/bi.go new file mode 100644 index 00000000..3958cda8 --- /dev/null +++ b/ee/services/bi/bi.go @@ -0,0 +1,37 @@ +package bi + +import ( + "context" + + "gitlab.com/beneath-hq/beneath/bus" + "gitlab.com/beneath-hq/beneath/infrastructure/db" + "gitlab.com/beneath-hq/beneath/models" +) + +// Service wraps business intelligence-related functionality +type Service struct { + Bus *bus.Bus + DB db.DB +} + +// New creates a new user service +func New(bus *bus.Bus, db db.DB) *Service { + s := &Service{ + Bus: bus, + DB: db, + } + bus.AddSyncListener(s.UserCreated) + return s +} + +// UserCreated handles models.UserCreatedEvent events +func (s *Service) UserCreated(ctx context.Context, msg *models.UserCreatedEvent) error { + err := s.Bus.PublishControlEvent(ctx, "user_create", map[string]interface{}{ + "organization_id": msg.User.BillingOrganizationID, + "user_id": msg.User.UserID, + }) + if err != nil { + return err + } + return nil +} diff --git a/ee/services/billing/billing.go b/ee/services/billing/billing.go new file mode 100644 index 00000000..96ce6b4e --- /dev/null +++ b/ee/services/billing/billing.go @@ -0,0 +1,117 @@ +package billing + +import ( + "context" + "fmt" + "time" + + "gitlab.com/beneath-hq/beneath/control/entity" + "gitlab.com/beneath-hq/beneath/hub" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/pkg/timeutil" +) + +// ADD TO WillCreateProjectEvent +// // check billing info if project is private +// if public != nil && !*public { +// bi := models.FindBillingInfo(ctx, organization.OrganizationID) +// if bi == nil { +// return nil, gqlerror.Errorf("Could not find billing info for organization %s", organizationName) +// } + +// if !bi.BillingPlan.PrivateProjects { +// return nil, gqlerror.Errorf("Your organization's billing plan does not permit private projects") +// } +// } + +type Service struct{} + +func (s *Service) AddBilling(ctx context.Context, msg *models.OrganizationCreatedEvent) error { + + defaultBillingPlan := entity.FindDefaultBillingPlan(ctx) + + // set the organization's default quotas + org.PrepaidReadQuota = &defaultBillingPlan.ReadQuota + org.PrepaidWriteQuota = &defaultBillingPlan.WriteQuota + org.PrepaidScanQuota = &defaultBillingPlan.ScanQuota + org.ReadQuota = &defaultBillingPlan.ReadQuota + org.WriteQuota = &defaultBillingPlan.WriteQuota + org.ScanQuota = &defaultBillingPlan.ScanQuota + + // create billing info + bi := &BillingInfo{ + OrganizationID: org.OrganizationID, + BillingPlanID: defaultBillingPlan.BillingPlanID, + } + _, err = tx.Model(bi).Insert() + if err != nil { + return err + } +} + +func (s *Service) UpdatexXX(ctx context.Context, msg *models.OrganizationTransferredUserEvent) error { + + // TODO (and what about deducting from fromOrg??? ) + + // find target billing info + targetBillingInfo := FindBillingInfo(ctx, targetOrg.OrganizationID) + if targetBillingInfo == nil { + return fmt.Errorf("Couldn't find billing info for target organization") + } + + // add prorated seat to the target organization's next month's bill + billingTime := timeutil.Next(time.Now(), targetBillingInfo.BillingPlan.Period) + err = commitProratedSeatsToBill(ctx, targetBillingInfo, billingTime, []*User{user}) + if err != nil { + panic("unable to commit prorated seat to bill") + } + + // increment the target organization's prepaid quota by the seat quota + // we do this now because we want to show the new usage capacity in the UI as soon as possible + if targetBillingInfo.BillingPlan.SeatReadQuota > 0 || targetBillingInfo.BillingPlan.SeatWriteQuota > 0 || targetBillingInfo.BillingPlan.SeatScanQuota > 0 { + newPrepaidReadQuota := *targetOrg.PrepaidReadQuota + targetBillingInfo.BillingPlan.SeatReadQuota + newPrepaidWriteQuota := *targetOrg.PrepaidWriteQuota + targetBillingInfo.BillingPlan.SeatWriteQuota + newPrepaidScanQuota := *targetOrg.PrepaidScanQuota + targetBillingInfo.BillingPlan.SeatScanQuota + + targetOrg.PrepaidReadQuota = &newPrepaidReadQuota + targetOrg.PrepaidWriteQuota = &newPrepaidWriteQuota + targetOrg.PrepaidScanQuota = &newPrepaidScanQuota + + targetOrg.UpdatedOn = time.Now() + + _, err = hub.DB.WithContext(ctx).Model(targetOrg). + Column("prepaid_read_quota", "prepaid_write_quota", "prepaid_scan_quota", "updated_on"). + WherePK(). + Update() + if err != nil { + return err + } + } + + return nil + +} + +func (s *Service) UpdatePrepaidQuotas(ctx context.Context, o *models.Organization, bp *models.BillingPlan) error { + numSeats := int64(len(o.Users)) + prepaidReadQuota := billingPlan.BaseReadQuota + billingPlan.SeatReadQuota*numSeats + prepaidWriteQuota := billingPlan.BaseWriteQuota + billingPlan.SeatWriteQuota*numSeats + prepaidScanQuota := billingPlan.BaseScanQuota + billingPlan.SeatScanQuota*numSeats + + // set fields + o.PrepaidReadQuota = &prepaidReadQuota + o.PrepaidWriteQuota = &prepaidWriteQuota + o.PrepaidScanQuota = &prepaidScanQuota + o.UpdatedOn = time.Now() + + // update + _, err := hub.DB.WithContext(ctx).Model(o). + Column("prepaid_read_quota", "prepaid_write_quota", "prepaid_scan_quota", "updated_on"). + WherePK(). + Update() + if err != nil { + return err + } + + return err +} diff --git a/control/entity/base.go b/ee/services/entity/base.go similarity index 100% rename from control/entity/base.go rename to ee/services/entity/base.go diff --git a/control/entity/billed_resources.go b/ee/services/entity/billed_resources.go similarity index 100% rename from control/entity/billed_resources.go rename to ee/services/entity/billed_resources.go diff --git a/control/entity/billing_info.go b/ee/services/entity/billing_info.go similarity index 97% rename from control/entity/billing_info.go rename to ee/services/entity/billing_info.go index c24edc98..456e8536 100644 --- a/control/entity/billing_info.go +++ b/ee/services/entity/billing_info.go @@ -4,7 +4,6 @@ import ( "context" "time" - "gitlab.com/beneath-hq/beneath/control/taskqueue" "gitlab.com/beneath-hq/beneath/hub" "gitlab.com/beneath-hq/beneath/pkg/log" "gitlab.com/beneath-hq/beneath/pkg/timeutil" @@ -86,7 +85,7 @@ func (bi *BillingInfo) Update(ctx context.Context, billingMethodID *uuid.UUID, b if err != nil { panic("could not commit overage to bill") } - err = taskqueue.Submit(ctx, &SendInvoiceTask{ + err = hub.Bus.Publish(ctx, &SendInvoiceTask{ BillingInfo: bi, BillingTime: billingTime, }) @@ -137,7 +136,7 @@ func (bi *BillingInfo) Update(ctx context.Context, billingMethodID *uuid.UUID, b // upgrading from Free plan if prevBillingPlan.Default { // trigger bill for prorated items - err = taskqueue.Submit(ctx, &SendInvoiceTask{ + err = hub.Bus.Publish(ctx, &SendInvoiceTask{ BillingInfo: bi, BillingTime: billingTime, }) diff --git a/control/entity/billing_method.go b/ee/services/entity/billing_method.go similarity index 100% rename from control/entity/billing_method.go rename to ee/services/entity/billing_method.go diff --git a/control/entity/billing_plan.go b/ee/services/entity/billing_plan.go similarity index 100% rename from control/entity/billing_plan.go rename to ee/services/entity/billing_plan.go diff --git a/control/entity/billing_task_a_run.go b/ee/services/entity/billing_task_a_run.go similarity index 81% rename from control/entity/billing_task_a_run.go rename to ee/services/entity/billing_task_a_run.go index 414bf535..56f7b79b 100644 --- a/control/entity/billing_task_a_run.go +++ b/ee/services/entity/billing_task_a_run.go @@ -4,7 +4,7 @@ import ( "context" "time" - "gitlab.com/beneath-hq/beneath/control/taskqueue" + "gitlab.com/beneath-hq/beneath/hub" "gitlab.com/beneath-hq/beneath/pkg/log" ) @@ -12,11 +12,6 @@ import ( type RunBillingTask struct { } -// register task -func init() { - taskqueue.RegisterTask(&RunBillingTask{}) -} - // Run triggers the task // it is expected that the task is run at the beginning of each month // organizations will be assessed usage and corresponding overage fees for the previous month @@ -27,7 +22,7 @@ func (t *RunBillingTask) Run(ctx context.Context) error { timestamp = timestamp.AddDate(0, 1, 0) // FOR TESTING: simulate that we are in the next month for _, bi := range billingInfos { - err := taskqueue.Submit(context.Background(), &ComputeBillResourcesTask{ + err := hub.Bus.Publish(ctx, &ComputeBillResourcesTask{ BillingInfo: bi, Timestamp: timestamp, }) diff --git a/control/entity/billing_task_b_compute_bill_resources.go b/ee/services/entity/billing_task_b_compute_bill_resources.go similarity index 96% rename from control/entity/billing_task_b_compute_bill_resources.go rename to ee/services/entity/billing_task_b_compute_bill_resources.go index bdd13617..697d2dd5 100644 --- a/control/entity/billing_task_b_compute_bill_resources.go +++ b/ee/services/entity/billing_task_b_compute_bill_resources.go @@ -5,9 +5,7 @@ import ( "math" "time" - "gitlab.com/beneath-hq/beneath/control/taskqueue" "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/internal/metrics" "gitlab.com/beneath-hq/beneath/pkg/log" "gitlab.com/beneath-hq/beneath/pkg/timeutil" ) @@ -18,11 +16,6 @@ type ComputeBillResourcesTask struct { Timestamp time.Time } -// register task -func init() { - taskqueue.RegisterTask(&ComputeBillResourcesTask{}) -} - // Run triggers the task func (t *ComputeBillResourcesTask) Run(ctx context.Context) error { // if applicable, add "prepaid usage" line item @@ -50,7 +43,7 @@ func (t *ComputeBillResourcesTask) Run(ctx context.Context) error { return err } - err = taskqueue.Submit(context.Background(), &SendInvoiceTask{ + err = hub.Bus.Publish(ctx, &SendInvoiceTask{ BillingInfo: t.BillingInfo, BillingTime: timeutil.Floor(t.Timestamp, t.BillingInfo.BillingPlan.Period), }) @@ -132,7 +125,7 @@ func commitOverageToBill(ctx context.Context, bi *BillingInfo, ts time.Time) err startTime := timeutil.Last(ts, bi.BillingPlan.Period) endTime := timeutil.Floor(ts, bi.BillingPlan.Period) - _, usages, err := metrics.GetHistoricalUsage(ctx, bi.OrganizationID, bi.BillingPlan.Period, startTime, endTime) + _, usages, err := hub.Metrics.GetHistoricalUsage(ctx, bi.OrganizationID, bi.BillingPlan.Period, startTime, endTime) if err != nil { panic("unable to get historical usage for organization") } diff --git a/control/entity/billing_task_c_send_invoice.go b/ee/services/entity/billing_task_c_send_invoice.go similarity index 89% rename from control/entity/billing_task_c_send_invoice.go rename to ee/services/entity/billing_task_c_send_invoice.go index 4d647d82..bab489a3 100644 --- a/control/entity/billing_task_c_send_invoice.go +++ b/ee/services/entity/billing_task_c_send_invoice.go @@ -4,8 +4,7 @@ import ( "context" "time" - "gitlab.com/beneath-hq/beneath/control/payments/driver" - "gitlab.com/beneath-hq/beneath/control/taskqueue" + "gitlab.com/beneath-hq/beneath/ee/infrastructure/payments/driver" "gitlab.com/beneath-hq/beneath/hub" "gitlab.com/beneath-hq/beneath/pkg/log" ) @@ -16,11 +15,6 @@ type SendInvoiceTask struct { BillingTime time.Time } -// register task -func init() { - taskqueue.RegisterTask(&SendInvoiceTask{}) -} - // Run triggers the task func (t *SendInvoiceTask) Run(ctx context.Context) error { billedResources := FindBilledResources(ctx, t.BillingInfo.OrganizationID, t.BillingTime) diff --git a/control/entity/util.go b/ee/services/entity/util.go similarity index 100% rename from control/entity/util.go rename to ee/services/entity/util.go diff --git a/control/entity/validate.go b/ee/services/entity/validate.go similarity index 100% rename from control/entity/validate.go rename to ee/services/entity/validate.go diff --git a/engine/control_events.go b/engine/control_events.go deleted file mode 100644 index 5adc9643..00000000 --- a/engine/control_events.go +++ /dev/null @@ -1,54 +0,0 @@ -package engine - -import ( - "context" - "encoding/json" - "fmt" - "time" - - uuid "github.com/satori/go.uuid" -) - -const ( - controlEventsTopic = "control-events" - controlEventsSubscription = "control-events-worker" -) - -// ControlEvent describes a control-plane event -type ControlEvent struct { - ID uuid.UUID `json:"id"` - Name string `json:"name"` - Timestamp time.Time `json:"timestamp"` - Data map[string]interface{} `json:"data"` -} - -// PublishControlEvent publishes a control-plane event to controlEventsTopic -// for external consumption (e.g. for BI purposes) -func (e *Engine) PublishControlEvent(ctx context.Context, name string, data map[string]interface{}) error { - msg := ControlEvent{ - ID: uuid.NewV4(), - Name: name, - Timestamp: time.Now(), - Data: data, - } - json, err := json.Marshal(msg) - if err != nil { - return err - } - if len(json) > e.MQ.MaxMessageSize() { - return fmt.Errorf("control event message %v has invalid size", json) - } - return e.MQ.Publish(ctx, controlEventsTopic, json) -} - -// SubscribeControlEvents subscribes to all control events -func (e *Engine) SubscribeControlEvents(ctx context.Context, fn func(context.Context, *ControlEvent) error) error { - return e.MQ.Subscribe(ctx, controlEventsTopic, controlEventsSubscription, true, func(ctx context.Context, msg []byte) error { - t := &ControlEvent{} - err := json.Unmarshal(msg, t) - if err != nil { - return err - } - return fn(ctx, t) - }) -} diff --git a/engine/driver/bigquery/bigquery.go b/engine/driver/bigquery/bigquery.go deleted file mode 100644 index 426ca6a7..00000000 --- a/engine/driver/bigquery/bigquery.go +++ /dev/null @@ -1,65 +0,0 @@ -package bigquery - -import ( - "context" - "sync" - - bq "cloud.google.com/go/bigquery" - - "gitlab.com/beneath-hq/beneath/engine/driver" - "gitlab.com/beneath-hq/beneath/pkg/envutil" -) - -// configSpecification defines the config variables to load from ENV -type configSpecification struct { - ProjectID string `envconfig:"PROJECT_ID" required:"true"` - InstancesDatasetID string `envconfig:"INSTANCES_DATASET_ID" required:"true"` -} - -// BigQuery implements beneath.WarehouseService -type BigQuery struct { - ProjectID string - Client *bq.Client - InstancesDataset *bq.Dataset -} - -const ( - // OriginalStreamPathLabel is a label that gives the original path of the instance - OriginalStreamPathLabel = "original_stream_path" -) - -// Global -var global BigQuery -var once sync.Once - -func createGlobal() { - // parse config from env - var config configSpecification - envutil.LoadConfig("beneath_engine_bigquery", &config) - - // create client - client, err := bq.NewClient(context.Background(), config.ProjectID) - if err != nil { - panic(err) - } - - // create instances dataset if it doesn't exist - instancesDataset := client.Dataset(config.InstancesDatasetID) - err = instancesDataset.Create(context.Background(), nil) - if err != nil && !isAlreadyExists(err) { - panic(err) - } - - // create instance - global = BigQuery{ - ProjectID: config.ProjectID, - Client: client, - InstancesDataset: instancesDataset, - } -} - -// GetWarehouseService todo -func GetWarehouseService() driver.WarehouseService { - once.Do(createGlobal) - return global -} diff --git a/engine/driver/mock/mock.go b/engine/driver/mock/mock.go deleted file mode 100644 index f2c55c5d..00000000 --- a/engine/driver/mock/mock.go +++ /dev/null @@ -1,13 +0,0 @@ -package mock - -import ( - "gitlab.com/beneath-hq/beneath/engine/driver" -) - -// Mock implements beneath.WarehouseService -type Mock struct{} - -// GetWarehouseService returns a Postgres implementation of beneath.LookupService -func GetWarehouseService() driver.WarehouseService { - return Mock{} -} diff --git a/engine/driver/mock/service.go b/engine/driver/mock/service.go deleted file mode 100644 index c8dd8cf4..00000000 --- a/engine/driver/mock/service.go +++ /dev/null @@ -1,52 +0,0 @@ -package mock - -import ( - "context" - - "gitlab.com/beneath-hq/beneath/engine/driver" -) - -// MaxKeySize implements beneath.Service -func (m Mock) MaxKeySize() int { - return 1024 // 1 kb -} - -// MaxRecordSize implements beneath.Service -func (m Mock) MaxRecordSize() int { - return 1048576 // 1 mb -} - -// MaxRecordsInBatch implements beneath.Service -func (m Mock) MaxRecordsInBatch() int { - return 10000 -} - -// RegisterProject implements beneath.Service -func (m Mock) RegisterProject(ctx context.Context, p driver.Project) error { - return nil -} - -// RemoveProject implements beneath.Service -func (m Mock) RemoveProject(ctx context.Context, p driver.Project) error { - return nil -} - -// RegisterInstance implements beneath.Service -func (m Mock) RegisterInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { - return nil -} - -// PromoteInstance implements beneath.Service -func (m Mock) PromoteInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { - return nil -} - -// RemoveInstance implements beneath.Service -func (m Mock) RemoveInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { - return nil -} - -// Reset implements beneath.Service -func (m Mock) Reset(ctx context.Context) error { - return nil -} diff --git a/engine/driver/postgres/postgres.go b/engine/driver/postgres/postgres.go deleted file mode 100644 index 14c1de79..00000000 --- a/engine/driver/postgres/postgres.go +++ /dev/null @@ -1,41 +0,0 @@ -package postgres - -import ( - "sync" - - "gitlab.com/beneath-hq/beneath/pkg/envutil" - "gitlab.com/beneath-hq/beneath/engine/driver" -) - -// configSpecification defines the config variables to load from ENV -type configSpecification struct { -} - -// Postgres implements beneath.LookupService and beneath.WarehouseService -type Postgres struct { -} - -// Global -var global Postgres -var once sync.Once - -func createGlobal() { - // parse config from env - var config configSpecification - envutil.LoadConfig("beneath_engine_postgres", &config) - - // create instance - global = Postgres{} -} - -// GetLookupService returns a Postgres implementation of beneath.LookupService -func GetLookupService() driver.LookupService { - once.Do(createGlobal) - return global -} - -// GetWarehouseService returns a Postgres implementation of beneath.LookupService -func GetWarehouseService() driver.WarehouseService { - once.Do(createGlobal) - return global -} diff --git a/engine/driver/postgres/service.go b/engine/driver/postgres/service.go deleted file mode 100644 index e72a62ef..00000000 --- a/engine/driver/postgres/service.go +++ /dev/null @@ -1,52 +0,0 @@ -package postgres - -import ( - "context" - - "gitlab.com/beneath-hq/beneath/engine/driver" -) - -// MaxKeySize implements beneath.Service -func (b Postgres) MaxKeySize() int { - panic("todo") -} - -// MaxRecordSize implements beneath.Service -func (b Postgres) MaxRecordSize() int { - panic("todo") -} - -// MaxRecordsInBatch implements beneath.Service -func (b Postgres) MaxRecordsInBatch() int { - panic("todo") -} - -// RegisterProject implements beneath.Service -func (b Postgres) RegisterProject(ctx context.Context, p driver.Project) error { - panic("todo") -} - -// RemoveProject implements beneath.Service -func (b Postgres) RemoveProject(ctx context.Context, p driver.Project) error { - panic("todo") -} - -// RegisterInstance implements beneath.Service -func (b Postgres) RegisterInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { - panic("todo") -} - -// PromoteInstance implements beneath.Service -func (b Postgres) PromoteInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { - panic("todo") -} - -// RemoveInstance implements beneath.Service -func (b Postgres) RemoveInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { - panic("todo") -} - -// Reset implements beneath.Service -func (b Postgres) Reset(ctx context.Context) error { - panic("todo") -} diff --git a/engine/driver/pubsub/pubsub.go b/engine/driver/pubsub/pubsub.go deleted file mode 100644 index efb8aecc..00000000 --- a/engine/driver/pubsub/pubsub.go +++ /dev/null @@ -1,64 +0,0 @@ -package pubsub - -import ( - "context" - "os" - "sync" - - "cloud.google.com/go/pubsub" - - "gitlab.com/beneath-hq/beneath/engine/driver" - "gitlab.com/beneath-hq/beneath/pkg/envutil" -) - -// configSpecification defines the config variables to load from ENV -// See https://github.com/kelseyhightower/envconfig -type configSpecification struct { - ProjectID string `envconfig:"PROJECT_ID" required:"true"` - SubscriberID string `envconfig:"SUBSCRIBER_ID" required:"true"` - EmulatorHost string `envconfig:"EMULATOR_HOST" required:"false"` - TopicPrefix string `envconfig:"TOPIC_PREFIX" required:"false"` - SubscriptionPrefix string `envconfig:"SUBSCRIPTION_PREFIX" required:"false"` -} - -// PubSub implements beneath.MessageQueue -type PubSub struct { - config *configSpecification - Client *pubsub.Client - Topics map[string]*pubsub.Topic -} - -// Global -var global PubSub -var once sync.Once - -func createGlobal() { - // parse config from env - var config configSpecification - envutil.LoadConfig("beneath_engine_pubsub", &config) - - // if EMULATOR_HOST set, configure pubsub for the emulator - if config.EmulatorHost != "" { - os.Setenv("PUBSUB_PROJECT_ID", config.ProjectID) - os.Setenv("PUBSUB_EMULATOR_HOST", config.EmulatorHost) - } - - // prepare pubsub client - client, err := pubsub.NewClient(context.Background(), config.ProjectID) - if err != nil { - panic(err) - } - - // create instance - global = PubSub{ - config: &config, - Client: client, - Topics: make(map[string]*pubsub.Topic), - } -} - -// GetMessageQueue returns a Google PubSub implementation of beneath.MessageQueue -func GetMessageQueue() driver.MessageQueue { - once.Do(createGlobal) - return global -} diff --git a/engine/engine.go b/engine/engine.go deleted file mode 100644 index d52b83c0..00000000 --- a/engine/engine.go +++ /dev/null @@ -1,160 +0,0 @@ -package engine - -import ( - "context" - "fmt" - - "golang.org/x/sync/errgroup" - - "gitlab.com/beneath-hq/beneath/engine/driver" - "gitlab.com/beneath-hq/beneath/engine/driver/bigquery" - "gitlab.com/beneath-hq/beneath/engine/driver/bigtable" - "gitlab.com/beneath-hq/beneath/engine/driver/mock" - "gitlab.com/beneath-hq/beneath/engine/driver/postgres" - "gitlab.com/beneath-hq/beneath/engine/driver/pubsub" - "gitlab.com/beneath-hq/beneath/pkg/codec" - "gitlab.com/beneath-hq/beneath/pkg/mathutil" -) - -// Engine interfaces with the data layer -type Engine struct { - MQ driver.MessageQueue - Lookup driver.LookupService - Warehouse driver.WarehouseService - - maxBatchLength int - maxRecordSize int - maxKeySize int -} - -// NewEngine creates a new Engine instance -func NewEngine(mqDriver, lookupDriver, warehouseDriver string) *Engine { - e := &Engine{} - e.MQ = makeMQ(mqDriver) - e.Lookup = makeLookup(lookupDriver) - e.Warehouse = makeWarehouse(warehouseDriver) - - e.maxBatchLength = mathutil.MinInts(e.Lookup.MaxRecordsInBatch(), e.Warehouse.MaxRecordsInBatch()) - e.maxRecordSize = mathutil.MinInts(e.Lookup.MaxRecordSize(), e.Warehouse.MaxRecordSize()) - e.maxKeySize = mathutil.MinInts(e.Lookup.MaxKeySize(), e.Warehouse.MaxKeySize()) - - err := e.MQ.RegisterTopic(tasksTopic) - if err != nil { - panic(err) - } - err = e.MQ.RegisterTopic(writeRequestsTopic) - if err != nil { - panic(err) - } - err = e.MQ.RegisterTopic(writeReportsTopic) - if err != nil { - panic(err) - } - err = e.MQ.RegisterTopic(controlEventsTopic) - if err != nil { - panic(err) - } - - return e -} - -func makeMQ(driver string) driver.MessageQueue { - switch driver { - case "pubsub": - return pubsub.GetMessageQueue() - default: - panic(fmt.Errorf("invalid mq driver '%s'", driver)) - } -} - -func makeLookup(driver string) driver.LookupService { - switch driver { - case "bigtable": - return bigtable.GetLookupService() - case "postgres": - return postgres.GetLookupService() - default: - panic(fmt.Errorf("invalid lookup driver '%s'", driver)) - } -} - -func makeWarehouse(driver string) driver.WarehouseService { - switch driver { - case "bigquery": - return bigquery.GetWarehouseService() - case "postgres": - return postgres.GetWarehouseService() - case "mock": - return mock.GetWarehouseService() - default: - panic(fmt.Errorf("invalid warehouse driver '%s'", driver)) - } -} - -// Healthy returns true if connected to all services -func (e *Engine) Healthy() bool { - return true -} - -// CheckRecordSize validates that the record fits within the constraints of the underlying infrastructure -func (e *Engine) CheckRecordSize(s driver.Stream, structured map[string]interface{}, avroBytesLen int) error { - if avroBytesLen > e.maxRecordSize { - return fmt.Errorf("encoded record size exceeds maximum of %d bytes", e.maxRecordSize) - } - - codec := s.GetCodec() - - err := e.checkKeySize(codec, codec.PrimaryIndex, structured) - if err != nil { - return err - } - - for _, index := range codec.SecondaryIndexes { - err := e.checkKeySize(codec, index, structured) - if err != nil { - return err - } - } - - return nil -} - -func (e *Engine) checkKeySize(codec *codec.Codec, index codec.Index, structured map[string]interface{}) error { - key, err := codec.MarshalKey(index, structured) - if err != nil { - return err - } - - if len(key) > e.maxKeySize { - return fmt.Errorf("encoded key size for index on fields %v exceeds maximum length of %d bytes", index.GetFields(), e.maxKeySize) - } - - return nil -} - -// CheckBatchLength validates that the number of records in a batch fits within the constraints of the underlying infrastructure -func (e *Engine) CheckBatchLength(length int) error { - if length > e.maxBatchLength { - return fmt.Errorf("batch length exceeds maximum of %d", e.maxBatchLength) - } - return nil -} - -// Reset resets the state of the engine (useful during testing) -func (e *Engine) Reset(ctx context.Context) error { - group, ctx := errgroup.WithContext(ctx) - - group.Go(func() error { - return e.MQ.Reset(ctx) - }) - - group.Go(func() error { - return e.Lookup.Reset(ctx) - }) - - group.Go(func() error { - return e.Warehouse.Reset(ctx) - }) - - return group.Wait() -} diff --git a/engine/proto/taskqueue.pb.go b/engine/proto/taskqueue.pb.go deleted file mode 100644 index 1c4cdc1a..00000000 --- a/engine/proto/taskqueue.pb.go +++ /dev/null @@ -1,105 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: engine/proto/taskqueue.proto - -package proto - -import ( - fmt "fmt" - proto "github.com/golang/protobuf/proto" - math "math" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -type QueuedTask struct { - UniqueId string `protobuf:"bytes,1,opt,name=unique_id,json=uniqueId,proto3" json:"unique_id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Timestamp int64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *QueuedTask) Reset() { *m = QueuedTask{} } -func (m *QueuedTask) String() string { return proto.CompactTextString(m) } -func (*QueuedTask) ProtoMessage() {} -func (*QueuedTask) Descriptor() ([]byte, []int) { - return fileDescriptor_51d8e4fa168af5ca, []int{0} -} - -func (m *QueuedTask) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_QueuedTask.Unmarshal(m, b) -} -func (m *QueuedTask) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_QueuedTask.Marshal(b, m, deterministic) -} -func (m *QueuedTask) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueuedTask.Merge(m, src) -} -func (m *QueuedTask) XXX_Size() int { - return xxx_messageInfo_QueuedTask.Size(m) -} -func (m *QueuedTask) XXX_DiscardUnknown() { - xxx_messageInfo_QueuedTask.DiscardUnknown(m) -} - -var xxx_messageInfo_QueuedTask proto.InternalMessageInfo - -func (m *QueuedTask) GetUniqueId() string { - if m != nil { - return m.UniqueId - } - return "" -} - -func (m *QueuedTask) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -func (m *QueuedTask) GetTimestamp() int64 { - if m != nil { - return m.Timestamp - } - return 0 -} - -func (m *QueuedTask) GetData() []byte { - if m != nil { - return m.Data - } - return nil -} - -func init() { - proto.RegisterType((*QueuedTask)(nil), "engine.QueuedTask") -} - -func init() { proto.RegisterFile("engine/proto/taskqueue.proto", fileDescriptor_51d8e4fa168af5ca) } - -var fileDescriptor_51d8e4fa168af5ca = []byte{ - // 176 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x49, 0xcd, 0x4b, 0xcf, - 0xcc, 0x4b, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0xd7, 0x2f, 0x49, 0x2c, 0xce, 0x2e, 0x2c, 0x4d, - 0x2d, 0x4d, 0xd5, 0x03, 0xf3, 0x85, 0xd8, 0x20, 0xb2, 0x4a, 0xf9, 0x5c, 0x5c, 0x81, 0x20, 0xe1, - 0x94, 0x90, 0xc4, 0xe2, 0x6c, 0x21, 0x69, 0x2e, 0xce, 0xd2, 0xbc, 0xcc, 0xc2, 0xd2, 0xd4, 0xf8, - 0xcc, 0x14, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x0e, 0x88, 0x80, 0x67, 0x8a, 0x90, 0x10, - 0x17, 0x4b, 0x5e, 0x62, 0x6e, 0xaa, 0x04, 0x13, 0x58, 0x1c, 0xcc, 0x16, 0x92, 0xe1, 0xe2, 0x2c, - 0xc9, 0xcc, 0x4d, 0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0x90, 0x60, 0x56, 0x60, 0xd4, 0x60, 0x0e, 0x42, - 0x08, 0x80, 0x74, 0xa4, 0x24, 0x96, 0x24, 0x4a, 0xb0, 0x28, 0x30, 0x6a, 0xf0, 0x04, 0x81, 0xd9, - 0x4e, 0x3a, 0x51, 0x5a, 0xe9, 0x99, 0x25, 0x39, 0x89, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x49, - 0xa9, 0x79, 0xa9, 0x89, 0x25, 0x19, 0xba, 0x19, 0x85, 0x30, 0xa6, 0x3e, 0xb2, 0xb3, 0x93, 0xd8, - 0xc0, 0x94, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xcf, 0xe5, 0x83, 0xde, 0xcd, 0x00, 0x00, 0x00, -} diff --git a/engine/proto/taskqueue.proto b/engine/proto/taskqueue.proto deleted file mode 100644 index 9086e41b..00000000 --- a/engine/proto/taskqueue.proto +++ /dev/null @@ -1,10 +0,0 @@ -syntax = "proto3"; -option go_package = "gitlab.com/beneath-hq/beneath/engine/proto"; -package engine; - -message QueuedTask { - string unique_id = 1; - string name = 2; - int64 timestamp = 3; - bytes data = 4; -} diff --git a/engine/service.go b/engine/service.go deleted file mode 100644 index f34a203e..00000000 --- a/engine/service.go +++ /dev/null @@ -1,90 +0,0 @@ -package engine - -import ( - "context" - - "golang.org/x/sync/errgroup" - - "gitlab.com/beneath-hq/beneath/engine/driver" -) - -// RegisterProject is called when a project is created *or updated* -func (e *Engine) RegisterProject(ctx context.Context, p driver.Project) error { - group, ctx := errgroup.WithContext(ctx) - - group.Go(func() error { - return e.Lookup.RegisterProject(ctx, p) - }) - - group.Go(func() error { - return e.Warehouse.RegisterProject(ctx, p) - }) - - return group.Wait() -} - -// RemoveProject is called when a project is deleted -func (e *Engine) RemoveProject(ctx context.Context, p driver.Project) error { - group, ctx := errgroup.WithContext(ctx) - - group.Go(func() error { - return e.Lookup.RemoveProject(ctx, p) - }) - - group.Go(func() error { - return e.Warehouse.RemoveProject(ctx, p) - }) - - return group.Wait() -} - -// RegisterInstance is called when a new instance is created -func (e *Engine) RegisterInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { - group, ctx := errgroup.WithContext(ctx) - - group.Go(func() error { - return e.Lookup.RegisterInstance(ctx, p, s, i) - }) - - if s.GetUseWarehouse() { - group.Go(func() error { - return e.Warehouse.RegisterInstance(ctx, p, s, i) - }) - } - - return group.Wait() -} - -// PromoteInstance is called when an instance is promoted to be the main instance of the stream -func (e *Engine) PromoteInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { - group, ctx := errgroup.WithContext(ctx) - - group.Go(func() error { - return e.Lookup.PromoteInstance(ctx, p, s, i) - }) - - if s.GetUseWarehouse() { - group.Go(func() error { - return e.Warehouse.PromoteInstance(ctx, p, s, i) - }) - } - - return group.Wait() -} - -// RemoveInstance is called when an instance is deleted -func (e *Engine) RemoveInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { - group, ctx := errgroup.WithContext(ctx) - - group.Go(func() error { - return e.Lookup.RemoveInstance(ctx, p, s, i) - }) - - if s.GetUseWarehouse() { - group.Go(func() error { - return e.Warehouse.RemoveInstance(ctx, p, s, i) - }) - } - - return group.Wait() -} diff --git a/engine/tasks.go b/engine/tasks.go deleted file mode 100644 index 65d6c5f1..00000000 --- a/engine/tasks.go +++ /dev/null @@ -1,39 +0,0 @@ -package engine - -import ( - "context" - "fmt" - - "github.com/golang/protobuf/proto" - - pb "gitlab.com/beneath-hq/beneath/engine/proto" -) - -const ( - tasksTopic = "tasks" - tasksSubscription = "tasks-worker" -) - -// QueueTask queues a task for processing -func (e *Engine) QueueTask(ctx context.Context, t *pb.QueuedTask) error { - msg, err := proto.Marshal(t) - if err != nil { - panic(err) - } - if len(msg) > e.MQ.MaxMessageSize() { - return fmt.Errorf("task %v has invalid size", t) - } - return e.MQ.Publish(ctx, tasksTopic, msg) -} - -// ReadTasks reads queued tasks -func (e *Engine) ReadTasks(ctx context.Context, fn func(context.Context, *pb.QueuedTask) error) error { - return e.MQ.Subscribe(ctx, tasksTopic, tasksSubscription, true, func(ctx context.Context, msg []byte) error { - t := &pb.QueuedTask{} - err := proto.Unmarshal(msg, t) - if err != nil { - return err - } - return fn(ctx, t) - }) -} diff --git a/gateway/gateway.go b/gateway/gateway.go deleted file mode 100644 index e4fbebe4..00000000 --- a/gateway/gateway.go +++ /dev/null @@ -1,27 +0,0 @@ -package gateway - -import ( - "time" - - "gitlab.com/beneath-hq/beneath/engine" - "gitlab.com/beneath-hq/beneath/gateway/subscriptions" - "gitlab.com/beneath-hq/beneath/internal/metrics" -) - -var ( - // Metrics collects stats on records read from/written to Beneath - Metrics *metrics.Broker - - // Subscriptions handles real-time data subscriptions - Subscriptions *subscriptions.Broker -) - -// InitMetrics initializes the Metrics global -func InitMetrics(cacheSize int, commitInterval time.Duration) { - Metrics = metrics.NewBroker(cacheSize, commitInterval) -} - -// InitSubscriptions initializes the Subscriptionsglobal -func InitSubscriptions(eng *engine.Engine) { - Subscriptions = subscriptions.NewBroker(eng) -} diff --git a/gateway/grpc/subscription.go b/gateway/grpc/subscription.go deleted file mode 100644 index 6e8decee..00000000 --- a/gateway/grpc/subscription.go +++ /dev/null @@ -1,71 +0,0 @@ -package grpc - -import ( - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/gateway" - pb "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" - "gitlab.com/beneath-hq/beneath/gateway/subscriptions" - "gitlab.com/beneath-hq/beneath/gateway/util" - "gitlab.com/beneath-hq/beneath/internal/middleware" -) - -func (s *gRPCServer) Subscribe(req *pb.SubscribeRequest, ss pb.Gateway_SubscribeServer) error { - // get auth - secret := middleware.GetSecret(ss.Context()) - if secret == nil { - return grpc.Errorf(codes.PermissionDenied, "not authenticated") - } - - // parse cursor - cursor, err := util.CursorFromBytes(req.Cursor) - if err != nil { - return grpc.Errorf(codes.InvalidArgument, "%s", err.Error()) - } - - // ensure log cursor - if cursor.GetType() != util.LogCursorType { - return grpc.Errorf(codes.InvalidArgument, "cannot subscribe to non-log cursor") - } - - // read instanceID - instanceID := cursor.GetID() - - // get cached stream - stream := entity.FindCachedStreamByCurrentInstanceID(ss.Context(), instanceID) - if stream == nil { - return status.Error(codes.NotFound, "stream not found") - } - - // check permissions - perms := secret.StreamPermissions(ss.Context(), stream.StreamID, stream.ProjectID, stream.Public) - if !perms.Read { - return grpc.Errorf(codes.PermissionDenied, "token doesn't grant right to read this stream") - } - - // get subscription channel - ch := make(chan subscriptions.Message) - cancel, err := gateway.Subscriptions.Subscribe(instanceID, cursor.GetPayload(), func(msg subscriptions.Message) { - ch <- msg - }) - if err != nil { - return err - } - defer cancel() - - // read messages until disconnect - for { - select { - case <-ss.Context().Done(): - return nil - case _ = <-ch: - err := ss.Send(&pb.SubscribeResponse{}) - if err != nil { - return err - } - } - } -} diff --git a/gateway/http/server.go b/gateway/http/server.go deleted file mode 100644 index 41229b39..00000000 --- a/gateway/http/server.go +++ /dev/null @@ -1,107 +0,0 @@ -package http - -import ( - "fmt" - "net/http" - "strconv" - "strings" - - "github.com/go-chi/chi" - chimiddleware "github.com/go-chi/chi/middleware" - "github.com/rs/cors" - - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/internal/middleware" - "gitlab.com/beneath-hq/beneath/pkg/httputil" - "gitlab.com/beneath-hq/beneath/pkg/log" - "gitlab.com/beneath-hq/beneath/pkg/ws" -) - -// Handler serves the gateway HTTP API -func Handler() http.Handler { - handler := chi.NewRouter() - - corsOptions := cors.Options{ - AllowedOrigins: []string{"*"}, - AllowedHeaders: []string{"*"}, - AllowCredentials: true, - MaxAge: 7200, - Debug: false, - } - - handler.Use(chimiddleware.RealIP) - handler.Use(chimiddleware.DefaultCompress) - handler.Use(cors.New(corsOptions).Handler) - handler.Use(middleware.InjectTags) - handler.Use(middleware.Logger) - handler.Use(middleware.Recoverer) - handler.Use(middleware.Auth) - handler.Use(middleware.IPRateLimit()) - - // Add health check - handler.Get("/", healthCheck) - handler.Get("/healthz", healthCheck) - - // Add ping - handler.Method("GET", "/v1/-/ping", httputil.AppHandler(getPing)) - - // index and log endpoints - handler.Method("GET", "/v1/{organizationName}/{projectName}/{streamName}", httputil.AppHandler(getFromOrganizationAndProjectAndStream)) - handler.Method("GET", "/v1/-/instances/{instanceID}", httputil.AppHandler(getFromInstance)) - - // write endpoint - handler.Method("POST", "/v1/{organizationName}/{projectName}/{streamName}", httputil.AppHandler(postToOrganizationAndProjectAndStream)) - handler.Method("POST", "/v1/-/instances/{instanceID}", httputil.AppHandler(postToInstance)) - - // warehouse job endpoints - handler.Method("GET", "/v1/-/warehouse/{jobID}", httputil.AppHandler(getFromWarehouseJob)) - handler.Method("POST", "/v1/-/warehouse", httputil.AppHandler(postToWarehouseJob)) - - // read endpoint - handler.Method("GET", "/v1/-/cursor", httputil.AppHandler(getFromCursor)) - - // create websocket broker and start accepting new connections on /ws - wss := ws.NewBroker(&wsServer{}) - handler.Method("GET", "/v1/-/ws", httputil.AppHandler(wss.HTTPHandler)) - - return handler -} - -func healthCheck(w http.ResponseWriter, r *http.Request) { - if hub.Healthy() { - w.WriteHeader(http.StatusOK) - w.Write([]byte(http.StatusText(http.StatusOK))) - } else { - log.S.Errorf("Gateway database health check failed") - http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - } -} - -func parseBoolParam(name string, val string) (bool, error) { - if val == "" { - return false, nil - } else if val == "true" { - return true, nil - } else if val == "false" { - return false, nil - } - - return false, fmt.Errorf("expected '%s' parameter to be 'true' or 'false'", name) -} - -func parseIntParam(name string, val string) (int, error) { - if val == "" { - return 0, nil - } - - res, err := strconv.Atoi(val) - if err != nil { - return 0, fmt.Errorf("couldn't parse '%s' as integer", name) - } - - return res, nil -} - -func toBackendName(s string) string { - return strings.ToLower(strings.ReplaceAll(s, "-", "_")) -} diff --git a/gateway/http/subscription.go b/gateway/http/subscription.go deleted file mode 100644 index cedb9424..00000000 --- a/gateway/http/subscription.go +++ /dev/null @@ -1,183 +0,0 @@ -package http - -import ( - "context" - "fmt" - "time" - - "github.com/mr-tron/base58" - uuid "github.com/satori/go.uuid" - - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/gateway" - "gitlab.com/beneath-hq/beneath/gateway/subscriptions" - "gitlab.com/beneath-hq/beneath/gateway/util" - "gitlab.com/beneath-hq/beneath/pkg/log" - "gitlab.com/beneath-hq/beneath/pkg/secrettoken" - "gitlab.com/beneath-hq/beneath/pkg/ws" -) - -// wsServer implements ws.Server -type wsServer struct{} - -// KeepAlive implements ws.Server -func (s wsServer) KeepAlive(numClients int, elapsed time.Duration) { - // log state - log.S.Infow( - "ws keepalive", - "clients", numClients, - "elapsed", elapsed, - ) -} - -// InitClient implements ws.Server -func (s wsServer) InitClient(client *ws.Client, payload map[string]interface{}) error { - // get secret - var secret entity.Secret - tokenStr, ok := payload["secret"].(string) - if ok { - // parse token - token, err := secrettoken.FromString(tokenStr) - if err != nil { - return fmt.Errorf("malformed secret") - } - - // authenticate - secret = entity.AuthenticateWithToken(client.Context, token) - if secret == nil { - return fmt.Errorf("couldn't authenticate secret") - } - } - - if secret == nil { - secret = &entity.AnonymousSecret{} - } - - // set secret as state - client.SetState(secret) - - // log - s.logWithSecret(secret, "ws init client", - "ip", client.GetRemoteAddr(), - ) - - return nil -} - -// CloseClient implements ws.Server -func (s wsServer) CloseClient(client *ws.Client) { - // the client state is the secret - secret := client.GetState().(entity.Secret) - - // log - s.logWithSecret(secret, "ws close client", - "ip", client.GetRemoteAddr(), - "reads", client.MessagesRead, - "bytes_read", client.BytesRead, - "writes", client.MessagesWritten, - "bytes_written", client.BytesWritten, - "elapsed", time.Since(client.StartTime), - "error", client.Err, - ) -} - -// StartQuery implements ws.Server -func (s wsServer) StartQuery(client *ws.Client, id ws.QueryID, payload map[string]interface{}) error { - // get instance id - instanceIDStr, ok := payload["instance_id"].(string) - if !ok { - return fmt.Errorf("payload must contain key 'instance_id'") - } - instanceID := uuid.FromStringOrNil(instanceIDStr) - if instanceID == uuid.Nil { - return fmt.Errorf("query is not a valid instance ID") - } - - // get cursor - cursorStr, ok := payload["cursor"].(string) - if !ok { - return fmt.Errorf("payload must contain key 'cursor'") - } - cursor, err := base58.Decode(cursorStr) - if err != nil { - return fmt.Errorf("payload key 'cursor' must contain a base58-encoded cursor") - } - - // the client state is the secret - secret := client.GetState().(entity.Secret) - - // get cached stream - stream := entity.FindCachedStreamByCurrentInstanceID(client.Context, instanceID) - if stream == nil { - return fmt.Errorf("stream not found") - } - - // check permissions - perms := secret.StreamPermissions(client.Context, stream.StreamID, stream.ProjectID, stream.Public) - if !perms.Read { - return fmt.Errorf("token doesn't grant right to read this stream") - } - - // check usage - err = util.CheckReadQuota(client.Context, secret) - if err != nil { - return fmt.Errorf(err.Error()) - } - - // get subscription channel - cancel, err := gateway.Subscriptions.Subscribe(instanceID, cursor, func(msg subscriptions.Message) { - // TODO: For now, just sending empty messages - client.SendData(id, "") - }) - if err != nil { - return err - } - - // set cancel as query state - client.SetQueryState(id, cancel) - - // log - s.logWithSecret(secret, "ws start query", - "ip", client.GetRemoteAddr(), - "id", id, - "instance", instanceID.String(), - ) - - return nil -} - -// StopQuery implements ws.Server -func (s wsServer) StopQuery(client *ws.Client, id ws.QueryID) error { - // the query state is the cancel func - cancel := client.GetQueryState(id).(context.CancelFunc) - cancel() - - // the client state is the secret - secret := client.GetState().(entity.Secret) - - // log - s.logWithSecret(secret, "ws stop query", - "ip", client.GetRemoteAddr(), - "id", id, - ) - - return nil -} - -func (s wsServer) logWithSecret(sec entity.Secret, msg string, keysAndValues ...interface{}) { - l := log.S - - if sec.IsUser() { - l = l.With( - "secret", sec.GetSecretID().String(), - "user", sec.GetOwnerID().String(), - ) - } else if sec.IsService() { - l = l.With( - "secret", sec.GetSecretID().String(), - "service", sec.GetOwnerID().String(), - ) - } - - l.Infow(msg, keysAndValues...) -} diff --git a/gateway/subscriptions/broker.go b/gateway/subscriptions/broker.go deleted file mode 100644 index d98842c3..00000000 --- a/gateway/subscriptions/broker.go +++ /dev/null @@ -1,124 +0,0 @@ -package subscriptions - -import ( - "context" - "sync" - "time" - - uuid "github.com/satori/go.uuid" - - "gitlab.com/beneath-hq/beneath/engine" - "gitlab.com/beneath-hq/beneath/engine/driver" - pb "gitlab.com/beneath-hq/beneath/engine/proto" - "gitlab.com/beneath-hq/beneath/pkg/log" -) - -// Message encapsulates a subscription update dispatched by a Broker -type Message struct { - Iterator driver.RecordsIterator - PrevCursor []byte -} - -// Broker manages cursor update subscriptions -type Broker struct { - Engine *engine.Engine - subscriptions subscriptions -} - -// subscriptions manages a map of instances to subscription callbacks -type subscriptions struct { - sync.RWMutex - i int - m map[uuid.UUID]*callbacks -} - -// callbacks manages a set of subscription callbacks -type callbacks struct { - sync.RWMutex - m map[int]func(Message) -} - -// NewBroker initalizes a new broker -func NewBroker(eng *engine.Engine) *Broker { - b := &Broker{ - Engine: eng, - subscriptions: subscriptions{ - m: make(map[uuid.UUID]*callbacks), - }, - } - return b -} - -// RunForever brokers subscriptions until ctx is cancelled or an error occurs -func (b *Broker) RunForever(ctx context.Context) { - err := b.Engine.ReadWriteReports(ctx, b.handleWriteReport) - if err != nil { - panic(err) - } - - // TODO: gracefully shutdown subscriptions - - log.S.Infow("subscriptions broker shutdown gracefully") -} - -// Subscribe opens a new subscription on an instance -func (b *Broker) Subscribe(instanceID uuid.UUID, cursor []byte, cb func(Message)) (context.CancelFunc, error) { - b.subscriptions.Lock() - cbs := b.subscriptions.m[instanceID] - if cbs == nil { - cbs = &callbacks{m: make(map[int]func(Message))} - b.subscriptions.m[instanceID] = cbs - } - b.subscriptions.i++ - cbID := b.subscriptions.i - b.subscriptions.Unlock() - - cbs.Lock() - cbs.m[cbID] = cb - cbs.Unlock() - - cancel := func() { - cbs.Lock() - delete(cbs.m, cbID) - cbs.Unlock() - } - return cancel, nil -} - -// handleWriteReport processes a write report -func (b *Broker) handleWriteReport(ctx context.Context, rep *pb.WriteReport) error { - startTime := time.Now() - - instanceID := uuid.FromBytesOrNil(rep.InstanceId) - - b.subscriptions.RLock() - cbs := b.subscriptions.m[instanceID] - b.subscriptions.RUnlock() - - if cbs == nil { - return nil - } - - cbs.RLock() - n := len(cbs.m) - if n == 0 { - cbs.RUnlock() - return nil - } - - msg := Message{} - for _, cb := range cbs.m { - cb(msg) - } - - cbs.RUnlock() - - log.S.Infow( - "subscription dispatch", - "instance", instanceID.String(), - "clients", n, - "elapsed", time.Since(startTime), - ) - - return nil -} diff --git a/go.mod b/go.mod index 5977c18f..a07c670d 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,16 @@ module gitlab.com/beneath-hq/beneath go 1.12 require ( - cloud.google.com/go v0.40.0 - github.com/99designs/gqlgen v0.9.1 + cloud.google.com/go v0.65.0 + cloud.google.com/go/bigquery v1.8.0 + cloud.google.com/go/bigtable v1.6.0 + cloud.google.com/go/pubsub v1.3.1 + github.com/99designs/gqlgen v0.13.0 github.com/alecthomas/participle v0.3.0 github.com/bluele/gcache v0.0.0-20190518031135-bc40bd653833 github.com/go-chi/chi v4.0.2+incompatible github.com/go-pg/migrations/v7 v7.0.0 + github.com/go-pg/pg v8.0.7+incompatible github.com/go-pg/pg/v9 v9.0.0-beta github.com/go-playground/locales v0.12.1 // indirect github.com/go-playground/universal-translator v0.16.0 // indirect @@ -16,13 +20,13 @@ require ( github.com/go-redis/redis/v7 v7.0.0-beta.4 github.com/go-redis/redis_rate/v8 v8.0.0-beta github.com/go-test/deep v1.0.1 - github.com/gogo/protobuf v1.0.0 + github.com/gogo/protobuf v1.2.1 github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 - github.com/golang/protobuf v1.3.2 + github.com/golang/protobuf v1.4.2 github.com/google/btree v1.0.0 // indirect github.com/googleapis/gax-go/v2 v2.0.5 // indirect github.com/gorilla/sessions v1.1.1 - github.com/gorilla/websocket v1.2.0 + github.com/gorilla/websocket v1.4.2 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 github.com/hashicorp/go-version v1.2.0 github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365 @@ -33,27 +37,27 @@ require ( github.com/leodido/go-urn v1.1.0 // indirect github.com/linkedin/goavro/v2 v2.8.5 github.com/markbates/goth v1.64.2 + github.com/mitchellh/mapstructure v1.2.2 github.com/mr-tron/base58 v1.1.2 github.com/rs/cors v1.6.0 github.com/satori/go.uuid v1.2.0 github.com/segmentio/ksuid v1.0.2 github.com/sendgrid/rest v2.6.1+incompatible // indirect github.com/sendgrid/sendgrid-go v3.6.4+incompatible + github.com/spf13/cobra v1.1.0 + github.com/spf13/pflag v1.0.5 + github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.4.0 github.com/stripe/stripe-go v66.1.1+incompatible github.com/vektah/gqlparser v1.1.2 + github.com/vektah/gqlparser/v2 v2.1.0 github.com/vmihailenco/msgpack v4.0.4+incompatible github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c - go.opencensus.io v0.22.0 // indirect - go.uber.org/atomic v1.4.0 // indirect - go.uber.org/multierr v1.1.0 // indirect + go.uber.org/fx v1.13.1 go.uber.org/zap v1.10.0 - golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 // indirect - golang.org/x/sync v0.0.0-20190423024810-112230192c58 - golang.org/x/sys v0.0.0-20190614084037-d442b75600c5 // indirect - google.golang.org/api v0.6.0 - google.golang.org/genproto v0.0.0-20190611190212-a7e196e89fd3 // indirect - google.golang.org/grpc v1.21.1 + golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 + google.golang.org/api v0.31.0 + google.golang.org/grpc v1.31.1 gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/validator.v9 v9.29.0 robpike.io/filter v0.0.0-20150108201509-2984852a2183 diff --git a/go.sum b/go.sum index 119257d6..72ea3e5e 100644 --- a/go.sum +++ b/go.sum @@ -4,32 +4,118 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.40.0 h1:FjSY7bOj+WzJe6TZRVtXI2b9kAYvtNg4lMbcH2+MUkk= cloud.google.com/go v0.40.0/go.mod h1:Tk58MuI9rbLMKlAjeO/bDnteAx7tX2gJIXw4T5Jwlro= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3 h1:AVXDdKsrtX33oR9fbCMu/+c1o8Ofjq6Ku/MInaLVg5Y= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.69.1 h1:01WAtK12Fes1PhlpkgDf6iifgXbrdczf+6Cec2S+Aa8= +cloud.google.com/go/bigquery v1.0.1 h1:hL+ycaJpVE9M7nLoiXb/Pn10ENE2u+oddxbD8uu0ZVU= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/bigtable v1.6.0 h1:hcHWHVX8sfXW4qgfB0fYVd3i22Od2TK6gxoN7EWsbwY= +cloud.google.com/go/bigtable v1.6.0/go.mod h1:tqUJmGg13x13j3xXf6oUXsB7ZEI1mxd5wGMvLStr8y0= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1 h1:W9tAK3E57P75u0XLLR82LZyw8VpAnhmyTOxW9qzmyj8= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/99designs/gqlgen v0.9.1 h1:YqEOgwamerz8mNGwqL5fX/SJS3+TdQ8zE02jhHIwjx0= github.com/99designs/gqlgen v0.9.1/go.mod h1:HrrG7ic9EgLPsULxsZh/Ti+p0HNWgR3XRuvnD0pb5KY= +github.com/99designs/gqlgen v0.13.0 h1:haLTcUp3Vwp80xMVEg5KRNwzfUrgFdRmtBY8fuB8scA= +github.com/99designs/gqlgen v0.13.0/go.mod h1:NV130r6f4tpRWuAI+zsrSdooO/eWUv+Gyyoi3rEfXIk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0= +github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs= github.com/alecthomas/participle v0.3.0 h1:e8vhrYR1nDjzDxyDwpLO27TWOYWilaT+glkwbPadj50= github.com/alecthomas/participle v0.3.0/go.mod h1:SW6HZGeZgSIpcUWX3fXpfZhuaWHnmoD5KCVaqSaNTkk= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bem7/goavro/v2 v2.0.0-20191009165622-2e928607d532 h1:9GlWukYKXZLUVt+twk+yHJ8g3w6bffkFKB2Mn+ATR2s= github.com/bem7/goavro/v2 v2.0.0-20191009165622-2e928607d532/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bluele/gcache v0.0.0-20190518031135-bc40bd653833 h1:yCfXxYaelOyqnia8F/Yng47qhmfC9nKTRIbYRrRueq4= github.com/bluele/gcache v0.0.0-20190518031135-bc40bd653833/go.mod h1:8c4/i2VlovMO2gBnHGQPN5EJw+H0lx1u/5p+cgsXtCk= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs= github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-pg/migrations/v7 v7.0.0 h1:tdF8nOmaQjuTRNfros2JnhFY1suHtERQLbPD6Qkbcoo= github.com/go-pg/migrations/v7 v7.0.0/go.mod h1:GgKaGo+vh7szcv3I/+m8xOvDa4nry/UaKQehrnN2IE0= +github.com/go-pg/pg v8.0.7+incompatible h1:ty/sXL1OZLo+47KK9N8llRcmbA9tZasqbQ/OO4ld53g= +github.com/go-pg/pg v8.0.7+incompatible/go.mod h1:a2oXow+aFOrvwcKs3eIA0lNFmMilrxK2sOkB5NWe0vA= github.com/go-pg/pg/v9 v9.0.0-beta h1:xDOf5SoLdUpMcE2/Ontb7dAgq2pqnVahAe8L1aYHrXg= github.com/go-pg/pg/v9 v9.0.0-beta/go.mod h1:iVSTa1IJiCa0cN5cJJD5n0k3zYliVQC35Wq8nU82zIo= github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= @@ -38,29 +124,55 @@ github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rm github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-redis/cache/v7 v7.0.0 h1:NojroNZ47PdPL92nOPFkB6os7ccPEO+Cz3Z+OE9dySg= github.com/go-redis/cache/v7 v7.0.0/go.mod h1:kU4KrHnEgL5lvCsExlPPSnMGs1TSZzsPMo51NcR9mQM= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis/v7 v7.0.0-beta/go.mod h1:dohSoK1cSNPaisjbZhSk7RYyPhVx2k+4sAbJdPK5KPs= github.com/go-redis/redis/v7 v7.0.0-beta.3/go.mod h1:dohSoK1cSNPaisjbZhSk7RYyPhVx2k+4sAbJdPK5KPs= github.com/go-redis/redis/v7 v7.0.0-beta.4 h1:p6z7Pde69EGRWvlC++y8aFcaWegyrKHzOBGo0zUACTQ= github.com/go-redis/redis/v7 v7.0.0-beta.4/go.mod h1:xhhSbUMTsleRPur+Vgx9sUHtyN33bdjxY+9/0n9Ig8s= github.com/go-redis/redis_rate/v8 v8.0.0-beta h1:HXEYE0I9+VFoCW8fHeVNrAZ5wj970o12uA5msqveneQ= github.com/go-redis/redis_rate/v8 v8.0.0-beta/go.mod h1:ITsJdV9pvvB9uMSjeStdSzbrabHs7SBEQHldJRVRhTE= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.1 h1:UQhStjbkDClarlmv0am7OXXO4/GaPdCGiUiMTvi28sg= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gogo/protobuf v1.0.0 h1:2jyBKDKU/8v3v2xVR2PtiWQviFUyiaGk2rpfyFT8rTM= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4= github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -69,13 +181,29 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -89,17 +217,42 @@ github.com/gorilla/sessions v1.1.1 h1:YMDmfaK68mUixINzY/XjscuJ47uXFWSSHzFbBQM0Pr github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ= github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365 h1:ECW73yc9MY7935nNYXUkK7Dz17YuSUI9yqRqYS8aBww= github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jackc/chunkreader/v2 v2.0.0 h1:DUwgMQuuPnS0rhMXenUtZpqZqrR/30NWY+qQvTpSvEs= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= @@ -114,9 +267,18 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -125,15 +287,41 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/lestrrat-go/jwx v0.9.0/go.mod h1:iEoxlYfZjvoGpuWwxUz+eR5e6KTJGsaRcy/YNA/UnBk= +github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA= github.com/markbates/goth v1.54.1 h1:kqj1BfY3SQ+GiOeEFTtd+ZTc0FBKYhwXCz2clAZ2uT0= github.com/markbates/goth v1.54.1/go.mod h1:zZmAw0Es0Dpm7TT/4AdN14QrkiWLMrrU9Xei1o+/mdA= github.com/markbates/goth v1.64.2 h1:HDFwyuB6/ATU1USTvd/Rb3C9XE0VAxeuciSz+aUZHHA= github.com/markbates/goth v1.64.2/go.mod h1:hSFJFfH56BfFCX4+hBIxyd3o5VzuH5rNwKVRsFr/JPk= +github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.2.2 h1:dxe5oCinTXiTIcfgmZecdCzPmAJKd46KsCWc35r0TV4= +github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -141,14 +329,35 @@ github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/ksuid v1.0.2 h1:9yBfKyw4ECGTdALaF09Snw3sLJmYIX6AbPJrAy6MrDc= github.com/segmentio/ksuid v1.0.2/go.mod h1:BXuJDr2byAiHuQaQtSKoXh1J0YmUDurywOXgB2w+OSU= github.com/sendgrid/rest v1.0.2 h1:xdfALkR1m9eqf41/zEnUmV0fw4b31ZzGZ4Dj5f2/w04= @@ -159,10 +368,33 @@ github.com/sendgrid/sendgrid-go v3.6.4+incompatible h1:FYh0yWd99fIPbq6vnDUfnS74n github.com/sendgrid/sendgrid-go v3.6.4+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.1.0 h1:aq3wCKjTPmzcNWLVGnsFVN4rflK7Uzn10F8/aw8MhdQ= +github.com/spf13/cobra v1.1.0/go.mod h1:yk5b0mALVusDL5fMM6Rd1wgnoO5jUPhwsQ6LQAJTidQ= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= +github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= @@ -172,44 +404,106 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stripe/stripe-go v66.1.1+incompatible h1:D8qUD1rxv+RdXi2qo+IdDELkDevxYUQDfje20bGQPiw= github.com/stripe/stripe-go v66.1.1+incompatible/go.mod h1:A1dQZmO/QypXmsL0T8axYZkSN/uA/T/A64pfKdBAMiY= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= +github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U= github.com/vektah/gqlparser v1.1.2 h1:ZsyLGn7/7jDNI+y4SEhI4yAxRChlv15pUHMjijT+e68= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/vektah/gqlparser/v2 v2.1.0 h1:uiKJ+T5HMGGQM2kRKQ8Pxw8+Zq9qhhZhz/lieYvCMns= +github.com/vektah/gqlparser/v2 v2.1.0/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.2.0 h1:c4L4gd938BvSjSsfr9YahJcvasEf5JZ9W7rcEXfgyys= github.com/vmihailenco/msgpack/v4 v4.2.0/go.mod h1:Mu3B7ZwLd5nNOLVOKt9DecVl7IVg0xkDiEjk6CwMrww= github.com/vmihailenco/tagparser v0.1.0 h1:u6yzKTY6gW/KxL/K2NTEQUOSXZipyGiIRarGjJKmQzU= github.com/vmihailenco/tagparser v0.1.0/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g= github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/dig v1.10.0 h1:yLmDDj9/zuDjv3gz8GQGviXMs9TfysIUMUilCpgzUJY= +go.uber.org/dig v1.10.0/go.mod h1:X34SnWGr8Fyla9zQNO2GSO2D+TIuqB14OS8JhYocIyw= +go.uber.org/fx v1.13.1 h1:CFNTr1oin5OJ0VCZ8EycL3wzF29Jz2g0xe55RFsf2a4= +go.uber.org/fx v1.13.1/go.mod h1:bREWhavnedxpJeTq9pQT53BbvwhUv7TcpsOqcH4a+3w= +go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E= +go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -220,23 +514,56 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 h1:ld7aEMNHoBnnDAX15v1T6z31v8HwR2A9FYOuAhWqkwc= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201008141435-b3e1573b7520 h1:Bx6FllMpG4NWDOfhMBz1VR2QYNp/SAOHPIAsaVmxfPo= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -244,31 +571,128 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190614084037-d442b75600c5 h1:tQrtnaPeNyfkuD2UMixVD6lAa7WngkIFvtWcdzNeq80= golang.org/x/sys v0.0.0-20190614084037-d442b75600c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200828194041-157a740278f4 h1:kCCpuwSAoYJPkNc6x0xT9yTtV4oKtARo4RGBQWOfg9E= +golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b h1:mSUCVIwDx4hfXJfWsOPfdzEHxzb2Xjl6BQ8YgPnazQA= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191030062658-86caa796c7ab/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc h1:NCy3Ohtk6Iny5V/reW2Ktypo4zIpWBdRJ1uFMjBxdg8= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191114200427-caa0b0f7d508/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200828161849-5deb26317202/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200910222312-571a207697e7 h1:SJWJaZU+0cpPpc8YPrjwTiNrjlqgNl09cAFXuSijD2k= +golang.org/x/tools v0.0.0-20200910222312-571a207697e7/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.6.0 h1:2tJEkRfnZL5g1GeBUlITh/rqT5HG3sFcoVCUUxmgJ2g= google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0 h1:Q3Ui3V3/CVinFWFiW39Iw0kMuVrRzYX0wN6OPFp0lTA= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.31.0 h1:1w5Sz/puhxFo9lTtip2n47k7toB/U2nCqOKNHd3Yrbo= +google.golang.org/api v0.31.0/go.mod h1:CL+9IBCa2WWU6gRuBWaKqGWLFFwbEUXkfeMkHLQWYWo= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -278,34 +702,100 @@ google.golang.org/genproto v0.0.0-20190530194941-fb225487d101 h1:wuGevabY6r+ivPN google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190611190212-a7e196e89fd3 h1:0LGHEA/u5XLibPOx6D7D8FBT/ax6wT57vNKY0QckCwo= google.golang.org/genproto v0.0.0-20190611190212-a7e196e89fd3/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a h1:Ob5/580gVHBJZgXnff1cZDbG+xLtMVE5mDRTe+nIsX4= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200831141814-d751682dd103/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f h1:Yv4xsIx7HZOoyUGSJ2ksDyWE2qIBXROsZKt2ny3hCGM= +google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.29.0 h1:5ofssLNYgAA/inWn6rTZ4juWpRJUwEnXc1LG2IeXwgQ= gopkg.in/go-playground/validator.v9 v9.29.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w= mellium.im/sasl v0.2.1/go.mod h1:ROaEDLQNuf9vjKqE1SrAfnsobm2YKXT1gnN1uDp1PjQ= robpike.io/filter v0.0.0-20150108201509-2984852a2183 h1:b7Y5VfvTcuK1JCT6YKDIaw5w8j/AYBz6DkX/pStQCsM= robpike.io/filter v0.0.0-20150108201509-2984852a2183/go.mod h1:JQLSCVDQbISDYGuIQqGa40P6NsyycM3cVAiOKl0tjfI= rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k= diff --git a/hub/hub.go b/hub/hub.go deleted file mode 100644 index a84fb8b3..00000000 --- a/hub/hub.go +++ /dev/null @@ -1,55 +0,0 @@ -package hub - -import ( - "gitlab.com/beneath-hq/beneath/control/payments/driver" - "gitlab.com/beneath-hq/beneath/engine" - "github.com/go-pg/pg/v9" - "github.com/go-redis/redis/v7" -) - -var ( - // DB is the postgres connection - DB *pg.DB - - // Redis connection - Redis *redis.Client - - // Engine is the data plane - Engine *engine.Engine - - // PaymentDrivers handle payment methods - PaymentDrivers map[string]driver.PaymentsDriver -) - -// InitPostgres sets up Postgres connection -func InitPostgres(host string, database string, username string, password string) { - DB = newDatabase(host, database, username, password) -} - -// InitRedis sets up Redis connection -func InitRedis(redisURL string) { - Redis = newRedis(redisURL) -} - -// InitEngine sets up the engine connection -func InitEngine(mqDriver, lookupDriver, warehouseDriver string) { - Engine = engine.NewEngine(mqDriver, lookupDriver, warehouseDriver) -} - -// SetPaymentDrivers injects the payment drivers into the hub.PaymentDrivers object -func SetPaymentDrivers(paymentDrivers map[string]driver.PaymentsDriver) { - PaymentDrivers = paymentDrivers -} - -// Healthy returns true if connections are live -func Healthy() bool { - // check postgres - _, err := DB.Exec("SELECT 1") - pg := err == nil - - // check redis - _, err = Redis.Ping().Result() - redis := err == nil - - return pg && redis && Engine.Healthy() -} diff --git a/hub/pg.go b/hub/pg.go deleted file mode 100644 index 65ec894c..00000000 --- a/hub/pg.go +++ /dev/null @@ -1,34 +0,0 @@ -package hub - -import ( - "context" - "fmt" - - "github.com/go-pg/pg/v9" -) - -func newDatabase(host, database, username, password string) *pg.DB { - db := pg.Connect(&pg.Options{ - Addr: host + ":5432", - Database: database, - User: username, - Password: password, - }) - - // Uncomment to log database queries - // db.AddQueryHook(queryLoggerHook{}) - - return db -} - -// queryLoggerHook logs every database query -type queryLoggerHook struct{} - -func (h queryLoggerHook) BeforeQuery(ctx context.Context, q *pg.QueryEvent) (context.Context, error) { - fmt.Print(q.FormattedQuery()) - return ctx, nil -} - -func (h queryLoggerHook) AfterQuery(ctx context.Context, q *pg.QueryEvent) (context.Context, error) { - return ctx, nil -} diff --git a/hub/redis.go b/hub/redis.go deleted file mode 100644 index 81fe7aa1..00000000 --- a/hub/redis.go +++ /dev/null @@ -1,15 +0,0 @@ -package hub - -import ( - "github.com/go-redis/redis/v7" -) - -func newRedis(redisURL string) *redis.Client { - opts, err := redis.ParseURL(redisURL) - if err != nil { - panic(err) - } - - client := redis.NewClient(opts) - return client -} diff --git a/infrastructure/db/db.go b/infrastructure/db/db.go new file mode 100644 index 00000000..f4cd6877 --- /dev/null +++ b/infrastructure/db/db.go @@ -0,0 +1,82 @@ +package db + +import ( + "context" + "fmt" + + "github.com/go-pg/pg/v9" + "github.com/go-pg/pg/v9/orm" +) + +// DB represents the control-plane SQL (Postgres) database +type DB interface { + // Returns the current transaction or the DB connection outright + GetDB(ctx context.Context) orm.DB + + // InTransaction starts a DB transaction. Any call to GetDB with the derived ctx returns the transaction. + InTransaction(ctx context.Context, fn func(context.Context) error) error +} + +// Options for opening a new DB connection +type Options struct { + Host string + Database string + User string + Password string +} + +// NewDB connects to the control-plane DB +func NewDB(opts *Options) DB { + postgres := pg.Connect(&pg.Options{ + Addr: opts.Host + ":5432", + Database: opts.Database, + User: opts.User, + Password: opts.Password, + }) + + // Uncomment to log database queries + // postgres.AddQueryHook(queryLoggerHook{}) + + return db{ + postgres: postgres, + } +} + +// queryLoggerHook logs every database query +type queryLoggerHook struct{} + +func (h queryLoggerHook) BeforeQuery(ctx context.Context, q *pg.QueryEvent) (context.Context, error) { + fmt.Print(q.FormattedQuery()) + return ctx, nil +} + +func (h queryLoggerHook) AfterQuery(ctx context.Context, q *pg.QueryEvent) (context.Context, error) { + return ctx, nil +} + +// DB implementation +// ----------------- + +// txContextKey is the transaction context key +type txContextKey struct{} + +type db struct { + postgres *pg.DB +} + +func (d db) GetDB(ctx context.Context) orm.DB { + if tx, ok := ctx.Value(txContextKey{}).(*pg.Tx); ok { + return tx + } + return d.postgres +} + +func (d db) InTransaction(ctx context.Context, fn func(context.Context) error) error { + if _, ok := ctx.Value(txContextKey{}).(*pg.Tx); ok { + return fn(ctx) + } + return d.postgres.RunInTransaction(func(tx *pg.Tx) error { + txCtx := context.WithValue(ctx, txContextKey{}, tx) + return fn(txCtx) + }) +} diff --git a/infrastructure/db/util.go b/infrastructure/db/util.go new file mode 100644 index 00000000..ad803637 --- /dev/null +++ b/infrastructure/db/util.go @@ -0,0 +1,18 @@ +package db + +import ( + "github.com/go-pg/pg/v9" +) + +// AssertFoundOne uses the error from a QueryOne operation +// (which includes Select for a single object) to determine +// if a result was found or not. Panics on database errors +func AssertFoundOne(err error) bool { + if err != nil { + if err == pg.ErrNoRows { + return false + } + panic(err) + } + return true +} diff --git a/engine/README.md b/infrastructure/engine/README.md similarity index 100% rename from engine/README.md rename to infrastructure/engine/README.md diff --git a/engine/driver/README.md b/infrastructure/engine/driver/README.md similarity index 100% rename from engine/driver/README.md rename to infrastructure/engine/driver/README.md diff --git a/infrastructure/engine/driver/bigquery/bigquery.go b/infrastructure/engine/driver/bigquery/bigquery.go new file mode 100644 index 00000000..6d89bf3f --- /dev/null +++ b/infrastructure/engine/driver/bigquery/bigquery.go @@ -0,0 +1,66 @@ +package bigquery + +import ( + "context" + "fmt" + + bq "cloud.google.com/go/bigquery" + "github.com/mitchellh/mapstructure" + + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" +) + +// BigQuery implements beneath.WarehouseService +type BigQuery struct { + ProjectID string + Client *bq.Client + InstancesDataset *bq.Dataset +} + +// Options for connecting to Postgres +type Options struct { + ProjectID string `mapstructure:"project_id"` + InstancesDatasetID string `mapstructure:"instances_dataset_id"` +} + +func init() { + driver.AddDriver("bigquery", newBigQuery) +} + +func newBigQuery(optsMap map[string]interface{}) (driver.Service, error) { + // load options + var opts Options + err := mapstructure.Decode(optsMap, &opts) + if err != nil { + return nil, fmt.Errorf("error decoding bigquery options: %s", err.Error()) + } + + // create client + client, err := bq.NewClient(context.Background(), opts.ProjectID) + if err != nil { + return nil, err + } + + // create instances dataset if it doesn't exist + instancesDataset := client.Dataset(opts.InstancesDatasetID) + err = instancesDataset.Create(context.Background(), nil) + if err != nil && !isAlreadyExists(err) { + return nil, err + } + + return &BigQuery{ + ProjectID: opts.ProjectID, + Client: client, + InstancesDataset: instancesDataset, + }, nil +} + +// AsLookupService implements Service +func (b *BigQuery) AsLookupService() driver.LookupService { + return nil +} + +// AsWarehouseService implements Service +func (b *BigQuery) AsWarehouseService() driver.WarehouseService { + return b +} diff --git a/engine/driver/bigquery/proto/bigquery.pb.go b/infrastructure/engine/driver/bigquery/proto/bigquery.pb.go similarity index 63% rename from engine/driver/bigquery/proto/bigquery.pb.go rename to infrastructure/engine/driver/bigquery/proto/bigquery.pb.go index 1e0a255d..94aea1b6 100644 --- a/engine/driver/bigquery/proto/bigquery.pb.go +++ b/infrastructure/engine/driver/bigquery/proto/bigquery.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: engine/driver/bigquery/proto/bigquery.proto +// source: infrastructure/engine/driver/bigquery/proto/bigquery.proto package proto @@ -34,7 +34,7 @@ func (m *Cursor) Reset() { *m = Cursor{} } func (m *Cursor) String() string { return proto.CompactTextString(m) } func (*Cursor) ProtoMessage() {} func (*Cursor) Descriptor() ([]byte, []int) { - return fileDescriptor_7a9e211ec3e97f0b, []int{0} + return fileDescriptor_8560bb419b3113e7, []int{0} } func (m *Cursor) XXX_Unmarshal(b []byte) error { @@ -88,19 +88,20 @@ func init() { } func init() { - proto.RegisterFile("engine/driver/bigquery/proto/bigquery.proto", fileDescriptor_7a9e211ec3e97f0b) + proto.RegisterFile("infrastructure/engine/driver/bigquery/proto/bigquery.proto", fileDescriptor_8560bb419b3113e7) } -var fileDescriptor_7a9e211ec3e97f0b = []byte{ - // 154 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4e, 0xcd, 0x4b, 0xcf, - 0xcc, 0x4b, 0xd5, 0x4f, 0x29, 0xca, 0x2c, 0x4b, 0x2d, 0xd2, 0x4f, 0xca, 0x4c, 0x2f, 0x2c, 0x4d, - 0x2d, 0xaa, 0xd4, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x87, 0x73, 0xf5, 0xc0, 0x5c, 0x21, 0x0e, 0x18, - 0x5f, 0x29, 0x9f, 0x8b, 0xcd, 0xb9, 0xb4, 0xa8, 0x38, 0xbf, 0x48, 0x48, 0x82, 0x8b, 0x3d, 0x25, - 0xb1, 0x24, 0xb1, 0x38, 0xb5, 0x44, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, 0x08, 0xc6, 0x15, 0x12, - 0xe1, 0x62, 0x2d, 0x49, 0x4c, 0xca, 0x49, 0x95, 0x60, 0x02, 0x8b, 0x43, 0x38, 0x60, 0xd1, 0xfc, - 0xec, 0xd4, 0x3c, 0x09, 0x66, 0xa8, 0x28, 0x88, 0x23, 0x24, 0xcf, 0xc5, 0x9d, 0x58, 0x56, 0x94, - 0x1f, 0x5f, 0x9c, 0x9c, 0x91, 0x9a, 0x9b, 0x28, 0xc1, 0x02, 0x96, 0xe3, 0x02, 0x09, 0x05, 0x83, - 0x45, 0x9c, 0xd8, 0xa3, 0x58, 0xc1, 0x6e, 0x48, 0x62, 0x03, 0x53, 0xc6, 0x80, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xdf, 0xee, 0xe7, 0xbe, 0xb9, 0x00, 0x00, 0x00, +var fileDescriptor_8560bb419b3113e7 = []byte{ + // 165 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x3c, 0xce, 0xb1, 0x12, 0x01, 0x31, + 0x10, 0xc6, 0xf1, 0x39, 0xdc, 0x1d, 0xd1, 0x65, 0x14, 0xe9, 0x18, 0x95, 0x4a, 0x0a, 0x9d, 0x92, + 0x37, 0xa0, 0xd3, 0x98, 0xe4, 0x6e, 0x9d, 0x0c, 0x12, 0x36, 0x9b, 0x9b, 0xf1, 0xf6, 0xe6, 0x96, + 0x53, 0xed, 0xfc, 0xfe, 0xdb, 0x7c, 0x62, 0xeb, 0xfc, 0x05, 0x4d, 0x24, 0x4c, 0x15, 0x25, 0x04, + 0x0d, 0xbe, 0x71, 0x1e, 0x74, 0x8d, 0xae, 0x05, 0xd4, 0xd6, 0x35, 0xaf, 0x04, 0xf8, 0xd6, 0x4f, + 0x0c, 0x14, 0xfe, 0x5c, 0x33, 0xe5, 0xb8, 0xf7, 0x32, 0x88, 0x62, 0x9f, 0x30, 0x06, 0x94, 0x4a, + 0x94, 0xb5, 0x21, 0x13, 0x81, 0x54, 0xb6, 0xc8, 0x56, 0x93, 0x43, 0x4f, 0x39, 0x13, 0x39, 0x19, + 0x7b, 0x07, 0x35, 0xe0, 0xfe, 0x05, 0xd7, 0x70, 0x03, 0xaf, 0x86, 0xbf, 0xda, 0x41, 0xce, 0xc5, + 0xd4, 0xb4, 0x18, 0xce, 0xb1, 0xba, 0xc2, 0xc3, 0xa8, 0x11, 0xff, 0x44, 0x97, 0x8e, 0x5c, 0x76, + 0xe5, 0x29, 0xe7, 0x0d, 0xb6, 0xe0, 0xb3, 0xf9, 0x04, 0x00, 0x00, 0xff, 0xff, 0x9a, 0x28, 0x66, + 0xd5, 0xc8, 0x00, 0x00, 0x00, } diff --git a/engine/driver/bigquery/proto/bigquery.proto b/infrastructure/engine/driver/bigquery/proto/bigquery.proto similarity index 100% rename from engine/driver/bigquery/proto/bigquery.proto rename to infrastructure/engine/driver/bigquery/proto/bigquery.proto diff --git a/engine/driver/bigquery/query.go b/infrastructure/engine/driver/bigquery/query.go similarity index 98% rename from engine/driver/bigquery/query.go rename to infrastructure/engine/driver/bigquery/query.go index 1ef26471..99c6486e 100644 --- a/engine/driver/bigquery/query.go +++ b/infrastructure/engine/driver/bigquery/query.go @@ -10,8 +10,8 @@ import ( uuid "github.com/satori/go.uuid" "google.golang.org/api/iterator" - "gitlab.com/beneath-hq/beneath/engine/driver" - pb "gitlab.com/beneath-hq/beneath/engine/driver/bigquery/proto" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver/bigquery/proto" "gitlab.com/beneath-hq/beneath/pkg/codec" "gitlab.com/beneath-hq/beneath/pkg/schemalang" "gitlab.com/beneath-hq/beneath/pkg/schemalang/transpilers" diff --git a/engine/driver/bigquery/service.go b/infrastructure/engine/driver/bigquery/service.go similarity index 67% rename from engine/driver/bigquery/service.go rename to infrastructure/engine/driver/bigquery/service.go index d57cace9..0736d8a2 100644 --- a/engine/driver/bigquery/service.go +++ b/infrastructure/engine/driver/bigquery/service.go @@ -2,11 +2,10 @@ package bigquery import ( "context" - "fmt" "cloud.google.com/go/bigquery" - "gitlab.com/beneath-hq/beneath/engine/driver" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" "gitlab.com/beneath-hq/beneath/pkg/schemalang/transpilers" ) @@ -25,18 +24,8 @@ func (b BigQuery) MaxRecordsInBatch() int { return 10000 } -// RegisterProject implements beneath.Service -func (b BigQuery) RegisterProject(ctx context.Context, p driver.Project) error { - return nil -} - -// RemoveProject implements beneath.Service -func (b BigQuery) RemoveProject(ctx context.Context, p driver.Project) error { - return nil -} - // RegisterInstance implements beneath.Service -func (b BigQuery) RegisterInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { +func (b BigQuery) RegisterInstance(ctx context.Context, s driver.Stream, i driver.StreamInstance) error { // get bigquery schema schema, err := transpilers.FromAvro(s.GetCodec().AvroSchema) if err != nil { @@ -63,7 +52,6 @@ func (b BigQuery) RegisterInstance(ctx context.Context, p driver.Project, s driv } // create table - streamPath := fmt.Sprintf("%s-%s-%s", p.GetOrganizationName(), p.GetProjectName(), s.GetStreamName()) table := b.InstancesDataset.Table(instanceTableName(i.GetStreamInstanceID())) err = table.Create(ctx, &bigquery.TableMetadata{ Schema: bqSchema, @@ -71,9 +59,6 @@ func (b BigQuery) RegisterInstance(ctx context.Context, p driver.Project, s driv Clustering: &bigquery.Clustering{ Fields: s.GetCodec().PrimaryIndex.GetFields(), }, - Labels: map[string]string{ - OriginalStreamPathLabel: streamPath, - }, }) if err != nil && !isAlreadyExists(err) { // for idempotency, we don't care if it exists return err @@ -82,13 +67,8 @@ func (b BigQuery) RegisterInstance(ctx context.Context, p driver.Project, s driv return nil } -// PromoteInstance implements beneath.Service -func (b BigQuery) PromoteInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { - return nil -} - // RemoveInstance implements beneath.Service -func (b BigQuery) RemoveInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { +func (b BigQuery) RemoveInstance(ctx context.Context, s driver.Stream, i driver.StreamInstance) error { // delete instance table table := b.InstancesDataset.Table(instanceTableName(i.GetStreamInstanceID())) err := table.Delete(ctx) diff --git a/engine/driver/bigquery/util.go b/infrastructure/engine/driver/bigquery/util.go similarity index 100% rename from engine/driver/bigquery/util.go rename to infrastructure/engine/driver/bigquery/util.go diff --git a/engine/driver/bigquery/warehouse.go b/infrastructure/engine/driver/bigquery/warehouse.go similarity index 97% rename from engine/driver/bigquery/warehouse.go rename to infrastructure/engine/driver/bigquery/warehouse.go index 5ef3cf6d..20921d60 100644 --- a/engine/driver/bigquery/warehouse.go +++ b/infrastructure/engine/driver/bigquery/warehouse.go @@ -9,7 +9,7 @@ import ( "cloud.google.com/go/bigquery" - "gitlab.com/beneath-hq/beneath/engine/driver" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" "gitlab.com/beneath-hq/beneath/pkg/timeutil" ) diff --git a/engine/driver/bigtable/bigtable.go b/infrastructure/engine/driver/bigtable/bigtable.go similarity index 72% rename from engine/driver/bigtable/bigtable.go rename to infrastructure/engine/driver/bigtable/bigtable.go index b91208a0..6e72f1e0 100644 --- a/engine/driver/bigtable/bigtable.go +++ b/infrastructure/engine/driver/bigtable/bigtable.go @@ -4,25 +4,17 @@ import ( "context" "fmt" "os" - "sync" "time" "cloud.google.com/go/bigtable" + "github.com/mitchellh/mapstructure" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "gitlab.com/beneath-hq/beneath/engine/driver" - "gitlab.com/beneath-hq/beneath/engine/driver/bigtable/sequencer" - "gitlab.com/beneath-hq/beneath/pkg/envutil" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver/bigtable/sequencer" ) -// configSpecification defines the config variables to load from ENV -type configSpecification struct { - ProjectID string `envconfig:"PROJECT_ID" required:"true"` - InstanceID string `envconfig:"INSTANCE_ID" required:"true"` - EmulatorHost string `envconfig:"EMULATOR_HOST" required:"false"` -} - // BigTable implements beneath.Log and beneath.LookupService type BigTable struct { Admin *bigtable.AdminClient @@ -36,6 +28,17 @@ type BigTable struct { UsageTemp *bigtable.Table } +// Options for BigTable +type Options struct { + ProjectID string `mapstructure:"project_id"` + InstanceID string `mapstructure:"instance_id"` + EmulatorHost string `mapstructure:"emulator_host"` +} + +func init() { + driver.AddDriver("bigtable", newBigTable) +} + const ( /* SCHEMA NOTES: @@ -81,58 +84,63 @@ const ( usageScanBytesColumnName = "sb" ) -// Global -var global BigTable -var once sync.Once - -func createGlobal() { - // parse config from env - var config configSpecification - envutil.LoadConfig("beneath_engine_bigtable", &config) +func newBigTable(optsMap map[string]interface{}) (driver.Service, error) { + // load options + var opts Options + err := mapstructure.Decode(optsMap, &opts) + if err != nil { + return nil, fmt.Errorf("error decoding bigtable options: %s", err.Error()) + } // if EMULATOR_HOST set, configure bigtable for the emulator - if config.EmulatorHost != "" { - os.Setenv("BIGTABLE_PROJECT_ID", config.ProjectID) - os.Setenv("BIGTABLE_EMULATOR_HOST", config.EmulatorHost) + if opts.EmulatorHost != "" { + os.Setenv("BIGTABLE_PROJECT_ID", opts.ProjectID) + os.Setenv("BIGTABLE_EMULATOR_HOST", opts.EmulatorHost) } // create BigTable admin - admin, err := bigtable.NewAdminClient(context.Background(), config.ProjectID, config.InstanceID) + admin, err := bigtable.NewAdminClient(context.Background(), opts.ProjectID, opts.InstanceID) if err != nil { - panic(err) + return nil, err } // prepare BigTable client - client, err := bigtable.NewClient(context.Background(), config.ProjectID, config.InstanceID) + client, err := bigtable.NewClient(context.Background(), opts.ProjectID, opts.InstanceID) if err != nil { - panic(err) + return nil, err } // create instance - global = BigTable{ + bt := &BigTable{ Admin: admin, Client: client, } - global.Sequencer, err = sequencer.New(admin, client, sequencerTableName) + bt.Sequencer, err = sequencer.New(admin, client, sequencerTableName) if err != nil { - panic(err) + return nil, err } // expiring tables have max age of 1 second, making their timestamps expiration dates - global.Log = global.openTable(logTableName, logColumnFamilyName, 1, 0) - global.LogExpiring = global.openTable(logExpiringTableName, logColumnFamilyName, 1, time.Second) - global.Indexes = global.openTable(indexesTableName, indexesColumnFamilyName, 1, 0) - global.IndexesExpiring = global.openTable(indexesExpiringTableName, indexesColumnFamilyName, 1, time.Second) - global.Usage = global.openTable(usageTableName, usageColumnFamilyName, 1, 0) - global.UsageTemp = global.openTable(usageTempTableName, usageColumnFamilyName, 1, usageTempRetention) + bt.Log = bt.openTable(logTableName, logColumnFamilyName, 1, 0) + bt.LogExpiring = bt.openTable(logExpiringTableName, logColumnFamilyName, 1, time.Second) + bt.Indexes = bt.openTable(indexesTableName, indexesColumnFamilyName, 1, 0) + bt.IndexesExpiring = bt.openTable(indexesExpiringTableName, indexesColumnFamilyName, 1, time.Second) + bt.Usage = bt.openTable(usageTableName, usageColumnFamilyName, 1, 0) + bt.UsageTemp = bt.openTable(usageTempTableName, usageColumnFamilyName, 1, usageTempRetention) + + return bt, nil +} + +// AsLookupService implements Service +func (b *BigTable) AsLookupService() driver.LookupService { + return b } -// GetLookupService returns a BigTable implementation of beneath.LookupService -func GetLookupService() driver.LookupService { - once.Do(createGlobal) - return global +// AsWarehouseService implements Service +func (b *BigTable) AsWarehouseService() driver.WarehouseService { + return nil } func (b BigTable) openTable(name string, cfName string, maxVersions int, maxAge time.Duration) *bigtable.Table { diff --git a/engine/driver/bigtable/bigtable_test.go b/infrastructure/engine/driver/bigtable/bigtable_test.go similarity index 100% rename from engine/driver/bigtable/bigtable_test.go rename to infrastructure/engine/driver/bigtable/bigtable_test.go diff --git a/engine/driver/bigtable/loading.go b/infrastructure/engine/driver/bigtable/loading.go similarity index 99% rename from engine/driver/bigtable/loading.go rename to infrastructure/engine/driver/bigtable/loading.go index f76fb74a..be6d46e1 100644 --- a/engine/driver/bigtable/loading.go +++ b/infrastructure/engine/driver/bigtable/loading.go @@ -9,7 +9,7 @@ import ( "cloud.google.com/go/bigtable" - "gitlab.com/beneath-hq/beneath/engine/driver" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" "gitlab.com/beneath-hq/beneath/pkg/codec" "gitlab.com/beneath-hq/beneath/pkg/codec/ext/tuple" ) diff --git a/engine/driver/bigtable/lookup.go b/infrastructure/engine/driver/bigtable/lookup.go similarity index 98% rename from engine/driver/bigtable/lookup.go rename to infrastructure/engine/driver/bigtable/lookup.go index 0c647424..62f4f4e8 100644 --- a/engine/driver/bigtable/lookup.go +++ b/infrastructure/engine/driver/bigtable/lookup.go @@ -11,9 +11,9 @@ import ( "cloud.google.com/go/bigtable" "github.com/golang/protobuf/proto" - "gitlab.com/beneath-hq/beneath/engine/driver" - pb "gitlab.com/beneath-hq/beneath/engine/driver/bigtable/proto" - "gitlab.com/beneath-hq/beneath/engine/driver/bigtable/sequencer" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver/bigtable/proto" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver/bigtable/sequencer" "gitlab.com/beneath-hq/beneath/pkg/codec" "gitlab.com/beneath-hq/beneath/pkg/mathutil" "gitlab.com/beneath-hq/beneath/pkg/queryparse" diff --git a/engine/driver/bigtable/proto/cursor.pb.go b/infrastructure/engine/driver/bigtable/proto/cursor.pb.go similarity index 68% rename from engine/driver/bigtable/proto/cursor.pb.go rename to infrastructure/engine/driver/bigtable/proto/cursor.pb.go index 82c2d1f5..b265b74a 100644 --- a/engine/driver/bigtable/proto/cursor.pb.go +++ b/infrastructure/engine/driver/bigtable/proto/cursor.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: engine/driver/bigtable/proto/cursor.proto +// source: infrastructure/engine/driver/bigtable/proto/cursor.proto package proto @@ -45,7 +45,7 @@ func (x Cursor_Type) String() string { } func (Cursor_Type) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_09dade45cc45a2f4, []int{1, 0} + return fileDescriptor_f278abf2123fd65e, []int{1, 0} } type CursorSet struct { @@ -59,7 +59,7 @@ func (m *CursorSet) Reset() { *m = CursorSet{} } func (m *CursorSet) String() string { return proto.CompactTextString(m) } func (*CursorSet) ProtoMessage() {} func (*CursorSet) Descriptor() ([]byte, []int) { - return fileDescriptor_09dade45cc45a2f4, []int{0} + return fileDescriptor_f278abf2123fd65e, []int{0} } func (m *CursorSet) XXX_Unmarshal(b []byte) error { @@ -103,7 +103,7 @@ func (m *Cursor) Reset() { *m = Cursor{} } func (m *Cursor) String() string { return proto.CompactTextString(m) } func (*Cursor) ProtoMessage() {} func (*Cursor) Descriptor() ([]byte, []int) { - return fileDescriptor_09dade45cc45a2f4, []int{1} + return fileDescriptor_f278abf2123fd65e, []int{1} } func (m *Cursor) XXX_Unmarshal(b []byte) error { @@ -173,27 +173,27 @@ func init() { } func init() { - proto.RegisterFile("engine/driver/bigtable/proto/cursor.proto", fileDescriptor_09dade45cc45a2f4) -} - -var fileDescriptor_09dade45cc45a2f4 = []byte{ - // 275 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x90, 0x4f, 0x4b, 0xc3, 0x30, - 0x18, 0xc6, 0x8d, 0xeb, 0xdf, 0xb7, 0x22, 0xe5, 0xc5, 0x69, 0x65, 0x07, 0x4b, 0xf1, 0xd0, 0x79, - 0x68, 0x61, 0x1e, 0xbc, 0xab, 0x45, 0x86, 0xa2, 0xd2, 0x79, 0x10, 0x2f, 0x63, 0x35, 0xa1, 0x04, - 0x4a, 0x52, 0xd2, 0x28, 0xee, 0x1b, 0xfb, 0x31, 0xa4, 0x09, 0xbd, 0x78, 0x0a, 0xcf, 0xf3, 0xfb, - 0xe5, 0x21, 0x04, 0x96, 0x4c, 0xb4, 0x5c, 0xb0, 0x92, 0x2a, 0xfe, 0xcd, 0x54, 0xd9, 0xf0, 0x56, - 0xef, 0x9a, 0x8e, 0x95, 0xbd, 0x92, 0x5a, 0x96, 0x9f, 0x5f, 0x6a, 0x90, 0xaa, 0x30, 0x01, 0x83, - 0x09, 0x66, 0x37, 0x10, 0xde, 0x19, 0xb2, 0x61, 0x1a, 0xaf, 0xc0, 0xb7, 0xda, 0x90, 0x90, 0x74, - 0x96, 0x47, 0xab, 0xb8, 0x98, 0xc4, 0xc2, 0x5a, 0xf5, 0x24, 0x64, 0xbf, 0x04, 0x3c, 0xdb, 0xe1, - 0x12, 0x1c, 0xbd, 0xef, 0x59, 0x42, 0x52, 0x92, 0x1f, 0xaf, 0xe6, 0xff, 0xef, 0x14, 0x6f, 0xfb, - 0x9e, 0xd5, 0x46, 0xc1, 0x05, 0x84, 0x9d, 0x6c, 0xb7, 0x83, 0xde, 0x29, 0x9d, 0x40, 0x4a, 0xf2, - 0x59, 0x1d, 0x74, 0xb2, 0xdd, 0x8c, 0x19, 0xcf, 0xc0, 0x1f, 0x21, 0x13, 0x34, 0x89, 0x0c, 0xf2, - 0x3a, 0xd9, 0x56, 0x82, 0xe2, 0x39, 0x04, 0x5c, 0x50, 0xf6, 0xb3, 0xe5, 0x34, 0x39, 0x49, 0x49, - 0xee, 0xd6, 0xbe, 0xc9, 0x6b, 0x8a, 0x17, 0x10, 0x59, 0x64, 0x27, 0xe7, 0x29, 0xc9, 0x8f, 0x6a, - 0x30, 0x95, 0x1d, 0x5d, 0x40, 0x68, 0x85, 0x71, 0xf6, 0xd4, 0x60, 0x3b, 0x56, 0x09, 0x9a, 0x5d, - 0x82, 0x33, 0x3e, 0x0e, 0x7d, 0x98, 0x3d, 0xbd, 0x3c, 0xc4, 0x07, 0x18, 0x82, 0xbb, 0x7e, 0xbe, - 0xaf, 0xde, 0x63, 0x82, 0x01, 0x38, 0xaf, 0x55, 0xf5, 0x18, 0x1f, 0xde, 0xfa, 0x1f, 0xae, 0xf9, - 0xb6, 0xc6, 0x33, 0xc7, 0xf5, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5a, 0x0c, 0x9d, 0x84, 0x6a, - 0x01, 0x00, 0x00, + proto.RegisterFile("infrastructure/engine/driver/bigtable/proto/cursor.proto", fileDescriptor_f278abf2123fd65e) +} + +var fileDescriptor_f278abf2123fd65e = []byte{ + // 287 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x90, 0xcf, 0x4a, 0xec, 0x30, + 0x1c, 0x85, 0x6f, 0x6e, 0xff, 0xff, 0x2a, 0x52, 0x82, 0xa3, 0x95, 0x59, 0x58, 0x8a, 0x8b, 0xea, + 0xa2, 0x85, 0x71, 0xa1, 0x6b, 0xb5, 0xc8, 0xa0, 0xa8, 0x74, 0x5c, 0x88, 0x9b, 0xa1, 0x9d, 0xc4, + 0x12, 0x28, 0x49, 0x49, 0x53, 0x71, 0xde, 0xd8, 0xc7, 0x90, 0x26, 0x74, 0xe3, 0x2a, 0x9c, 0xf3, + 0x7d, 0x39, 0x84, 0xc0, 0x0d, 0xe3, 0x9f, 0xb2, 0x1e, 0x94, 0x1c, 0x77, 0x6a, 0x94, 0xb4, 0xa0, + 0xbc, 0x65, 0x9c, 0x16, 0x44, 0xb2, 0x2f, 0x2a, 0x8b, 0x86, 0xb5, 0xaa, 0x6e, 0x3a, 0x5a, 0xf4, + 0x52, 0x28, 0x51, 0xec, 0x46, 0x39, 0x08, 0x99, 0xeb, 0x80, 0xfd, 0x19, 0xa6, 0xd7, 0x10, 0xdc, + 0x69, 0xb2, 0xa1, 0x0a, 0x5f, 0x82, 0x67, 0xb4, 0x21, 0x46, 0x89, 0x95, 0x85, 0xab, 0x28, 0x9f, + 0xc5, 0xdc, 0x58, 0xd5, 0x2c, 0xa4, 0x3f, 0x08, 0x5c, 0xd3, 0xe1, 0x0b, 0xb0, 0xd5, 0xbe, 0xa7, + 0x31, 0x4a, 0x50, 0x76, 0xb8, 0x5a, 0xfc, 0xbd, 0x93, 0xbf, 0xed, 0x7b, 0x5a, 0x69, 0x05, 0x2f, + 0x21, 0xe8, 0x44, 0xbb, 0x1d, 0x54, 0x2d, 0x55, 0x0c, 0x09, 0xca, 0xac, 0xca, 0xef, 0x44, 0xbb, + 0x99, 0x32, 0x3e, 0x01, 0x6f, 0x82, 0x94, 0x93, 0x38, 0xd4, 0xc8, 0xed, 0x44, 0x5b, 0x72, 0x82, + 0x4f, 0xc1, 0x67, 0x9c, 0xd0, 0xef, 0x2d, 0x23, 0xf1, 0x51, 0x82, 0x32, 0xa7, 0xf2, 0x74, 0x5e, + 0x13, 0x7c, 0x06, 0xa1, 0x41, 0x66, 0x72, 0x91, 0xa0, 0xec, 0xa0, 0x02, 0x5d, 0x99, 0xd1, 0x25, + 0x04, 0x46, 0x98, 0x66, 0x8f, 0x35, 0x36, 0x63, 0x25, 0x27, 0xe9, 0x39, 0xd8, 0xd3, 0xe3, 0xb0, + 0x07, 0xd6, 0xd3, 0xcb, 0x43, 0xf4, 0x0f, 0x07, 0xe0, 0xac, 0x9f, 0xef, 0xcb, 0xf7, 0x08, 0x61, + 0x1f, 0xec, 0xd7, 0xb2, 0x7c, 0x8c, 0xfe, 0xdf, 0x7a, 0x1f, 0x8e, 0xfe, 0xb6, 0xc6, 0xd5, 0xc7, + 0xd5, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x69, 0x32, 0x1b, 0xa1, 0x79, 0x01, 0x00, 0x00, } diff --git a/engine/driver/bigtable/proto/cursor.proto b/infrastructure/engine/driver/bigtable/proto/cursor.proto similarity index 100% rename from engine/driver/bigtable/proto/cursor.proto rename to infrastructure/engine/driver/bigtable/proto/cursor.proto diff --git a/engine/driver/bigtable/schema.go b/infrastructure/engine/driver/bigtable/schema.go similarity index 100% rename from engine/driver/bigtable/schema.go rename to infrastructure/engine/driver/bigtable/schema.go diff --git a/engine/driver/bigtable/sequencer/sequencer.go b/infrastructure/engine/driver/bigtable/sequencer/sequencer.go similarity index 100% rename from engine/driver/bigtable/sequencer/sequencer.go rename to infrastructure/engine/driver/bigtable/sequencer/sequencer.go diff --git a/engine/driver/bigtable/sequencer/sequencer_test.go b/infrastructure/engine/driver/bigtable/sequencer/sequencer_test.go similarity index 100% rename from engine/driver/bigtable/sequencer/sequencer_test.go rename to infrastructure/engine/driver/bigtable/sequencer/sequencer_test.go diff --git a/engine/driver/bigtable/service.go b/infrastructure/engine/driver/bigtable/service.go similarity index 72% rename from engine/driver/bigtable/service.go rename to infrastructure/engine/driver/bigtable/service.go index 0a563b21..b62b273d 100644 --- a/engine/driver/bigtable/service.go +++ b/infrastructure/engine/driver/bigtable/service.go @@ -3,7 +3,7 @@ package bigtable import ( "context" - "gitlab.com/beneath-hq/beneath/engine/driver" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" ) // MaxKeySize implements beneath.Service @@ -25,28 +25,13 @@ func (b BigTable) MaxRecordsInBatch() int { return 10000 } -// RegisterProject implements beneath.Service -func (b BigTable) RegisterProject(ctx context.Context, p driver.Project) error { - return nil -} - -// RemoveProject implements beneath.Service -func (b BigTable) RemoveProject(ctx context.Context, p driver.Project) error { - return nil -} - // RegisterInstance implements beneath.Service -func (b BigTable) RegisterInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { - return nil -} - -// PromoteInstance implements beneath.Service -func (b BigTable) PromoteInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { +func (b BigTable) RegisterInstance(ctx context.Context, s driver.Stream, i driver.StreamInstance) error { return nil } // RemoveInstance implements beneath.Service -func (b BigTable) RemoveInstance(ctx context.Context, p driver.Project, s driver.Stream, i driver.StreamInstance) error { +func (b BigTable) RemoveInstance(ctx context.Context, s driver.Stream, i driver.StreamInstance) error { codec := s.GetCodec() // get table names diff --git a/engine/driver/bigtable/usage.go b/infrastructure/engine/driver/bigtable/usage.go similarity index 98% rename from engine/driver/bigtable/usage.go rename to infrastructure/engine/driver/bigtable/usage.go index c269d2d0..4c87a92c 100644 --- a/engine/driver/bigtable/usage.go +++ b/infrastructure/engine/driver/bigtable/usage.go @@ -8,7 +8,7 @@ import ( "cloud.google.com/go/bigtable" uuid "github.com/satori/go.uuid" - pb "gitlab.com/beneath-hq/beneath/engine/proto" + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" "gitlab.com/beneath-hq/beneath/pkg/timeutil" ) diff --git a/engine/driver/bigtable/util.go b/infrastructure/engine/driver/bigtable/util.go similarity index 97% rename from engine/driver/bigtable/util.go rename to infrastructure/engine/driver/bigtable/util.go index 5e9a43c6..9eb3754e 100644 --- a/engine/driver/bigtable/util.go +++ b/infrastructure/engine/driver/bigtable/util.go @@ -5,7 +5,7 @@ import ( "encoding/binary" "time" - "gitlab.com/beneath-hq/beneath/engine/driver" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" "gitlab.com/beneath-hq/beneath/pkg/timeutil" ) diff --git a/engine/driver/bigtable/util_test.go b/infrastructure/engine/driver/bigtable/util_test.go similarity index 100% rename from engine/driver/bigtable/util_test.go rename to infrastructure/engine/driver/bigtable/util_test.go diff --git a/engine/driver/driver.go b/infrastructure/engine/driver/driver.go similarity index 85% rename from engine/driver/driver.go rename to infrastructure/engine/driver/driver.go index bbec43f5..ed63a51f 100644 --- a/engine/driver/driver.go +++ b/infrastructure/engine/driver/driver.go @@ -2,120 +2,36 @@ package driver import ( "context" + "fmt" "time" uuid "github.com/satori/go.uuid" - pb "gitlab.com/beneath-hq/beneath/engine/proto" + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" "gitlab.com/beneath-hq/beneath/pkg/codec" "gitlab.com/beneath-hq/beneath/pkg/queryparse" "gitlab.com/beneath-hq/beneath/pkg/timeutil" ) -// MessageQueue encapsulates functionality necessary for message passing in Beneath -type MessageQueue interface { - // MaxMessageSize should return the maximum allowed byte size of published messages - MaxMessageSize() int +// Tracking drivers +// ---------------- - // RegisterTopic should register a new topic for message passing - RegisterTopic(name string) error +// Driver is a function that creates an engine service (LookupService or WarehouseService) from a config object +type Driver func(opts map[string]interface{}) (Service, error) - // Publish should issue a new message to all the topic's subscribers - Publish(ctx context.Context, topic string, msg []byte) error +// Drivers is a registry of drivers +var Drivers = make(map[string]Driver) - // Subscribe should create a subscription for new messages on the topic. - // If persistent, messages missed when offline should accumulate and be delivered on reconnect. - Subscribe(ctx context.Context, topic string, name string, persistent bool, fn func(ctx context.Context, msg []byte) error) error - - // Reset should clear all data in the service (useful during testing) - Reset(ctx context.Context) error -} - -// Service encapsulates functionality expected of components that store instance data in Beneath -type Service interface { - // MaxKeySize should return the maximum allowed byte size of a single record's key - MaxKeySize() int - - // MaxRecordSize should return the maximum allowed byte size of a single record - MaxRecordSize() int - - // MaxRecordsInBatch should return the highest number of records that may be passed in one RecordsReader - MaxRecordsInBatch() int - - // RegisterProject is called when a project is created *or updated* - RegisterProject(ctx context.Context, p Project) error - - // RemoveProject is called when a project is deleted - RemoveProject(ctx context.Context, p Project) error - - // RegisterInstance is called when a new instance is created - RegisterInstance(ctx context.Context, p Project, s Stream, i StreamInstance) error - - // PromoteInstance is called when an instance is promoted to be the main instance of the stream - PromoteInstance(ctx context.Context, p Project, s Stream, i StreamInstance) error - - // RemoveInstance is called when an instance is deleted - RemoveInstance(ctx context.Context, p Project, s Stream, i StreamInstance) error - - // Reset should clear all data in the service (useful during testing) - Reset(ctx context.Context) error -} - -// LookupService encapsulates functionality necessary to lookup, replay and subscribe to data. -// It's implementation is likely a mixture of a log and an indexed operational data store. -type LookupService interface { - Service - - // ParseQuery returns (replayCursors, changeCursors, err) - ParseQuery(ctx context.Context, p Project, s Stream, i StreamInstance, where queryparse.Query, compacted bool, partitions int) ([][]byte, [][]byte, error) - - // Peek returns (rewindCursor, changeCursor, err) - Peek(ctx context.Context, p Project, s Stream, i StreamInstance) ([]byte, []byte, error) - - // ReadCursor returns (records, nextCursor, err) - ReadCursor(ctx context.Context, p Project, s Stream, i StreamInstance, cursor []byte, limit int) (RecordsIterator, error) - - // WriteRecord persists the records - WriteRecords(ctx context.Context, p Project, s Stream, i StreamInstance, rs []Record) error - - // NOTE: Usage tracking is temporarily implemented here, but really should be implemented on top of the engine, not in it - - // CommitUsage writes a batch of usage metrics - CommitUsage(ctx context.Context, id uuid.UUID, period timeutil.Period, ts time.Time, usage pb.QuotaUsage) error - - // ReadSingleUsage reads usage metrics for one key - ReadSingleUsage(ctx context.Context, id uuid.UUID, period timeutil.Period, ts time.Time) (pb.QuotaUsage, error) - - // ReadUsage reads usage metrics for multiple periods and calls fn one by one - ReadUsage(ctx context.Context, id uuid.UUID, period timeutil.Period, from time.Time, until time.Time, fn func(ts time.Time, usage pb.QuotaUsage) error) error - - // ClearUsage clears all usage data saved for the id - ClearUsage(ctx context.Context, id uuid.UUID) error +// AddDriver registers a new driver (by passing the driver's constructor) +func AddDriver(name string, driver Driver) { + if Drivers[name] != nil { + panic(fmt.Errorf("Service driver already registered with name '%s'", name)) + } + Drivers[name] = driver } -// WarehouseService encapsulates functionality to analytically query records in an instance -type WarehouseService interface { - Service - - // WriteToWarehouse should insert the records in r for querying on the given instance - WriteToWarehouse(ctx context.Context, p Project, s Stream, i StreamInstance, rs []Record) error - - // GetWarehouseTableName should return the table name that the driver wants stream references in queries expanded to - GetWarehouseTableName(p Project, s Stream, i StreamInstance) string - - // AnalyzeWarehouseQuery should perform a dry-run of query - AnalyzeWarehouseQuery(ctx context.Context, query string) (WarehouseJob, error) - - // RunWarehouseQuery should start a query and return a job. If the job is not completed outright, it should be - // possible to poll the job with PollWarehouseJob using the job ID. - RunWarehouseQuery(ctx context.Context, jobID uuid.UUID, query string, partitions int, timeoutMs int, maxBytesScanned int) (WarehouseJob, error) - - // PollWarehouseJob should return the current state of the job identified by jobID - PollWarehouseJob(ctx context.Context, jobID uuid.UUID) (WarehouseJob, error) - - // ReadWarehouseCursor returns records for the cursor - ReadWarehouseCursor(ctx context.Context, cursor []byte, limit int) (RecordsIterator, error) -} +// Base +// ------ // Project encapsulates metadata about a Beneath project type Project interface { @@ -201,6 +117,98 @@ type Record interface { GetPrimaryKey() []byte } +// Services base +// ------------- + +// Service encapsulates functionality expected of components that store instance data in Beneath +type Service interface { + // AsLookupService should return the service cast as a LookupService if supported, else false + AsLookupService() LookupService + + // AsWarehouseService should return the service cast as a WarehouseService if supported, else false + AsWarehouseService() WarehouseService + + // MaxKeySize should return the maximum allowed byte size of a single record's key + MaxKeySize() int + + // MaxRecordSize should return the maximum allowed byte size of a single record + MaxRecordSize() int + + // MaxRecordsInBatch should return the highest number of records that may be passed in one RecordsReader + MaxRecordsInBatch() int + + // RegisterInstance is called when a new instance is created + RegisterInstance(ctx context.Context, s Stream, i StreamInstance) error + + // RemoveInstance is called when an instance is deleted + RemoveInstance(ctx context.Context, s Stream, i StreamInstance) error + + // Reset should clear all data in the service (useful during testing) + Reset(ctx context.Context) error +} + +// Lookup +// ------ + +// LookupService encapsulates functionality necessary to lookup, replay and subscribe to data. +// It's implementation is likely a mixture of a log and an indexed operational data store. +type LookupService interface { + Service + + // ParseQuery returns (replayCursors, changeCursors, err) + ParseQuery(ctx context.Context, p Project, s Stream, i StreamInstance, where queryparse.Query, compacted bool, partitions int) ([][]byte, [][]byte, error) + + // Peek returns (rewindCursor, changeCursor, err) + Peek(ctx context.Context, p Project, s Stream, i StreamInstance) ([]byte, []byte, error) + + // ReadCursor returns (records, nextCursor, err) + ReadCursor(ctx context.Context, p Project, s Stream, i StreamInstance, cursor []byte, limit int) (RecordsIterator, error) + + // WriteRecord persists the records + WriteRecords(ctx context.Context, p Project, s Stream, i StreamInstance, rs []Record) error + + // NOTE: Usage tracking is temporarily implemented here, but really should be implemented on top of the engine, not in it + + // CommitUsage writes a batch of usage metrics + CommitUsage(ctx context.Context, id uuid.UUID, period timeutil.Period, ts time.Time, usage pb.QuotaUsage) error + + // ReadSingleUsage reads usage metrics for one key + ReadSingleUsage(ctx context.Context, id uuid.UUID, period timeutil.Period, ts time.Time) (pb.QuotaUsage, error) + + // ReadUsage reads usage metrics for multiple periods and calls fn one by one + ReadUsage(ctx context.Context, id uuid.UUID, period timeutil.Period, from time.Time, until time.Time, fn func(ts time.Time, usage pb.QuotaUsage) error) error + + // ClearUsage clears all usage data saved for the id + ClearUsage(ctx context.Context, id uuid.UUID) error +} + +// Warehouse +// --------- + +// WarehouseService encapsulates functionality to analytically query records in an instance +type WarehouseService interface { + Service + + // WriteToWarehouse should insert the records in r for querying on the given instance + WriteToWarehouse(ctx context.Context, p Project, s Stream, i StreamInstance, rs []Record) error + + // GetWarehouseTableName should return the table name that the driver wants stream references in queries expanded to + GetWarehouseTableName(p Project, s Stream, i StreamInstance) string + + // AnalyzeWarehouseQuery should perform a dry-run of query + AnalyzeWarehouseQuery(ctx context.Context, query string) (WarehouseJob, error) + + // RunWarehouseQuery should start a query and return a job. If the job is not completed outright, it should be + // possible to poll the job with PollWarehouseJob using the job ID. + RunWarehouseQuery(ctx context.Context, jobID uuid.UUID, query string, partitions int, timeoutMs int, maxBytesScanned int) (WarehouseJob, error) + + // PollWarehouseJob should return the current state of the job identified by jobID + PollWarehouseJob(ctx context.Context, jobID uuid.UUID) (WarehouseJob, error) + + // ReadWarehouseCursor returns records for the cursor + ReadWarehouseCursor(ctx context.Context, cursor []byte, limit int) (RecordsIterator, error) +} + // WarehouseJobStatus represents the current status of a warehouse job type WarehouseJobStatus int diff --git a/infrastructure/engine/driver/mock/mock.go b/infrastructure/engine/driver/mock/mock.go new file mode 100644 index 00000000..ef524303 --- /dev/null +++ b/infrastructure/engine/driver/mock/mock.go @@ -0,0 +1,27 @@ +package mock + +import ( + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" +) + +// Mock implements WarehouseService +type Mock struct { +} + +func init() { + driver.AddDriver("mock", newMock) +} + +func newMock(optsMap map[string]interface{}) (driver.Service, error) { + return &Mock{}, nil +} + +// AsLookupService implements Service +func (p *Mock) AsLookupService() driver.LookupService { + return nil +} + +// AsWarehouseService implements Service +func (p *Mock) AsWarehouseService() driver.WarehouseService { + return p +} diff --git a/infrastructure/engine/driver/mock/service.go b/infrastructure/engine/driver/mock/service.go new file mode 100644 index 00000000..a38cf148 --- /dev/null +++ b/infrastructure/engine/driver/mock/service.go @@ -0,0 +1,37 @@ +package mock + +import ( + "context" + + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" +) + +// MaxKeySize implements beneath.Service +func (m Mock) MaxKeySize() int { + return 1024 // 1 kb +} + +// MaxRecordSize implements beneath.Service +func (m Mock) MaxRecordSize() int { + return 1048576 // 1 mb +} + +// MaxRecordsInBatch implements beneath.Service +func (m Mock) MaxRecordsInBatch() int { + return 10000 +} + +// RegisterInstance implements beneath.Service +func (m Mock) RegisterInstance(ctx context.Context, s driver.Stream, i driver.StreamInstance) error { + return nil +} + +// RemoveInstance implements beneath.Service +func (m Mock) RemoveInstance(ctx context.Context, s driver.Stream, i driver.StreamInstance) error { + return nil +} + +// Reset implements beneath.Service +func (m Mock) Reset(ctx context.Context) error { + return nil +} diff --git a/engine/driver/mock/util.go b/infrastructure/engine/driver/mock/util.go similarity index 83% rename from engine/driver/mock/util.go rename to infrastructure/engine/driver/mock/util.go index 9739ac37..16a36eec 100644 --- a/engine/driver/mock/util.go +++ b/infrastructure/engine/driver/mock/util.go @@ -1,6 +1,8 @@ package mock -import "gitlab.com/beneath-hq/beneath/engine/driver" +import ( + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" +) type mockRecordsIterator struct{} diff --git a/engine/driver/mock/warehouse.go b/infrastructure/engine/driver/mock/warehouse.go similarity index 95% rename from engine/driver/mock/warehouse.go rename to infrastructure/engine/driver/mock/warehouse.go index c2dbb9e6..133e35dd 100644 --- a/engine/driver/mock/warehouse.go +++ b/infrastructure/engine/driver/mock/warehouse.go @@ -6,7 +6,7 @@ import ( "fmt" uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/engine/driver" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" ) // WriteToWarehouse implements beneath.WarehouseService diff --git a/engine/driver/postgres/lookup.go b/infrastructure/engine/driver/postgres/lookup.go similarity index 95% rename from engine/driver/postgres/lookup.go rename to infrastructure/engine/driver/postgres/lookup.go index ffda3842..5b4e0f1e 100644 --- a/engine/driver/postgres/lookup.go +++ b/infrastructure/engine/driver/postgres/lookup.go @@ -3,7 +3,7 @@ package postgres import ( "context" - "gitlab.com/beneath-hq/beneath/engine/driver" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" "gitlab.com/beneath-hq/beneath/pkg/queryparse" ) diff --git a/infrastructure/engine/driver/postgres/postgres.go b/infrastructure/engine/driver/postgres/postgres.go new file mode 100644 index 00000000..66d4661c --- /dev/null +++ b/infrastructure/engine/driver/postgres/postgres.go @@ -0,0 +1,41 @@ +package postgres + +import ( + "fmt" + + "github.com/mitchellh/mapstructure" + + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" +) + +// Postgres implements LookupService and WarehouseService +type Postgres struct { +} + +// Options for connecting to Postgres +type Options struct { +} + +func init() { + driver.AddDriver("postgres", newPostgres) +} + +func newPostgres(optsMap map[string]interface{}) (driver.Service, error) { + var opts Options + err := mapstructure.Decode(optsMap, &opts) + if err != nil { + return nil, fmt.Errorf("error decoding postgres options: %s", err.Error()) + } + + return &Postgres{}, nil +} + +// AsLookupService implements Service +func (p *Postgres) AsLookupService() driver.LookupService { + return p +} + +// AsWarehouseService implements Service +func (p *Postgres) AsWarehouseService() driver.WarehouseService { + return p +} diff --git a/infrastructure/engine/driver/postgres/service.go b/infrastructure/engine/driver/postgres/service.go new file mode 100644 index 00000000..d869ae35 --- /dev/null +++ b/infrastructure/engine/driver/postgres/service.go @@ -0,0 +1,37 @@ +package postgres + +import ( + "context" + + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" +) + +// MaxKeySize implements beneath.Service +func (b Postgres) MaxKeySize() int { + panic("todo") +} + +// MaxRecordSize implements beneath.Service +func (b Postgres) MaxRecordSize() int { + panic("todo") +} + +// MaxRecordsInBatch implements beneath.Service +func (b Postgres) MaxRecordsInBatch() int { + panic("todo") +} + +// RegisterInstance implements beneath.Service +func (b Postgres) RegisterInstance(ctx context.Context, s driver.Stream, i driver.StreamInstance) error { + panic("todo") +} + +// RemoveInstance implements beneath.Service +func (b Postgres) RemoveInstance(ctx context.Context, s driver.Stream, i driver.StreamInstance) error { + panic("todo") +} + +// Reset implements beneath.Service +func (b Postgres) Reset(ctx context.Context) error { + panic("todo") +} diff --git a/engine/driver/postgres/usage.go b/infrastructure/engine/driver/postgres/usage.go similarity index 93% rename from engine/driver/postgres/usage.go rename to infrastructure/engine/driver/postgres/usage.go index d666583f..40eacb11 100644 --- a/engine/driver/postgres/usage.go +++ b/infrastructure/engine/driver/postgres/usage.go @@ -6,7 +6,7 @@ import ( uuid "github.com/satori/go.uuid" - pb "gitlab.com/beneath-hq/beneath/engine/proto" + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" "gitlab.com/beneath-hq/beneath/pkg/timeutil" ) diff --git a/engine/driver/postgres/warehouse.go b/infrastructure/engine/driver/postgres/warehouse.go similarity index 95% rename from engine/driver/postgres/warehouse.go rename to infrastructure/engine/driver/postgres/warehouse.go index 96c4feb0..410a02a6 100644 --- a/engine/driver/postgres/warehouse.go +++ b/infrastructure/engine/driver/postgres/warehouse.go @@ -4,7 +4,7 @@ import ( "context" uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/engine/driver" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" ) // WriteToWarehouse implements beneath.WarehouseService diff --git a/infrastructure/engine/engine.go b/infrastructure/engine/engine.go new file mode 100644 index 00000000..5369241a --- /dev/null +++ b/infrastructure/engine/engine.go @@ -0,0 +1,148 @@ +package engine + +import ( + "context" + "fmt" + + "golang.org/x/sync/errgroup" + + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" + "gitlab.com/beneath-hq/beneath/pkg/codec" + "gitlab.com/beneath-hq/beneath/pkg/mathutil" +) + +// Engine interfaces with the data layer +type Engine struct { + Lookup driver.LookupService + Warehouse driver.WarehouseService + + maxBatchLength int + maxRecordSize int + maxKeySize int +} + +// IndexOptions configures the index service +type IndexOptions struct { + DriverName string `mapstructure:"driver"` + DriverOptions map[string]interface{} `mapstructure:",remain"` +} + +// WarehouseOptions configures the warehouse service +type WarehouseOptions struct { + DriverName string `mapstructure:"driver"` + DriverOptions map[string]interface{} `mapstructure:",remain"` +} + +// NewEngine constructs a new Engine for the given drivers +func NewEngine(indexOpts *IndexOptions, warehouseOpts *WarehouseOptions) (*Engine, error) { + // make lookup service + lookupServiceT, err := getService(indexOpts.DriverName, indexOpts.DriverOptions) + if err != nil { + return nil, err + } + lookupService := lookupServiceT.AsLookupService() + if lookupService == nil { + return nil, fmt.Errorf("driver '%s' is not a valid index service driver", indexOpts.DriverName) + } + + // make warehouse service + var warehouseService driver.WarehouseService + if warehouseOpts.DriverName == indexOpts.DriverName { + warehouseService = lookupServiceT.AsWarehouseService() + if warehouseService == nil { + return nil, fmt.Errorf("driver '%s' is not a valid warehouse service driver", warehouseOpts.DriverName) + } + } else { + warehouseServiceT, err := getService(warehouseOpts.DriverName, warehouseOpts.DriverOptions) + if err != nil { + return nil, err + } + warehouseService = warehouseServiceT.AsWarehouseService() + if warehouseService == nil { + return nil, fmt.Errorf("driver '%s' is not a valid warehouse service driver", warehouseOpts.DriverName) + } + } + + e := &Engine{ + Lookup: lookupService, + Warehouse: warehouseService, + maxBatchLength: mathutil.MinInts(lookupService.MaxRecordsInBatch(), warehouseService.MaxRecordsInBatch()), + maxRecordSize: mathutil.MinInts(lookupService.MaxRecordSize(), warehouseService.MaxRecordSize()), + maxKeySize: mathutil.MinInts(lookupService.MaxKeySize(), warehouseService.MaxKeySize()), + } + + return e, nil +} + +func getService(driverName string, driverOpts map[string]interface{}) (driver.Service, error) { + driver, ok := driver.Drivers[driverName] + if !ok { + return nil, fmt.Errorf("no driver found with name '%s'", driverName) + } + + return driver(driverOpts) +} + +// Healthy returns true if connected to all services +func (e *Engine) Healthy() bool { + return true +} + +// CheckRecordSize validates that the record fits within the constraints of the underlying infrastructure +func (e *Engine) CheckRecordSize(s driver.Stream, structured map[string]interface{}, avroBytesLen int) error { + if avroBytesLen > e.maxRecordSize { + return fmt.Errorf("encoded record size exceeds maximum of %d bytes", e.maxRecordSize) + } + + codec := s.GetCodec() + + err := e.checkKeySize(codec, codec.PrimaryIndex, structured) + if err != nil { + return err + } + + for _, index := range codec.SecondaryIndexes { + err := e.checkKeySize(codec, index, structured) + if err != nil { + return err + } + } + + return nil +} + +func (e *Engine) checkKeySize(codec *codec.Codec, index codec.Index, structured map[string]interface{}) error { + key, err := codec.MarshalKey(index, structured) + if err != nil { + return err + } + + if len(key) > e.maxKeySize { + return fmt.Errorf("encoded key size for index on fields %v exceeds maximum length of %d bytes", index.GetFields(), e.maxKeySize) + } + + return nil +} + +// CheckBatchLength validates that the number of records in a batch fits within the constraints of the underlying infrastructure +func (e *Engine) CheckBatchLength(length int) error { + if length > e.maxBatchLength { + return fmt.Errorf("batch length exceeds maximum of %d", e.maxBatchLength) + } + return nil +} + +// Reset resets the state of the engine (useful during testing) +func (e *Engine) Reset(ctx context.Context) error { + group, ctx := errgroup.WithContext(ctx) + + group.Go(func() error { + return e.Lookup.Reset(ctx) + }) + + group.Go(func() error { + return e.Warehouse.Reset(ctx) + }) + + return group.Wait() +} diff --git a/engine/metrics.go b/infrastructure/engine/metrics.go similarity index 94% rename from engine/metrics.go rename to infrastructure/engine/metrics.go index 8af22639..07fc4302 100644 --- a/engine/metrics.go +++ b/infrastructure/engine/metrics.go @@ -6,7 +6,7 @@ import ( uuid "github.com/satori/go.uuid" - pb "gitlab.com/beneath-hq/beneath/engine/proto" + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" "gitlab.com/beneath-hq/beneath/pkg/timeutil" ) diff --git a/engine/proto/engine.pb.go b/infrastructure/engine/proto/engine.pb.go similarity index 68% rename from engine/proto/engine.pb.go rename to infrastructure/engine/proto/engine.pb.go index 059a3749..898d3b1a 100644 --- a/engine/proto/engine.pb.go +++ b/infrastructure/engine/proto/engine.pb.go @@ -1,12 +1,12 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: engine/proto/engine.proto +// source: infrastructure/engine/proto/engine.proto package proto import ( fmt "fmt" proto "github.com/golang/protobuf/proto" - proto1 "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" + proto1 "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" math "math" ) @@ -33,7 +33,7 @@ func (m *WriteRequest) Reset() { *m = WriteRequest{} } func (m *WriteRequest) String() string { return proto.CompactTextString(m) } func (*WriteRequest) ProtoMessage() {} func (*WriteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_48584fac715a225d, []int{0} + return fileDescriptor_0e27bf340d39c716, []int{0} } func (m *WriteRequest) XXX_Unmarshal(b []byte) error { @@ -82,7 +82,7 @@ func (m *WriteReport) Reset() { *m = WriteReport{} } func (m *WriteReport) String() string { return proto.CompactTextString(m) } func (*WriteReport) ProtoMessage() {} func (*WriteReport) Descriptor() ([]byte, []int) { - return fileDescriptor_48584fac715a225d, []int{1} + return fileDescriptor_0e27bf340d39c716, []int{1} } func (m *WriteReport) XXX_Unmarshal(b []byte) error { @@ -136,24 +136,27 @@ func init() { proto.RegisterType((*WriteReport)(nil), "engine.WriteReport") } -func init() { proto.RegisterFile("engine/proto/engine.proto", fileDescriptor_48584fac715a225d) } +func init() { + proto.RegisterFile("infrastructure/engine/proto/engine.proto", fileDescriptor_0e27bf340d39c716) +} -var fileDescriptor_48584fac715a225d = []byte{ - // 255 bytes of a gzipped FileDescriptorProto +var fileDescriptor_0e27bf340d39c716 = []byte{ + // 271 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0x41, 0x4b, 0xc3, 0x30, - 0x14, 0xc7, 0xe9, 0xa6, 0x53, 0xd2, 0x8a, 0xd2, 0x53, 0xa6, 0x07, 0xcb, 0xbc, 0x14, 0xd1, 0x06, - 0xf5, 0x1b, 0x28, 0x08, 0xbd, 0x06, 0x41, 0xf0, 0x52, 0xd2, 0xe4, 0xd1, 0x05, 0x66, 0xd2, 0xa6, - 0x6f, 0x8e, 0x7d, 0x0a, 0xbf, 0xb2, 0x34, 0x4d, 0x45, 0x2f, 0x3b, 0x25, 0xff, 0x5f, 0x7e, 0xbc, - 0x7f, 0x78, 0x64, 0x09, 0xa6, 0xd1, 0x06, 0x58, 0xeb, 0x2c, 0x5a, 0x36, 0x86, 0xc2, 0x87, 0x74, - 0x31, 0xa6, 0xcb, 0xac, 0x11, 0x08, 0x3b, 0xb1, 0x67, 0x8d, 0x6b, 0x65, 0x10, 0x03, 0x1a, 0xcd, - 0x55, 0x47, 0x92, 0x77, 0xa7, 0x11, 0x38, 0x74, 0x5b, 0xe8, 0x31, 0x5d, 0x92, 0xd3, 0xdd, 0x90, - 0x2b, 0xad, 0x68, 0x94, 0x45, 0x79, 0xc2, 0x4f, 0x7c, 0x2e, 0x55, 0xfa, 0x4a, 0x2e, 0xb4, 0xe9, - 0x51, 0x18, 0x09, 0x95, 0x03, 0x69, 0x9d, 0xea, 0xe9, 0x2c, 0x9b, 0xe7, 0xf1, 0xe3, 0x55, 0x31, - 0x0d, 0xfd, 0x7a, 0x28, 0xca, 0xe0, 0xf0, 0x51, 0xe1, 0xe7, 0xfa, 0x3f, 0x58, 0x7d, 0x47, 0x24, - 0x0e, 0x9d, 0xad, 0x75, 0x07, 0x2b, 0xaf, 0x49, 0xfc, 0x5b, 0xa9, 0x15, 0x9d, 0xf9, 0x57, 0x32, - 0xa1, 0x52, 0xa5, 0x37, 0xe4, 0x2c, 0x7c, 0xa5, 0x92, 0x76, 0x6b, 0x90, 0xce, 0xb3, 0x28, 0x3f, - 0xe6, 0x49, 0x80, 0x2f, 0x03, 0x1b, 0xa6, 0xd4, 0x7b, 0x84, 0xbe, 0x42, 0x8b, 0x62, 0x43, 0x8f, - 0xbc, 0x42, 0x3c, 0x7a, 0x1b, 0xc8, 0xf3, 0xdd, 0xc7, 0x6d, 0xa3, 0x71, 0x23, 0xea, 0x42, 0xda, - 0x4f, 0x56, 0x83, 0x01, 0x81, 0xeb, 0xfb, 0x75, 0x37, 0x5d, 0xd9, 0xdf, 0x4d, 0xd7, 0x0b, 0x7f, - 0x3c, 0xfd, 0x04, 0x00, 0x00, 0xff, 0xff, 0x10, 0xa3, 0x81, 0x02, 0x80, 0x01, 0x00, 0x00, + 0x14, 0xc7, 0xe9, 0xa6, 0x53, 0xd2, 0x8a, 0xd2, 0x53, 0xd5, 0x83, 0x65, 0x7a, 0xe8, 0xc5, 0x06, + 0xf5, 0x24, 0xde, 0x14, 0x84, 0x5e, 0x8b, 0x20, 0x78, 0x29, 0x69, 0xf2, 0xec, 0x02, 0x33, 0x69, + 0x93, 0xd7, 0x8d, 0x7d, 0x0a, 0xbf, 0xb2, 0x34, 0x4d, 0x85, 0x5d, 0x76, 0x4a, 0xfe, 0xbf, 0xfc, + 0x78, 0xff, 0xf0, 0x48, 0x26, 0xd5, 0xb7, 0x61, 0x16, 0x4d, 0xcf, 0xb1, 0x37, 0x40, 0x41, 0x35, + 0x52, 0x01, 0x6d, 0x8d, 0x46, 0xed, 0x43, 0xee, 0x42, 0xbc, 0x18, 0xd3, 0xd5, 0x9d, 0x05, 0xb3, + 0x01, 0x43, 0x05, 0x43, 0x46, 0x1b, 0xd3, 0x72, 0x2f, 0x37, 0x0c, 0x61, 0xcb, 0x76, 0xa3, 0xbd, + 0xec, 0x48, 0xf4, 0x69, 0x24, 0x42, 0x09, 0x5d, 0x0f, 0x16, 0xe3, 0x4b, 0x72, 0xba, 0x1d, 0x72, + 0x25, 0x45, 0x12, 0xa4, 0x41, 0x16, 0x95, 0x27, 0x2e, 0x17, 0x22, 0x7e, 0x27, 0x17, 0x52, 0x59, + 0x64, 0x8a, 0x43, 0x65, 0x80, 0x6b, 0x23, 0x6c, 0x32, 0x4b, 0xe7, 0x59, 0xf8, 0x78, 0x9d, 0x4f, + 0x43, 0x37, 0x0f, 0x79, 0xe1, 0x9d, 0x72, 0x54, 0xca, 0x73, 0xb9, 0x0f, 0x96, 0xbf, 0x01, 0x09, + 0x7d, 0x67, 0xab, 0xcd, 0xc1, 0xca, 0x1b, 0x12, 0xfe, 0x57, 0x4a, 0x91, 0xcc, 0xdc, 0x2b, 0x99, + 0x50, 0x21, 0xe2, 0x5b, 0x72, 0xe6, 0xbf, 0x52, 0x71, 0xdd, 0x2b, 0x4c, 0xe6, 0x69, 0x90, 0x1d, + 0x97, 0x91, 0x87, 0x6f, 0x03, 0x1b, 0xa6, 0xd4, 0x3b, 0x04, 0x5b, 0xa1, 0x46, 0xb6, 0x4e, 0x8e, + 0x9c, 0x42, 0x1c, 0xfa, 0x18, 0xc8, 0xeb, 0xcb, 0xd7, 0x73, 0x23, 0x71, 0xcd, 0xea, 0x9c, 0xeb, + 0x1f, 0x5a, 0x83, 0x02, 0x86, 0xab, 0xfb, 0x55, 0x37, 0x5d, 0xe9, 0x81, 0xe5, 0xd7, 0x0b, 0x77, + 0x3c, 0xfd, 0x05, 0x00, 0x00, 0xff, 0xff, 0x0e, 0x9f, 0xbf, 0xd4, 0xa2, 0x01, 0x00, 0x00, } diff --git a/engine/proto/engine.proto b/infrastructure/engine/proto/engine.proto similarity index 67% rename from engine/proto/engine.proto rename to infrastructure/engine/proto/engine.proto index 857d0c25..737be54b 100644 --- a/engine/proto/engine.proto +++ b/infrastructure/engine/proto/engine.proto @@ -1,8 +1,8 @@ syntax = "proto3"; -option go_package = "gitlab.com/beneath-hq/beneath/engine/proto"; +option go_package = "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto"; package engine; -import "gateway/grpc/proto/gateway.proto"; +import "server/data/grpc/proto/gateway.proto"; message WriteRequest { bytes write_id = 1; diff --git a/engine/proto/quota.pb.go b/infrastructure/engine/proto/quota.pb.go similarity index 65% rename from engine/proto/quota.pb.go rename to infrastructure/engine/proto/quota.pb.go index a7c9db6b..724723fe 100644 --- a/engine/proto/quota.pb.go +++ b/infrastructure/engine/proto/quota.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: engine/proto/quota.proto +// source: infrastructure/engine/proto/quota.proto package proto @@ -38,7 +38,7 @@ func (m *QuotaUsage) Reset() { *m = QuotaUsage{} } func (m *QuotaUsage) String() string { return proto.CompactTextString(m) } func (*QuotaUsage) ProtoMessage() {} func (*QuotaUsage) Descriptor() ([]byte, []int) { - return fileDescriptor_0e6f517179ac6746, []int{0} + return fileDescriptor_c0a3f0563eb98c2f, []int{0} } func (m *QuotaUsage) XXX_Unmarshal(b []byte) error { @@ -119,23 +119,26 @@ func init() { proto.RegisterType((*QuotaUsage)(nil), "engine.QuotaUsage") } -func init() { proto.RegisterFile("engine/proto/quota.proto", fileDescriptor_0e6f517179ac6746) } - -var fileDescriptor_0e6f517179ac6746 = []byte{ - // 238 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0xcf, 0x4a, 0xc3, 0x40, - 0x10, 0xc6, 0x69, 0xab, 0x69, 0x3a, 0xad, 0x97, 0x3d, 0xa5, 0x48, 0xf1, 0xdf, 0x45, 0x44, 0x9b, - 0x83, 0x6f, 0xd0, 0x17, 0x10, 0x0b, 0x5e, 0xbc, 0xc8, 0x6e, 0x3a, 0xa4, 0x01, 0xdd, 0x4d, 0x76, - 0x57, 0xc4, 0x17, 0xf0, 0xb9, 0x65, 0xbe, 0x21, 0xd0, 0xd3, 0xce, 0xfc, 0xbe, 0x6f, 0xe6, 0x1b, - 0x96, 0x2a, 0xf6, 0x6d, 0xe7, 0xb9, 0xee, 0x63, 0xc8, 0xa1, 0x1e, 0xbe, 0x43, 0xb6, 0x5b, 0xd4, - 0xa6, 0x50, 0xe5, 0xf6, 0x6f, 0x4a, 0xf4, 0x2a, 0xfc, 0x2d, 0xd9, 0x96, 0xcd, 0x9a, 0xca, 0xc8, - 0xf6, 0xf0, 0x11, 0xfa, 0x54, 0x4d, 0xae, 0x27, 0xf7, 0xb3, 0xfd, 0x5c, 0xfa, 0x97, 0x3e, 0x99, - 0x1b, 0x5a, 0x41, 0x8a, 0xdc, 0x84, 0x78, 0x48, 0xd5, 0x14, 0xf2, 0x52, 0xd8, 0x5e, 0x91, 0xd9, - 0x10, 0xc1, 0xe2, 0x7e, 0x33, 0xa7, 0x6a, 0x06, 0xc3, 0x42, 0xc8, 0x4e, 0x80, 0xb9, 0xa4, 0xc5, - 0x4f, 0xec, 0x32, 0x63, 0xfb, 0x19, 0xd4, 0x12, 0x40, 0xd6, 0xdf, 0xd1, 0x85, 0x8a, 0xe3, 0xfe, - 0x73, 0x18, 0x56, 0x80, 0x63, 0xc0, 0x15, 0x2d, 0xd5, 0xa4, 0x09, 0x05, 0x2c, 0x04, 0xa4, 0x11, - 0x6b, 0x2a, 0x53, 0x63, 0x3d, 0x12, 0xe6, 0x7a, 0xbf, 0xf4, 0x12, 0xb0, 0x21, 0x82, 0xa4, 0xa3, - 0xa5, 0x1e, 0x27, 0x04, 0x93, 0xbb, 0xc7, 0xf7, 0x87, 0xb6, 0xcb, 0x9f, 0xd6, 0x6d, 0x9b, 0xf0, - 0x55, 0x3b, 0xf6, 0x6c, 0xf3, 0xf1, 0xe9, 0x38, 0x8c, 0x65, 0x7d, 0xfa, 0x95, 0xae, 0xc0, 0xf3, - 0xfc, 0x1f, 0x00, 0x00, 0xff, 0xff, 0x15, 0x56, 0x89, 0x7d, 0x61, 0x01, 0x00, 0x00, +func init() { + proto.RegisterFile("infrastructure/engine/proto/quota.proto", fileDescriptor_c0a3f0563eb98c2f) +} + +var fileDescriptor_c0a3f0563eb98c2f = []byte{ + // 250 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0xbf, 0x4e, 0xc3, 0x40, + 0x0c, 0xc6, 0xd5, 0x16, 0xd2, 0xd4, 0x2d, 0xcb, 0x4d, 0xa9, 0x50, 0xc5, 0xbf, 0x01, 0x16, 0x7a, + 0x03, 0x13, 0x62, 0xeb, 0x0b, 0x20, 0x2a, 0xb1, 0xb0, 0xa0, 0x4b, 0x6a, 0xd2, 0x93, 0xe0, 0x2e, + 0xb9, 0x73, 0x84, 0x78, 0x01, 0x9e, 0x1b, 0xd9, 0x56, 0x56, 0xa6, 0xb3, 0x7f, 0xdf, 0x67, 0x7f, + 0xd6, 0xc1, 0xad, 0x0f, 0x1f, 0xc9, 0x65, 0x4a, 0x43, 0x43, 0x43, 0x42, 0x8b, 0xa1, 0xf5, 0x01, + 0x6d, 0x97, 0x22, 0x45, 0xdb, 0x0f, 0x91, 0xdc, 0x56, 0x6a, 0x53, 0xa8, 0x72, 0xfd, 0x3b, 0x05, + 0x78, 0x61, 0xfe, 0x9a, 0x5d, 0x8b, 0x66, 0x0d, 0x65, 0x42, 0x77, 0x78, 0x8f, 0x5d, 0xae, 0x26, + 0x97, 0x93, 0xbb, 0xd9, 0x7e, 0xce, 0xfd, 0x73, 0x97, 0xcd, 0x15, 0xac, 0x44, 0x4a, 0xd8, 0xc4, + 0x74, 0xc8, 0xd5, 0x54, 0xe4, 0x25, 0xb3, 0xbd, 0x22, 0xb3, 0x01, 0x10, 0x4b, 0xfd, 0x43, 0x98, + 0xab, 0x99, 0x18, 0x16, 0x4c, 0x76, 0x0c, 0xcc, 0x39, 0x2c, 0xbe, 0x93, 0x27, 0x94, 0xed, 0x27, + 0xa2, 0x96, 0x02, 0x78, 0xfd, 0x0d, 0x9c, 0xa9, 0x38, 0xee, 0x3f, 0x15, 0xc3, 0x4a, 0xe0, 0x18, + 0x70, 0x01, 0x4b, 0x35, 0x69, 0x42, 0x21, 0x16, 0x10, 0xa4, 0x11, 0x6b, 0x28, 0x73, 0xe3, 0x82, + 0x24, 0xcc, 0xf5, 0x7e, 0xee, 0x39, 0x60, 0x03, 0x20, 0x92, 0x8e, 0x96, 0x7a, 0x1c, 0x13, 0x99, + 0xdc, 0x3d, 0xbd, 0x3d, 0xb6, 0x9e, 0x3e, 0x5d, 0xbd, 0x6d, 0xe2, 0x97, 0xad, 0x31, 0xa0, 0xa3, + 0xe3, 0xfd, 0xb1, 0x1f, 0x4b, 0xfb, 0xcf, 0xcf, 0xd6, 0x85, 0x3c, 0x0f, 0x7f, 0x01, 0x00, 0x00, + 0xff, 0xff, 0xf9, 0x15, 0x4b, 0xf6, 0x7f, 0x01, 0x00, 0x00, } diff --git a/engine/proto/quota.proto b/infrastructure/engine/proto/quota.proto similarity index 75% rename from engine/proto/quota.proto rename to infrastructure/engine/proto/quota.proto index d336eaa6..732c7d62 100644 --- a/engine/proto/quota.proto +++ b/infrastructure/engine/proto/quota.proto @@ -1,5 +1,5 @@ syntax = "proto3"; -option go_package = "gitlab.com/beneath-hq/beneath/engine/proto"; +option go_package = "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto"; package engine; message QuotaUsage { diff --git a/infrastructure/engine/proto/taskqueue.pb.go b/infrastructure/engine/proto/taskqueue.pb.go new file mode 100644 index 00000000..2eccb912 --- /dev/null +++ b/infrastructure/engine/proto/taskqueue.pb.go @@ -0,0 +1,108 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: infrastructure/engine/proto/taskqueue.proto + +package proto + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type BusMsg struct { + Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Timestamp int64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Payload []byte `protobuf:"bytes,4,opt,name=payload,proto3" json:"payload,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BusMsg) Reset() { *m = BusMsg{} } +func (m *BusMsg) String() string { return proto.CompactTextString(m) } +func (*BusMsg) ProtoMessage() {} +func (*BusMsg) Descriptor() ([]byte, []int) { + return fileDescriptor_aa449069ff79111e, []int{0} +} + +func (m *BusMsg) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BusMsg.Unmarshal(m, b) +} +func (m *BusMsg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BusMsg.Marshal(b, m, deterministic) +} +func (m *BusMsg) XXX_Merge(src proto.Message) { + xxx_messageInfo_BusMsg.Merge(m, src) +} +func (m *BusMsg) XXX_Size() int { + return xxx_messageInfo_BusMsg.Size(m) +} +func (m *BusMsg) XXX_DiscardUnknown() { + xxx_messageInfo_BusMsg.DiscardUnknown(m) +} + +var xxx_messageInfo_BusMsg proto.InternalMessageInfo + +func (m *BusMsg) GetId() []byte { + if m != nil { + return m.Id + } + return nil +} + +func (m *BusMsg) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *BusMsg) GetTimestamp() int64 { + if m != nil { + return m.Timestamp + } + return 0 +} + +func (m *BusMsg) GetPayload() []byte { + if m != nil { + return m.Payload + } + return nil +} + +func init() { + proto.RegisterType((*BusMsg)(nil), "engine.BusMsg") +} + +func init() { + proto.RegisterFile("infrastructure/engine/proto/taskqueue.proto", fileDescriptor_aa449069ff79111e) +} + +var fileDescriptor_aa449069ff79111e = []byte{ + // 185 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x8e, 0x31, 0x6b, 0x85, 0x30, + 0x14, 0x85, 0x89, 0x8a, 0xc5, 0x50, 0x3a, 0x64, 0xca, 0xd0, 0x41, 0x3a, 0x09, 0xa5, 0x66, 0xe8, + 0x54, 0xba, 0xb9, 0x77, 0x71, 0xec, 0x76, 0x35, 0xb7, 0x1a, 0x6a, 0x12, 0x4d, 0x6e, 0x86, 0xf7, + 0xef, 0x1f, 0xe4, 0x21, 0x6f, 0x7b, 0xd3, 0xfd, 0xbe, 0x7b, 0xe0, 0x70, 0xf8, 0xbb, 0x71, 0x7f, + 0x01, 0x22, 0x85, 0x34, 0x53, 0x0a, 0xa8, 0xd0, 0x2d, 0xc6, 0xa1, 0xda, 0x83, 0x27, 0xaf, 0x08, + 0xe2, 0xff, 0x91, 0x30, 0x61, 0x9f, 0x5d, 0xd4, 0xb7, 0xf4, 0x4d, 0xf3, 0x7a, 0x48, 0xf1, 0x27, + 0x2e, 0xe2, 0x85, 0x17, 0x46, 0x4b, 0xd6, 0xb2, 0xee, 0x79, 0x2c, 0x8c, 0x16, 0x82, 0x57, 0x0e, + 0x2c, 0xca, 0xa2, 0x65, 0x5d, 0x33, 0x66, 0x16, 0xaf, 0xbc, 0x21, 0x63, 0x31, 0x12, 0xd8, 0x5d, + 0x96, 0x2d, 0xeb, 0xca, 0xf1, 0xfe, 0x10, 0x92, 0x3f, 0xed, 0x70, 0xd9, 0x3c, 0x68, 0x59, 0xe5, + 0x9a, 0x53, 0x87, 0xef, 0xdf, 0xaf, 0xc5, 0xd0, 0x06, 0x53, 0x3f, 0x7b, 0xab, 0x26, 0x74, 0x08, + 0xb4, 0x7e, 0xac, 0xc7, 0x89, 0xea, 0xc1, 0xf4, 0xa9, 0xce, 0xe7, 0xf3, 0x1a, 0x00, 0x00, 0xff, + 0xff, 0x8e, 0xa0, 0xad, 0x56, 0xe0, 0x00, 0x00, 0x00, +} diff --git a/infrastructure/engine/proto/taskqueue.proto b/infrastructure/engine/proto/taskqueue.proto new file mode 100644 index 00000000..407e9f8e --- /dev/null +++ b/infrastructure/engine/proto/taskqueue.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; +option go_package = "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto"; +package engine; + +message BusMsg { + bytes id = 1; + string name = 2; + int64 timestamp = 3; + bytes payload = 4; +} diff --git a/engine/query.go b/infrastructure/engine/query.go similarity index 97% rename from engine/query.go rename to infrastructure/engine/query.go index fdfb31f8..2ff81d26 100644 --- a/engine/query.go +++ b/infrastructure/engine/query.go @@ -9,7 +9,7 @@ import ( "golang.org/x/sync/errgroup" - "gitlab.com/beneath-hq/beneath/engine/driver" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" ) const ( diff --git a/engine/query_test.go b/infrastructure/engine/query_test.go similarity index 94% rename from engine/query_test.go rename to infrastructure/engine/query_test.go index c0edfb6e..73e08acb 100644 --- a/engine/query_test.go +++ b/infrastructure/engine/query_test.go @@ -8,8 +8,8 @@ import ( uuid "github.com/satori/go.uuid" "github.com/stretchr/testify/assert" - "gitlab.com/beneath-hq/beneath/engine/driver" - "gitlab.com/beneath-hq/beneath/engine/driver/mock" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver/mock" "gitlab.com/beneath-hq/beneath/pkg/codec" ) diff --git a/infrastructure/engine/service.go b/infrastructure/engine/service.go new file mode 100644 index 00000000..7491931f --- /dev/null +++ b/infrastructure/engine/service.go @@ -0,0 +1,43 @@ +package engine + +import ( + "context" + + "golang.org/x/sync/errgroup" + + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" +) + +// RegisterInstance is called when a new instance is created +func (e *Engine) RegisterInstance(ctx context.Context, s driver.Stream, i driver.StreamInstance) error { + group, ctx := errgroup.WithContext(ctx) + + group.Go(func() error { + return e.Lookup.RegisterInstance(ctx, s, i) + }) + + if s.GetUseWarehouse() { + group.Go(func() error { + return e.Warehouse.RegisterInstance(ctx, s, i) + }) + } + + return group.Wait() +} + +// RemoveInstance is called when an instance is deleted +func (e *Engine) RemoveInstance(ctx context.Context, s driver.Stream, i driver.StreamInstance) error { + group, ctx := errgroup.WithContext(ctx) + + group.Go(func() error { + return e.Lookup.RemoveInstance(ctx, s, i) + }) + + if s.GetUseWarehouse() { + group.Go(func() error { + return e.Warehouse.RemoveInstance(ctx, s, i) + }) + } + + return group.Wait() +} diff --git a/engine/driver/pubsub/mq.go b/infrastructure/mq/driver/pubsub/mq.go similarity index 91% rename from engine/driver/pubsub/mq.go rename to infrastructure/mq/driver/pubsub/mq.go index c3c6a24c..bdb18828 100644 --- a/engine/driver/pubsub/mq.go +++ b/infrastructure/mq/driver/pubsub/mq.go @@ -5,23 +5,22 @@ import ( "fmt" "time" - "google.golang.org/api/iterator" - "cloud.google.com/go/pubsub" "gitlab.com/beneath-hq/beneath/pkg/log" + "google.golang.org/api/iterator" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) -// MaxMessageSize implements beneath.MessageQueue +// MaxMessageSize implements MessageQueue func (p PubSub) MaxMessageSize() int { // The total request size is capped at 10MB, we set it slightly lower to not run into problems return 9999360 // floor1024(10MB) } -// RegisterTopic implements beneath.MessageQueue +// RegisterTopic implements MessageQueue func (p PubSub) RegisterTopic(name string) error { - qualified := fmt.Sprintf("%s-%s", p.config.TopicPrefix, name) + qualified := fmt.Sprintf("%s-%s", p.Opts.TopicPrefix, name) topic, err := p.Client.CreateTopic(context.Background(), qualified) if err != nil { status, ok := status.FromError(err) @@ -35,7 +34,7 @@ func (p PubSub) RegisterTopic(name string) error { return nil } -// Publish implements beneath.MessageQueue +// Publish implements MessageQueue func (p PubSub) Publish(ctx context.Context, topic string, msg []byte) error { // push result := p.Topics[topic].Publish(ctx, &pubsub.Message{ @@ -47,17 +46,17 @@ func (p PubSub) Publish(ctx context.Context, topic string, msg []byte) error { return err } -// Subscribe implements beneath.MessageQueue +// Subscribe implements MessageQueue func (p PubSub) Subscribe(ctx context.Context, topic string, name string, persistent bool, fn func(ctx context.Context, msg []byte) error) error { // create name - fullName := fmt.Sprintf("%s-%s", p.config.SubscriptionPrefix, name) + fullName := fmt.Sprintf("%s-%s", p.Opts.SubscriptionPrefix, name) // get subscription var sub *pubsub.Subscription if persistent { sub = p.getPersistentSubscription(ctx, p.Topics[topic], fullName) } else { - sub = p.getEphemeralSubscription(ctx, p.Topics[topic], fullName, p.config.SubscriberID) + sub = p.getEphemeralSubscription(ctx, p.Topics[topic], fullName, p.Opts.SubscriberID) } // receive messages forever (or until error occurs) @@ -134,7 +133,7 @@ func (p PubSub) getEphemeralSubscription(ctx context.Context, topic *pubsub.Topi err = subscription.SeekToTime(context.Background(), time.Now()) if err != nil { status, ok := status.FromError(err) - if ok && status.Code() == codes.Unimplemented && p.config.EmulatorHost != "" { + if ok && status.Code() == codes.Unimplemented && p.Opts.EmulatorHost != "" { // Seek not implemented on Emulator, ignore } else { panic(fmt.Errorf("error seeking on subscription '%s': %v", subname, err)) diff --git a/infrastructure/mq/driver/pubsub/pubsub.go b/infrastructure/mq/driver/pubsub/pubsub.go new file mode 100644 index 00000000..91001d53 --- /dev/null +++ b/infrastructure/mq/driver/pubsub/pubsub.go @@ -0,0 +1,59 @@ +package pubsub + +import ( + "context" + "fmt" + "os" + + "cloud.google.com/go/pubsub" + "github.com/mitchellh/mapstructure" + + "gitlab.com/beneath-hq/beneath/infrastructure/mq" +) + +func init() { + mq.AddDriver("pubsub", newPubsub) +} + +// PubSub implements beneath.MessageQueue +type PubSub struct { + Client *pubsub.Client + Topics map[string]*pubsub.Topic + Opts *Options +} + +// Options for creating a Pubsub +type Options struct { + ProjectID string `mapstructure:"project_id"` + SubscriberID string `mapstructure:"subscriber_id"` + TopicPrefix string `mapstructure:"topic_prefix"` + SubscriptionPrefix string `mapstructure:"subscription_prefix"` + EmulatorHost string `mapstructure:"emulator_host"` +} + +func newPubsub(optsMap map[string]interface{}) (mq.MessageQueue, error) { + // decode options + var opts Options + err := mapstructure.Decode(optsMap, &opts) + if err != nil { + return nil, fmt.Errorf("error decoding pubsub options: %s", err.Error()) + } + + // connect to emulator if set + if opts.EmulatorHost != "" { + os.Setenv("PUBSUB_PROJECT_ID", opts.ProjectID) + os.Setenv("PUBSUB_EMULATOR_HOST", opts.EmulatorHost) + } + + // prepare pubsub client + client, err := pubsub.NewClient(context.Background(), opts.ProjectID) + if err != nil { + return nil, fmt.Errorf("failed connecting to pubsub: %s", err) + } + + return &PubSub{ + Client: client, + Topics: make(map[string]*pubsub.Topic), + Opts: &opts, + }, nil +} diff --git a/infrastructure/mq/mq.go b/infrastructure/mq/mq.go new file mode 100644 index 00000000..f0dba38d --- /dev/null +++ b/infrastructure/mq/mq.go @@ -0,0 +1,54 @@ +package mq + +import ( + "context" + "fmt" +) + +// MessageQueue encapsulates functionality for message passing in Beneath +type MessageQueue interface { + // MaxMessageSize should return the maximum allowed byte size of published messages + MaxMessageSize() int + + // RegisterTopic should register a new topic for message passing + RegisterTopic(name string) error + + // Publish should issue a new message to all the topic's subscribers + Publish(ctx context.Context, topic string, msg []byte) error + + // Subscribe should create a subscription for new messages on the topic. + // If persistent, messages missed when offline should accumulate and be delivered on reconnect. + Subscribe(ctx context.Context, topic string, name string, persistent bool, fn func(ctx context.Context, msg []byte) error) error + + // Reset should clear all data in the service (useful during testing) + Reset(ctx context.Context) error +} + +// Driver is a function that creates a MessageQueue from a config object +type Driver func(opts map[string]interface{}) (MessageQueue, error) + +// drivers is a registry of MessageQueue drivers +var drivers = make(map[string]Driver) + +// AddDriver registers a new driver (by passing the driver's constructor) +func AddDriver(name string, driver Driver) { + if drivers[name] != nil { + panic(fmt.Errorf("MessageQueue driver already registered with name '%s'", name)) + } + drivers[name] = driver +} + +// Options for opening a message queue connection +type Options struct { + DriverName string `mapstructure:"driver"` + DriverOptions map[string]interface{} `mapstructure:",remain"` +} + +// NewMessageQueue constructs a new MessageQueue +func NewMessageQueue(opts *Options) (MessageQueue, error) { + constructor := drivers[opts.DriverName] + if constructor == nil { + return nil, fmt.Errorf("'%s' is not a valid MessageQueue driver", opts.DriverName) + } + return constructor(opts.DriverOptions) +} diff --git a/infrastructure/mq/write.go b/infrastructure/mq/write.go new file mode 100644 index 00000000..96930942 --- /dev/null +++ b/infrastructure/mq/write.go @@ -0,0 +1,67 @@ +package mq + +// import ( +// "context" +// "fmt" + +// "github.com/golang/protobuf/proto" + +// pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" +// ) + +// const ( +// writeRequestsTopic = "write-requests" +// writeRequestsSubscription = "write-requests-worker" +// writeReportsTopic = "write-reports" +// writeReportsSubscription = "write-reports-reader" +// ) + +// // QueueWriteRequest queues a write request -- concretely, it results in +// // the write request being written to Pubsub, then from there read by +// // the data processing pipeline and written to BigTable and BigQuery +// func (e *MQ) QueueWriteRequest(ctx context.Context, req *pb.WriteRequest) error { +// msg, err := proto.Marshal(req) +// if err != nil { +// panic(err) +// } +// if len(msg) > e.MQ.MaxMessageSize() { +// return fmt.Errorf("total write size <%d bytes> exceeds maximum <%d bytes>", len(msg), e.MQ.MaxMessageSize()) +// } +// return e.MQ.Publish(ctx, writeRequestsTopic, msg) +// } + +// // ReadWriteRequests triggers fn for every WriteRecordsRequest that's written with QueueWriteRequest +// func (e *MQ) ReadWriteRequests(ctx context.Context, fn func(context.Context, *pb.WriteRequest) error) error { +// return e.MQ.Subscribe(ctx, writeRequestsTopic, writeRequestsSubscription, true, func(ctx context.Context, msg []byte) error { +// req := &pb.WriteRequest{} +// err := proto.Unmarshal(msg, req) +// if err != nil { +// return err +// } +// return fn(ctx, req) +// }) +// } + +// // QueueWriteReport publishes a WriteReport (used to notify of completed processing of a WriteRequest) +// func (e *Engine) QueueWriteReport(ctx context.Context, rep *pb.WriteReport) error { +// msg, err := proto.Marshal(rep) +// if err != nil { +// panic(err) +// } +// if len(msg) > e.MQ.MaxMessageSize() { +// return fmt.Errorf("total write report size <%d bytes> exceeds maximum <%d bytes>", len(msg), e.MQ.MaxMessageSize()) +// } +// return e.MQ.Publish(ctx, writeReportsTopic, msg) +// } + +// // ReadWriteReports reads messages published with QueueWriteReport +// func (e *Engine) ReadWriteReports(ctx context.Context, fn func(context.Context, *pb.WriteReport) error) error { +// return e.MQ.Subscribe(ctx, writeReportsTopic, writeReportsSubscription, false, func(ctx context.Context, msg []byte) error { +// rep := &pb.WriteReport{} +// err := proto.Unmarshal(msg, rep) +// if err != nil { +// return err +// } +// return fn(ctx, rep) +// }) +// } diff --git a/infrastructure/redis/redis.go b/infrastructure/redis/redis.go new file mode 100644 index 00000000..6102c81b --- /dev/null +++ b/infrastructure/redis/redis.go @@ -0,0 +1,21 @@ +package redis + +import ( + "github.com/go-redis/redis/v7" +) + +// Options for opening a new Redis connection +type Options struct { + URL string +} + +// NewRedis opens a new Redis connection +func NewRedis(opts *Options) *redis.Client { + redisOpts, err := redis.ParseURL(opts.URL) + if err != nil { + panic(err) + } + + client := redis.NewClient(redisOpts) + return client +} diff --git a/internal/README.md b/internal/README.md deleted file mode 100644 index 815edfe3..00000000 --- a/internal/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# `internal/` - -This directory contains utility libraries that are not directly related to any specific part of the system, but does not belong in `pkg` (i.e. it is not a stand-alone utility) diff --git a/internal/metrics/reader.go b/internal/metrics/reader.go deleted file mode 100644 index 0a29e1e3..00000000 --- a/internal/metrics/reader.go +++ /dev/null @@ -1,65 +0,0 @@ -package metrics - -import ( - "context" - "fmt" - "time" - - uuid "github.com/satori/go.uuid" - - pb "gitlab.com/beneath-hq/beneath/engine/proto" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/timeutil" -) - -const ( - maxPeriods = 175 // roughly one week on an hourly basis -) - -// GetCurrentUsage returns an ID's usage for the current monthly period -func GetCurrentUsage(ctx context.Context, entityID uuid.UUID) pb.QuotaUsage { - // load from bigtable - usage, err := hub.Engine.ReadSingleUsage(ctx, entityID, timeutil.PeriodMonth, time.Now()) - if err != nil { - panic(fmt.Errorf("error reading metrics: %s", err.Error())) - } - - return usage -} - -// GetHistoricalUsage returns usage info for the given length of time -func GetHistoricalUsage(ctx context.Context, entityID uuid.UUID, period timeutil.Period, from time.Time, until time.Time) ([]time.Time, []pb.QuotaUsage, error) { - // check is supported period - if period != timeutil.PeriodHour && period != timeutil.PeriodMonth { - return nil, nil, fmt.Errorf("usage is calculated only in hourly and monthly periods") - } - - // if "until" is 0, set it to the current time - if until.IsZero() { - until = timeutil.Floor(time.Now(), period) - } - - // check that the provided time range corresponds to keys in the table - if from != timeutil.Floor(from, period) || until != timeutil.Floor(until, period) { - return nil, nil, fmt.Errorf("from and until must exactly match period beginnings") - } - - // prevent the retrieval of too many rows at once - if period.Count(from, until) > maxPeriods { - return nil, nil, fmt.Errorf("time span too long") - } - - // read usage table and collect usage metrics - var times []time.Time - var usages []pb.QuotaUsage - err := hub.Engine.ReadUsage(ctx, entityID, period, from, until, func(ts time.Time, usage pb.QuotaUsage) error { - times = append(times, ts) - usages = append(usages, usage) - return nil - }) - if err != nil { - panic(fmt.Errorf("error reading from metrics table: %s", err.Error())) - } - - return times, usages, nil -} diff --git a/control/migrations/001_organization.go b/migrations/001_organization.go similarity index 100% rename from control/migrations/001_organization.go rename to migrations/001_organization.go diff --git a/control/migrations/002_project.go b/migrations/002_project.go similarity index 100% rename from control/migrations/002_project.go rename to migrations/002_project.go diff --git a/control/migrations/003_user.go b/migrations/003_user.go similarity index 100% rename from control/migrations/003_user.go rename to migrations/003_user.go diff --git a/control/migrations/004_stream.go b/migrations/004_stream.go similarity index 100% rename from control/migrations/004_stream.go rename to migrations/004_stream.go diff --git a/control/migrations/005_service.go b/migrations/005_service.go similarity index 100% rename from control/migrations/005_service.go rename to migrations/005_service.go diff --git a/control/migrations/006_secret.go b/migrations/006_secret.go similarity index 100% rename from control/migrations/006_secret.go rename to migrations/006_secret.go diff --git a/control/migrations/007_model.go b/migrations/007_model.go similarity index 100% rename from control/migrations/007_model.go rename to migrations/007_model.go diff --git a/control/migrations/008_service_dates.go b/migrations/008_service_dates.go similarity index 100% rename from control/migrations/008_service_dates.go rename to migrations/008_service_dates.go diff --git a/control/migrations/009_organization_unique.go b/migrations/009_organization_unique.go similarity index 100% rename from control/migrations/009_organization_unique.go rename to migrations/009_organization_unique.go diff --git a/control/migrations/010_project_display_name.go b/migrations/010_project_display_name.go similarity index 100% rename from control/migrations/010_project_display_name.go rename to migrations/010_project_display_name.go diff --git a/control/migrations/011_service_unique.go b/migrations/011_service_unique.go similarity index 100% rename from control/migrations/011_service_unique.go rename to migrations/011_service_unique.go diff --git a/control/migrations/012_stream_instances_counts.go b/migrations/012_stream_instances_counts.go similarity index 100% rename from control/migrations/012_stream_instances_counts.go rename to migrations/012_stream_instances_counts.go diff --git a/control/migrations/013_better_secrets.go b/migrations/013_better_secrets.go similarity index 100% rename from control/migrations/013_better_secrets.go rename to migrations/013_better_secrets.go diff --git a/control/migrations/014_billing.go b/migrations/014_billing.go similarity index 100% rename from control/migrations/014_billing.go rename to migrations/014_billing.go diff --git a/control/migrations/015_stream_retention.go b/migrations/015_stream_retention.go similarity index 100% rename from control/migrations/015_stream_retention.go rename to migrations/015_stream_retention.go diff --git a/control/migrations/016_stream_index.go b/migrations/016_stream_index.go similarity index 100% rename from control/migrations/016_stream_index.go rename to migrations/016_stream_index.go diff --git a/control/migrations/017_project_index.go b/migrations/017_project_index.go similarity index 100% rename from control/migrations/017_project_index.go rename to migrations/017_project_index.go diff --git a/control/migrations/018_two_organizations.go b/migrations/018_two_organizations.go similarity index 100% rename from control/migrations/018_two_organizations.go rename to migrations/018_two_organizations.go diff --git a/control/migrations/019_billing_method.go b/migrations/019_billing_method.go similarity index 100% rename from control/migrations/019_billing_method.go rename to migrations/019_billing_method.go diff --git a/control/migrations/020_tax_info.go b/migrations/020_tax_info.go similarity index 100% rename from control/migrations/020_tax_info.go rename to migrations/020_tax_info.go diff --git a/control/migrations/021_master_users.go b/migrations/021_master_users.go similarity index 100% rename from control/migrations/021_master_users.go rename to migrations/021_master_users.go diff --git a/control/migrations/022_nullable_billing_method.go b/migrations/022_nullable_billing_method.go similarity index 100% rename from control/migrations/022_nullable_billing_method.go rename to migrations/022_nullable_billing_method.go diff --git a/control/migrations/023_organization_invite.go b/migrations/023_organization_invite.go similarity index 100% rename from control/migrations/023_organization_invite.go rename to migrations/023_organization_invite.go diff --git a/control/migrations/024_user_org_perms_create.go b/migrations/024_user_org_perms_create.go similarity index 100% rename from control/migrations/024_user_org_perms_create.go rename to migrations/024_user_org_perms_create.go diff --git a/control/migrations/025_organization_quotas.go b/migrations/025_organization_quotas.go similarity index 100% rename from control/migrations/025_organization_quotas.go rename to migrations/025_organization_quotas.go diff --git a/control/migrations/026_user_details_to_organization.go b/migrations/026_user_details_to_organization.go similarity index 100% rename from control/migrations/026_user_details_to_organization.go rename to migrations/026_user_details_to_organization.go diff --git a/control/migrations/027_billing_plan_quotas.go b/migrations/027_billing_plan_quotas.go similarity index 100% rename from control/migrations/027_billing_plan_quotas.go rename to migrations/027_billing_plan_quotas.go diff --git a/control/migrations/028_rm_entity_name.go b/migrations/028_rm_entity_name.go similarity index 100% rename from control/migrations/028_rm_entity_name.go rename to migrations/028_rm_entity_name.go diff --git a/control/migrations/029_prepaid_quotas.go b/migrations/029_prepaid_quotas.go similarity index 100% rename from control/migrations/029_prepaid_quotas.go rename to migrations/029_prepaid_quotas.go diff --git a/control/migrations/030_billing_floats.go b/migrations/030_billing_floats.go similarity index 100% rename from control/migrations/030_billing_floats.go rename to migrations/030_billing_floats.go diff --git a/control/migrations/031_billing_plan_base_price.go b/migrations/031_billing_plan_base_price.go similarity index 100% rename from control/migrations/031_billing_plan_base_price.go rename to migrations/031_billing_plan_base_price.go diff --git a/control/migrations/032_streams_tidy_up.go b/migrations/032_streams_tidy_up.go similarity index 100% rename from control/migrations/032_streams_tidy_up.go rename to migrations/032_streams_tidy_up.go diff --git a/control/migrations/033_billing_plan_multiple_users.go b/migrations/033_billing_plan_multiple_users.go similarity index 100% rename from control/migrations/033_billing_plan_multiple_users.go rename to migrations/033_billing_plan_multiple_users.go diff --git a/control/migrations/034_user_consent.go b/migrations/034_user_consent.go similarity index 100% rename from control/migrations/034_user_consent.go rename to migrations/034_user_consent.go diff --git a/control/migrations/035_streams_options.go b/migrations/035_streams_options.go similarity index 100% rename from control/migrations/035_streams_options.go rename to migrations/035_streams_options.go diff --git a/control/migrations/036_drop_models.go b/migrations/036_drop_models.go similarity index 100% rename from control/migrations/036_drop_models.go rename to migrations/036_drop_models.go diff --git a/control/migrations/037_services_to_projects.go b/migrations/037_services_to_projects.go similarity index 100% rename from control/migrations/037_services_to_projects.go rename to migrations/037_services_to_projects.go diff --git a/control/migrations/038_instance_versions.go b/migrations/038_instance_versions.go similarity index 100% rename from control/migrations/038_instance_versions.go rename to migrations/038_instance_versions.go diff --git a/control/migrations/039_scan_quotas.go b/migrations/039_scan_quotas.go similarity index 100% rename from control/migrations/039_scan_quotas.go rename to migrations/039_scan_quotas.go diff --git a/control/migrations/040_different_stream_schema_types.go b/migrations/040_different_stream_schema_types.go similarity index 100% rename from control/migrations/040_different_stream_schema_types.go rename to migrations/040_different_stream_schema_types.go diff --git a/control/migrations/041_featured_projects.go b/migrations/041_featured_projects.go similarity index 100% rename from control/migrations/041_featured_projects.go rename to migrations/041_featured_projects.go diff --git a/control/migrations/migrations.go b/migrations/migrations.go similarity index 100% rename from control/migrations/migrations.go rename to migrations/migrations.go diff --git a/models/README.md b/models/README.md new file mode 100644 index 00000000..fc8ed977 --- /dev/null +++ b/models/README.md @@ -0,0 +1,7 @@ +# `models/` + +This folder contains structs for database models and bus events. It also contains simple implementation code, e.g. for validation or for adhering to interfaces, but it should not contain complex functionality (certainly not code that calls services or infrastructure). + +When you add or change a model, remember to add related migrations to `migrations/` + +`bus.Bus` marshals async events with `msgpack`, so every struct used in events should have sensible `msgpack` struct tags (eg. use `msgpack:"-"` for sub-objects like database relationships). diff --git a/models/organization.go b/models/organization.go new file mode 100644 index 00000000..13de6762 --- /dev/null +++ b/models/organization.go @@ -0,0 +1,178 @@ +package models + +import ( + "fmt" + "regexp" + "time" + + uuid "github.com/satori/go.uuid" + "gopkg.in/go-playground/validator.v9" +) + +// Organization represents the entity that manages billing on behalf of its users +type Organization struct { + _msgpack struct{} `msgpack:",omitempty"` + OrganizationID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` + Name string `sql:",unique,notnull",validate:"required,gte=3,lte=40"` // NOTE: when updating, clear stream cache + DisplayName string `sql:",notnull",validate:"required,gte=1,lte=50"` + Description string `validate:"omitempty,lte=255"` + PhotoURL string `validate:"omitempty,url,lte=400"` + UserID *uuid.UUID `sql:",on_delete:restrict,type:uuid"` + User *User `msgpack:"-"` + CreatedOn time.Time `sql:",default:now()"` + UpdatedOn time.Time `sql:",default:now()"` + PrepaidReadQuota *int64 // bytes + PrepaidWriteQuota *int64 // bytes + PrepaidScanQuota *int64 // bytes + ReadQuota *int64 // bytes // NOTE: when updating value, clear secret cache + WriteQuota *int64 // bytes // NOTE: when updating value, clear secret cache + ScanQuota *int64 // bytes // NOTE: when updating value, clear secret cache + Projects []*Project `msgpack:"-"` + Users []*User `pg:"fk:billing_organization_id",msgpack:"-"` + + // used to indicate requestor's permissions in resolvers + Permissions *PermissionsUsersOrganizations `sql:"-",msgpack:"-"` +} + +// Validate runs validation on the organization +func (o *Organization) Validate() error { + return Validator.Struct(o) +} + +// IsMulti returns true if o is a multi-user organization +func (o *Organization) IsMulti() bool { + return o.UserID == nil +} + +// IsOrganization implements gql.Organization +func (o *Organization) IsOrganization() {} + +// IsBillingOrganizationForUser returns true if o is also the billing org for the user it represents. +// It panics if called on a non-personal organization. +func (o *Organization) IsBillingOrganizationForUser() bool { + if o.UserID == nil { + panic(fmt.Errorf("Called IsBillingOrganizationForUser on non-personal organization")) + } + return o.User.BillingOrganizationID == o.OrganizationID +} + +// StripPrivateProjects removes private projects from o.Projects (no changes in database, just the loaded object) +func (o *Organization) StripPrivateProjects() { + for i, p := range o.Projects { + if !p.Public { + n := len(o.Projects) + o.Projects[n-1], o.Projects[i] = o.Projects[i], o.Projects[n-1] + o.Projects = o.Projects[:n-1] + } + } +} + +// OrganizationMember is a convenience representation of organization membership +type OrganizationMember struct { + OrganizationID uuid.UUID + UserID uuid.UUID + BillingOrganizationID uuid.UUID + Name string + DisplayName string + PhotoURL string + View bool + Create bool + Admin bool + ReadQuota *int + WriteQuota *int + ScanQuota *int +} + +// OrganizationInvite represents invites to use an organization as your billing organization. +type OrganizationInvite struct { + OrganizationInviteID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` + OrganizationID uuid.UUID `sql:"on_delete:CASCADE,type:uuid"` + Organization *Organization + UserID uuid.UUID `sql:"on_delete:CASCADE,type:uuid"` + User *User + CreatedOn time.Time `sql:",default:now()"` + UpdatedOn time.Time `sql:",default:now()"` + View bool `sql:",notnull"` + Create bool `sql:",notnull"` + Admin bool `sql:",notnull"` +} + +// Validate runs validation on the organization invite +func (i *OrganizationInvite) Validate() error { + return Validator.Struct(i) +} + +// --------------- +// Events + +// OrganizationCreatedEvent is sent when an organization is created +type OrganizationCreatedEvent struct { + Organization *Organization +} + +// OrganizationUpdatedEvent is sent when an organization is updated +type OrganizationUpdatedEvent struct { + Organization *Organization +} + +// OrganizationTransferredUserEvent is sent when a user is transferred from one org to another +type OrganizationTransferredUserEvent struct { + Source *Organization + Target *Organization + User *User +} + +// --------------- +// Validation + +var orgNameRegex = regexp.MustCompile("^[_a-z][_a-z0-9]*$") + +var orgNameBlacklist = []string{ + "api", + "auth", + "billing", + "console", + "control", + "data", + "docs", + "documentation", + "ee", + "enterprise", + "explore", + "gateway", + "gql", + "graphql", + "health", + "healthz", + "instance", + "instances", + "organization", + "organizations", + "permissions", + "project", + "projects", + "redirects", + "secret", + "secrets", + "stream", + "streams", + "terminal", + "user", + "username", + "users", +} + +func init() { + Validator.RegisterStructValidation(func(sl validator.StructLevel) { + s := sl.Current().Interface().(Organization) + if !orgNameRegex.MatchString(s.Name) { + sl.ReportError(s.Name, "Name", "", "alphanumericorunderscore", "") + } + for _, blacklisted := range orgNameBlacklist { + if s.Name == blacklisted { + sl.ReportError(s.Name, "Name", "", "blacklisted", "") + break + } + } + }, Organization{}) +} diff --git a/models/permission.go b/models/permission.go new file mode 100644 index 00000000..94833608 --- /dev/null +++ b/models/permission.go @@ -0,0 +1,67 @@ +package models + +import ( + "github.com/go-pg/pg/v9/orm" + uuid "github.com/satori/go.uuid" +) + +// PermissionsUsersProjects represents the many-to-many relationship between users and projects +type PermissionsUsersProjects struct { + tableName struct{} `sql:"permissions_users_projects"` + UserID uuid.UUID `sql:"on_delete:CASCADE,pk,type:uuid"` + User *User + ProjectID uuid.UUID `sql:"on_delete:CASCADE,pk,type:uuid"` + Project *Project + View bool `sql:",notnull"` + Create bool `sql:",notnull"` + Admin bool `sql:",notnull"` +} + +// PermissionsUsersOrganizations represents the many-to-one relationship between users and organizations +type PermissionsUsersOrganizations struct { + tableName struct{} `sql:"permissions_users_organizations"` + UserID uuid.UUID `sql:"on_delete:CASCADE,pk,type:uuid"` + User *User + OrganizationID uuid.UUID `sql:"on_delete:CASCADE,pk,type:uuid"` + Organization *Organization + View bool `sql:",notnull"` + Create bool `sql:",notnull"` + Admin bool `sql:",notnull"` +} + +// PermissionsServicesStreams represnts the many-to-many relationship between services and projects +type PermissionsServicesStreams struct { + tableName struct{} `sql:"permissions_services_streams"` + ServiceID uuid.UUID `sql:"on_delete:CASCADE,pk,type:uuid"` + Service *Service + StreamID uuid.UUID `sql:"on_delete:CASCADE,pk,type:uuid"` + Stream *Stream + Read bool `sql:",notnull"` + Write bool `sql:",notnull"` +} + +// ProjectPermissions represents permissions that a user has for a given project +type ProjectPermissions struct { + View bool + Create bool + Admin bool +} + +// StreamPermissions represents permissions that a service has for a given stream +type StreamPermissions struct { + Read bool + Write bool +} + +// OrganizationPermissions represents permissions that a user has for a given organization +type OrganizationPermissions struct { + View bool + Create bool + Admin bool +} + +func init() { + orm.RegisterTable((*PermissionsUsersProjects)(nil)) + orm.RegisterTable((*PermissionsUsersOrganizations)(nil)) + orm.RegisterTable((*PermissionsServicesStreams)(nil)) +} diff --git a/models/project.go b/models/project.go new file mode 100644 index 00000000..e7e5b548 --- /dev/null +++ b/models/project.go @@ -0,0 +1,98 @@ +package models + +import ( + "regexp" + "time" + + uuid "github.com/satori/go.uuid" + "gopkg.in/go-playground/validator.v9" +) + +// Project represents a Beneath project +type Project struct { + _msgpack struct{} `msgpack:",omitempty"` + ProjectID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` + Name string `sql:",notnull",validate:"required,gte=3,lte=16"` + DisplayName string `validate:"omitempty,lte=40"` + Site string `validate:"omitempty,url,lte=255"` + Description string `validate:"omitempty,lte=255"` + PhotoURL string `validate:"omitempty,url,lte=255"` + Public bool `sql:",notnull,default:true"` + Locked bool `sql:",notnull,default:false"` + ExploreRank int + OrganizationID uuid.UUID `sql:",on_delete:restrict,notnull,type:uuid"` + Organization *Organization `msgpack:"-"` + CreatedOn time.Time `sql:",default:now()"` + UpdatedOn time.Time `sql:",default:now()"` + Streams []*Stream `msgpack:"-"` + Services []*Service `msgpack:"-"` + Users []*User `pg:"many2many:permissions_users_projects,fk:project_id,joinFK:user_id",msgpack:"-"` + + // used to indicate requestor's permissions in resolvers + Permissions *PermissionsUsersProjects `sql:"-",msgpack:"-"` +} + +// Validate runs validation on the project +func (p *Project) Validate() error { + return Validator.Struct(p) +} + +// GetProjectID implements engine/driver.Project +func (p *Project) GetProjectID() uuid.UUID { + return p.ProjectID +} + +// GetOrganizationName implements engine/driver.Project +func (p *Project) GetOrganizationName() string { + return p.Organization.Name +} + +// GetProjectName implements engine/driver.Project +func (p *Project) GetProjectName() string { + return p.Name +} + +// GetPublic implements engine/driver.Project +func (p *Project) GetPublic() bool { + return p.Public +} + +// ProjectMember is a convenience representation of a user in a project +type ProjectMember struct { + ProjectID uuid.UUID + UserID uuid.UUID + Name string + DisplayName string + PhotoURL string + View bool + Create bool + Admin bool +} + +// --------------- +// Events + +// ProjectUpdatedEvent is sent when a project is updated +type ProjectUpdatedEvent struct { + Project *Project +} + +// ProjectDeletedEvent is setn when a project is deleted +type ProjectDeletedEvent struct { + ProjectID uuid.UUID +} + +// --------------- +// Validation + +var projectNameRegex = regexp.MustCompile("^[_a-z][_a-z0-9]*$") + +func init() { + Validator.RegisterStructValidation(func(sl validator.StructLevel) { + p := sl.Current().Interface().(Project) + + if !projectNameRegex.MatchString(p.Name) { + sl.ReportError(p.Name, "Name", "", "alphanumericorunderscore", "") + } + }, Project{}) +} diff --git a/models/secret.go b/models/secret.go new file mode 100644 index 00000000..31ccf164 --- /dev/null +++ b/models/secret.go @@ -0,0 +1,265 @@ +package models + +import ( + "fmt" + "time" + + uuid "github.com/satori/go.uuid" + + "gitlab.com/beneath-hq/beneath/pkg/secrettoken" +) + +// Secret represents an access token to Beneath +type Secret interface { + // GetSecretID returns a unique identifier of the secret + GetSecretID() uuid.UUID + + // GetOwnerID returns the ID of the secret's owner, i.e. a user or service (or uuid.Nil for anonymous) + GetOwnerID() uuid.UUID + + // GetBillingOrganizationID returns the ID of the organization responsible for the secret's billing + GetBillingOrganizationID() uuid.UUID + + // IsAnonymous is true iff the secret is anonymous + IsAnonymous() bool + + // IsUser is true iff the secret is a user + IsUser() bool + + // IsService is true iff the secret is a service + IsService() bool + + // IsMaster is true iff the secret is a master secret + IsMaster() bool + + // GetBillingReadQuota returns the billing organization's read quota (or nil if unlimited) + GetBillingReadQuota() *int64 + + // GetBillingWriteQuota returns the billing organization's write quota (or nil if unlimited) + GetBillingWriteQuota() *int64 + + // GetBillingScanQuota returns the billing organization's scan quota (or nil if unlimited) + GetBillingScanQuota() *int64 + + // GetOwnerReadQuota returns the owner's read quota (or nil if unlimited) + GetOwnerReadQuota() *int64 + + // GetOwnerWriteQuota returns the owner's write quota (or nil if unlimited) + GetOwnerWriteQuota() *int64 + + // GetOwnerScanQuota returns the owner's scan quota (or nil if unlimited) + GetOwnerScanQuota() *int64 +} + +// BaseSecret is the "abstract" base of structs that implement the Secret interface +type BaseSecret struct { + _msgpack struct{} `msgpack:",omitempty"` + Prefix string `sql:",notnull",validate:"required,len=4"` + HashedToken []byte `sql:",unique,notnull",validate:"required,lte=64"` + Description string `validate:"omitempty,lte=40"` + CreatedOn time.Time `sql:",notnull,default:now()"` + UpdatedOn time.Time `sql:",notnull,default:now()"` + + Token secrettoken.Token `sql:"-"` + Master bool `sql:"-"` + BillingOrganizationID uuid.UUID `sql:"-"` + BillingReadQuota *int64 `sql:"-"` + BillingWriteQuota *int64 `sql:"-"` + BillingScanQuota *int64 `sql:"-"` + OwnerReadQuota *int64 `sql:"-"` + OwnerWriteQuota *int64 `sql:"-"` + OwnerScanQuota *int64 `sql:"-"` +} + +// GetBillingOrganizationID implements Secret +func (s *BaseSecret) GetBillingOrganizationID() uuid.UUID { + return s.BillingOrganizationID +} + +// IsMaster implements Secret +func (s *BaseSecret) IsMaster() bool { + return s.Master +} + +// GetBillingReadQuota implements Secret +func (s *BaseSecret) GetBillingReadQuota() *int64 { + return s.BillingReadQuota +} + +// GetBillingWriteQuota implements Secret +func (s *BaseSecret) GetBillingWriteQuota() *int64 { + return s.BillingWriteQuota +} + +// GetBillingScanQuota implements Secret +func (s *BaseSecret) GetBillingScanQuota() *int64 { + return s.BillingScanQuota +} + +// GetOwnerReadQuota implements Secret +func (s *BaseSecret) GetOwnerReadQuota() *int64 { + return s.OwnerReadQuota +} + +// GetOwnerWriteQuota implements Secret +func (s *BaseSecret) GetOwnerWriteQuota() *int64 { + return s.OwnerWriteQuota +} + +// GetOwnerScanQuota implements Secret +func (s *BaseSecret) GetOwnerScanQuota() *int64 { + return s.OwnerScanQuota +} + +// UserSecret implements Secret for User entities +type UserSecret struct { + _msgpack struct{} `msgpack:",omitempty"` + UserSecretID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` + BaseSecret + UserID uuid.UUID `sql:"on_delete:CASCADE,notnull,type:uuid"` + User *User `msgpack:"-"` + ReadOnly bool `sql:",notnull"` + PublicOnly bool `sql:",notnull"` +} + +// Validate runs validation on the secret +func (s *UserSecret) Validate() error { + return Validator.Struct(s) +} + +// GetSecretID implements the Secret interface +func (s *UserSecret) GetSecretID() uuid.UUID { + return s.UserSecretID +} + +// GetOwnerID implements the Secret interface +func (s *UserSecret) GetOwnerID() uuid.UUID { + return s.UserID +} + +// IsAnonymous implements the Secret interface +func (s *UserSecret) IsAnonymous() bool { + return false +} + +// IsUser implements the Secret interface +func (s *UserSecret) IsUser() bool { + return true +} + +// IsService implements the Secret interface +func (s *UserSecret) IsService() bool { + return false +} + +// ServiceSecret implements Secret for Token entities +type ServiceSecret struct { + _msgpack struct{} `msgpack:",omitempty"` + ServiceSecretID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` + BaseSecret + ServiceID uuid.UUID `sql:"on_delete:CASCADE,type:uuid"` + Service *Service `msgpack:"-"` +} + +// Validate runs validation on the secret +func (s *ServiceSecret) Validate() error { + return Validator.Struct(s) +} + +// GetSecretID implements the Secret interface +func (s *ServiceSecret) GetSecretID() uuid.UUID { + return s.ServiceSecretID +} + +// GetOwnerID implements the Secret interface +func (s *ServiceSecret) GetOwnerID() uuid.UUID { + return s.ServiceID +} + +// IsAnonymous implements the Secret interface +func (s *ServiceSecret) IsAnonymous() bool { + return false +} + +// IsUser implements the Secret interface +func (s *ServiceSecret) IsUser() bool { + return false +} + +// IsService implements the Secret interface +func (s *ServiceSecret) IsService() bool { + return true +} + +// IsMaster implements the Secret interface +func (s *ServiceSecret) IsMaster() bool { + return false +} + +// AnonymousSecret implements Secret for anonymous requests +type AnonymousSecret struct{} + +// GetSecretID implements the Secret interface +func (s *AnonymousSecret) GetSecretID() uuid.UUID { + return uuid.Nil +} + +// GetOwnerID implements the Secret interface +func (s *AnonymousSecret) GetOwnerID() uuid.UUID { + return uuid.Nil +} + +// GetBillingOrganizationID implements the Secret interface +func (s *AnonymousSecret) GetBillingOrganizationID() uuid.UUID { + return uuid.Nil +} + +// IsAnonymous implements the Secret interface +func (s *AnonymousSecret) IsAnonymous() bool { + return true +} + +// IsUser implements the Secret interface +func (s *AnonymousSecret) IsUser() bool { + return false +} + +// IsService implements the Secret interface +func (s *AnonymousSecret) IsService() bool { + return false +} + +// IsMaster implements the Secret interface +func (s *AnonymousSecret) IsMaster() bool { + return false +} + +// GetBillingReadQuota implements Secret +func (s *AnonymousSecret) GetBillingReadQuota() *int64 { + panic(fmt.Errorf("Called GetBillingReadQuota on an anonymous secret")) +} + +// GetBillingWriteQuota implements Secret +func (s *AnonymousSecret) GetBillingWriteQuota() *int64 { + panic(fmt.Errorf("Called GetBillingWriteQuota on an anonymous secret")) +} + +// GetBillingScanQuota implements Secret +func (s *AnonymousSecret) GetBillingScanQuota() *int64 { + panic(fmt.Errorf("Called GetBillingScanQuota on an anonymous secret")) +} + +// GetOwnerReadQuota implements Secret +func (s *AnonymousSecret) GetOwnerReadQuota() *int64 { + panic(fmt.Errorf("Called GetOwnerReadQuota on an anonymous secret")) +} + +// GetOwnerWriteQuota implements Secret +func (s *AnonymousSecret) GetOwnerWriteQuota() *int64 { + panic(fmt.Errorf("Called GetOwnerWriteQuota on an anonymous secret")) +} + +// GetOwnerScanQuota implements Secret +func (s *AnonymousSecret) GetOwnerScanQuota() *int64 { + panic(fmt.Errorf("Called GetOwnerScanQuota on an anonymous secret")) +} diff --git a/models/service.go b/models/service.go new file mode 100644 index 00000000..3d5e3c82 --- /dev/null +++ b/models/service.go @@ -0,0 +1,59 @@ +package models + +import ( + "regexp" + "time" + + uuid "github.com/satori/go.uuid" + "gopkg.in/go-playground/validator.v9" +) + +// Service represents non-user accounts, which have distinct access permissions, API secrets, monitoring and quotas. +// They're used eg. when deploying to production. +type Service struct { + _msgpack struct{} `msgpack:",omitempty"` + ServiceID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` + Name string `sql:",notnull",validate:"required,gte=1,lte=40"` // not unique because of (organization_id, service_id) index + Description string `validate:"omitempty,lte=255"` + SourceURL string `validate:"omitempty,url,lte=255"` + ProjectID uuid.UUID `sql:"on_delete:restrict,notnull,type:uuid"` + Project *Project `msgpack:"-"` + ReadQuota *int64 // NOTE: when updating value, clear secret cache + WriteQuota *int64 // NOTE: when updating value, clear secret cache + ScanQuota *int64 // NOTE: when updating value, clear secret cache + CreatedOn time.Time `sql:",notnull,default:now()"` + UpdatedOn time.Time `sql:",notnull,default:now()"` + Secrets []*ServiceSecret `msgpack:"-"` +} + +// Validate runs validation on the service +func (s *Service) Validate() error { + return Validator.Struct(s) +} + +// --------------- +// Events + +// ServiceUpdatedEvent is sent when a service is updated +type ServiceUpdatedEvent struct { + Service *Service +} + +// ServiceDeletedEvent is sent when a service is deleted +type ServiceDeletedEvent struct { + ServiceID uuid.UUID +} + +// --------------- +// Validation + +var serviceNameRegex = regexp.MustCompile("^[_a-z][_a-z0-9]*$") + +func init() { + Validator.RegisterStructValidation(func(sl validator.StructLevel) { + s := sl.Current().Interface().(Service) + if !serviceNameRegex.MatchString(s.Name) { + sl.ReportError(s.Name, "Name", "", "alphanumericorunderscore", "") + } + }, Service{}) +} diff --git a/models/stream.go b/models/stream.go new file mode 100644 index 00000000..c1d287e5 --- /dev/null +++ b/models/stream.go @@ -0,0 +1,371 @@ +package models + +import ( + "fmt" + "regexp" + "time" + + uuid "github.com/satori/go.uuid" + "gopkg.in/go-playground/validator.v9" + + "gitlab.com/beneath-hq/beneath/pkg/codec" +) + +// StreamSchemaKind indicates the SDL of a stream's schema +type StreamSchemaKind string + +// Constants for StreamSchemaKind +const ( + StreamSchemaKindGraphQL StreamSchemaKind = "GraphQL" + StreamSchemaKindAvro StreamSchemaKind = "Avro" +) + +// Stream represents a collection of data +type Stream struct { + _msgpack struct{} `msgpack:",omitempty"` + + // Descriptive fields + StreamID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` + Name string `sql:",notnull",validate:"required,gte=1,lte=40"` // not unique because of (project_id, lower(name)) index // note: used in stream cache + Description string `validate:"omitempty,lte=255"` + CreatedOn time.Time `sql:",default:now()"` + UpdatedOn time.Time `sql:",default:now()"` + ProjectID uuid.UUID `sql:"on_delete:RESTRICT,notnull,type:uuid"` + Project *Project `msgpack:"-"` + AllowManualWrites bool `sql:",notnull"` + + // Schema-related fields (note: some are used in stream cache) + SchemaKind StreamSchemaKind `sql:",notnull",validate:"required"` + Schema string `sql:",notnull",validate:"required"` + SchemaMD5 []byte `sql:"schema_md5,notnull",validate:"required"` + AvroSchema string `sql:",type:json,notnull",validate:"required"` + CanonicalAvroSchema string `sql:",type:json,notnull",validate:"required"` + CanonicalIndexes string `sql:",type:json,notnull",validate:"required"` + StreamIndexes []*StreamIndex + + // Behaviour-related fields (note: used in stream cache) + UseLog bool `sql:",notnull"` + UseIndex bool `sql:",notnull"` + UseWarehouse bool `sql:",notnull"` + LogRetentionSeconds int32 `sql:",notnull,default:0"` + IndexRetentionSeconds int32 `sql:",notnull,default:0"` + WarehouseRetentionSeconds int32 `sql:",notnull,default:0"` + + // Instances-related fields + StreamInstances []*StreamInstance `msgpack:"-"` + PrimaryStreamInstanceID *uuid.UUID `sql:"on_delete:SET NULL,type:uuid"` + PrimaryStreamInstance *StreamInstance `msgpack:"-"` + InstancesCreatedCount int32 `sql:",notnull,default:0"` + InstancesDeletedCount int32 `sql:",notnull,default:0"` + InstancesMadeFinalCount int32 `sql:",notnull,default:0"` + InstancesMadePrimaryCount int32 `sql:",notnull,default:0"` +} + +// Validate runs validation on the stream +func (s *Stream) Validate() error { + return Validator.Struct(s) +} + +// GetStreamID implements engine/driver.Stream +func (s *Stream) GetStreamID() uuid.UUID { + return s.StreamID +} + +// GetStreamName implements engine/driver.Stream +func (s *Stream) GetStreamName() string { + return s.Name +} + +// GetUseLog implements engine/driver.Stream +func (s *Stream) GetUseLog() bool { + return s.UseLog +} + +// GetUseIndex implements engine/driver.Stream +func (s *Stream) GetUseIndex() bool { + return s.UseIndex +} + +// GetUseWarehouse implements engine/driver.Stream +func (s *Stream) GetUseWarehouse() bool { + return s.UseWarehouse +} + +// GetLogRetention implements engine/driver.Stream +func (s *Stream) GetLogRetention() time.Duration { + return time.Duration(s.LogRetentionSeconds) * time.Second +} + +// GetIndexRetention implements engine/driver.Stream +func (s *Stream) GetIndexRetention() time.Duration { + return time.Duration(s.IndexRetentionSeconds) * time.Second +} + +// GetWarehouseRetention implements engine/driver.Stream +func (s *Stream) GetWarehouseRetention() time.Duration { + return time.Duration(s.WarehouseRetentionSeconds) * time.Second +} + +// GetCodec implements engine/driver.Stream +func (s *Stream) GetCodec() *codec.Codec { + if len(s.StreamIndexes) == 0 { + panic(fmt.Errorf("GetCodec must not be called without StreamIndexes loaded")) + } + + var primaryIndex codec.Index + var secondaryIndexes []codec.Index + for _, index := range s.StreamIndexes { + if index.Primary { + primaryIndex = index + } else { + secondaryIndexes = append(secondaryIndexes, index) + } + } + + c, err := codec.New(s.CanonicalAvroSchema, primaryIndex, secondaryIndexes) + if err != nil { + panic(err) + } + + return c +} + +// StreamIndex represents an index on a stream +type StreamIndex struct { + _msgpack struct{} `msgpack:",omitempty"` + tableName struct{} `sql:"stream_indexes"` + StreamIndexID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` + StreamID uuid.UUID `sql:"on_delete:CASCADE,notnull,type:uuid"` + Stream *Stream `msgpack:"-"` + ShortID int `sql:",notnull",validate:"required"` + Fields []string `sql:",notnull",validate:"required,gte=1"` + Primary bool `sql:",notnull"` + Normalize bool `sql:",notnull"` +} + +// GetIndexID implements codec.Index +func (i *StreamIndex) GetIndexID() uuid.UUID { + return i.StreamIndexID +} + +// GetShortID implements codec.Index +func (i *StreamIndex) GetShortID() int { + return i.ShortID +} + +// GetFields implements codec.Index +func (i *StreamIndex) GetFields() []string { + return i.Fields +} + +// GetNormalize implements codec.Index +func (i *StreamIndex) GetNormalize() bool { + return i.Normalize +} + +// StreamInstance represents a single version of a stream (for a streaming stream, +// there will only be one instance; but for a batch stream, each update represents +// a new instance) +type StreamInstance struct { + _msgpack struct{} `msgpack:",omitempty"` + StreamInstanceID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` + StreamID uuid.UUID `sql:"on_delete:RESTRICT,notnull,type:uuid"` + Stream *Stream `msgpack:"-"` + CreatedOn time.Time `sql:",default:now()"` + UpdatedOn time.Time `sql:",default:now()"` + MadePrimaryOn *time.Time + MadeFinalOn *time.Time + Version int `sql:",notnull,default:0"` +} + +// EfficientStreamInstance can be used to efficiently make a UUID conform to engine/driver.StreamInstance +type EfficientStreamInstance uuid.UUID + +// GetStreamInstanceID implements engine/driver.StreamInstance +func (si EfficientStreamInstance) GetStreamInstanceID() uuid.UUID { + return uuid.UUID(si) +} + +// GetStreamInstanceID implements engine/driver.StreamInstance +func (si *StreamInstance) GetStreamInstanceID() uuid.UUID { + return si.StreamInstanceID +} + +// CachedInstance contains key information about a stream for rapid (cached) lookup +type CachedInstance struct { + StreamID uuid.UUID + Public bool + Final bool + UseLog bool + UseIndex bool + UseWarehouse bool + LogRetentionSeconds int32 + IndexRetentionSeconds int32 + WarehouseRetentionSeconds int32 + OrganizationID uuid.UUID + OrganizationName string + ProjectID uuid.UUID + ProjectName string + StreamName string + Codec *codec.Codec +} + +// CachedInstance implements engine/driver.Organization, engine/driver.Project, engine/driver.StreamInstance, and engine/driver.Stream + +// GetOrganizationID implements engine/driver.Organization +func (c *CachedInstance) GetOrganizationID() uuid.UUID { + return c.OrganizationID +} + +// GetOrganizationName implements engine/driver.Project +func (c *CachedInstance) GetOrganizationName() string { + return c.OrganizationName +} + +// GetProjectID implements engine/driver.Project +func (c *CachedInstance) GetProjectID() uuid.UUID { + return c.ProjectID +} + +// GetProjectName implements engine/driver.Project +func (c *CachedInstance) GetProjectName() string { + return c.ProjectName +} + +// GetPublic implements engine/driver.Project +func (c *CachedInstance) GetPublic() bool { + return c.Public +} + +// GetStreamID implements engine/driver.Stream +func (c *CachedInstance) GetStreamID() uuid.UUID { + return c.StreamID +} + +// GetStreamName implements engine/driver.Stream +func (c *CachedInstance) GetStreamName() string { + return c.StreamName +} + +// GetUseLog implements engine/driver.Stream +func (c *CachedInstance) GetUseLog() bool { + return c.UseLog +} + +// GetUseIndex implements engine/driver.Stream +func (c *CachedInstance) GetUseIndex() bool { + return c.UseIndex +} + +// GetUseWarehouse implements engine/driver.Stream +func (c *CachedInstance) GetUseWarehouse() bool { + return c.UseWarehouse +} + +// GetLogRetention implements engine/driver.Stream +func (c *CachedInstance) GetLogRetention() time.Duration { + return time.Duration(c.LogRetentionSeconds) * time.Second +} + +// GetIndexRetention implements engine/driver.Stream +func (c *CachedInstance) GetIndexRetention() time.Duration { + return time.Duration(c.IndexRetentionSeconds) * time.Second +} + +// GetWarehouseRetention implements engine/driver.Stream +func (c *CachedInstance) GetWarehouseRetention() time.Duration { + return time.Duration(c.WarehouseRetentionSeconds) * time.Second +} + +// GetCodec implements engine/driver.Stream +func (c *CachedInstance) GetCodec() *codec.Codec { + return c.Codec +} + +// --------------- +// Commands + +// CreateStreamCommand contains args for creating a stream +type CreateStreamCommand struct { + Project *Project + Name string + SchemaKind StreamSchemaKind + Schema string + Indexes *string + Description *string + AllowManualWrites *bool + UseLog *bool + UseIndex *bool + UseWarehouse *bool + LogRetentionSeconds *int + IndexRetentionSeconds *int + WarehouseRetentionSeconds *int +} + +// UpdateStreamCommand contains args for updating a stream +type UpdateStreamCommand struct { + Stream *Stream + SchemaKind *StreamSchemaKind + Schema *string + Description *string + AllowManualWrites *bool +} + +// --------------- +// Events + +// StreamCreatedEvent is sent when a stream is created +type StreamCreatedEvent struct { + Stream *Stream +} + +// StreamUpdatedEvent is sent when a stream is updated +type StreamUpdatedEvent struct { + Stream *Stream + ModifiedSchema bool +} + +// StreamDeletedEvent is sent when a stream is deleted +type StreamDeletedEvent struct { + StreamID uuid.UUID +} + +// StreamInstanceCreatedEvent is sent when a stream instance is created +type StreamInstanceCreatedEvent struct { + Stream *Stream + StreamInstance *StreamInstance + MakePrimary bool +} + +// StreamInstanceUpdatedEvent is sent when a stream instance is updated (made primary or final) +type StreamInstanceUpdatedEvent struct { + Stream *Stream + StreamInstance *StreamInstance + MakeFinal bool + MakePrimary bool + + // needed downstream + OrganizationName string + ProjectName string +} + +// StreamInstanceDeletedEvent is sent when a stream instance is deleted +type StreamInstanceDeletedEvent struct { + Stream *Stream + StreamInstance *StreamInstance +} + +// --------------- +// Validation + +var streamNameRegex = regexp.MustCompile("^[_a-z][_a-z0-9]*$") + +func init() { + Validator.RegisterStructValidation(func(sl validator.StructLevel) { + s := sl.Current().Interface().(Stream) + + if !streamNameRegex.MatchString(s.Name) { + sl.ReportError(s.Name, "Name", "", "alphanumericorunderscore", "") + } + }, Stream{}) +} diff --git a/models/user.go b/models/user.go new file mode 100644 index 00000000..d6b97d11 --- /dev/null +++ b/models/user.go @@ -0,0 +1,47 @@ +package models + +import ( + "time" + + uuid "github.com/satori/go.uuid" +) + +// User represents a Beneath user +type User struct { + _msgpack struct{} `msgpack:",omitempty"` + UserID uuid.UUID `sql:",pk,type:uuid,default:uuid_generate_v4()"` + Email string `sql:",notnull",validate:"required,email"` + GoogleID string `sql:",unique",validate:"omitempty,lte=255"` + GithubID string `sql:",unique",validate:"omitempty,lte=255"` + CreatedOn time.Time `sql:",default:now()"` + UpdatedOn time.Time `sql:",default:now()"` + Master bool `sql:",notnull,default:false"` // NOTE: when updating value, clear secret cache + ConsentTerms bool `sql:",notnull,default:false"` + ConsentNewsletter bool `sql:",notnull,default:false"` + ReadQuota *int64 // NOTE: when updating value, clear secret cache + WriteQuota *int64 // NOTE: when updating value, clear secret cache + ScanQuota *int64 // NOTE: when updating value, clear secret cache + BillingOrganizationID uuid.UUID `sql:",on_delete:restrict,notnull,type:uuid"` // NOTE: when updating value, clear secret cache + BillingOrganization *Organization `msgpack:"-"` + Projects []*Project `pg:"many2many:permissions_users_projects,fk:user_id,joinFK:project_id",msgpack:"-"` + Organizations []*Organization `pg:"many2many:permissions_users_organizations,fk:user_id,joinFK:organization_id",msgpack:"-"` + Secrets []*UserSecret `msgpack:"-"` +} + +// Validate runs validation on the user +func (u *User) Validate() error { + return Validator.Struct(u) +} + +// --------------- +// Events + +// UserCreatedEvent is sent when a user is created +type UserCreatedEvent struct { + User *User +} + +// UserUpdatedEvent is sent when a user is updated +type UserUpdatedEvent struct { + User *User +} diff --git a/models/validate.go b/models/validate.go new file mode 100644 index 00000000..b185fa2c --- /dev/null +++ b/models/validate.go @@ -0,0 +1,6 @@ +package models + +import "gopkg.in/go-playground/validator.v9" + +// Validator used for validation of models +var Validator = validator.New() diff --git a/pkg/envutil/config.go b/pkg/envutil/config.go index fa844372..9403b21c 100644 --- a/pkg/envutil/config.go +++ b/pkg/envutil/config.go @@ -3,9 +3,6 @@ package envutil import ( "fmt" "os" - - "github.com/joho/godotenv" - "github.com/kelseyhightower/envconfig" ) // Env represents a runtime environment @@ -42,27 +39,3 @@ func GetEnv() Env { panic(fmt.Errorf("ENV <%s> not recognized", env)) } } - -// LoadConfig loads config from env and panics on error -// For more details, see https://github.com/kelseyhightower/envconfig -func LoadConfig(prefix string, spec interface{}) { - // load .env if present - env := GetEnv() - loadEnv(fmt.Sprintf("configs/.%s.env", string(env))) - - // parse env into config - err := envconfig.Process(prefix, spec) - if err != nil { - panic(err) - } -} - -// loadEnv attempts to load .env files into the process. It panics on error. -func loadEnv(paths ...string) { - for _, path := range paths { - err := godotenv.Load(path) - if err != nil && err.Error() != fmt.Sprintf("open %s: no such file or directory", path) { - panic(err) - } - } -} diff --git a/pkg/grpcutil/grpcutil.go b/pkg/grpcutil/grpcutil.go new file mode 100644 index 00000000..2e1946a1 --- /dev/null +++ b/pkg/grpcutil/grpcutil.go @@ -0,0 +1,32 @@ +package grpcutil + +import ( + "context" + "fmt" + "net" + + "google.golang.org/grpc" +) + +// ListenAndServeContext serves a GRPC server and performs a graceful shutdown +// if/when ctx is cancelled. +func ListenAndServeContext(ctx context.Context, server *grpc.Server, port int) error { + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + return err + } + + cctx, cancel := context.WithCancel(ctx) + var serveErr error + go func() { + serveErr = server.Serve(lis) + cancel() + }() + + <-cctx.Done() + if serveErr == nil { + server.GracefulStop() + } + + return serveErr +} diff --git a/pkg/httputil/httputil.go b/pkg/httputil/httputil.go index 6afbc4b7..a9cfe0f7 100644 --- a/pkg/httputil/httputil.go +++ b/pkg/httputil/httputil.go @@ -1,11 +1,38 @@ package httputil import ( + "context" "encoding/json" "fmt" + "net" "net/http" ) +// ListenAndServeContext serves a HTTP server and performs a graceful shutdown +// if/when ctx is cancelled. +func ListenAndServeContext(ctx context.Context, server *http.Server, port int) error { + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + return err + } + + cctx, cancel := context.WithCancel(ctx) + var serveErr error + go func() { + serveErr = server.Serve(lis) + cancel() + }() + + <-cctx.Done() + if serveErr == nil { + // server.Serve always returns a non-nil err, so this must be a cancel on the parent ctx. + // We perform a graceful shutdown. + serveErr = server.Shutdown(context.Background()) + } + + return serveErr +} + // Error represents an error with a HTTP status code type Error struct { Code int diff --git a/scripts/gqlgen-control.sh b/scripts/gqlgen-control.sh index 20324621..ac511ce9 100755 --- a/scripts/gqlgen-control.sh +++ b/scripts/gqlgen-control.sh @@ -1 +1 @@ -go run github.com/99designs/gqlgen -c control/gql/gqlgen.yml \ No newline at end of file +go run github.com/99designs/gqlgen --config server/control/gql/gqlgen.yml \ No newline at end of file diff --git a/scripts/proto-build.sh b/scripts/proto-build.sh index 6dda35d5..5fffb676 100755 --- a/scripts/proto-build.sh +++ b/scripts/proto-build.sh @@ -3,7 +3,7 @@ shopt -s expand_aliases alias compile="protoc --go_out=plugins=grpc,paths=source_relative:." -compile engine/proto/*.proto -compile engine/driver/bigtable/proto/*.proto -compile engine/driver/bigquery/proto/*.proto -compile gateway/grpc/proto/*.proto +compile infrastructure/engine/proto/*.proto +compile infrastructure/engine/driver/bigtable/proto/*.proto +compile infrastructure/engine/driver/bigquery/proto/*.proto +compile server/data/grpc/proto/*.proto diff --git a/control/README.md b/server/control/README.md similarity index 100% rename from control/README.md rename to server/control/README.md diff --git a/server/control/auth.go b/server/control/auth.go new file mode 100644 index 00000000..1442fd3e --- /dev/null +++ b/server/control/auth.go @@ -0,0 +1,142 @@ +package control + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" + + "github.com/go-chi/chi" + "github.com/gorilla/sessions" + "github.com/markbates/goth" + "github.com/markbates/goth/gothic" + "github.com/markbates/goth/providers/github" + "github.com/markbates/goth/providers/google" + + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/pkg/httputil" + "gitlab.com/beneath-hq/beneath/pkg/log" + "gitlab.com/beneath-hq/beneath/services/middleware" +) + +// AuthOptions configures Beneath authentication +type AuthOptions struct { + Github struct { + ID string `mapstructure:"id"` + Secret string `mapstructure:"secret"` + } + Google struct { + ID string `mapstructure:"id"` + Secret string `mapstructure:"secret"` + } +} + +func (s *Server) initGoth() { + // add providers + goth.UseProviders( + google.New( + s.Options.Auth.Google.ID, s.Options.Auth.Google.Secret, s.authCallbackURL("google"), + "https://www.googleapis.com/auth/plus.login", "email", + ), + github.New( + s.Options.Auth.Github.ID, s.Options.Auth.Github.Secret, s.authCallbackURL("github"), + "user:email", + ), + ) + + // set store for oauth state + store := sessions.NewCookieStore([]byte(s.Options.SessionSecret)) + store.Options.HttpOnly = true + store.Options.Secure = strings.HasPrefix(s.Options.Host, "https") + gothic.Store = store +} + +func (s *Server) authCallbackURL(provider string) string { + return fmt.Sprintf("%s/auth/%s/callback", s.Options.Host, provider) +} + +func (s *Server) registerAuth() { + // social auth handlers + router := s.Router.With(providerParamToContext) + router.MethodFunc("GET", "/auth/{provider}", gothic.BeginAuthHandler) + router.Method("GET", "/auth/{provider}/callback", httputil.AppHandler(s.authCallbackHandler)) + + // logout handler + router.Method("GET", "/auth/logout", httputil.AppHandler(s.logoutHandler)) +} + +// providerParamToContext is a middleware that reads the url param "provider" and +// saves it in the request context -- necessary because goth reads the provider name +// from the key "provider" in the request context +func providerParamToContext(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + provider := chi.URLParam(r, "provider") + ctx := context.WithValue(r.Context(), interface{}("provider"), provider) + next.ServeHTTP(w, r.WithContext(ctx)) + }) +} + +// authCallbackHandler gets called after social authentication +func (s *Server) authCallbackHandler(w http.ResponseWriter, r *http.Request) error { + // handle with gothic + info, err := gothic.CompleteUserAuth(w, r) + if err != nil { + return err + } + + // we're not using gothic for auth management, so end the user session immediately + gothic.Logout(w, r) + + // get googleID or githubID + var googleID string + var githubID string + if info.Provider == "google" { + googleID = info.UserID + } else if info.Provider == "github" { + githubID = info.UserID + } else { + return httputil.NewError(500, "expected provider to be 'google' or 'github'") + } + + // we only want to use Github's nicknames + var nickname string + if githubID != "" { + nickname = info.NickName + } + + // upsert user + user, err := s.Users.CreateOrUpdateUser(r.Context(), githubID, googleID, info.Email, nickname, info.Name, info.AvatarURL) + if err != nil { + return err + } + + // create session secret + secret, err := s.Secrets.CreateUserSecret(r.Context(), user.UserID, "Browser session", false, false) + if err != nil { + return err + } + + // redirect to client, setting token + url := fmt.Sprintf("%s/-/redirects/auth/login/callback?token=%s", s.Options.FrontendHost, url.QueryEscape(secret.Token.String())) + http.Redirect(w, r, url, http.StatusSeeOther) + + // done + return nil +} + +// logoutHandler revokes the current auth secret +func (s *Server) logoutHandler(w http.ResponseWriter, r *http.Request) error { + secret := middleware.GetSecret(r.Context()) + if secret != nil { + if secret.IsUser() { + s.Secrets.RevokeUserSecret(r.Context(), secret.(*models.UserSecret)) + log.S.Infow( + "control user logout", + "user_id", secret.GetOwnerID(), + "secret_id", secret.GetSecretID(), + ) + } + } + return nil +} diff --git a/server/control/gql/gqlgen.yml b/server/control/gql/gqlgen.yml new file mode 100644 index 00000000..bde1b009 --- /dev/null +++ b/server/control/gql/gqlgen.yml @@ -0,0 +1,48 @@ +# Configures gqlgen – docs at https://gqlgen.com/config/ +# skip_validation: true +schema: +- "server/control/schema/**/*.graphql" +exec: + filename: server/control/gql/schema_gen.go + package: gql +model: + filename: server/control/gql/models_gen.go + package: gql +resolver: + filename: server/control/resolver/generated.go + package: resolver + type: Resolver +autobind: [] +models: + UUID: + model: gitlab.com/beneath-hq/beneath/server/control/gql.UUID + UserSecret: + model: gitlab.com/beneath-hq/beneath/models.UserSecret + ServiceSecret: + model: gitlab.com/beneath-hq/beneath/models.ServiceSecret + Project: + model: gitlab.com/beneath-hq/beneath/models.Project + Stream: + model: gitlab.com/beneath-hq/beneath/models.Stream + StreamInstance: + model: gitlab.com/beneath-hq/beneath/models.StreamInstance + StreamIndex: + model: gitlab.com/beneath-hq/beneath/models.StreamIndex + PrivateUser: + model: gitlab.com/beneath-hq/beneath/models.User + PublicOrganization: + model: gitlab.com/beneath-hq/beneath/models.Organization + ProjectMember: + model: gitlab.com/beneath-hq/beneath/models.ProjectMember + OrganizationMember: + model: gitlab.com/beneath-hq/beneath/models.OrganizationMember + Service: + model: gitlab.com/beneath-hq/beneath/models.Service + PermissionsUsersProjects: + model: gitlab.com/beneath-hq/beneath/models.PermissionsUsersProjects + PermissionsUsersOrganizations: + model: gitlab.com/beneath-hq/beneath/models.PermissionsUsersOrganizations + PermissionsServicesStreams: + model: gitlab.com/beneath-hq/beneath/models.PermissionsServicesStreams + StreamSchemaKind: + model: gitlab.com/beneath-hq/beneath/models.StreamSchemaKind diff --git a/control/gql/models_gen.go b/server/control/gql/models_gen.go similarity index 90% rename from control/gql/models_gen.go rename to server/control/gql/models_gen.go index 251dc6a4..e3edd736 100644 --- a/control/gql/models_gen.go +++ b/server/control/gql/models_gen.go @@ -9,7 +9,7 @@ import ( "time" "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/control/entity" + "gitlab.com/beneath-hq/beneath/models" ) type Organization interface { @@ -31,12 +31,12 @@ type Metrics struct { } type NewServiceSecret struct { - Secret *entity.ServiceSecret `json:"secret"` + Secret *models.ServiceSecret `json:"secret"` Token string `json:"token"` } type NewUserSecret struct { - Secret *entity.UserSecret `json:"secret"` + Secret *models.UserSecret `json:"secret"` Token string `json:"token"` } @@ -57,10 +57,10 @@ type PrivateOrganization struct { ReadUsage int `json:"readUsage"` WriteUsage int `json:"writeUsage"` ScanUsage int `json:"scanUsage"` - Projects []*entity.Project `json:"projects"` + Projects []*models.Project `json:"projects"` PersonalUserID *uuid.UUID `json:"personalUserID"` - PersonalUser *entity.User `json:"personalUser"` - Permissions *entity.PermissionsUsersOrganizations `json:"permissions"` + PersonalUser *models.User `json:"personalUser"` + Permissions *models.PermissionsUsersOrganizations `json:"permissions"` } func (PrivateOrganization) IsOrganization() {} diff --git a/control/gql/schema_gen.go b/server/control/gql/schema_gen.go similarity index 62% rename from control/gql/schema_gen.go rename to server/control/gql/schema_gen.go index 2e3cbb98..f6b73957 100644 --- a/control/gql/schema_gen.go +++ b/server/control/gql/schema_gen.go @@ -16,9 +16,9 @@ import ( "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/introspection" "github.com/satori/go.uuid" - "github.com/vektah/gqlparser" - "github.com/vektah/gqlparser/ast" - "gitlab.com/beneath-hq/beneath/control/entity" + gqlparser "github.com/vektah/gqlparser/v2" + "github.com/vektah/gqlparser/v2/ast" + "gitlab.com/beneath-hq/beneath/models" ) // region ************************** generated!.gotpl ************************** @@ -39,9 +39,6 @@ type Config struct { } type ResolverRoot interface { - BilledResource() BilledResourceResolver - BillingMethod() BillingMethodResolver - BillingPlan() BillingPlanResolver Mutation() MutationResolver OrganizationMember() OrganizationMemberResolver PrivateUser() PrivateUserResolver @@ -61,61 +58,6 @@ type DirectiveRoot struct { } type ComplexityRoot struct { - BilledResource struct { - BilledResourceID func(childComplexity int) int - BillingTime func(childComplexity int) int - CreatedOn func(childComplexity int) int - Currency func(childComplexity int) int - EndTime func(childComplexity int) int - EntityID func(childComplexity int) int - EntityKind func(childComplexity int) int - OrganizationID func(childComplexity int) int - Product func(childComplexity int) int - Quantity func(childComplexity int) int - StartTime func(childComplexity int) int - TotalPriceCents func(childComplexity int) int - UpdatedOn func(childComplexity int) int - } - - BillingInfo struct { - BillingMethod func(childComplexity int) int - BillingPlan func(childComplexity int) int - CompanyName func(childComplexity int) int - Country func(childComplexity int) int - OrganizationID func(childComplexity int) int - Region func(childComplexity int) int - TaxNumber func(childComplexity int) int - } - - BillingMethod struct { - BillingMethodID func(childComplexity int) int - DriverPayload func(childComplexity int) int - OrganizationID func(childComplexity int) int - PaymentsDriver func(childComplexity int) int - } - - BillingPlan struct { - AvailableInUI func(childComplexity int) int - BaseReadQuota func(childComplexity int) int - BaseScanQuota func(childComplexity int) int - BaseWriteQuota func(childComplexity int) int - BillingPlanID func(childComplexity int) int - Currency func(childComplexity int) int - Default func(childComplexity int) int - Description func(childComplexity int) int - Period func(childComplexity int) int - ReadOveragePriceCents func(childComplexity int) int - ReadQuota func(childComplexity int) int - ScanOveragePriceCents func(childComplexity int) int - ScanQuota func(childComplexity int) int - SeatPriceCents func(childComplexity int) int - SeatReadQuota func(childComplexity int) int - SeatScanQuota func(childComplexity int) int - SeatWriteQuota func(childComplexity int) int - WriteOveragePriceCents func(childComplexity int) int - WriteQuota func(childComplexity int) int - } - Metrics struct { EntityID func(childComplexity int) int Period func(childComplexity int) int @@ -147,10 +89,9 @@ type ComplexityRoot struct { RevokeUserSecret func(childComplexity int, secretID uuid.UUID) int StageProject func(childComplexity int, organizationName string, projectName string, displayName *string, public *bool, description *string, site *string, photoURL *string) int StageService func(childComplexity int, organizationName string, projectName string, serviceName string, description *string, sourceURL *string, readQuota *int, writeQuota *int, scanQuota *int) int - StageStream func(childComplexity int, organizationName string, projectName string, streamName string, schemaKind entity.StreamSchemaKind, schema string, indexes *string, description *string, allowManualWrites *bool, useLog *bool, useIndex *bool, useWarehouse *bool, logRetentionSeconds *int, indexRetentionSeconds *int, warehouseRetentionSeconds *int) int + StageStream func(childComplexity int, organizationName string, projectName string, streamName string, schemaKind models.StreamSchemaKind, schema string, indexes *string, description *string, allowManualWrites *bool, useLog *bool, useIndex *bool, useWarehouse *bool, logRetentionSeconds *int, indexRetentionSeconds *int, warehouseRetentionSeconds *int) int StageStreamInstance func(childComplexity int, streamID uuid.UUID, version int, makeFinal *bool, makePrimary *bool) int TransferProjectToOrganization func(childComplexity int, projectID uuid.UUID, organizationID uuid.UUID) int - UpdateBillingInfo func(childComplexity int, organizationID uuid.UUID, billingMethodID *uuid.UUID, billingPlanID uuid.UUID, country string, region *string, companyName *string, taxNumber *string) int UpdateOrganization func(childComplexity int, organizationID uuid.UUID, name *string, displayName *string, description *string, photoURL *string) int UpdateOrganizationQuotas func(childComplexity int, organizationID uuid.UUID, readQuota *int, writeQuota *int, scanQuota *int) int UpdateServiceStreamPermissions func(childComplexity int, serviceID uuid.UUID, streamID uuid.UUID, read *bool, write *bool) int @@ -284,10 +225,6 @@ type ComplexityRoot struct { } Query struct { - BilledResources func(childComplexity int, organizationID uuid.UUID, billingTime time.Time) int - BillingInfo func(childComplexity int, organizationID uuid.UUID) int - BillingMethods func(childComplexity int, organizationID uuid.UUID) int - BillingPlans func(childComplexity int) int Empty func(childComplexity int) int ExploreProjects func(childComplexity int) int GetMetrics func(childComplexity int, entityKind EntityKind, entityID uuid.UUID, period string, from time.Time, until *time.Time) int @@ -397,77 +334,56 @@ type ComplexityRoot struct { } } -type BilledResourceResolver interface { - EntityKind(ctx context.Context, obj *entity.BilledResource) (string, error) - - Product(ctx context.Context, obj *entity.BilledResource) (string, error) - Quantity(ctx context.Context, obj *entity.BilledResource) (float64, error) - - Currency(ctx context.Context, obj *entity.BilledResource) (string, error) -} -type BillingMethodResolver interface { - PaymentsDriver(ctx context.Context, obj *entity.BillingMethod) (string, error) - DriverPayload(ctx context.Context, obj *entity.BillingMethod) (string, error) -} -type BillingPlanResolver interface { - Currency(ctx context.Context, obj *entity.BillingPlan) (string, error) - Period(ctx context.Context, obj *entity.BillingPlan) (string, error) -} type MutationResolver interface { Empty(ctx context.Context) (*string, error) - UpdateBillingInfo(ctx context.Context, organizationID uuid.UUID, billingMethodID *uuid.UUID, billingPlanID uuid.UUID, country string, region *string, companyName *string, taxNumber *string) (*entity.BillingInfo, error) CreateOrganization(ctx context.Context, name string) (*PrivateOrganization, error) UpdateOrganization(ctx context.Context, organizationID uuid.UUID, name *string, displayName *string, description *string, photoURL *string) (*PrivateOrganization, error) UpdateOrganizationQuotas(ctx context.Context, organizationID uuid.UUID, readQuota *int, writeQuota *int, scanQuota *int) (*PrivateOrganization, error) InviteUserToOrganization(ctx context.Context, userID uuid.UUID, organizationID uuid.UUID, view bool, create bool, admin bool) (bool, error) AcceptOrganizationInvite(ctx context.Context, organizationID uuid.UUID) (bool, error) - LeaveBillingOrganization(ctx context.Context, userID uuid.UUID) (*entity.User, error) - TransferProjectToOrganization(ctx context.Context, projectID uuid.UUID, organizationID uuid.UUID) (*entity.Project, error) - StageProject(ctx context.Context, organizationName string, projectName string, displayName *string, public *bool, description *string, site *string, photoURL *string) (*entity.Project, error) + LeaveBillingOrganization(ctx context.Context, userID uuid.UUID) (*models.User, error) + TransferProjectToOrganization(ctx context.Context, projectID uuid.UUID, organizationID uuid.UUID) (*models.Project, error) + StageProject(ctx context.Context, organizationName string, projectName string, displayName *string, public *bool, description *string, site *string, photoURL *string) (*models.Project, error) DeleteProject(ctx context.Context, projectID uuid.UUID) (bool, error) IssueServiceSecret(ctx context.Context, serviceID uuid.UUID, description string) (*NewServiceSecret, error) IssueUserSecret(ctx context.Context, description string, readOnly bool, publicOnly bool) (*NewUserSecret, error) RevokeServiceSecret(ctx context.Context, secretID uuid.UUID) (bool, error) RevokeUserSecret(ctx context.Context, secretID uuid.UUID) (bool, error) - StageService(ctx context.Context, organizationName string, projectName string, serviceName string, description *string, sourceURL *string, readQuota *int, writeQuota *int, scanQuota *int) (*entity.Service, error) - UpdateServiceStreamPermissions(ctx context.Context, serviceID uuid.UUID, streamID uuid.UUID, read *bool, write *bool) (*entity.PermissionsServicesStreams, error) + StageService(ctx context.Context, organizationName string, projectName string, serviceName string, description *string, sourceURL *string, readQuota *int, writeQuota *int, scanQuota *int) (*models.Service, error) + UpdateServiceStreamPermissions(ctx context.Context, serviceID uuid.UUID, streamID uuid.UUID, read *bool, write *bool) (*models.PermissionsServicesStreams, error) DeleteService(ctx context.Context, serviceID uuid.UUID) (bool, error) - StageStream(ctx context.Context, organizationName string, projectName string, streamName string, schemaKind entity.StreamSchemaKind, schema string, indexes *string, description *string, allowManualWrites *bool, useLog *bool, useIndex *bool, useWarehouse *bool, logRetentionSeconds *int, indexRetentionSeconds *int, warehouseRetentionSeconds *int) (*entity.Stream, error) + StageStream(ctx context.Context, organizationName string, projectName string, streamName string, schemaKind models.StreamSchemaKind, schema string, indexes *string, description *string, allowManualWrites *bool, useLog *bool, useIndex *bool, useWarehouse *bool, logRetentionSeconds *int, indexRetentionSeconds *int, warehouseRetentionSeconds *int) (*models.Stream, error) DeleteStream(ctx context.Context, streamID uuid.UUID) (bool, error) - StageStreamInstance(ctx context.Context, streamID uuid.UUID, version int, makeFinal *bool, makePrimary *bool) (*entity.StreamInstance, error) - UpdateStreamInstance(ctx context.Context, instanceID uuid.UUID, makeFinal *bool, makePrimary *bool) (*entity.StreamInstance, error) + StageStreamInstance(ctx context.Context, streamID uuid.UUID, version int, makeFinal *bool, makePrimary *bool) (*models.StreamInstance, error) + UpdateStreamInstance(ctx context.Context, instanceID uuid.UUID, makeFinal *bool, makePrimary *bool) (*models.StreamInstance, error) DeleteStreamInstance(ctx context.Context, instanceID uuid.UUID) (bool, error) - RegisterUserConsent(ctx context.Context, userID uuid.UUID, terms *bool, newsletter *bool) (*entity.User, error) - UpdateUserQuotas(ctx context.Context, userID uuid.UUID, readQuota *int, writeQuota *int, scanQuota *int) (*entity.User, error) - UpdateUserProjectPermissions(ctx context.Context, userID uuid.UUID, projectID uuid.UUID, view *bool, create *bool, admin *bool) (*entity.PermissionsUsersProjects, error) - UpdateUserOrganizationPermissions(ctx context.Context, userID uuid.UUID, organizationID uuid.UUID, view *bool, create *bool, admin *bool) (*entity.PermissionsUsersOrganizations, error) + RegisterUserConsent(ctx context.Context, userID uuid.UUID, terms *bool, newsletter *bool) (*models.User, error) + UpdateUserQuotas(ctx context.Context, userID uuid.UUID, readQuota *int, writeQuota *int, scanQuota *int) (*models.User, error) + UpdateUserProjectPermissions(ctx context.Context, userID uuid.UUID, projectID uuid.UUID, view *bool, create *bool, admin *bool) (*models.PermissionsUsersProjects, error) + UpdateUserOrganizationPermissions(ctx context.Context, userID uuid.UUID, organizationID uuid.UUID, view *bool, create *bool, admin *bool) (*models.PermissionsUsersOrganizations, error) } type OrganizationMemberResolver interface { - OrganizationID(ctx context.Context, obj *entity.OrganizationMember) (string, error) - UserID(ctx context.Context, obj *entity.OrganizationMember) (string, error) + OrganizationID(ctx context.Context, obj *models.OrganizationMember) (string, error) + UserID(ctx context.Context, obj *models.OrganizationMember) (string, error) } type PrivateUserResolver interface { - UserID(ctx context.Context, obj *entity.User) (string, error) + UserID(ctx context.Context, obj *models.User) (string, error) } type ProjectResolver interface { - ProjectID(ctx context.Context, obj *entity.Project) (string, error) + ProjectID(ctx context.Context, obj *models.Project) (string, error) } type ProjectMemberResolver interface { - ProjectID(ctx context.Context, obj *entity.ProjectMember) (string, error) - UserID(ctx context.Context, obj *entity.ProjectMember) (string, error) + ProjectID(ctx context.Context, obj *models.ProjectMember) (string, error) + UserID(ctx context.Context, obj *models.ProjectMember) (string, error) } type PublicOrganizationResolver interface { - OrganizationID(ctx context.Context, obj *entity.Organization) (string, error) + OrganizationID(ctx context.Context, obj *models.Organization) (string, error) - PersonalUserID(ctx context.Context, obj *entity.Organization) (*uuid.UUID, error) + PersonalUserID(ctx context.Context, obj *models.Organization) (*uuid.UUID, error) } type QueryResolver interface { Empty(ctx context.Context) (*string, error) Ping(ctx context.Context) (string, error) - BilledResources(ctx context.Context, organizationID uuid.UUID, billingTime time.Time) ([]*entity.BilledResource, error) - BillingInfo(ctx context.Context, organizationID uuid.UUID) (*entity.BillingInfo, error) - BillingMethods(ctx context.Context, organizationID uuid.UUID) ([]*entity.BillingMethod, error) - BillingPlans(ctx context.Context) ([]*entity.BillingPlan, error) GetMetrics(ctx context.Context, entityKind EntityKind, entityID uuid.UUID, period string, from time.Time, until *time.Time) ([]*Metrics, error) GetOrganizationMetrics(ctx context.Context, organizationID uuid.UUID, period string, from time.Time, until *time.Time) ([]*Metrics, error) GetServiceMetrics(ctx context.Context, serviceID uuid.UUID, period string, from time.Time, until *time.Time) ([]*Metrics, error) @@ -478,38 +394,38 @@ type QueryResolver interface { OrganizationByName(ctx context.Context, name string) (Organization, error) OrganizationByID(ctx context.Context, organizationID uuid.UUID) (Organization, error) OrganizationByUserID(ctx context.Context, userID uuid.UUID) (Organization, error) - OrganizationMembers(ctx context.Context, organizationID uuid.UUID) ([]*entity.OrganizationMember, error) - ExploreProjects(ctx context.Context) ([]*entity.Project, error) - ProjectsForUser(ctx context.Context, userID uuid.UUID) ([]*entity.Project, error) - ProjectByOrganizationAndName(ctx context.Context, organizationName string, projectName string) (*entity.Project, error) - ProjectByID(ctx context.Context, projectID uuid.UUID) (*entity.Project, error) - ProjectMembers(ctx context.Context, projectID uuid.UUID) ([]*entity.ProjectMember, error) - SecretsForService(ctx context.Context, serviceID uuid.UUID) ([]*entity.ServiceSecret, error) - SecretsForUser(ctx context.Context, userID uuid.UUID) ([]*entity.UserSecret, error) - ServiceByID(ctx context.Context, serviceID uuid.UUID) (*entity.Service, error) - ServiceByOrganizationProjectAndName(ctx context.Context, organizationName string, projectName string, serviceName string) (*entity.Service, error) - StreamByID(ctx context.Context, streamID uuid.UUID) (*entity.Stream, error) - StreamByOrganizationProjectAndName(ctx context.Context, organizationName string, projectName string, streamName string) (*entity.Stream, error) - StreamInstancesForStream(ctx context.Context, streamID uuid.UUID) ([]*entity.StreamInstance, error) - StreamInstancesByOrganizationProjectAndStreamName(ctx context.Context, organizationName string, projectName string, streamName string) ([]*entity.StreamInstance, error) + OrganizationMembers(ctx context.Context, organizationID uuid.UUID) ([]*models.OrganizationMember, error) + ExploreProjects(ctx context.Context) ([]*models.Project, error) + ProjectsForUser(ctx context.Context, userID uuid.UUID) ([]*models.Project, error) + ProjectByOrganizationAndName(ctx context.Context, organizationName string, projectName string) (*models.Project, error) + ProjectByID(ctx context.Context, projectID uuid.UUID) (*models.Project, error) + ProjectMembers(ctx context.Context, projectID uuid.UUID) ([]*models.ProjectMember, error) + SecretsForService(ctx context.Context, serviceID uuid.UUID) ([]*models.ServiceSecret, error) + SecretsForUser(ctx context.Context, userID uuid.UUID) ([]*models.UserSecret, error) + ServiceByID(ctx context.Context, serviceID uuid.UUID) (*models.Service, error) + ServiceByOrganizationProjectAndName(ctx context.Context, organizationName string, projectName string, serviceName string) (*models.Service, error) + StreamByID(ctx context.Context, streamID uuid.UUID) (*models.Stream, error) + StreamByOrganizationProjectAndName(ctx context.Context, organizationName string, projectName string, streamName string) (*models.Stream, error) + StreamInstancesForStream(ctx context.Context, streamID uuid.UUID) ([]*models.StreamInstance, error) + StreamInstancesByOrganizationProjectAndStreamName(ctx context.Context, organizationName string, projectName string, streamName string) ([]*models.StreamInstance, error) } type ServiceSecretResolver interface { - ServiceSecretID(ctx context.Context, obj *entity.ServiceSecret) (string, error) + ServiceSecretID(ctx context.Context, obj *models.ServiceSecret) (string, error) } type StreamResolver interface { - StreamID(ctx context.Context, obj *entity.Stream) (string, error) + StreamID(ctx context.Context, obj *models.Stream) (string, error) } type StreamIndexResolver interface { - IndexID(ctx context.Context, obj *entity.StreamIndex) (string, error) + IndexID(ctx context.Context, obj *models.StreamIndex) (string, error) } type StreamInstanceResolver interface { - StreamInstanceID(ctx context.Context, obj *entity.StreamInstance) (string, error) + StreamInstanceID(ctx context.Context, obj *models.StreamInstance) (string, error) } type SubscriptionResolver interface { Empty(ctx context.Context) (<-chan *string, error) } type UserSecretResolver interface { - UserSecretID(ctx context.Context, obj *entity.UserSecret) (string, error) + UserSecretID(ctx context.Context, obj *models.UserSecret) (string, error) } type executableSchema struct { @@ -527,307 +443,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in _ = ec switch typeName + "." + field { - case "BilledResource.billedResourceID": - if e.complexity.BilledResource.BilledResourceID == nil { - break - } - - return e.complexity.BilledResource.BilledResourceID(childComplexity), true - - case "BilledResource.billingTime": - if e.complexity.BilledResource.BillingTime == nil { - break - } - - return e.complexity.BilledResource.BillingTime(childComplexity), true - - case "BilledResource.createdOn": - if e.complexity.BilledResource.CreatedOn == nil { - break - } - - return e.complexity.BilledResource.CreatedOn(childComplexity), true - - case "BilledResource.currency": - if e.complexity.BilledResource.Currency == nil { - break - } - - return e.complexity.BilledResource.Currency(childComplexity), true - - case "BilledResource.endTime": - if e.complexity.BilledResource.EndTime == nil { - break - } - - return e.complexity.BilledResource.EndTime(childComplexity), true - - case "BilledResource.entityID": - if e.complexity.BilledResource.EntityID == nil { - break - } - - return e.complexity.BilledResource.EntityID(childComplexity), true - - case "BilledResource.entityKind": - if e.complexity.BilledResource.EntityKind == nil { - break - } - - return e.complexity.BilledResource.EntityKind(childComplexity), true - - case "BilledResource.organizationID": - if e.complexity.BilledResource.OrganizationID == nil { - break - } - - return e.complexity.BilledResource.OrganizationID(childComplexity), true - - case "BilledResource.product": - if e.complexity.BilledResource.Product == nil { - break - } - - return e.complexity.BilledResource.Product(childComplexity), true - - case "BilledResource.quantity": - if e.complexity.BilledResource.Quantity == nil { - break - } - - return e.complexity.BilledResource.Quantity(childComplexity), true - - case "BilledResource.startTime": - if e.complexity.BilledResource.StartTime == nil { - break - } - - return e.complexity.BilledResource.StartTime(childComplexity), true - - case "BilledResource.totalPriceCents": - if e.complexity.BilledResource.TotalPriceCents == nil { - break - } - - return e.complexity.BilledResource.TotalPriceCents(childComplexity), true - - case "BilledResource.updatedOn": - if e.complexity.BilledResource.UpdatedOn == nil { - break - } - - return e.complexity.BilledResource.UpdatedOn(childComplexity), true - - case "BillingInfo.billingMethod": - if e.complexity.BillingInfo.BillingMethod == nil { - break - } - - return e.complexity.BillingInfo.BillingMethod(childComplexity), true - - case "BillingInfo.billingPlan": - if e.complexity.BillingInfo.BillingPlan == nil { - break - } - - return e.complexity.BillingInfo.BillingPlan(childComplexity), true - - case "BillingInfo.companyName": - if e.complexity.BillingInfo.CompanyName == nil { - break - } - - return e.complexity.BillingInfo.CompanyName(childComplexity), true - - case "BillingInfo.country": - if e.complexity.BillingInfo.Country == nil { - break - } - - return e.complexity.BillingInfo.Country(childComplexity), true - - case "BillingInfo.organizationID": - if e.complexity.BillingInfo.OrganizationID == nil { - break - } - - return e.complexity.BillingInfo.OrganizationID(childComplexity), true - - case "BillingInfo.region": - if e.complexity.BillingInfo.Region == nil { - break - } - - return e.complexity.BillingInfo.Region(childComplexity), true - - case "BillingInfo.taxNumber": - if e.complexity.BillingInfo.TaxNumber == nil { - break - } - - return e.complexity.BillingInfo.TaxNumber(childComplexity), true - - case "BillingMethod.billingMethodID": - if e.complexity.BillingMethod.BillingMethodID == nil { - break - } - - return e.complexity.BillingMethod.BillingMethodID(childComplexity), true - - case "BillingMethod.driverPayload": - if e.complexity.BillingMethod.DriverPayload == nil { - break - } - - return e.complexity.BillingMethod.DriverPayload(childComplexity), true - - case "BillingMethod.organizationID": - if e.complexity.BillingMethod.OrganizationID == nil { - break - } - - return e.complexity.BillingMethod.OrganizationID(childComplexity), true - - case "BillingMethod.paymentsDriver": - if e.complexity.BillingMethod.PaymentsDriver == nil { - break - } - - return e.complexity.BillingMethod.PaymentsDriver(childComplexity), true - - case "BillingPlan.availableInUI": - if e.complexity.BillingPlan.AvailableInUI == nil { - break - } - - return e.complexity.BillingPlan.AvailableInUI(childComplexity), true - - case "BillingPlan.baseReadQuota": - if e.complexity.BillingPlan.BaseReadQuota == nil { - break - } - - return e.complexity.BillingPlan.BaseReadQuota(childComplexity), true - - case "BillingPlan.baseScanQuota": - if e.complexity.BillingPlan.BaseScanQuota == nil { - break - } - - return e.complexity.BillingPlan.BaseScanQuota(childComplexity), true - - case "BillingPlan.baseWriteQuota": - if e.complexity.BillingPlan.BaseWriteQuota == nil { - break - } - - return e.complexity.BillingPlan.BaseWriteQuota(childComplexity), true - - case "BillingPlan.billingPlanID": - if e.complexity.BillingPlan.BillingPlanID == nil { - break - } - - return e.complexity.BillingPlan.BillingPlanID(childComplexity), true - - case "BillingPlan.currency": - if e.complexity.BillingPlan.Currency == nil { - break - } - - return e.complexity.BillingPlan.Currency(childComplexity), true - - case "BillingPlan.default": - if e.complexity.BillingPlan.Default == nil { - break - } - - return e.complexity.BillingPlan.Default(childComplexity), true - - case "BillingPlan.description": - if e.complexity.BillingPlan.Description == nil { - break - } - - return e.complexity.BillingPlan.Description(childComplexity), true - - case "BillingPlan.period": - if e.complexity.BillingPlan.Period == nil { - break - } - - return e.complexity.BillingPlan.Period(childComplexity), true - - case "BillingPlan.readOveragePriceCents": - if e.complexity.BillingPlan.ReadOveragePriceCents == nil { - break - } - - return e.complexity.BillingPlan.ReadOveragePriceCents(childComplexity), true - - case "BillingPlan.readQuota": - if e.complexity.BillingPlan.ReadQuota == nil { - break - } - - return e.complexity.BillingPlan.ReadQuota(childComplexity), true - - case "BillingPlan.scanOveragePriceCents": - if e.complexity.BillingPlan.ScanOveragePriceCents == nil { - break - } - - return e.complexity.BillingPlan.ScanOveragePriceCents(childComplexity), true - - case "BillingPlan.scanQuota": - if e.complexity.BillingPlan.ScanQuota == nil { - break - } - - return e.complexity.BillingPlan.ScanQuota(childComplexity), true - - case "BillingPlan.seatPriceCents": - if e.complexity.BillingPlan.SeatPriceCents == nil { - break - } - - return e.complexity.BillingPlan.SeatPriceCents(childComplexity), true - - case "BillingPlan.seatReadQuota": - if e.complexity.BillingPlan.SeatReadQuota == nil { - break - } - - return e.complexity.BillingPlan.SeatReadQuota(childComplexity), true - - case "BillingPlan.seatScanQuota": - if e.complexity.BillingPlan.SeatScanQuota == nil { - break - } - - return e.complexity.BillingPlan.SeatScanQuota(childComplexity), true - - case "BillingPlan.seatWriteQuota": - if e.complexity.BillingPlan.SeatWriteQuota == nil { - break - } - - return e.complexity.BillingPlan.SeatWriteQuota(childComplexity), true - - case "BillingPlan.writeOveragePriceCents": - if e.complexity.BillingPlan.WriteOveragePriceCents == nil { - break - } - - return e.complexity.BillingPlan.WriteOveragePriceCents(childComplexity), true - - case "BillingPlan.writeQuota": - if e.complexity.BillingPlan.WriteQuota == nil { - break - } - - return e.complexity.BillingPlan.WriteQuota(childComplexity), true - case "Metrics.entityID": if e.complexity.Metrics.EntityID == nil { break @@ -1102,7 +717,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Mutation.StageStream(childComplexity, args["organizationName"].(string), args["projectName"].(string), args["streamName"].(string), args["schemaKind"].(entity.StreamSchemaKind), args["schema"].(string), args["indexes"].(*string), args["description"].(*string), args["allowManualWrites"].(*bool), args["useLog"].(*bool), args["useIndex"].(*bool), args["useWarehouse"].(*bool), args["logRetentionSeconds"].(*int), args["indexRetentionSeconds"].(*int), args["warehouseRetentionSeconds"].(*int)), true + return e.complexity.Mutation.StageStream(childComplexity, args["organizationName"].(string), args["projectName"].(string), args["streamName"].(string), args["schemaKind"].(models.StreamSchemaKind), args["schema"].(string), args["indexes"].(*string), args["description"].(*string), args["allowManualWrites"].(*bool), args["useLog"].(*bool), args["useIndex"].(*bool), args["useWarehouse"].(*bool), args["logRetentionSeconds"].(*int), args["indexRetentionSeconds"].(*int), args["warehouseRetentionSeconds"].(*int)), true case "Mutation.stageStreamInstance": if e.complexity.Mutation.StageStreamInstance == nil { @@ -1128,18 +743,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.TransferProjectToOrganization(childComplexity, args["projectID"].(uuid.UUID), args["organizationID"].(uuid.UUID)), true - case "Mutation.updateBillingInfo": - if e.complexity.Mutation.UpdateBillingInfo == nil { - break - } - - args, err := ec.field_Mutation_updateBillingInfo_args(context.TODO(), rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Mutation.UpdateBillingInfo(childComplexity, args["organizationID"].(uuid.UUID), args["billingMethodID"].(*uuid.UUID), args["billingPlanID"].(uuid.UUID), args["country"].(string), args["region"].(*string), args["companyName"].(*string), args["taxNumber"].(*string)), true - case "Mutation.updateOrganization": if e.complexity.Mutation.UpdateOrganization == nil { break @@ -1854,49 +1457,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PublicOrganization.Projects(childComplexity), true - case "Query.billedResources": - if e.complexity.Query.BilledResources == nil { - break - } - - args, err := ec.field_Query_billedResources_args(context.TODO(), rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Query.BilledResources(childComplexity, args["organizationID"].(uuid.UUID), args["billingTime"].(time.Time)), true - - case "Query.billingInfo": - if e.complexity.Query.BillingInfo == nil { - break - } - - args, err := ec.field_Query_billingInfo_args(context.TODO(), rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Query.BillingInfo(childComplexity, args["organizationID"].(uuid.UUID)), true - - case "Query.billingMethods": - if e.complexity.Query.BillingMethods == nil { - break - } - - args, err := ec.field_Query_billingMethods_args(context.TODO(), rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Query.BillingMethods(childComplexity, args["organizationID"].(uuid.UUID)), true - - case "Query.billingPlans": - if e.complexity.Query.BillingPlans == nil { - break - } - - return e.complexity.Query.BillingPlans(childComplexity), true - case "Query.empty": if e.complexity.Query.Empty == nil { break @@ -2606,51 +2166,45 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } -func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { - ec := executionContext{graphql.GetRequestContext(ctx), e} +func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { + rc := graphql.GetOperationContext(ctx) + ec := executionContext{rc, e} + first := true - buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._Query(ctx, op.SelectionSet) - var buf bytes.Buffer - data.MarshalGQL(&buf) - return buf.Bytes() - }) + switch rc.Operation.Operation { + case ast.Query: + return func(ctx context.Context) *graphql.Response { + if !first { + return nil + } + first = false + data := ec._Query(ctx, rc.Operation.SelectionSet) + var buf bytes.Buffer + data.MarshalGQL(&buf) - return &graphql.Response{ - Data: buf, - Errors: ec.Errors, - Extensions: ec.Extensions, - } -} + return &graphql.Response{ + Data: buf.Bytes(), + } + } + case ast.Mutation: + return func(ctx context.Context) *graphql.Response { + if !first { + return nil + } + first = false + data := ec._Mutation(ctx, rc.Operation.SelectionSet) + var buf bytes.Buffer + data.MarshalGQL(&buf) -func (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response { - ec := executionContext{graphql.GetRequestContext(ctx), e} + return &graphql.Response{ + Data: buf.Bytes(), + } + } + case ast.Subscription: + next := ec._Subscription(ctx, rc.Operation.SelectionSet) - buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { - data := ec._Mutation(ctx, op.SelectionSet) var buf bytes.Buffer - data.MarshalGQL(&buf) - return buf.Bytes() - }) - - return &graphql.Response{ - Data: buf, - Errors: ec.Errors, - Extensions: ec.Extensions, - } -} - -func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response { - ec := executionContext{graphql.GetRequestContext(ctx), e} - - next := ec._Subscription(ctx, op.SelectionSet) - if ec.Errors != nil { - return graphql.OneShot(&graphql.Response{Data: []byte("null"), Errors: ec.Errors}) - } - - var buf bytes.Buffer - return func() *graphql.Response { - buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte { + return func(ctx context.Context) *graphql.Response { buf.Reset() data := next() @@ -2658,23 +2212,19 @@ func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDe return nil } data.MarshalGQL(&buf) - return buf.Bytes() - }) - if buf == nil { - return nil + return &graphql.Response{ + Data: buf.Bytes(), + } } - return &graphql.Response{ - Data: buf, - Errors: ec.Errors, - Extensions: ec.Extensions, - } + default: + return graphql.OneShot(graphql.ErrorResponse(ctx, "unsupported GraphQL operation")) } } type executionContext struct { - *graphql.RequestContext + *graphql.OperationContext *executableSchema } @@ -2692,8 +2242,8 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil } -var parsedSchema = gqlparser.MustLoadSchema( - &ast.Source{Name: "control/gql/schema/base.graphql", Input: `scalar Time +var sources = []*ast.Source{ + {Name: "server/control/schema/base.graphql", Input: `scalar Time scalar UUID type Query { @@ -2708,89 +2258,14 @@ type Mutation { type Subscription { empty: String } -`}, - &ast.Source{Name: "control/gql/schema/billed_resources.graphql", Input: `extend type Query { - billedResources(organizationID: UUID!, billingTime: Time!): [BilledResource!]! -} - -type BilledResource { - billedResourceID: UUID! - organizationID: UUID! - billingTime: Time! - entityID: UUID! - entityKind: String! - startTime: Time! - endTime: Time! - product: String! - quantity: Float! - totalPriceCents: Int! - currency: String! - createdOn: Time! - updatedOn: Time! -} -`}, - &ast.Source{Name: "control/gql/schema/billing_info.graphql", Input: `extend type Query { - billingInfo(organizationID: UUID!): BillingInfo! -} - -extend type Mutation { - updateBillingInfo(organizationID: UUID!, billingMethodID: UUID, billingPlanID: UUID!, country: String!, region: String, companyName: String, taxNumber: String): BillingInfo! -} - -type BillingInfo { - organizationID: UUID! - billingMethod: BillingMethod - billingPlan: BillingPlan! - country: String! - region: String - companyName: String - taxNumber: String -} -`}, - &ast.Source{Name: "control/gql/schema/billing_method.graphql", Input: `extend type Query { - billingMethods(organizationID: UUID!): [BillingMethod!]! -} - -type BillingMethod { - billingMethodID: UUID! - organizationID: UUID! - paymentsDriver: String! - driverPayload: String! -} -`}, - &ast.Source{Name: "control/gql/schema/billing_plans.graphql", Input: `extend type Query { - billingPlans: [BillingPlan!]! -} - -type BillingPlan { - billingPlanID: UUID! - default: Boolean! - description: String - currency: String! - period: String! - seatPriceCents: Int! - seatReadQuota: Int! - seatWriteQuota: Int! - seatScanQuota: Int! - readOveragePriceCents: Int! - writeOveragePriceCents: Int! - scanOveragePriceCents: Int! - baseReadQuota: Int! - baseWriteQuota: Int! - baseScanQuota: Int! - readQuota: Int! - writeQuota: Int! - scanQuota: Int! - availableInUI: Boolean! -} -`}, - &ast.Source{Name: "control/gql/schema/metrics.graphql", Input: `extend type Query { - getMetrics(entityKind: EntityKind!, entityID: UUID!, period: String!, from: Time!, until: Time): [Metrics!]! - getOrganizationMetrics(organizationID: UUID!, period: String!, from: Time!, until: Time): [Metrics!]! - getServiceMetrics(serviceID: UUID!, period: String!, from: Time!, until: Time): [Metrics!]! - getStreamInstanceMetrics(streamInstanceID: UUID!, period: String!, from: Time!, until: Time): [Metrics!]! - getStreamMetrics(streamID: UUID!, period: String!, from: Time!, until: Time): [Metrics!]! - getUserMetrics(userID: UUID!, period: String!, from: Time!, until: Time): [Metrics!]! +`, BuiltIn: false}, + {Name: "server/control/schema/metrics.graphql", Input: `extend type Query { + getMetrics(entityKind: EntityKind!, entityID: UUID!, period: String!, from: Time!, until: Time): [Metrics!]! + getOrganizationMetrics(organizationID: UUID!, period: String!, from: Time!, until: Time): [Metrics!]! + getServiceMetrics(serviceID: UUID!, period: String!, from: Time!, until: Time): [Metrics!]! + getStreamInstanceMetrics(streamInstanceID: UUID!, period: String!, from: Time!, until: Time): [Metrics!]! + getStreamMetrics(streamID: UUID!, period: String!, from: Time!, until: Time): [Metrics!]! + getUserMetrics(userID: UUID!, period: String!, from: Time!, until: Time): [Metrics!]! } type Metrics { @@ -2813,8 +2288,8 @@ enum EntityKind { StreamInstance Stream User -}`}, - &ast.Source{Name: "control/gql/schema/organizations.graphql", Input: `extend type Query { +}`, BuiltIn: false}, + {Name: "server/control/schema/organizations.graphql", Input: `extend type Query { me: PrivateOrganization organizationByName(name: String!): Organization! organizationByID(organizationID: UUID!): Organization! @@ -2893,8 +2368,8 @@ type OrganizationMember { writeQuota: Int scanQuota: Int } -`}, - &ast.Source{Name: "control/gql/schema/projects.graphql", Input: `extend type Query { +`, BuiltIn: false}, + {Name: "server/control/schema/projects.graphql", Input: `extend type Query { exploreProjects: [Project!] projectsForUser(userID: UUID!): [Project!] projectByOrganizationAndName(organizationName: String!, projectName: String!): Project! @@ -2941,8 +2416,8 @@ type ProjectMember { create: Boolean! admin: Boolean! } -`}, - &ast.Source{Name: "control/gql/schema/secrets.graphql", Input: `extend type Query { +`, BuiltIn: false}, + {Name: "server/control/schema/secrets.graphql", Input: `extend type Query { secretsForService(serviceID: UUID!): [ServiceSecret!]! secretsForUser(userID: UUID!): [UserSecret!]! } @@ -2982,8 +2457,8 @@ type NewUserSecret { secret: UserSecret! token: String! } -`}, - &ast.Source{Name: "control/gql/schema/services.graphql", Input: `extend type Query { +`, BuiltIn: false}, + {Name: "server/control/schema/services.graphql", Input: `extend type Query { serviceByID(serviceID: UUID!): Service! serviceByOrganizationProjectAndName(organizationName: String!, projectName: String!, serviceName: String!): Service! } @@ -3022,8 +2497,8 @@ type PermissionsServicesStreams { read: Boolean! write: Boolean! } -`}, - &ast.Source{Name: "control/gql/schema/streams.graphql", Input: `extend type Query { +`, BuiltIn: false}, + {Name: "server/control/schema/streams.graphql", Input: `extend type Query { streamByID(streamID: UUID!): Stream! streamByOrganizationProjectAndName(organizationName: String!, projectName: String!, streamName: String!): Stream! streamInstancesForStream(streamID: UUID!): [StreamInstance!]! @@ -3112,8 +2587,8 @@ type StreamIndex { primary: Boolean! normalize: Boolean! } -`}, - &ast.Source{Name: "control/gql/schema/users.graphql", Input: `# extend type Query {} +`, BuiltIn: false}, + {Name: "server/control/schema/users.graphql", Input: `# extend type Query {} extend type Mutation { registerUserConsent(userID: UUID!, terms: Boolean, newsletter: Boolean): PrivateUser! @@ -3151,8 +2626,9 @@ type PermissionsUsersOrganizations { create: Boolean! admin: Boolean! } -`}, -) +`, BuiltIn: false}, +} +var parsedSchema = gqlparser.MustLoadSchema(sources...) // endregion ************************** generated!.gotpl ************************** @@ -3163,6 +2639,7 @@ func (ec *executionContext) field_Mutation_acceptOrganizationInvite_args(ctx con args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["organizationID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3177,6 +2654,7 @@ func (ec *executionContext) field_Mutation_createOrganization_args(ctx context.C args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["name"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -3191,6 +2669,7 @@ func (ec *executionContext) field_Mutation_deleteProject_args(ctx context.Contex args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["projectID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3205,6 +2684,7 @@ func (ec *executionContext) field_Mutation_deleteService_args(ctx context.Contex args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["serviceID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("serviceID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3219,6 +2699,7 @@ func (ec *executionContext) field_Mutation_deleteStreamInstance_args(ctx context args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["instanceID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("instanceID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3233,6 +2714,7 @@ func (ec *executionContext) field_Mutation_deleteStream_args(ctx context.Context args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["streamID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("streamID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3247,6 +2729,7 @@ func (ec *executionContext) field_Mutation_inviteUserToOrganization_args(ctx con args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["userID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3255,6 +2738,7 @@ func (ec *executionContext) field_Mutation_inviteUserToOrganization_args(ctx con args["userID"] = arg0 var arg1 uuid.UUID if tmp, ok := rawArgs["organizationID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationID")) arg1, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3263,6 +2747,7 @@ func (ec *executionContext) field_Mutation_inviteUserToOrganization_args(ctx con args["organizationID"] = arg1 var arg2 bool if tmp, ok := rawArgs["view"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("view")) arg2, err = ec.unmarshalNBoolean2bool(ctx, tmp) if err != nil { return nil, err @@ -3271,6 +2756,7 @@ func (ec *executionContext) field_Mutation_inviteUserToOrganization_args(ctx con args["view"] = arg2 var arg3 bool if tmp, ok := rawArgs["create"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("create")) arg3, err = ec.unmarshalNBoolean2bool(ctx, tmp) if err != nil { return nil, err @@ -3279,6 +2765,7 @@ func (ec *executionContext) field_Mutation_inviteUserToOrganization_args(ctx con args["create"] = arg3 var arg4 bool if tmp, ok := rawArgs["admin"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("admin")) arg4, err = ec.unmarshalNBoolean2bool(ctx, tmp) if err != nil { return nil, err @@ -3293,6 +2780,7 @@ func (ec *executionContext) field_Mutation_issueServiceSecret_args(ctx context.C args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["serviceID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("serviceID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3301,6 +2789,7 @@ func (ec *executionContext) field_Mutation_issueServiceSecret_args(ctx context.C args["serviceID"] = arg0 var arg1 string if tmp, ok := rawArgs["description"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("description")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -3315,6 +2804,7 @@ func (ec *executionContext) field_Mutation_issueUserSecret_args(ctx context.Cont args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["description"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("description")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -3323,6 +2813,7 @@ func (ec *executionContext) field_Mutation_issueUserSecret_args(ctx context.Cont args["description"] = arg0 var arg1 bool if tmp, ok := rawArgs["readOnly"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("readOnly")) arg1, err = ec.unmarshalNBoolean2bool(ctx, tmp) if err != nil { return nil, err @@ -3331,6 +2822,7 @@ func (ec *executionContext) field_Mutation_issueUserSecret_args(ctx context.Cont args["readOnly"] = arg1 var arg2 bool if tmp, ok := rawArgs["publicOnly"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("publicOnly")) arg2, err = ec.unmarshalNBoolean2bool(ctx, tmp) if err != nil { return nil, err @@ -3345,6 +2837,7 @@ func (ec *executionContext) field_Mutation_leaveBillingOrganization_args(ctx con args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["userID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3359,6 +2852,7 @@ func (ec *executionContext) field_Mutation_registerUserConsent_args(ctx context. args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["userID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3367,6 +2861,7 @@ func (ec *executionContext) field_Mutation_registerUserConsent_args(ctx context. args["userID"] = arg0 var arg1 *bool if tmp, ok := rawArgs["terms"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("terms")) arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3375,6 +2870,7 @@ func (ec *executionContext) field_Mutation_registerUserConsent_args(ctx context. args["terms"] = arg1 var arg2 *bool if tmp, ok := rawArgs["newsletter"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("newsletter")) arg2, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3389,6 +2885,7 @@ func (ec *executionContext) field_Mutation_revokeServiceSecret_args(ctx context. args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["secretID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("secretID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3403,6 +2900,7 @@ func (ec *executionContext) field_Mutation_revokeUserSecret_args(ctx context.Con args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["secretID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("secretID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3417,6 +2915,7 @@ func (ec *executionContext) field_Mutation_stageProject_args(ctx context.Context args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["organizationName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationName")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -3425,6 +2924,7 @@ func (ec *executionContext) field_Mutation_stageProject_args(ctx context.Context args["organizationName"] = arg0 var arg1 string if tmp, ok := rawArgs["projectName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectName")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -3433,6 +2933,7 @@ func (ec *executionContext) field_Mutation_stageProject_args(ctx context.Context args["projectName"] = arg1 var arg2 *string if tmp, ok := rawArgs["displayName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("displayName")) arg2, err = ec.unmarshalOString2ᚖstring(ctx, tmp) if err != nil { return nil, err @@ -3441,6 +2942,7 @@ func (ec *executionContext) field_Mutation_stageProject_args(ctx context.Context args["displayName"] = arg2 var arg3 *bool if tmp, ok := rawArgs["public"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("public")) arg3, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3449,6 +2951,7 @@ func (ec *executionContext) field_Mutation_stageProject_args(ctx context.Context args["public"] = arg3 var arg4 *string if tmp, ok := rawArgs["description"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("description")) arg4, err = ec.unmarshalOString2ᚖstring(ctx, tmp) if err != nil { return nil, err @@ -3457,6 +2960,7 @@ func (ec *executionContext) field_Mutation_stageProject_args(ctx context.Context args["description"] = arg4 var arg5 *string if tmp, ok := rawArgs["site"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("site")) arg5, err = ec.unmarshalOString2ᚖstring(ctx, tmp) if err != nil { return nil, err @@ -3465,6 +2969,7 @@ func (ec *executionContext) field_Mutation_stageProject_args(ctx context.Context args["site"] = arg5 var arg6 *string if tmp, ok := rawArgs["photoURL"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("photoURL")) arg6, err = ec.unmarshalOString2ᚖstring(ctx, tmp) if err != nil { return nil, err @@ -3479,6 +2984,7 @@ func (ec *executionContext) field_Mutation_stageService_args(ctx context.Context args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["organizationName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationName")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -3487,6 +2993,7 @@ func (ec *executionContext) field_Mutation_stageService_args(ctx context.Context args["organizationName"] = arg0 var arg1 string if tmp, ok := rawArgs["projectName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectName")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -3495,6 +3002,7 @@ func (ec *executionContext) field_Mutation_stageService_args(ctx context.Context args["projectName"] = arg1 var arg2 string if tmp, ok := rawArgs["serviceName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("serviceName")) arg2, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -3503,6 +3011,7 @@ func (ec *executionContext) field_Mutation_stageService_args(ctx context.Context args["serviceName"] = arg2 var arg3 *string if tmp, ok := rawArgs["description"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("description")) arg3, err = ec.unmarshalOString2ᚖstring(ctx, tmp) if err != nil { return nil, err @@ -3511,6 +3020,7 @@ func (ec *executionContext) field_Mutation_stageService_args(ctx context.Context args["description"] = arg3 var arg4 *string if tmp, ok := rawArgs["sourceURL"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sourceURL")) arg4, err = ec.unmarshalOString2ᚖstring(ctx, tmp) if err != nil { return nil, err @@ -3519,6 +3029,7 @@ func (ec *executionContext) field_Mutation_stageService_args(ctx context.Context args["sourceURL"] = arg4 var arg5 *int if tmp, ok := rawArgs["readQuota"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("readQuota")) arg5, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err @@ -3527,6 +3038,7 @@ func (ec *executionContext) field_Mutation_stageService_args(ctx context.Context args["readQuota"] = arg5 var arg6 *int if tmp, ok := rawArgs["writeQuota"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("writeQuota")) arg6, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err @@ -3535,6 +3047,7 @@ func (ec *executionContext) field_Mutation_stageService_args(ctx context.Context args["writeQuota"] = arg6 var arg7 *int if tmp, ok := rawArgs["scanQuota"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("scanQuota")) arg7, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err @@ -3549,6 +3062,7 @@ func (ec *executionContext) field_Mutation_stageStreamInstance_args(ctx context. args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["streamID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("streamID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3557,6 +3071,7 @@ func (ec *executionContext) field_Mutation_stageStreamInstance_args(ctx context. args["streamID"] = arg0 var arg1 int if tmp, ok := rawArgs["version"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("version")) arg1, err = ec.unmarshalNInt2int(ctx, tmp) if err != nil { return nil, err @@ -3565,6 +3080,7 @@ func (ec *executionContext) field_Mutation_stageStreamInstance_args(ctx context. args["version"] = arg1 var arg2 *bool if tmp, ok := rawArgs["makeFinal"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("makeFinal")) arg2, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3573,6 +3089,7 @@ func (ec *executionContext) field_Mutation_stageStreamInstance_args(ctx context. args["makeFinal"] = arg2 var arg3 *bool if tmp, ok := rawArgs["makePrimary"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("makePrimary")) arg3, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3587,6 +3104,7 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["organizationName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationName")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -3595,6 +3113,7 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args["organizationName"] = arg0 var arg1 string if tmp, ok := rawArgs["projectName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectName")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -3603,15 +3122,17 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args["projectName"] = arg1 var arg2 string if tmp, ok := rawArgs["streamName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("streamName")) arg2, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err } } args["streamName"] = arg2 - var arg3 entity.StreamSchemaKind + var arg3 models.StreamSchemaKind if tmp, ok := rawArgs["schemaKind"]; ok { - arg3, err = ec.unmarshalNStreamSchemaKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamSchemaKind(ctx, tmp) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("schemaKind")) + arg3, err = ec.unmarshalNStreamSchemaKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamSchemaKind(ctx, tmp) if err != nil { return nil, err } @@ -3619,6 +3140,7 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args["schemaKind"] = arg3 var arg4 string if tmp, ok := rawArgs["schema"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("schema")) arg4, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -3627,6 +3149,7 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args["schema"] = arg4 var arg5 *string if tmp, ok := rawArgs["indexes"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("indexes")) arg5, err = ec.unmarshalOString2ᚖstring(ctx, tmp) if err != nil { return nil, err @@ -3635,6 +3158,7 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args["indexes"] = arg5 var arg6 *string if tmp, ok := rawArgs["description"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("description")) arg6, err = ec.unmarshalOString2ᚖstring(ctx, tmp) if err != nil { return nil, err @@ -3643,6 +3167,7 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args["description"] = arg6 var arg7 *bool if tmp, ok := rawArgs["allowManualWrites"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("allowManualWrites")) arg7, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3651,6 +3176,7 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args["allowManualWrites"] = arg7 var arg8 *bool if tmp, ok := rawArgs["useLog"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("useLog")) arg8, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3659,6 +3185,7 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args["useLog"] = arg8 var arg9 *bool if tmp, ok := rawArgs["useIndex"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("useIndex")) arg9, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3667,6 +3194,7 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args["useIndex"] = arg9 var arg10 *bool if tmp, ok := rawArgs["useWarehouse"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("useWarehouse")) arg10, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3675,6 +3203,7 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args["useWarehouse"] = arg10 var arg11 *int if tmp, ok := rawArgs["logRetentionSeconds"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("logRetentionSeconds")) arg11, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err @@ -3683,6 +3212,7 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args["logRetentionSeconds"] = arg11 var arg12 *int if tmp, ok := rawArgs["indexRetentionSeconds"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("indexRetentionSeconds")) arg12, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err @@ -3691,6 +3221,7 @@ func (ec *executionContext) field_Mutation_stageStream_args(ctx context.Context, args["indexRetentionSeconds"] = arg12 var arg13 *int if tmp, ok := rawArgs["warehouseRetentionSeconds"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("warehouseRetentionSeconds")) arg13, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err @@ -3705,6 +3236,7 @@ func (ec *executionContext) field_Mutation_transferProjectToOrganization_args(ct args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["projectID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3713,6 +3245,7 @@ func (ec *executionContext) field_Mutation_transferProjectToOrganization_args(ct args["projectID"] = arg0 var arg1 uuid.UUID if tmp, ok := rawArgs["organizationID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationID")) arg1, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3722,73 +3255,12 @@ func (ec *executionContext) field_Mutation_transferProjectToOrganization_args(ct return args, nil } -func (ec *executionContext) field_Mutation_updateBillingInfo_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { - var err error - args := map[string]interface{}{} - var arg0 uuid.UUID - if tmp, ok := rawArgs["organizationID"]; ok { - arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) - if err != nil { - return nil, err - } - } - args["organizationID"] = arg0 - var arg1 *uuid.UUID - if tmp, ok := rawArgs["billingMethodID"]; ok { - arg1, err = ec.unmarshalOUUID2ᚖgithubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) - if err != nil { - return nil, err - } - } - args["billingMethodID"] = arg1 - var arg2 uuid.UUID - if tmp, ok := rawArgs["billingPlanID"]; ok { - arg2, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) - if err != nil { - return nil, err - } - } - args["billingPlanID"] = arg2 - var arg3 string - if tmp, ok := rawArgs["country"]; ok { - arg3, err = ec.unmarshalNString2string(ctx, tmp) - if err != nil { - return nil, err - } - } - args["country"] = arg3 - var arg4 *string - if tmp, ok := rawArgs["region"]; ok { - arg4, err = ec.unmarshalOString2ᚖstring(ctx, tmp) - if err != nil { - return nil, err - } - } - args["region"] = arg4 - var arg5 *string - if tmp, ok := rawArgs["companyName"]; ok { - arg5, err = ec.unmarshalOString2ᚖstring(ctx, tmp) - if err != nil { - return nil, err - } - } - args["companyName"] = arg5 - var arg6 *string - if tmp, ok := rawArgs["taxNumber"]; ok { - arg6, err = ec.unmarshalOString2ᚖstring(ctx, tmp) - if err != nil { - return nil, err - } - } - args["taxNumber"] = arg6 - return args, nil -} - func (ec *executionContext) field_Mutation_updateOrganizationQuotas_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["organizationID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3797,6 +3269,7 @@ func (ec *executionContext) field_Mutation_updateOrganizationQuotas_args(ctx con args["organizationID"] = arg0 var arg1 *int if tmp, ok := rawArgs["readQuota"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("readQuota")) arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err @@ -3805,6 +3278,7 @@ func (ec *executionContext) field_Mutation_updateOrganizationQuotas_args(ctx con args["readQuota"] = arg1 var arg2 *int if tmp, ok := rawArgs["writeQuota"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("writeQuota")) arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err @@ -3813,6 +3287,7 @@ func (ec *executionContext) field_Mutation_updateOrganizationQuotas_args(ctx con args["writeQuota"] = arg2 var arg3 *int if tmp, ok := rawArgs["scanQuota"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("scanQuota")) arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err @@ -3827,6 +3302,7 @@ func (ec *executionContext) field_Mutation_updateOrganization_args(ctx context.C args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["organizationID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3835,6 +3311,7 @@ func (ec *executionContext) field_Mutation_updateOrganization_args(ctx context.C args["organizationID"] = arg0 var arg1 *string if tmp, ok := rawArgs["name"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) arg1, err = ec.unmarshalOString2ᚖstring(ctx, tmp) if err != nil { return nil, err @@ -3843,6 +3320,7 @@ func (ec *executionContext) field_Mutation_updateOrganization_args(ctx context.C args["name"] = arg1 var arg2 *string if tmp, ok := rawArgs["displayName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("displayName")) arg2, err = ec.unmarshalOString2ᚖstring(ctx, tmp) if err != nil { return nil, err @@ -3851,6 +3329,7 @@ func (ec *executionContext) field_Mutation_updateOrganization_args(ctx context.C args["displayName"] = arg2 var arg3 *string if tmp, ok := rawArgs["description"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("description")) arg3, err = ec.unmarshalOString2ᚖstring(ctx, tmp) if err != nil { return nil, err @@ -3859,6 +3338,7 @@ func (ec *executionContext) field_Mutation_updateOrganization_args(ctx context.C args["description"] = arg3 var arg4 *string if tmp, ok := rawArgs["photoURL"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("photoURL")) arg4, err = ec.unmarshalOString2ᚖstring(ctx, tmp) if err != nil { return nil, err @@ -3873,6 +3353,7 @@ func (ec *executionContext) field_Mutation_updateServiceStreamPermissions_args(c args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["serviceID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("serviceID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3881,6 +3362,7 @@ func (ec *executionContext) field_Mutation_updateServiceStreamPermissions_args(c args["serviceID"] = arg0 var arg1 uuid.UUID if tmp, ok := rawArgs["streamID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("streamID")) arg1, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3889,6 +3371,7 @@ func (ec *executionContext) field_Mutation_updateServiceStreamPermissions_args(c args["streamID"] = arg1 var arg2 *bool if tmp, ok := rawArgs["read"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("read")) arg2, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3897,6 +3380,7 @@ func (ec *executionContext) field_Mutation_updateServiceStreamPermissions_args(c args["read"] = arg2 var arg3 *bool if tmp, ok := rawArgs["write"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("write")) arg3, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3911,6 +3395,7 @@ func (ec *executionContext) field_Mutation_updateStreamInstance_args(ctx context args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["instanceID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("instanceID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3919,6 +3404,7 @@ func (ec *executionContext) field_Mutation_updateStreamInstance_args(ctx context args["instanceID"] = arg0 var arg1 *bool if tmp, ok := rawArgs["makeFinal"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("makeFinal")) arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3927,6 +3413,7 @@ func (ec *executionContext) field_Mutation_updateStreamInstance_args(ctx context args["makeFinal"] = arg1 var arg2 *bool if tmp, ok := rawArgs["makePrimary"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("makePrimary")) arg2, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3941,6 +3428,7 @@ func (ec *executionContext) field_Mutation_updateUserOrganizationPermissions_arg args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["userID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3949,6 +3437,7 @@ func (ec *executionContext) field_Mutation_updateUserOrganizationPermissions_arg args["userID"] = arg0 var arg1 uuid.UUID if tmp, ok := rawArgs["organizationID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationID")) arg1, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3957,6 +3446,7 @@ func (ec *executionContext) field_Mutation_updateUserOrganizationPermissions_arg args["organizationID"] = arg1 var arg2 *bool if tmp, ok := rawArgs["view"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("view")) arg2, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3965,6 +3455,7 @@ func (ec *executionContext) field_Mutation_updateUserOrganizationPermissions_arg args["view"] = arg2 var arg3 *bool if tmp, ok := rawArgs["create"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("create")) arg3, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3973,6 +3464,7 @@ func (ec *executionContext) field_Mutation_updateUserOrganizationPermissions_arg args["create"] = arg3 var arg4 *bool if tmp, ok := rawArgs["admin"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("admin")) arg4, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -3987,6 +3479,7 @@ func (ec *executionContext) field_Mutation_updateUserProjectPermissions_args(ctx args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["userID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -3995,6 +3488,7 @@ func (ec *executionContext) field_Mutation_updateUserProjectPermissions_args(ctx args["userID"] = arg0 var arg1 uuid.UUID if tmp, ok := rawArgs["projectID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectID")) arg1, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4003,6 +3497,7 @@ func (ec *executionContext) field_Mutation_updateUserProjectPermissions_args(ctx args["projectID"] = arg1 var arg2 *bool if tmp, ok := rawArgs["view"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("view")) arg2, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -4011,6 +3506,7 @@ func (ec *executionContext) field_Mutation_updateUserProjectPermissions_args(ctx args["view"] = arg2 var arg3 *bool if tmp, ok := rawArgs["create"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("create")) arg3, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -4019,6 +3515,7 @@ func (ec *executionContext) field_Mutation_updateUserProjectPermissions_args(ctx args["create"] = arg3 var arg4 *bool if tmp, ok := rawArgs["admin"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("admin")) arg4, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) if err != nil { return nil, err @@ -4033,6 +3530,7 @@ func (ec *executionContext) field_Mutation_updateUserQuotas_args(ctx context.Con args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["userID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4041,6 +3539,7 @@ func (ec *executionContext) field_Mutation_updateUserQuotas_args(ctx context.Con args["userID"] = arg0 var arg1 *int if tmp, ok := rawArgs["readQuota"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("readQuota")) arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err @@ -4049,6 +3548,7 @@ func (ec *executionContext) field_Mutation_updateUserQuotas_args(ctx context.Con args["readQuota"] = arg1 var arg2 *int if tmp, ok := rawArgs["writeQuota"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("writeQuota")) arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err @@ -4057,6 +3557,7 @@ func (ec *executionContext) field_Mutation_updateUserQuotas_args(ctx context.Con args["writeQuota"] = arg2 var arg3 *int if tmp, ok := rawArgs["scanQuota"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("scanQuota")) arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) if err != nil { return nil, err @@ -4071,6 +3572,7 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["name"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4080,62 +3582,13 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs return args, nil } -func (ec *executionContext) field_Query_billedResources_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { - var err error - args := map[string]interface{}{} - var arg0 uuid.UUID - if tmp, ok := rawArgs["organizationID"]; ok { - arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) - if err != nil { - return nil, err - } - } - args["organizationID"] = arg0 - var arg1 time.Time - if tmp, ok := rawArgs["billingTime"]; ok { - arg1, err = ec.unmarshalNTime2timeᚐTime(ctx, tmp) - if err != nil { - return nil, err - } - } - args["billingTime"] = arg1 - return args, nil -} - -func (ec *executionContext) field_Query_billingInfo_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { - var err error - args := map[string]interface{}{} - var arg0 uuid.UUID - if tmp, ok := rawArgs["organizationID"]; ok { - arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) - if err != nil { - return nil, err - } - } - args["organizationID"] = arg0 - return args, nil -} - -func (ec *executionContext) field_Query_billingMethods_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { - var err error - args := map[string]interface{}{} - var arg0 uuid.UUID - if tmp, ok := rawArgs["organizationID"]; ok { - arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) - if err != nil { - return nil, err - } - } - args["organizationID"] = arg0 - return args, nil -} - func (ec *executionContext) field_Query_getMetrics_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} var arg0 EntityKind if tmp, ok := rawArgs["entityKind"]; ok { - arg0, err = ec.unmarshalNEntityKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐEntityKind(ctx, tmp) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("entityKind")) + arg0, err = ec.unmarshalNEntityKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐEntityKind(ctx, tmp) if err != nil { return nil, err } @@ -4143,6 +3596,7 @@ func (ec *executionContext) field_Query_getMetrics_args(ctx context.Context, raw args["entityKind"] = arg0 var arg1 uuid.UUID if tmp, ok := rawArgs["entityID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("entityID")) arg1, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4151,6 +3605,7 @@ func (ec *executionContext) field_Query_getMetrics_args(ctx context.Context, raw args["entityID"] = arg1 var arg2 string if tmp, ok := rawArgs["period"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("period")) arg2, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4159,6 +3614,7 @@ func (ec *executionContext) field_Query_getMetrics_args(ctx context.Context, raw args["period"] = arg2 var arg3 time.Time if tmp, ok := rawArgs["from"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("from")) arg3, err = ec.unmarshalNTime2timeᚐTime(ctx, tmp) if err != nil { return nil, err @@ -4167,6 +3623,7 @@ func (ec *executionContext) field_Query_getMetrics_args(ctx context.Context, raw args["from"] = arg3 var arg4 *time.Time if tmp, ok := rawArgs["until"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("until")) arg4, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, tmp) if err != nil { return nil, err @@ -4181,6 +3638,7 @@ func (ec *executionContext) field_Query_getOrganizationMetrics_args(ctx context. args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["organizationID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4189,6 +3647,7 @@ func (ec *executionContext) field_Query_getOrganizationMetrics_args(ctx context. args["organizationID"] = arg0 var arg1 string if tmp, ok := rawArgs["period"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("period")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4197,6 +3656,7 @@ func (ec *executionContext) field_Query_getOrganizationMetrics_args(ctx context. args["period"] = arg1 var arg2 time.Time if tmp, ok := rawArgs["from"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("from")) arg2, err = ec.unmarshalNTime2timeᚐTime(ctx, tmp) if err != nil { return nil, err @@ -4205,6 +3665,7 @@ func (ec *executionContext) field_Query_getOrganizationMetrics_args(ctx context. args["from"] = arg2 var arg3 *time.Time if tmp, ok := rawArgs["until"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("until")) arg3, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, tmp) if err != nil { return nil, err @@ -4219,6 +3680,7 @@ func (ec *executionContext) field_Query_getServiceMetrics_args(ctx context.Conte args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["serviceID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("serviceID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4227,6 +3689,7 @@ func (ec *executionContext) field_Query_getServiceMetrics_args(ctx context.Conte args["serviceID"] = arg0 var arg1 string if tmp, ok := rawArgs["period"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("period")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4235,6 +3698,7 @@ func (ec *executionContext) field_Query_getServiceMetrics_args(ctx context.Conte args["period"] = arg1 var arg2 time.Time if tmp, ok := rawArgs["from"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("from")) arg2, err = ec.unmarshalNTime2timeᚐTime(ctx, tmp) if err != nil { return nil, err @@ -4243,6 +3707,7 @@ func (ec *executionContext) field_Query_getServiceMetrics_args(ctx context.Conte args["from"] = arg2 var arg3 *time.Time if tmp, ok := rawArgs["until"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("until")) arg3, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, tmp) if err != nil { return nil, err @@ -4257,6 +3722,7 @@ func (ec *executionContext) field_Query_getStreamInstanceMetrics_args(ctx contex args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["streamInstanceID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("streamInstanceID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4265,6 +3731,7 @@ func (ec *executionContext) field_Query_getStreamInstanceMetrics_args(ctx contex args["streamInstanceID"] = arg0 var arg1 string if tmp, ok := rawArgs["period"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("period")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4273,6 +3740,7 @@ func (ec *executionContext) field_Query_getStreamInstanceMetrics_args(ctx contex args["period"] = arg1 var arg2 time.Time if tmp, ok := rawArgs["from"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("from")) arg2, err = ec.unmarshalNTime2timeᚐTime(ctx, tmp) if err != nil { return nil, err @@ -4281,6 +3749,7 @@ func (ec *executionContext) field_Query_getStreamInstanceMetrics_args(ctx contex args["from"] = arg2 var arg3 *time.Time if tmp, ok := rawArgs["until"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("until")) arg3, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, tmp) if err != nil { return nil, err @@ -4295,6 +3764,7 @@ func (ec *executionContext) field_Query_getStreamMetrics_args(ctx context.Contex args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["streamID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("streamID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4303,6 +3773,7 @@ func (ec *executionContext) field_Query_getStreamMetrics_args(ctx context.Contex args["streamID"] = arg0 var arg1 string if tmp, ok := rawArgs["period"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("period")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4311,6 +3782,7 @@ func (ec *executionContext) field_Query_getStreamMetrics_args(ctx context.Contex args["period"] = arg1 var arg2 time.Time if tmp, ok := rawArgs["from"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("from")) arg2, err = ec.unmarshalNTime2timeᚐTime(ctx, tmp) if err != nil { return nil, err @@ -4319,6 +3791,7 @@ func (ec *executionContext) field_Query_getStreamMetrics_args(ctx context.Contex args["from"] = arg2 var arg3 *time.Time if tmp, ok := rawArgs["until"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("until")) arg3, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, tmp) if err != nil { return nil, err @@ -4333,6 +3806,7 @@ func (ec *executionContext) field_Query_getUserMetrics_args(ctx context.Context, args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["userID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4341,6 +3815,7 @@ func (ec *executionContext) field_Query_getUserMetrics_args(ctx context.Context, args["userID"] = arg0 var arg1 string if tmp, ok := rawArgs["period"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("period")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4349,6 +3824,7 @@ func (ec *executionContext) field_Query_getUserMetrics_args(ctx context.Context, args["period"] = arg1 var arg2 time.Time if tmp, ok := rawArgs["from"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("from")) arg2, err = ec.unmarshalNTime2timeᚐTime(ctx, tmp) if err != nil { return nil, err @@ -4357,6 +3833,7 @@ func (ec *executionContext) field_Query_getUserMetrics_args(ctx context.Context, args["from"] = arg2 var arg3 *time.Time if tmp, ok := rawArgs["until"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("until")) arg3, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, tmp) if err != nil { return nil, err @@ -4371,6 +3848,7 @@ func (ec *executionContext) field_Query_organizationByID_args(ctx context.Contex args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["organizationID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4385,6 +3863,7 @@ func (ec *executionContext) field_Query_organizationByName_args(ctx context.Cont args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["name"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4399,6 +3878,7 @@ func (ec *executionContext) field_Query_organizationByUserID_args(ctx context.Co args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["userID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4413,6 +3893,7 @@ func (ec *executionContext) field_Query_organizationMembers_args(ctx context.Con args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["organizationID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4427,6 +3908,7 @@ func (ec *executionContext) field_Query_projectByID_args(ctx context.Context, ra args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["projectID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4441,6 +3923,7 @@ func (ec *executionContext) field_Query_projectByOrganizationAndName_args(ctx co args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["organizationName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationName")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4449,6 +3932,7 @@ func (ec *executionContext) field_Query_projectByOrganizationAndName_args(ctx co args["organizationName"] = arg0 var arg1 string if tmp, ok := rawArgs["projectName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectName")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4463,6 +3947,7 @@ func (ec *executionContext) field_Query_projectMembers_args(ctx context.Context, args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["projectID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4477,6 +3962,7 @@ func (ec *executionContext) field_Query_projectsForUser_args(ctx context.Context args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["userID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4491,6 +3977,7 @@ func (ec *executionContext) field_Query_secretsForService_args(ctx context.Conte args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["serviceID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("serviceID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4505,6 +3992,7 @@ func (ec *executionContext) field_Query_secretsForUser_args(ctx context.Context, args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["userID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4519,6 +4007,7 @@ func (ec *executionContext) field_Query_serviceByID_args(ctx context.Context, ra args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["serviceID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("serviceID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4533,6 +4022,7 @@ func (ec *executionContext) field_Query_serviceByOrganizationProjectAndName_args args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["organizationName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationName")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4541,6 +4031,7 @@ func (ec *executionContext) field_Query_serviceByOrganizationProjectAndName_args args["organizationName"] = arg0 var arg1 string if tmp, ok := rawArgs["projectName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectName")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4549,6 +4040,7 @@ func (ec *executionContext) field_Query_serviceByOrganizationProjectAndName_args args["projectName"] = arg1 var arg2 string if tmp, ok := rawArgs["serviceName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("serviceName")) arg2, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4563,6 +4055,7 @@ func (ec *executionContext) field_Query_streamByID_args(ctx context.Context, raw args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["streamID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("streamID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4577,6 +4070,7 @@ func (ec *executionContext) field_Query_streamByOrganizationProjectAndName_args( args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["organizationName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationName")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4585,6 +4079,7 @@ func (ec *executionContext) field_Query_streamByOrganizationProjectAndName_args( args["organizationName"] = arg0 var arg1 string if tmp, ok := rawArgs["projectName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectName")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4593,6 +4088,7 @@ func (ec *executionContext) field_Query_streamByOrganizationProjectAndName_args( args["projectName"] = arg1 var arg2 string if tmp, ok := rawArgs["streamName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("streamName")) arg2, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4607,6 +4103,7 @@ func (ec *executionContext) field_Query_streamInstancesByOrganizationProjectAndS args := map[string]interface{}{} var arg0 string if tmp, ok := rawArgs["organizationName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("organizationName")) arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4615,6 +4112,7 @@ func (ec *executionContext) field_Query_streamInstancesByOrganizationProjectAndS args["organizationName"] = arg0 var arg1 string if tmp, ok := rawArgs["projectName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectName")) arg1, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4623,6 +4121,7 @@ func (ec *executionContext) field_Query_streamInstancesByOrganizationProjectAndS args["projectName"] = arg1 var arg2 string if tmp, ok := rawArgs["streamName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("streamName")) arg2, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err @@ -4637,6 +4136,7 @@ func (ec *executionContext) field_Query_streamInstancesForStream_args(ctx contex args := map[string]interface{}{} var arg0 uuid.UUID if tmp, ok := rawArgs["streamID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("streamID")) arg0, err = ec.unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, tmp) if err != nil { return nil, err @@ -4651,6 +4151,7 @@ func (ec *executionContext) field___Type_enumValues_args(ctx context.Context, ra args := map[string]interface{}{} var arg0 bool if tmp, ok := rawArgs["includeDeprecated"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) arg0, err = ec.unmarshalOBoolean2bool(ctx, tmp) if err != nil { return nil, err @@ -4665,6 +4166,7 @@ func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArg args := map[string]interface{}{} var arg0 bool if tmp, ok := rawArgs["includeDeprecated"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) arg0, err = ec.unmarshalOBoolean2bool(ctx, tmp) if err != nil { return nil, err @@ -4682,2267 +4184,614 @@ func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArg // region **************************** field.gotpl ***************************** -func (ec *executionContext) _BilledResource_billedResourceID(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Metrics_entityID(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Metrics", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.BilledResourceID, nil + return obj.EntityID, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _BilledResource_organizationID(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Metrics_period(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Metrics", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.OrganizationID, nil + return obj.Period, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _BilledResource_billingTime(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Metrics_time(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Metrics", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.BillingTime, nil + return obj.Time, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _BilledResource_entityID(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Metrics_readOps(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Metrics", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.EntityID, nil + return obj.ReadOps, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _BilledResource_entityKind(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Metrics_readBytes(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Metrics", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.BilledResource().EntityKind(rctx, obj) + return obj.ReadBytes, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _BilledResource_startTime(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Metrics_readRecords(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Metrics", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.StartTime, nil + return obj.ReadRecords, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _BilledResource_endTime(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Metrics_writeOps(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Metrics", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.EndTime, nil + return obj.WriteOps, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _BilledResource_product(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Metrics_writeBytes(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Metrics", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.BilledResource().Product(rctx, obj) + return obj.WriteBytes, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _BilledResource_quantity(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Metrics_writeRecords(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Metrics", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.BilledResource().Quantity(rctx, obj) + return obj.WriteRecords, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(float64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNFloat2float64(ctx, field.Selections, res) + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _BilledResource_totalPriceCents(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Metrics_scanOps(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Metrics", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.TotalPriceCents, nil + return obj.ScanOps, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(int32) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int32(ctx, field.Selections, res) + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _BilledResource_currency(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Metrics_scanBytes(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Metrics", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.BilledResource().Currency(rctx, obj) + return obj.ScanBytes, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _BilledResource_createdOn(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Mutation_empty(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.CreatedOn, nil + return ec.resolvers.Mutation().Empty(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) _BilledResource_updatedOn(ctx context.Context, field graphql.CollectedField, obj *entity.BilledResource) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Mutation_createOrganization(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BilledResource", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_createOrganization_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.UpdatedOn, nil + return ec.resolvers.Mutation().CreateOrganization(rctx, args["name"].(string)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) + res := resTmp.(*PrivateOrganization) + fc.Result = res + return ec.marshalNPrivateOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐPrivateOrganization(ctx, field.Selections, res) } -func (ec *executionContext) _BillingInfo_organizationID(ctx context.Context, field graphql.CollectedField, obj *entity.BillingInfo) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Mutation_updateOrganization(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BillingInfo", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_updateOrganization_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.OrganizationID, nil + return ec.resolvers.Mutation().UpdateOrganization(rctx, args["organizationID"].(uuid.UUID), args["name"].(*string), args["displayName"].(*string), args["description"].(*string), args["photoURL"].(*string)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) + res := resTmp.(*PrivateOrganization) + fc.Result = res + return ec.marshalNPrivateOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐPrivateOrganization(ctx, field.Selections, res) } -func (ec *executionContext) _BillingInfo_billingMethod(ctx context.Context, field graphql.CollectedField, obj *entity.BillingInfo) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Mutation_updateOrganizationQuotas(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BillingInfo", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_updateOrganizationQuotas_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.BillingMethod, nil + return ec.resolvers.Mutation().UpdateOrganizationQuotas(rctx, args["organizationID"].(uuid.UUID), args["readQuota"].(*int), args["writeQuota"].(*int), args["scanQuota"].(*int)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*entity.BillingMethod) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOBillingMethod2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingMethod(ctx, field.Selections, res) + res := resTmp.(*PrivateOrganization) + fc.Result = res + return ec.marshalNPrivateOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐPrivateOrganization(ctx, field.Selections, res) } -func (ec *executionContext) _BillingInfo_billingPlan(ctx context.Context, field graphql.CollectedField, obj *entity.BillingInfo) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Mutation_inviteUserToOrganization(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BillingInfo", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_inviteUserToOrganization_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.BillingPlan, nil + return ec.resolvers.Mutation().InviteUserToOrganization(rctx, args["userID"].(uuid.UUID), args["organizationID"].(uuid.UUID), args["view"].(bool), args["create"].(bool), args["admin"].(bool)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.BillingPlan) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNBillingPlan2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingPlan(ctx, field.Selections, res) + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _BillingInfo_country(ctx context.Context, field graphql.CollectedField, obj *entity.BillingInfo) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Mutation_acceptOrganizationInvite(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "BillingInfo", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Country, nil - }) + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_acceptOrganizationInvite_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingInfo_region(ctx context.Context, field graphql.CollectedField, obj *entity.BillingInfo) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingInfo", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Region, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingInfo_companyName(ctx context.Context, field graphql.CollectedField, obj *entity.BillingInfo) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingInfo", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.CompanyName, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingInfo_taxNumber(ctx context.Context, field graphql.CollectedField, obj *entity.BillingInfo) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingInfo", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.TaxNumber, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingMethod_billingMethodID(ctx context.Context, field graphql.CollectedField, obj *entity.BillingMethod) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingMethod", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.BillingMethodID, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingMethod_organizationID(ctx context.Context, field graphql.CollectedField, obj *entity.BillingMethod) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingMethod", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.OrganizationID, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingMethod_paymentsDriver(ctx context.Context, field graphql.CollectedField, obj *entity.BillingMethod) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingMethod", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.BillingMethod().PaymentsDriver(rctx, obj) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingMethod_driverPayload(ctx context.Context, field graphql.CollectedField, obj *entity.BillingMethod) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingMethod", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.BillingMethod().DriverPayload(rctx, obj) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_billingPlanID(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.BillingPlanID, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_default(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Default, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNBoolean2bool(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_description(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Description, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_currency(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.BillingPlan().Currency(rctx, obj) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_period(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.BillingPlan().Period(rctx, obj) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_seatPriceCents(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.SeatPriceCents, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int32) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int32(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_seatReadQuota(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.SeatReadQuota, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int64(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_seatWriteQuota(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.SeatWriteQuota, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int64(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_seatScanQuota(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.SeatScanQuota, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int64(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_readOveragePriceCents(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.ReadOveragePriceCents, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int32) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int32(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_writeOveragePriceCents(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.WriteOveragePriceCents, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int32) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int32(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_scanOveragePriceCents(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.ScanOveragePriceCents, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int32) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int32(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_baseReadQuota(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.BaseReadQuota, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int64(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_baseWriteQuota(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.BaseWriteQuota, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int64(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_baseScanQuota(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.BaseScanQuota, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int64(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_readQuota(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.ReadQuota, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int64(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_writeQuota(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.WriteQuota, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int64(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_scanQuota(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.ScanQuota, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int64(ctx, field.Selections, res) -} - -func (ec *executionContext) _BillingPlan_availableInUI(ctx context.Context, field graphql.CollectedField, obj *entity.BillingPlan) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "BillingPlan", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.AvailableInUI, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNBoolean2bool(ctx, field.Selections, res) -} - -func (ec *executionContext) _Metrics_entityID(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Metrics", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.EntityID, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) -} - -func (ec *executionContext) _Metrics_period(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Metrics", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Period, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) _Metrics_time(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Metrics", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Time, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) -} - -func (ec *executionContext) _Metrics_readOps(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Metrics", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.ReadOps, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) _Metrics_readBytes(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Metrics", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.ReadBytes, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) _Metrics_readRecords(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Metrics", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.ReadRecords, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) _Metrics_writeOps(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Metrics", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.WriteOps, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) _Metrics_writeBytes(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Metrics", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.WriteBytes, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) _Metrics_writeRecords(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Metrics", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.WriteRecords, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) _Metrics_scanOps(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Metrics", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.ScanOps, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) _Metrics_scanBytes(ctx context.Context, field graphql.CollectedField, obj *Metrics) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Metrics", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.ScanBytes, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNInt2int(ctx, field.Selections, res) -} - -func (ec *executionContext) _Mutation_empty(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().Empty(rctx) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(*string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) -} - -func (ec *executionContext) _Mutation_updateBillingInfo(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Mutation_updateBillingInfo_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().UpdateBillingInfo(rctx, args["organizationID"].(uuid.UUID), args["billingMethodID"].(*uuid.UUID), args["billingPlanID"].(uuid.UUID), args["country"].(string), args["region"].(*string), args["companyName"].(*string), args["taxNumber"].(*string)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(*entity.BillingInfo) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNBillingInfo2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingInfo(ctx, field.Selections, res) -} - -func (ec *executionContext) _Mutation_createOrganization(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Mutation_createOrganization_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().CreateOrganization(rctx, args["name"].(string)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(*PrivateOrganization) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPrivateOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐPrivateOrganization(ctx, field.Selections, res) -} - -func (ec *executionContext) _Mutation_updateOrganization(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Mutation_updateOrganization_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().UpdateOrganization(rctx, args["organizationID"].(uuid.UUID), args["name"].(*string), args["displayName"].(*string), args["description"].(*string), args["photoURL"].(*string)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(*PrivateOrganization) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPrivateOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐPrivateOrganization(ctx, field.Selections, res) -} - -func (ec *executionContext) _Mutation_updateOrganizationQuotas(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Mutation_updateOrganizationQuotas_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().UpdateOrganizationQuotas(rctx, args["organizationID"].(uuid.UUID), args["readQuota"].(*int), args["writeQuota"].(*int), args["scanQuota"].(*int)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(*PrivateOrganization) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPrivateOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐPrivateOrganization(ctx, field.Selections, res) -} - -func (ec *executionContext) _Mutation_inviteUserToOrganization(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Mutation_inviteUserToOrganization_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().InviteUserToOrganization(rctx, args["userID"].(uuid.UUID), args["organizationID"].(uuid.UUID), args["view"].(bool), args["create"].(bool), args["admin"].(bool)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNBoolean2bool(ctx, field.Selections, res) -} - -func (ec *executionContext) _Mutation_acceptOrganizationInvite(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Mutation_acceptOrganizationInvite_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().AcceptOrganizationInvite(rctx, args["organizationID"].(uuid.UUID)) @@ -6952,41 +4801,39 @@ func (ec *executionContext) _Mutation_acceptOrganizationInvite(ctx context.Conte return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_leaveBillingOrganization(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_leaveBillingOrganization_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().LeaveBillingOrganization(rctx, args["userID"].(uuid.UUID)) @@ -6996,41 +4843,39 @@ func (ec *executionContext) _Mutation_leaveBillingOrganization(ctx context.Conte return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.User) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUser(ctx, field.Selections, res) + res := resTmp.(*models.User) + fc.Result = res + return ec.marshalNPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐUser(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_transferProjectToOrganization(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_transferProjectToOrganization_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().TransferProjectToOrganization(rctx, args["projectID"].(uuid.UUID), args["organizationID"].(uuid.UUID)) @@ -7040,41 +4885,39 @@ func (ec *executionContext) _Mutation_transferProjectToOrganization(ctx context. return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Project) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx, field.Selections, res) + res := resTmp.(*models.Project) + fc.Result = res + return ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProject(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_stageProject(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_stageProject_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().StageProject(rctx, args["organizationName"].(string), args["projectName"].(string), args["displayName"].(*string), args["public"].(*bool), args["description"].(*string), args["site"].(*string), args["photoURL"].(*string)) @@ -7084,41 +4927,39 @@ func (ec *executionContext) _Mutation_stageProject(ctx context.Context, field gr return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Project) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx, field.Selections, res) + res := resTmp.(*models.Project) + fc.Result = res + return ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProject(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_deleteProject(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_deleteProject_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().DeleteProject(rctx, args["projectID"].(uuid.UUID)) @@ -7128,41 +4969,39 @@ func (ec *executionContext) _Mutation_deleteProject(ctx context.Context, field g return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_issueServiceSecret(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_issueServiceSecret_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().IssueServiceSecret(rctx, args["serviceID"].(uuid.UUID), args["description"].(string)) @@ -7172,41 +5011,39 @@ func (ec *executionContext) _Mutation_issueServiceSecret(ctx context.Context, fi return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(*NewServiceSecret) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNNewServiceSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐNewServiceSecret(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNNewServiceSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐNewServiceSecret(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_issueUserSecret(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_issueUserSecret_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().IssueUserSecret(rctx, args["description"].(string), args["readOnly"].(bool), args["publicOnly"].(bool)) @@ -7216,41 +5053,39 @@ func (ec *executionContext) _Mutation_issueUserSecret(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(*NewUserSecret) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNNewUserSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐNewUserSecret(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNNewUserSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐNewUserSecret(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_revokeServiceSecret(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_revokeServiceSecret_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().RevokeServiceSecret(rctx, args["secretID"].(uuid.UUID)) @@ -7260,41 +5095,39 @@ func (ec *executionContext) _Mutation_revokeServiceSecret(ctx context.Context, f return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_revokeUserSecret(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_revokeUserSecret_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().RevokeUserSecret(rctx, args["secretID"].(uuid.UUID)) @@ -7304,41 +5137,39 @@ func (ec *executionContext) _Mutation_revokeUserSecret(ctx context.Context, fiel return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_stageService(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_stageService_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().StageService(rctx, args["organizationName"].(string), args["projectName"].(string), args["serviceName"].(string), args["description"].(*string), args["sourceURL"].(*string), args["readQuota"].(*int), args["writeQuota"].(*int), args["scanQuota"].(*int)) @@ -7348,41 +5179,39 @@ func (ec *executionContext) _Mutation_stageService(ctx context.Context, field gr return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Service) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐService(ctx, field.Selections, res) + res := resTmp.(*models.Service) + fc.Result = res + return ec.marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐService(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_updateServiceStreamPermissions(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_updateServiceStreamPermissions_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().UpdateServiceStreamPermissions(rctx, args["serviceID"].(uuid.UUID), args["streamID"].(uuid.UUID), args["read"].(*bool), args["write"].(*bool)) @@ -7392,41 +5221,39 @@ func (ec *executionContext) _Mutation_updateServiceStreamPermissions(ctx context return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.PermissionsServicesStreams) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPermissionsServicesStreams2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐPermissionsServicesStreams(ctx, field.Selections, res) + res := resTmp.(*models.PermissionsServicesStreams) + fc.Result = res + return ec.marshalNPermissionsServicesStreams2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐPermissionsServicesStreams(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_deleteService(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_deleteService_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().DeleteService(rctx, args["serviceID"].(uuid.UUID)) @@ -7436,85 +5263,81 @@ func (ec *executionContext) _Mutation_deleteService(ctx context.Context, field g return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_stageStream(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_stageStream_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().StageStream(rctx, args["organizationName"].(string), args["projectName"].(string), args["streamName"].(string), args["schemaKind"].(entity.StreamSchemaKind), args["schema"].(string), args["indexes"].(*string), args["description"].(*string), args["allowManualWrites"].(*bool), args["useLog"].(*bool), args["useIndex"].(*bool), args["useWarehouse"].(*bool), args["logRetentionSeconds"].(*int), args["indexRetentionSeconds"].(*int), args["warehouseRetentionSeconds"].(*int)) + return ec.resolvers.Mutation().StageStream(rctx, args["organizationName"].(string), args["projectName"].(string), args["streamName"].(string), args["schemaKind"].(models.StreamSchemaKind), args["schema"].(string), args["indexes"].(*string), args["description"].(*string), args["allowManualWrites"].(*bool), args["useLog"].(*bool), args["useIndex"].(*bool), args["useWarehouse"].(*bool), args["logRetentionSeconds"].(*int), args["indexRetentionSeconds"].(*int), args["warehouseRetentionSeconds"].(*int)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Stream) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNStream2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStream(ctx, field.Selections, res) + res := resTmp.(*models.Stream) + fc.Result = res + return ec.marshalNStream2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStream(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_deleteStream(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_deleteStream_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().DeleteStream(rctx, args["streamID"].(uuid.UUID)) @@ -7524,41 +5347,39 @@ func (ec *executionContext) _Mutation_deleteStream(ctx context.Context, field gr return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_stageStreamInstance(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_stageStreamInstance_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().StageStreamInstance(rctx, args["streamID"].(uuid.UUID), args["version"].(int), args["makeFinal"].(*bool), args["makePrimary"].(*bool)) @@ -7568,41 +5389,39 @@ func (ec *executionContext) _Mutation_stageStreamInstance(ctx context.Context, f return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.StreamInstance) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamInstance(ctx, field.Selections, res) + res := resTmp.(*models.StreamInstance) + fc.Result = res + return ec.marshalNStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamInstance(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_updateStreamInstance(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_updateStreamInstance_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().UpdateStreamInstance(rctx, args["instanceID"].(uuid.UUID), args["makeFinal"].(*bool), args["makePrimary"].(*bool)) @@ -7612,41 +5431,39 @@ func (ec *executionContext) _Mutation_updateStreamInstance(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.StreamInstance) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamInstance(ctx, field.Selections, res) + res := resTmp.(*models.StreamInstance) + fc.Result = res + return ec.marshalNStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamInstance(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_deleteStreamInstance(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_deleteStreamInstance_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().DeleteStreamInstance(rctx, args["instanceID"].(uuid.UUID)) @@ -7656,41 +5473,39 @@ func (ec *executionContext) _Mutation_deleteStreamInstance(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_registerUserConsent(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_registerUserConsent_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().RegisterUserConsent(rctx, args["userID"].(uuid.UUID), args["terms"].(*bool), args["newsletter"].(*bool)) @@ -7700,41 +5515,39 @@ func (ec *executionContext) _Mutation_registerUserConsent(ctx context.Context, f return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.User) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUser(ctx, field.Selections, res) + res := resTmp.(*models.User) + fc.Result = res + return ec.marshalNPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐUser(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_updateUserQuotas(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_updateUserQuotas_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().UpdateUserQuotas(rctx, args["userID"].(uuid.UUID), args["readQuota"].(*int), args["writeQuota"].(*int), args["scanQuota"].(*int)) @@ -7744,41 +5557,39 @@ func (ec *executionContext) _Mutation_updateUserQuotas(ctx context.Context, fiel return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.User) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUser(ctx, field.Selections, res) + res := resTmp.(*models.User) + fc.Result = res + return ec.marshalNPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐUser(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_updateUserProjectPermissions(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_updateUserProjectPermissions_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().UpdateUserProjectPermissions(rctx, args["userID"].(uuid.UUID), args["projectID"].(uuid.UUID), args["view"].(*bool), args["create"].(*bool), args["admin"].(*bool)) @@ -7788,41 +5599,39 @@ func (ec *executionContext) _Mutation_updateUserProjectPermissions(ctx context.C return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.PermissionsUsersProjects) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPermissionsUsersProjects2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐPermissionsUsersProjects(ctx, field.Selections, res) + res := resTmp.(*models.PermissionsUsersProjects) + fc.Result = res + return ec.marshalNPermissionsUsersProjects2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐPermissionsUsersProjects(ctx, field.Selections, res) } func (ec *executionContext) _Mutation_updateUserOrganizationPermissions(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Mutation", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Mutation_updateUserOrganizationPermissions_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Mutation().UpdateUserOrganizationPermissions(rctx, args["userID"].(uuid.UUID), args["organizationID"].(uuid.UUID), args["view"].(*bool), args["create"].(*bool), args["admin"].(*bool)) @@ -7832,34 +5641,32 @@ func (ec *executionContext) _Mutation_updateUserOrganizationPermissions(ctx cont return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.PermissionsUsersOrganizations) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPermissionsUsersOrganizations2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐPermissionsUsersOrganizations(ctx, field.Selections, res) + res := resTmp.(*models.PermissionsUsersOrganizations) + fc.Result = res + return ec.marshalNPermissionsUsersOrganizations2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐPermissionsUsersOrganizations(ctx, field.Selections, res) } func (ec *executionContext) _NewServiceSecret_secret(ctx context.Context, field graphql.CollectedField, obj *NewServiceSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "NewServiceSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "NewServiceSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Secret, nil @@ -7869,34 +5676,32 @@ func (ec *executionContext) _NewServiceSecret_secret(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.ServiceSecret) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNServiceSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐServiceSecret(ctx, field.Selections, res) + res := resTmp.(*models.ServiceSecret) + fc.Result = res + return ec.marshalNServiceSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐServiceSecret(ctx, field.Selections, res) } func (ec *executionContext) _NewServiceSecret_token(ctx context.Context, field graphql.CollectedField, obj *NewServiceSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "NewServiceSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "NewServiceSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Token, nil @@ -7906,34 +5711,32 @@ func (ec *executionContext) _NewServiceSecret_token(ctx context.Context, field g return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) _NewUserSecret_secret(ctx context.Context, field graphql.CollectedField, obj *NewUserSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "NewUserSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "NewUserSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Secret, nil @@ -7943,34 +5746,32 @@ func (ec *executionContext) _NewUserSecret_secret(ctx context.Context, field gra return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.UserSecret) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNUserSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUserSecret(ctx, field.Selections, res) + res := resTmp.(*models.UserSecret) + fc.Result = res + return ec.marshalNUserSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐUserSecret(ctx, field.Selections, res) } func (ec *executionContext) _NewUserSecret_token(ctx context.Context, field graphql.CollectedField, obj *NewUserSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "NewUserSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "NewUserSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Token, nil @@ -7980,34 +5781,32 @@ func (ec *executionContext) _NewUserSecret_token(ctx context.Context, field grap return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _OrganizationMember_organizationID(ctx context.Context, field graphql.CollectedField, obj *entity.OrganizationMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _OrganizationMember_organizationID(ctx context.Context, field graphql.CollectedField, obj *models.OrganizationMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "OrganizationMember", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "OrganizationMember", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.OrganizationMember().OrganizationID(rctx, obj) @@ -8017,34 +5816,32 @@ func (ec *executionContext) _OrganizationMember_organizationID(ctx context.Conte return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _OrganizationMember_userID(ctx context.Context, field graphql.CollectedField, obj *entity.OrganizationMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _OrganizationMember_userID(ctx context.Context, field graphql.CollectedField, obj *models.OrganizationMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "OrganizationMember", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "OrganizationMember", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.OrganizationMember().UserID(rctx, obj) @@ -8054,34 +5851,32 @@ func (ec *executionContext) _OrganizationMember_userID(ctx context.Context, fiel return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _OrganizationMember_billingOrganizationID(ctx context.Context, field graphql.CollectedField, obj *entity.OrganizationMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _OrganizationMember_billingOrganizationID(ctx context.Context, field graphql.CollectedField, obj *models.OrganizationMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "OrganizationMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "OrganizationMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.BillingOrganizationID, nil @@ -8091,34 +5886,32 @@ func (ec *executionContext) _OrganizationMember_billingOrganizationID(ctx contex return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _OrganizationMember_name(ctx context.Context, field graphql.CollectedField, obj *entity.OrganizationMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _OrganizationMember_name(ctx context.Context, field graphql.CollectedField, obj *models.OrganizationMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "OrganizationMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "OrganizationMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil @@ -8128,34 +5921,32 @@ func (ec *executionContext) _OrganizationMember_name(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _OrganizationMember_displayName(ctx context.Context, field graphql.CollectedField, obj *entity.OrganizationMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _OrganizationMember_displayName(ctx context.Context, field graphql.CollectedField, obj *models.OrganizationMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "OrganizationMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "OrganizationMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.DisplayName, nil @@ -8165,34 +5956,32 @@ func (ec *executionContext) _OrganizationMember_displayName(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _OrganizationMember_photoURL(ctx context.Context, field graphql.CollectedField, obj *entity.OrganizationMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _OrganizationMember_photoURL(ctx context.Context, field graphql.CollectedField, obj *models.OrganizationMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "OrganizationMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "OrganizationMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PhotoURL, nil @@ -8205,28 +5994,26 @@ func (ec *executionContext) _OrganizationMember_photoURL(ctx context.Context, fi return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) _OrganizationMember_view(ctx context.Context, field graphql.CollectedField, obj *entity.OrganizationMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _OrganizationMember_view(ctx context.Context, field graphql.CollectedField, obj *models.OrganizationMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "OrganizationMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "OrganizationMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.View, nil @@ -8236,34 +6023,32 @@ func (ec *executionContext) _OrganizationMember_view(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _OrganizationMember_create(ctx context.Context, field graphql.CollectedField, obj *entity.OrganizationMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _OrganizationMember_create(ctx context.Context, field graphql.CollectedField, obj *models.OrganizationMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "OrganizationMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "OrganizationMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Create, nil @@ -8273,34 +6058,32 @@ func (ec *executionContext) _OrganizationMember_create(ctx context.Context, fiel return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _OrganizationMember_admin(ctx context.Context, field graphql.CollectedField, obj *entity.OrganizationMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _OrganizationMember_admin(ctx context.Context, field graphql.CollectedField, obj *models.OrganizationMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "OrganizationMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "OrganizationMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Admin, nil @@ -8310,34 +6093,32 @@ func (ec *executionContext) _OrganizationMember_admin(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _OrganizationMember_readQuota(ctx context.Context, field graphql.CollectedField, obj *entity.OrganizationMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _OrganizationMember_readQuota(ctx context.Context, field graphql.CollectedField, obj *models.OrganizationMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "OrganizationMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "OrganizationMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ReadQuota, nil @@ -8350,28 +6131,26 @@ func (ec *executionContext) _OrganizationMember_readQuota(ctx context.Context, f return graphql.Null } res := resTmp.(*int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint(ctx, field.Selections, res) } -func (ec *executionContext) _OrganizationMember_writeQuota(ctx context.Context, field graphql.CollectedField, obj *entity.OrganizationMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _OrganizationMember_writeQuota(ctx context.Context, field graphql.CollectedField, obj *models.OrganizationMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "OrganizationMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "OrganizationMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.WriteQuota, nil @@ -8384,28 +6163,26 @@ func (ec *executionContext) _OrganizationMember_writeQuota(ctx context.Context, return graphql.Null } res := resTmp.(*int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint(ctx, field.Selections, res) } -func (ec *executionContext) _OrganizationMember_scanQuota(ctx context.Context, field graphql.CollectedField, obj *entity.OrganizationMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _OrganizationMember_scanQuota(ctx context.Context, field graphql.CollectedField, obj *models.OrganizationMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "OrganizationMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "OrganizationMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ScanQuota, nil @@ -8418,28 +6195,26 @@ func (ec *executionContext) _OrganizationMember_scanQuota(ctx context.Context, f return graphql.Null } res := resTmp.(*int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsServicesStreams_serviceID(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsServicesStreams) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsServicesStreams_serviceID(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsServicesStreams) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsServicesStreams", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsServicesStreams", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ServiceID, nil @@ -8449,34 +6224,32 @@ func (ec *executionContext) _PermissionsServicesStreams_serviceID(ctx context.Co return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsServicesStreams_streamID(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsServicesStreams) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsServicesStreams_streamID(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsServicesStreams) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsServicesStreams", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsServicesStreams", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.StreamID, nil @@ -8486,34 +6259,32 @@ func (ec *executionContext) _PermissionsServicesStreams_streamID(ctx context.Con return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsServicesStreams_read(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsServicesStreams) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsServicesStreams_read(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsServicesStreams) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsServicesStreams", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsServicesStreams", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Read, nil @@ -8523,34 +6294,32 @@ func (ec *executionContext) _PermissionsServicesStreams_read(ctx context.Context return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsServicesStreams_write(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsServicesStreams) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsServicesStreams_write(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsServicesStreams) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsServicesStreams", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsServicesStreams", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Write, nil @@ -8560,34 +6329,32 @@ func (ec *executionContext) _PermissionsServicesStreams_write(ctx context.Contex return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsUsersOrganizations_userID(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsUsersOrganizations) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsUsersOrganizations_userID(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsUsersOrganizations) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsUsersOrganizations", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsUsersOrganizations", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.UserID, nil @@ -8597,34 +6364,32 @@ func (ec *executionContext) _PermissionsUsersOrganizations_userID(ctx context.Co return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsUsersOrganizations_organizationID(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsUsersOrganizations) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsUsersOrganizations_organizationID(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsUsersOrganizations) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsUsersOrganizations", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsUsersOrganizations", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.OrganizationID, nil @@ -8634,34 +6399,32 @@ func (ec *executionContext) _PermissionsUsersOrganizations_organizationID(ctx co return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsUsersOrganizations_view(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsUsersOrganizations) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsUsersOrganizations_view(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsUsersOrganizations) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsUsersOrganizations", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsUsersOrganizations", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.View, nil @@ -8671,34 +6434,32 @@ func (ec *executionContext) _PermissionsUsersOrganizations_view(ctx context.Cont return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsUsersOrganizations_create(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsUsersOrganizations) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsUsersOrganizations_create(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsUsersOrganizations) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsUsersOrganizations", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsUsersOrganizations", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Create, nil @@ -8708,34 +6469,32 @@ func (ec *executionContext) _PermissionsUsersOrganizations_create(ctx context.Co return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsUsersOrganizations_admin(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsUsersOrganizations) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsUsersOrganizations_admin(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsUsersOrganizations) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsUsersOrganizations", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsUsersOrganizations", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Admin, nil @@ -8745,34 +6504,32 @@ func (ec *executionContext) _PermissionsUsersOrganizations_admin(ctx context.Con return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsUsersProjects_userID(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsUsersProjects) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsUsersProjects_userID(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsUsersProjects) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsUsersProjects", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsUsersProjects", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.UserID, nil @@ -8782,34 +6539,32 @@ func (ec *executionContext) _PermissionsUsersProjects_userID(ctx context.Context return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsUsersProjects_projectID(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsUsersProjects) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsUsersProjects_projectID(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsUsersProjects) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsUsersProjects", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsUsersProjects", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ProjectID, nil @@ -8819,34 +6574,32 @@ func (ec *executionContext) _PermissionsUsersProjects_projectID(ctx context.Cont return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsUsersProjects_view(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsUsersProjects) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsUsersProjects_view(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsUsersProjects) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsUsersProjects", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsUsersProjects", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.View, nil @@ -8856,34 +6609,32 @@ func (ec *executionContext) _PermissionsUsersProjects_view(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsUsersProjects_create(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsUsersProjects) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsUsersProjects_create(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsUsersProjects) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsUsersProjects", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsUsersProjects", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Create, nil @@ -8893,34 +6644,32 @@ func (ec *executionContext) _PermissionsUsersProjects_create(ctx context.Context return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _PermissionsUsersProjects_admin(ctx context.Context, field graphql.CollectedField, obj *entity.PermissionsUsersProjects) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PermissionsUsersProjects_admin(ctx context.Context, field graphql.CollectedField, obj *models.PermissionsUsersProjects) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PermissionsUsersProjects", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PermissionsUsersProjects", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Admin, nil @@ -8930,34 +6679,32 @@ func (ec *executionContext) _PermissionsUsersProjects_admin(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_organizationID(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.OrganizationID, nil @@ -8967,34 +6714,32 @@ func (ec *executionContext) _PrivateOrganization_organizationID(ctx context.Cont return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_name(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil @@ -9004,34 +6749,32 @@ func (ec *executionContext) _PrivateOrganization_name(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_displayName(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.DisplayName, nil @@ -9041,34 +6784,32 @@ func (ec *executionContext) _PrivateOrganization_displayName(ctx context.Context return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_description(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil @@ -9081,28 +6822,26 @@ func (ec *executionContext) _PrivateOrganization_description(ctx context.Context return graphql.Null } res := resTmp.(*string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_photoURL(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PhotoURL, nil @@ -9115,28 +6854,26 @@ func (ec *executionContext) _PrivateOrganization_photoURL(ctx context.Context, f return graphql.Null } res := resTmp.(*string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_createdOn(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.CreatedOn, nil @@ -9146,34 +6883,32 @@ func (ec *executionContext) _PrivateOrganization_createdOn(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_updatedOn(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.UpdatedOn, nil @@ -9183,34 +6918,32 @@ func (ec *executionContext) _PrivateOrganization_updatedOn(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_prepaidReadQuota(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PrepaidReadQuota, nil @@ -9223,28 +6956,26 @@ func (ec *executionContext) _PrivateOrganization_prepaidReadQuota(ctx context.Co return graphql.Null } res := resTmp.(*int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_prepaidWriteQuota(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PrepaidWriteQuota, nil @@ -9257,28 +6988,26 @@ func (ec *executionContext) _PrivateOrganization_prepaidWriteQuota(ctx context.C return graphql.Null } res := resTmp.(*int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_prepaidScanQuota(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PrepaidScanQuota, nil @@ -9291,28 +7020,26 @@ func (ec *executionContext) _PrivateOrganization_prepaidScanQuota(ctx context.Co return graphql.Null } res := resTmp.(*int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_readQuota(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ReadQuota, nil @@ -9325,28 +7052,26 @@ func (ec *executionContext) _PrivateOrganization_readQuota(ctx context.Context, return graphql.Null } res := resTmp.(*int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_writeQuota(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.WriteQuota, nil @@ -9359,28 +7084,26 @@ func (ec *executionContext) _PrivateOrganization_writeQuota(ctx context.Context, return graphql.Null } res := resTmp.(*int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_scanQuota(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ScanQuota, nil @@ -9393,28 +7116,26 @@ func (ec *executionContext) _PrivateOrganization_scanQuota(ctx context.Context, return graphql.Null } res := resTmp.(*int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_readUsage(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ReadUsage, nil @@ -9424,34 +7145,32 @@ func (ec *executionContext) _PrivateOrganization_readUsage(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNInt2int(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_writeUsage(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.WriteUsage, nil @@ -9461,34 +7180,32 @@ func (ec *executionContext) _PrivateOrganization_writeUsage(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNInt2int(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_scanUsage(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ScanUsage, nil @@ -9498,34 +7215,32 @@ func (ec *executionContext) _PrivateOrganization_scanUsage(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNInt2int(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_projects(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Projects, nil @@ -9535,34 +7250,32 @@ func (ec *executionContext) _PrivateOrganization_projects(ctx context.Context, f return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.Project) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx, field.Selections, res) + res := resTmp.([]*models.Project) + fc.Result = res + return ec.marshalNProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProjectᚄ(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_personalUserID(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PersonalUserID, nil @@ -9575,28 +7288,26 @@ func (ec *executionContext) _PrivateOrganization_personalUserID(ctx context.Cont return graphql.Null } res := resTmp.(*uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOUUID2ᚖgithubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_personalUser(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PersonalUser, nil @@ -9608,29 +7319,27 @@ func (ec *executionContext) _PrivateOrganization_personalUser(ctx context.Contex if resTmp == nil { return graphql.Null } - res := resTmp.(*entity.User) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUser(ctx, field.Selections, res) + res := resTmp.(*models.User) + fc.Result = res + return ec.marshalOPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐUser(ctx, field.Selections, res) } func (ec *executionContext) _PrivateOrganization_permissions(ctx context.Context, field graphql.CollectedField, obj *PrivateOrganization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Permissions, nil @@ -9640,34 +7349,32 @@ func (ec *executionContext) _PrivateOrganization_permissions(ctx context.Context return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.PermissionsUsersOrganizations) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPermissionsUsersOrganizations2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐPermissionsUsersOrganizations(ctx, field.Selections, res) + res := resTmp.(*models.PermissionsUsersOrganizations) + fc.Result = res + return ec.marshalNPermissionsUsersOrganizations2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐPermissionsUsersOrganizations(ctx, field.Selections, res) } -func (ec *executionContext) _PrivateUser_userID(ctx context.Context, field graphql.CollectedField, obj *entity.User) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PrivateUser_userID(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateUser", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateUser", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.PrivateUser().UserID(rctx, obj) @@ -9677,34 +7384,32 @@ func (ec *executionContext) _PrivateUser_userID(ctx context.Context, field graph return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _PrivateUser_email(ctx context.Context, field graphql.CollectedField, obj *entity.User) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PrivateUser_email(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateUser", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateUser", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Email, nil @@ -9714,34 +7419,32 @@ func (ec *executionContext) _PrivateUser_email(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _PrivateUser_createdOn(ctx context.Context, field graphql.CollectedField, obj *entity.User) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PrivateUser_createdOn(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateUser", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateUser", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.CreatedOn, nil @@ -9751,34 +7454,32 @@ func (ec *executionContext) _PrivateUser_createdOn(ctx context.Context, field gr return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _PrivateUser_updatedOn(ctx context.Context, field graphql.CollectedField, obj *entity.User) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PrivateUser_updatedOn(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateUser", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateUser", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.UpdatedOn, nil @@ -9788,34 +7489,32 @@ func (ec *executionContext) _PrivateUser_updatedOn(ctx context.Context, field gr return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _PrivateUser_consentTerms(ctx context.Context, field graphql.CollectedField, obj *entity.User) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PrivateUser_consentTerms(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateUser", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateUser", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ConsentTerms, nil @@ -9825,34 +7524,32 @@ func (ec *executionContext) _PrivateUser_consentTerms(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _PrivateUser_consentNewsletter(ctx context.Context, field graphql.CollectedField, obj *entity.User) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PrivateUser_consentNewsletter(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateUser", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateUser", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ConsentNewsletter, nil @@ -9862,34 +7559,32 @@ func (ec *executionContext) _PrivateUser_consentNewsletter(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _PrivateUser_readQuota(ctx context.Context, field graphql.CollectedField, obj *entity.User) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PrivateUser_readQuota(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateUser", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateUser", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ReadQuota, nil @@ -9902,28 +7597,26 @@ func (ec *executionContext) _PrivateUser_readQuota(ctx context.Context, field gr return graphql.Null } res := resTmp.(*int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint64(ctx, field.Selections, res) } -func (ec *executionContext) _PrivateUser_writeQuota(ctx context.Context, field graphql.CollectedField, obj *entity.User) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PrivateUser_writeQuota(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateUser", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateUser", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.WriteQuota, nil @@ -9936,28 +7629,26 @@ func (ec *executionContext) _PrivateUser_writeQuota(ctx context.Context, field g return graphql.Null } res := resTmp.(*int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint64(ctx, field.Selections, res) } -func (ec *executionContext) _PrivateUser_scanQuota(ctx context.Context, field graphql.CollectedField, obj *entity.User) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PrivateUser_scanQuota(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateUser", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateUser", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ScanQuota, nil @@ -9970,28 +7661,26 @@ func (ec *executionContext) _PrivateUser_scanQuota(ctx context.Context, field gr return graphql.Null } res := resTmp.(*int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint64(ctx, field.Selections, res) } -func (ec *executionContext) _PrivateUser_billingOrganizationID(ctx context.Context, field graphql.CollectedField, obj *entity.User) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PrivateUser_billingOrganizationID(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateUser", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateUser", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.BillingOrganizationID, nil @@ -10001,34 +7690,32 @@ func (ec *executionContext) _PrivateUser_billingOrganizationID(ctx context.Conte return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _PrivateUser_billingOrganization(ctx context.Context, field graphql.CollectedField, obj *entity.User) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PrivateUser_billingOrganization(ctx context.Context, field graphql.CollectedField, obj *models.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PrivateUser", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PrivateUser", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.BillingOrganization, nil @@ -10038,34 +7725,32 @@ func (ec *executionContext) _PrivateUser_billingOrganization(ctx context.Context return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Organization) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPublicOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐOrganization(ctx, field.Selections, res) + res := resTmp.(*models.Organization) + fc.Result = res + return ec.marshalNPublicOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐOrganization(ctx, field.Selections, res) } -func (ec *executionContext) _Project_projectID(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_projectID(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Project().ProjectID(rctx, obj) @@ -10075,34 +7760,32 @@ func (ec *executionContext) _Project_projectID(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _Project_name(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_name(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil @@ -10112,34 +7795,32 @@ func (ec *executionContext) _Project_name(ctx context.Context, field graphql.Col return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Project_displayName(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_displayName(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.DisplayName, nil @@ -10149,34 +7830,32 @@ func (ec *executionContext) _Project_displayName(ctx context.Context, field grap return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Project_site(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_site(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Site, nil @@ -10189,28 +7868,26 @@ func (ec *executionContext) _Project_site(ctx context.Context, field graphql.Col return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Project_description(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_description(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil @@ -10223,28 +7900,26 @@ func (ec *executionContext) _Project_description(ctx context.Context, field grap return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Project_photoURL(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_photoURL(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PhotoURL, nil @@ -10257,28 +7932,26 @@ func (ec *executionContext) _Project_photoURL(ctx context.Context, field graphql return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Project_public(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_public(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Public, nil @@ -10288,34 +7961,32 @@ func (ec *executionContext) _Project_public(ctx context.Context, field graphql.C return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _Project_organization(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_organization(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Organization, nil @@ -10325,34 +7996,32 @@ func (ec *executionContext) _Project_organization(ctx context.Context, field gra return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Organization) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPublicOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐOrganization(ctx, field.Selections, res) + res := resTmp.(*models.Organization) + fc.Result = res + return ec.marshalNPublicOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐOrganization(ctx, field.Selections, res) } -func (ec *executionContext) _Project_createdOn(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_createdOn(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.CreatedOn, nil @@ -10362,34 +8031,32 @@ func (ec *executionContext) _Project_createdOn(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _Project_updatedOn(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_updatedOn(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.UpdatedOn, nil @@ -10399,34 +8066,32 @@ func (ec *executionContext) _Project_updatedOn(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _Project_streams(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_streams(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Streams, nil @@ -10436,34 +8101,32 @@ func (ec *executionContext) _Project_streams(ctx context.Context, field graphql. return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.Stream) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNStream2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStream(ctx, field.Selections, res) + res := resTmp.([]*models.Stream) + fc.Result = res + return ec.marshalNStream2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _Project_services(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_services(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Services, nil @@ -10473,34 +8136,32 @@ func (ec *executionContext) _Project_services(ctx context.Context, field graphql return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.Service) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNService2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐService(ctx, field.Selections, res) + res := resTmp.([]*models.Service) + fc.Result = res + return ec.marshalNService2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐServiceᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _Project_permissions(ctx context.Context, field graphql.CollectedField, obj *entity.Project) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Project_permissions(ctx context.Context, field graphql.CollectedField, obj *models.Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Project", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Project", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Permissions, nil @@ -10510,34 +8171,32 @@ func (ec *executionContext) _Project_permissions(ctx context.Context, field grap return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.PermissionsUsersProjects) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNPermissionsUsersProjects2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐPermissionsUsersProjects(ctx, field.Selections, res) + res := resTmp.(*models.PermissionsUsersProjects) + fc.Result = res + return ec.marshalNPermissionsUsersProjects2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐPermissionsUsersProjects(ctx, field.Selections, res) } -func (ec *executionContext) _ProjectMember_projectID(ctx context.Context, field graphql.CollectedField, obj *entity.ProjectMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ProjectMember_projectID(ctx context.Context, field graphql.CollectedField, obj *models.ProjectMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "ProjectMember", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "ProjectMember", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.ProjectMember().ProjectID(rctx, obj) @@ -10547,34 +8206,32 @@ func (ec *executionContext) _ProjectMember_projectID(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _ProjectMember_userID(ctx context.Context, field graphql.CollectedField, obj *entity.ProjectMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ProjectMember_userID(ctx context.Context, field graphql.CollectedField, obj *models.ProjectMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "ProjectMember", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "ProjectMember", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.ProjectMember().UserID(rctx, obj) @@ -10584,509 +8241,347 @@ func (ec *executionContext) _ProjectMember_userID(ctx context.Context, field gra return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _ProjectMember_name(ctx context.Context, field graphql.CollectedField, obj *entity.ProjectMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ProjectMember_name(ctx context.Context, field graphql.CollectedField, obj *models.ProjectMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "ProjectMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Name, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null + fc := &graphql.FieldContext{ + Object: "ProjectMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) -} -func (ec *executionContext) _ProjectMember_displayName(ctx context.Context, field graphql.CollectedField, obj *entity.ProjectMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "ProjectMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.DisplayName, nil + return obj.Name, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _ProjectMember_photoURL(ctx context.Context, field graphql.CollectedField, obj *entity.ProjectMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "ProjectMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.PhotoURL, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) _ProjectMember_view(ctx context.Context, field graphql.CollectedField, obj *entity.ProjectMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "ProjectMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.View, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNBoolean2bool(ctx, field.Selections, res) -} - -func (ec *executionContext) _ProjectMember_create(ctx context.Context, field graphql.CollectedField, obj *entity.ProjectMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ProjectMember_displayName(ctx context.Context, field graphql.CollectedField, obj *models.ProjectMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "ProjectMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Create, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null + fc := &graphql.FieldContext{ + Object: "ProjectMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, } - res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNBoolean2bool(ctx, field.Selections, res) -} -func (ec *executionContext) _ProjectMember_admin(ctx context.Context, field graphql.CollectedField, obj *entity.ProjectMember) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "ProjectMember", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Admin, nil + return obj.DisplayName, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _PublicOrganization_organizationID(ctx context.Context, field graphql.CollectedField, obj *entity.Organization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ProjectMember_photoURL(ctx context.Context, field graphql.CollectedField, obj *models.ProjectMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PublicOrganization", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "ProjectMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.PublicOrganization().OrganizationID(rctx, obj) + return obj.PhotoURL, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNID2string(ctx, field.Selections, res) + fc.Result = res + return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) _PublicOrganization_name(ctx context.Context, field graphql.CollectedField, obj *entity.Organization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ProjectMember_view(ctx context.Context, field graphql.CollectedField, obj *models.ProjectMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PublicOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "ProjectMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Name, nil + return obj.View, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _PublicOrganization_displayName(ctx context.Context, field graphql.CollectedField, obj *entity.Organization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ProjectMember_create(ctx context.Context, field graphql.CollectedField, obj *models.ProjectMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PublicOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "ProjectMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.DisplayName, nil + return obj.Create, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _PublicOrganization_description(ctx context.Context, field graphql.CollectedField, obj *entity.Organization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ProjectMember_admin(ctx context.Context, field graphql.CollectedField, obj *models.ProjectMember) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PublicOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "ProjectMember", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Description, nil + return obj.Admin, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOString2string(ctx, field.Selections, res) + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _PublicOrganization_photoURL(ctx context.Context, field graphql.CollectedField, obj *entity.Organization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PublicOrganization_organizationID(ctx context.Context, field graphql.CollectedField, obj *models.Organization) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PublicOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PublicOrganization", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PhotoURL, nil + return ec.resolvers.PublicOrganization().OrganizationID(rctx, obj) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOString2string(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _PublicOrganization_createdOn(ctx context.Context, field graphql.CollectedField, obj *entity.Organization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PublicOrganization_name(ctx context.Context, field graphql.CollectedField, obj *models.Organization) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PublicOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PublicOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.CreatedOn, nil + return obj.Name, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _PublicOrganization_projects(ctx context.Context, field graphql.CollectedField, obj *entity.Organization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PublicOrganization_displayName(ctx context.Context, field graphql.CollectedField, obj *models.Organization) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PublicOrganization", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PublicOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Projects, nil + return obj.DisplayName, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.Project) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx, field.Selections, res) + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _PublicOrganization_personalUserID(ctx context.Context, field graphql.CollectedField, obj *entity.Organization) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PublicOrganization_description(ctx context.Context, field graphql.CollectedField, obj *models.Organization) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "PublicOrganization", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PublicOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.PublicOrganization().PersonalUserID(rctx, obj) + return obj.Description, nil }) if err != nil { ec.Error(ctx, err) @@ -11095,32 +8590,30 @@ func (ec *executionContext) _PublicOrganization_personalUserID(ctx context.Conte if resTmp == nil { return graphql.Null } - res := resTmp.(*uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOUUID2ᚖgithubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) + res := resTmp.(string) + fc.Result = res + return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Query_empty(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PublicOrganization_photoURL(ctx context.Context, field graphql.CollectedField, obj *models.Organization) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PublicOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Empty(rctx) + return obj.PhotoURL, nil }) if err != nil { ec.Error(ctx, err) @@ -11129,242 +8622,203 @@ func (ec *executionContext) _Query_empty(ctx context.Context, field graphql.Coll if resTmp == nil { return graphql.Null } - res := resTmp.(*string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) + res := resTmp.(string) + fc.Result = res + return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Query_ping(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PublicOrganization_createdOn(ctx context.Context, field graphql.CollectedField, obj *models.Organization) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "PublicOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Ping(rctx) + return obj.CreatedOn, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2string(ctx, field.Selections, res) + res := resTmp.(time.Time) + fc.Result = res + return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _Query_billedResources(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PublicOrganization_projects(ctx context.Context, field graphql.CollectedField, obj *models.Organization) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_billedResources_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null + fc := &graphql.FieldContext{ + Object: "PublicOrganization", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().BilledResources(rctx, args["organizationID"].(uuid.UUID), args["billingTime"].(time.Time)) + return obj.Projects, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.BilledResource) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNBilledResource2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBilledResource(ctx, field.Selections, res) + res := resTmp.([]*models.Project) + fc.Result = res + return ec.marshalNProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProjectᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _Query_billingInfo(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _PublicOrganization_personalUserID(ctx context.Context, field graphql.CollectedField, obj *models.Organization) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_billingInfo_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null + fc := &graphql.FieldContext{ + Object: "PublicOrganization", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().BillingInfo(rctx, args["organizationID"].(uuid.UUID)) + return ec.resolvers.PublicOrganization().PersonalUserID(rctx, obj) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(*entity.BillingInfo) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNBillingInfo2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingInfo(ctx, field.Selections, res) + res := resTmp.(*uuid.UUID) + fc.Result = res + return ec.marshalOUUID2ᚖgithubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _Query_billingMethods(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Query_empty(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_billingMethods_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().BillingMethods(rctx, args["organizationID"].(uuid.UUID)) + return ec.resolvers.Query().Empty(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]*entity.BillingMethod) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNBillingMethod2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingMethod(ctx, field.Selections, res) + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) _Query_billingPlans(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Query_ping(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().BillingPlans(rctx) + return ec.resolvers.Query().Ping(rctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.BillingPlan) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNBillingPlan2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingPlan(ctx, field.Selections, res) + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) _Query_getMetrics(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_getMetrics_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().GetMetrics(rctx, args["entityKind"].(EntityKind), args["entityID"].(uuid.UUID), args["period"].(string), args["from"].(time.Time), args["until"].(*time.Time)) @@ -11374,41 +8828,39 @@ func (ec *executionContext) _Query_getMetrics(ctx context.Context, field graphql return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]*Metrics) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐMetrics(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐMetricsᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_getOrganizationMetrics(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_getOrganizationMetrics_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().GetOrganizationMetrics(rctx, args["organizationID"].(uuid.UUID), args["period"].(string), args["from"].(time.Time), args["until"].(*time.Time)) @@ -11418,41 +8870,39 @@ func (ec *executionContext) _Query_getOrganizationMetrics(ctx context.Context, f return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]*Metrics) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐMetrics(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐMetricsᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_getServiceMetrics(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_getServiceMetrics_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().GetServiceMetrics(rctx, args["serviceID"].(uuid.UUID), args["period"].(string), args["from"].(time.Time), args["until"].(*time.Time)) @@ -11462,41 +8912,39 @@ func (ec *executionContext) _Query_getServiceMetrics(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]*Metrics) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐMetrics(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐMetricsᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_getStreamInstanceMetrics(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_getStreamInstanceMetrics_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().GetStreamInstanceMetrics(rctx, args["streamInstanceID"].(uuid.UUID), args["period"].(string), args["from"].(time.Time), args["until"].(*time.Time)) @@ -11506,41 +8954,39 @@ func (ec *executionContext) _Query_getStreamInstanceMetrics(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]*Metrics) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐMetrics(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐMetricsᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_getStreamMetrics(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_getStreamMetrics_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().GetStreamMetrics(rctx, args["streamID"].(uuid.UUID), args["period"].(string), args["from"].(time.Time), args["until"].(*time.Time)) @@ -11550,41 +8996,39 @@ func (ec *executionContext) _Query_getStreamMetrics(ctx context.Context, field g return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]*Metrics) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐMetrics(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐMetricsᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_getUserMetrics(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_getUserMetrics_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().GetUserMetrics(rctx, args["userID"].(uuid.UUID), args["period"].(string), args["from"].(time.Time), args["until"].(*time.Time)) @@ -11594,34 +9038,32 @@ func (ec *executionContext) _Query_getUserMetrics(ctx context.Context, field gra return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]*Metrics) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐMetrics(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐMetricsᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_me(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().Me(rctx) @@ -11634,35 +9076,33 @@ func (ec *executionContext) _Query_me(ctx context.Context, field graphql.Collect return graphql.Null } res := resTmp.(*PrivateOrganization) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOPrivateOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐPrivateOrganization(ctx, field.Selections, res) + fc.Result = res + return ec.marshalOPrivateOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐPrivateOrganization(ctx, field.Selections, res) } func (ec *executionContext) _Query_organizationByName(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_organizationByName_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().OrganizationByName(rctx, args["name"].(string)) @@ -11672,41 +9112,39 @@ func (ec *executionContext) _Query_organizationByName(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(Organization) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNOrganization2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐOrganization(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNOrganization2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐOrganization(ctx, field.Selections, res) } func (ec *executionContext) _Query_organizationByID(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_organizationByID_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().OrganizationByID(rctx, args["organizationID"].(uuid.UUID)) @@ -11716,41 +9154,39 @@ func (ec *executionContext) _Query_organizationByID(ctx context.Context, field g return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(Organization) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNOrganization2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐOrganization(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNOrganization2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐOrganization(ctx, field.Selections, res) } func (ec *executionContext) _Query_organizationByUserID(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_organizationByUserID_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().OrganizationByUserID(rctx, args["userID"].(uuid.UUID)) @@ -11760,41 +9196,39 @@ func (ec *executionContext) _Query_organizationByUserID(ctx context.Context, fie return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(Organization) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNOrganization2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐOrganization(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNOrganization2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐOrganization(ctx, field.Selections, res) } func (ec *executionContext) _Query_organizationMembers(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_organizationMembers_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().OrganizationMembers(rctx, args["organizationID"].(uuid.UUID)) @@ -11804,34 +9238,32 @@ func (ec *executionContext) _Query_organizationMembers(ctx context.Context, fiel return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.OrganizationMember) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNOrganizationMember2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐOrganizationMember(ctx, field.Selections, res) + res := resTmp.([]*models.OrganizationMember) + fc.Result = res + return ec.marshalNOrganizationMember2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐOrganizationMemberᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_exploreProjects(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().ExploreProjects(rctx) @@ -11843,36 +9275,34 @@ func (ec *executionContext) _Query_exploreProjects(ctx context.Context, field gr if resTmp == nil { return graphql.Null } - res := resTmp.([]*entity.Project) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx, field.Selections, res) + res := resTmp.([]*models.Project) + fc.Result = res + return ec.marshalOProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProjectᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_projectsForUser(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_projectsForUser_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().ProjectsForUser(rctx, args["userID"].(uuid.UUID)) @@ -11884,36 +9314,34 @@ func (ec *executionContext) _Query_projectsForUser(ctx context.Context, field gr if resTmp == nil { return graphql.Null } - res := resTmp.([]*entity.Project) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx, field.Selections, res) + res := resTmp.([]*models.Project) + fc.Result = res + return ec.marshalOProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProjectᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_projectByOrganizationAndName(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_projectByOrganizationAndName_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().ProjectByOrganizationAndName(rctx, args["organizationName"].(string), args["projectName"].(string)) @@ -11923,41 +9351,39 @@ func (ec *executionContext) _Query_projectByOrganizationAndName(ctx context.Cont return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Project) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx, field.Selections, res) + res := resTmp.(*models.Project) + fc.Result = res + return ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProject(ctx, field.Selections, res) } func (ec *executionContext) _Query_projectByID(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_projectByID_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().ProjectByID(rctx, args["projectID"].(uuid.UUID)) @@ -11967,41 +9393,39 @@ func (ec *executionContext) _Query_projectByID(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Project) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx, field.Selections, res) + res := resTmp.(*models.Project) + fc.Result = res + return ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProject(ctx, field.Selections, res) } func (ec *executionContext) _Query_projectMembers(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_projectMembers_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().ProjectMembers(rctx, args["projectID"].(uuid.UUID)) @@ -12011,41 +9435,39 @@ func (ec *executionContext) _Query_projectMembers(ctx context.Context, field gra return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.ProjectMember) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNProjectMember2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProjectMember(ctx, field.Selections, res) + res := resTmp.([]*models.ProjectMember) + fc.Result = res + return ec.marshalNProjectMember2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProjectMemberᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_secretsForService(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_secretsForService_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().SecretsForService(rctx, args["serviceID"].(uuid.UUID)) @@ -12055,41 +9477,39 @@ func (ec *executionContext) _Query_secretsForService(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.ServiceSecret) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNServiceSecret2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐServiceSecret(ctx, field.Selections, res) + res := resTmp.([]*models.ServiceSecret) + fc.Result = res + return ec.marshalNServiceSecret2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐServiceSecretᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_secretsForUser(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_secretsForUser_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().SecretsForUser(rctx, args["userID"].(uuid.UUID)) @@ -12099,41 +9519,39 @@ func (ec *executionContext) _Query_secretsForUser(ctx context.Context, field gra return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.UserSecret) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNUserSecret2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUserSecret(ctx, field.Selections, res) + res := resTmp.([]*models.UserSecret) + fc.Result = res + return ec.marshalNUserSecret2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐUserSecretᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_serviceByID(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_serviceByID_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().ServiceByID(rctx, args["serviceID"].(uuid.UUID)) @@ -12143,41 +9561,39 @@ func (ec *executionContext) _Query_serviceByID(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Service) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐService(ctx, field.Selections, res) + res := resTmp.(*models.Service) + fc.Result = res + return ec.marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐService(ctx, field.Selections, res) } func (ec *executionContext) _Query_serviceByOrganizationProjectAndName(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_serviceByOrganizationProjectAndName_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().ServiceByOrganizationProjectAndName(rctx, args["organizationName"].(string), args["projectName"].(string), args["serviceName"].(string)) @@ -12187,41 +9603,39 @@ func (ec *executionContext) _Query_serviceByOrganizationProjectAndName(ctx conte return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Service) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐService(ctx, field.Selections, res) + res := resTmp.(*models.Service) + fc.Result = res + return ec.marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐService(ctx, field.Selections, res) } func (ec *executionContext) _Query_streamByID(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_streamByID_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().StreamByID(rctx, args["streamID"].(uuid.UUID)) @@ -12231,41 +9645,39 @@ func (ec *executionContext) _Query_streamByID(ctx context.Context, field graphql return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Stream) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNStream2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStream(ctx, field.Selections, res) + res := resTmp.(*models.Stream) + fc.Result = res + return ec.marshalNStream2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStream(ctx, field.Selections, res) } func (ec *executionContext) _Query_streamByOrganizationProjectAndName(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_streamByOrganizationProjectAndName_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().StreamByOrganizationProjectAndName(rctx, args["organizationName"].(string), args["projectName"].(string), args["streamName"].(string)) @@ -12275,41 +9687,39 @@ func (ec *executionContext) _Query_streamByOrganizationProjectAndName(ctx contex return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Stream) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNStream2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStream(ctx, field.Selections, res) + res := resTmp.(*models.Stream) + fc.Result = res + return ec.marshalNStream2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStream(ctx, field.Selections, res) } func (ec *executionContext) _Query_streamInstancesForStream(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_streamInstancesForStream_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().StreamInstancesForStream(rctx, args["streamID"].(uuid.UUID)) @@ -12319,41 +9729,39 @@ func (ec *executionContext) _Query_streamInstancesForStream(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.StreamInstance) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNStreamInstance2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamInstance(ctx, field.Selections, res) + res := resTmp.([]*models.StreamInstance) + fc.Result = res + return ec.marshalNStreamInstance2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamInstanceᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query_streamInstancesByOrganizationProjectAndStreamName(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query_streamInstancesByOrganizationProjectAndStreamName_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Query().StreamInstancesByOrganizationProjectAndStreamName(rctx, args["organizationName"].(string), args["projectName"].(string), args["streamName"].(string)) @@ -12363,41 +9771,39 @@ func (ec *executionContext) _Query_streamInstancesByOrganizationProjectAndStream return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.StreamInstance) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNStreamInstance2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamInstance(ctx, field.Selections, res) + res := resTmp.([]*models.StreamInstance) + fc.Result = res + return ec.marshalNStreamInstance2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamInstanceᚄ(ctx, field.Selections, res) } func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field_Query___type_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.introspectType(args["name"].(string)) @@ -12410,28 +9816,26 @@ func (ec *executionContext) _Query___type(ctx context.Context, field graphql.Col return graphql.Null } res := resTmp.(*introspection.Type) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Query", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.introspectSchema() @@ -12444,28 +9848,26 @@ func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.C return graphql.Null } res := resTmp.(*introspection.Schema) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res) } -func (ec *executionContext) _Service_serviceID(ctx context.Context, field graphql.CollectedField, obj *entity.Service) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Service_serviceID(ctx context.Context, field graphql.CollectedField, obj *models.Service) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Service", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Service", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ServiceID, nil @@ -12475,34 +9877,32 @@ func (ec *executionContext) _Service_serviceID(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _Service_name(ctx context.Context, field graphql.CollectedField, obj *entity.Service) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Service_name(ctx context.Context, field graphql.CollectedField, obj *models.Service) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Service", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Service", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil @@ -12512,34 +9912,32 @@ func (ec *executionContext) _Service_name(ctx context.Context, field graphql.Col return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Service_description(ctx context.Context, field graphql.CollectedField, obj *entity.Service) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Service_description(ctx context.Context, field graphql.CollectedField, obj *models.Service) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Service", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Service", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil @@ -12552,28 +9950,26 @@ func (ec *executionContext) _Service_description(ctx context.Context, field grap return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Service_sourceURL(ctx context.Context, field graphql.CollectedField, obj *entity.Service) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Service_sourceURL(ctx context.Context, field graphql.CollectedField, obj *models.Service) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Service", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Service", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.SourceURL, nil @@ -12586,28 +9982,26 @@ func (ec *executionContext) _Service_sourceURL(ctx context.Context, field graphq return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Service_project(ctx context.Context, field graphql.CollectedField, obj *entity.Service) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Service_project(ctx context.Context, field graphql.CollectedField, obj *models.Service) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Service", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Service", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Project, nil @@ -12617,34 +10011,32 @@ func (ec *executionContext) _Service_project(ctx context.Context, field graphql. return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Project) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx, field.Selections, res) + res := resTmp.(*models.Project) + fc.Result = res + return ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProject(ctx, field.Selections, res) } -func (ec *executionContext) _Service_readQuota(ctx context.Context, field graphql.CollectedField, obj *entity.Service) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Service_readQuota(ctx context.Context, field graphql.CollectedField, obj *models.Service) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Service", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Service", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ReadQuota, nil @@ -12657,28 +10049,26 @@ func (ec *executionContext) _Service_readQuota(ctx context.Context, field graphq return graphql.Null } res := resTmp.(*int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint64(ctx, field.Selections, res) } -func (ec *executionContext) _Service_writeQuota(ctx context.Context, field graphql.CollectedField, obj *entity.Service) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Service_writeQuota(ctx context.Context, field graphql.CollectedField, obj *models.Service) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Service", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Service", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.WriteQuota, nil @@ -12691,28 +10081,26 @@ func (ec *executionContext) _Service_writeQuota(ctx context.Context, field graph return graphql.Null } res := resTmp.(*int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint64(ctx, field.Selections, res) } -func (ec *executionContext) _Service_scanQuota(ctx context.Context, field graphql.CollectedField, obj *entity.Service) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Service_scanQuota(ctx context.Context, field graphql.CollectedField, obj *models.Service) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Service", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Service", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ScanQuota, nil @@ -12725,28 +10113,26 @@ func (ec *executionContext) _Service_scanQuota(ctx context.Context, field graphq return graphql.Null } res := resTmp.(*int64) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOInt2ᚖint64(ctx, field.Selections, res) } -func (ec *executionContext) _Service_createdOn(ctx context.Context, field graphql.CollectedField, obj *entity.Service) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Service_createdOn(ctx context.Context, field graphql.CollectedField, obj *models.Service) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Service", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Service", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.CreatedOn, nil @@ -12756,34 +10142,32 @@ func (ec *executionContext) _Service_createdOn(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _Service_updatedOn(ctx context.Context, field graphql.CollectedField, obj *entity.Service) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Service_updatedOn(ctx context.Context, field graphql.CollectedField, obj *models.Service) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Service", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Service", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.UpdatedOn, nil @@ -12793,34 +10177,32 @@ func (ec *executionContext) _Service_updatedOn(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _ServiceSecret_serviceSecretID(ctx context.Context, field graphql.CollectedField, obj *entity.ServiceSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ServiceSecret_serviceSecretID(ctx context.Context, field graphql.CollectedField, obj *models.ServiceSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "ServiceSecret", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "ServiceSecret", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.ServiceSecret().ServiceSecretID(rctx, obj) @@ -12830,34 +10212,32 @@ func (ec *executionContext) _ServiceSecret_serviceSecretID(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _ServiceSecret_prefix(ctx context.Context, field graphql.CollectedField, obj *entity.ServiceSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ServiceSecret_prefix(ctx context.Context, field graphql.CollectedField, obj *models.ServiceSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "ServiceSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "ServiceSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Prefix, nil @@ -12867,34 +10247,32 @@ func (ec *executionContext) _ServiceSecret_prefix(ctx context.Context, field gra return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _ServiceSecret_description(ctx context.Context, field graphql.CollectedField, obj *entity.ServiceSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ServiceSecret_description(ctx context.Context, field graphql.CollectedField, obj *models.ServiceSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "ServiceSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "ServiceSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil @@ -12904,34 +10282,32 @@ func (ec *executionContext) _ServiceSecret_description(ctx context.Context, fiel return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _ServiceSecret_service(ctx context.Context, field graphql.CollectedField, obj *entity.ServiceSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ServiceSecret_service(ctx context.Context, field graphql.CollectedField, obj *models.ServiceSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "ServiceSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "ServiceSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Service, nil @@ -12941,34 +10317,32 @@ func (ec *executionContext) _ServiceSecret_service(ctx context.Context, field gr return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Service) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐService(ctx, field.Selections, res) + res := resTmp.(*models.Service) + fc.Result = res + return ec.marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐService(ctx, field.Selections, res) } -func (ec *executionContext) _ServiceSecret_createdOn(ctx context.Context, field graphql.CollectedField, obj *entity.ServiceSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ServiceSecret_createdOn(ctx context.Context, field graphql.CollectedField, obj *models.ServiceSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "ServiceSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "ServiceSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.CreatedOn, nil @@ -12978,34 +10352,32 @@ func (ec *executionContext) _ServiceSecret_createdOn(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _ServiceSecret_updatedOn(ctx context.Context, field graphql.CollectedField, obj *entity.ServiceSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _ServiceSecret_updatedOn(ctx context.Context, field graphql.CollectedField, obj *models.ServiceSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "ServiceSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "ServiceSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.UpdatedOn, nil @@ -13015,34 +10387,32 @@ func (ec *executionContext) _ServiceSecret_updatedOn(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_streamID(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_streamID(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.Stream().StreamID(rctx, obj) @@ -13052,34 +10422,32 @@ func (ec *executionContext) _Stream_streamID(ctx context.Context, field graphql. return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_name(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_name(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil @@ -13089,34 +10457,32 @@ func (ec *executionContext) _Stream_name(ctx context.Context, field graphql.Coll return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_description(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_description(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil @@ -13129,28 +10495,26 @@ func (ec *executionContext) _Stream_description(ctx context.Context, field graph return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_createdOn(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_createdOn(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.CreatedOn, nil @@ -13160,34 +10524,32 @@ func (ec *executionContext) _Stream_createdOn(ctx context.Context, field graphql return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_updatedOn(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_updatedOn(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.UpdatedOn, nil @@ -13197,34 +10559,32 @@ func (ec *executionContext) _Stream_updatedOn(ctx context.Context, field graphql return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_project(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_project(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Project, nil @@ -13234,34 +10594,32 @@ func (ec *executionContext) _Stream_project(ctx context.Context, field graphql.C return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(*entity.Project) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx, field.Selections, res) + res := resTmp.(*models.Project) + fc.Result = res + return ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProject(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_allowManualWrites(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_allowManualWrites(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.AllowManualWrites, nil @@ -13271,34 +10629,32 @@ func (ec *executionContext) _Stream_allowManualWrites(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_schemaKind(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_schemaKind(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.SchemaKind, nil @@ -13308,34 +10664,32 @@ func (ec *executionContext) _Stream_schemaKind(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.(entity.StreamSchemaKind) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNStreamSchemaKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamSchemaKind(ctx, field.Selections, res) + res := resTmp.(models.StreamSchemaKind) + fc.Result = res + return ec.marshalNStreamSchemaKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamSchemaKind(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_schema(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_schema(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Schema, nil @@ -13345,34 +10699,32 @@ func (ec *executionContext) _Stream_schema(ctx context.Context, field graphql.Co return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_avroSchema(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_avroSchema(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.AvroSchema, nil @@ -13382,34 +10734,32 @@ func (ec *executionContext) _Stream_avroSchema(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_canonicalAvroSchema(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_canonicalAvroSchema(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.CanonicalAvroSchema, nil @@ -13419,34 +10769,32 @@ func (ec *executionContext) _Stream_canonicalAvroSchema(ctx context.Context, fie return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_canonicalIndexes(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_canonicalIndexes(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.CanonicalIndexes, nil @@ -13456,34 +10804,32 @@ func (ec *executionContext) _Stream_canonicalIndexes(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_streamIndexes(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_streamIndexes(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.StreamIndexes, nil @@ -13493,34 +10839,32 @@ func (ec *executionContext) _Stream_streamIndexes(ctx context.Context, field gra return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } - res := resTmp.([]*entity.StreamIndex) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNStreamIndex2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamIndex(ctx, field.Selections, res) + res := resTmp.([]*models.StreamIndex) + fc.Result = res + return ec.marshalNStreamIndex2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamIndexᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_useLog(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_useLog(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.UseLog, nil @@ -13530,34 +10874,32 @@ func (ec *executionContext) _Stream_useLog(ctx context.Context, field graphql.Co return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_useIndex(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_useIndex(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.UseIndex, nil @@ -13567,34 +10909,32 @@ func (ec *executionContext) _Stream_useIndex(ctx context.Context, field graphql. return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_useWarehouse(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_useWarehouse(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.UseWarehouse, nil @@ -13604,34 +10944,32 @@ func (ec *executionContext) _Stream_useWarehouse(ctx context.Context, field grap return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_logRetentionSeconds(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_logRetentionSeconds(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.LogRetentionSeconds, nil @@ -13641,34 +10979,32 @@ func (ec *executionContext) _Stream_logRetentionSeconds(ctx context.Context, fie return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int32) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNInt2int32(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_indexRetentionSeconds(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_indexRetentionSeconds(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.IndexRetentionSeconds, nil @@ -13678,34 +11014,32 @@ func (ec *executionContext) _Stream_indexRetentionSeconds(ctx context.Context, f return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int32) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNInt2int32(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_warehouseRetentionSeconds(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_warehouseRetentionSeconds(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.WarehouseRetentionSeconds, nil @@ -13715,34 +11049,32 @@ func (ec *executionContext) _Stream_warehouseRetentionSeconds(ctx context.Contex return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int32) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNInt2int32(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_primaryStreamInstance(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_primaryStreamInstance(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PrimaryStreamInstance, nil @@ -13754,29 +11086,27 @@ func (ec *executionContext) _Stream_primaryStreamInstance(ctx context.Context, f if resTmp == nil { return graphql.Null } - res := resTmp.(*entity.StreamInstance) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamInstance(ctx, field.Selections, res) + res := resTmp.(*models.StreamInstance) + fc.Result = res + return ec.marshalOStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamInstance(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_primaryStreamInstanceID(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_primaryStreamInstanceID(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PrimaryStreamInstanceID, nil @@ -13789,28 +11119,26 @@ func (ec *executionContext) _Stream_primaryStreamInstanceID(ctx context.Context, return graphql.Null } res := resTmp.(*uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOUUID2ᚖgithubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_instancesCreatedCount(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_instancesCreatedCount(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.InstancesCreatedCount, nil @@ -13820,34 +11148,32 @@ func (ec *executionContext) _Stream_instancesCreatedCount(ctx context.Context, f return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int32) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNInt2int32(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_instancesDeletedCount(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_instancesDeletedCount(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.InstancesDeletedCount, nil @@ -13857,34 +11183,32 @@ func (ec *executionContext) _Stream_instancesDeletedCount(ctx context.Context, f return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int32) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNInt2int32(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_instancesMadeFinalCount(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_instancesMadeFinalCount(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.InstancesMadeFinalCount, nil @@ -13894,34 +11218,32 @@ func (ec *executionContext) _Stream_instancesMadeFinalCount(ctx context.Context, return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int32) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNInt2int32(ctx, field.Selections, res) } -func (ec *executionContext) _Stream_instancesMadePrimaryCount(ctx context.Context, field graphql.CollectedField, obj *entity.Stream) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _Stream_instancesMadePrimaryCount(ctx context.Context, field graphql.CollectedField, obj *models.Stream) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "Stream", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "Stream", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.InstancesMadePrimaryCount, nil @@ -13931,34 +11253,32 @@ func (ec *executionContext) _Stream_instancesMadePrimaryCount(ctx context.Contex return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int32) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNInt2int32(ctx, field.Selections, res) } -func (ec *executionContext) _StreamIndex_indexID(ctx context.Context, field graphql.CollectedField, obj *entity.StreamIndex) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _StreamIndex_indexID(ctx context.Context, field graphql.CollectedField, obj *models.StreamIndex) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "StreamIndex", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "StreamIndex", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.StreamIndex().IndexID(rctx, obj) @@ -13968,34 +11288,32 @@ func (ec *executionContext) _StreamIndex_indexID(ctx context.Context, field grap return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _StreamIndex_fields(ctx context.Context, field graphql.CollectedField, obj *entity.StreamIndex) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _StreamIndex_fields(ctx context.Context, field graphql.CollectedField, obj *models.StreamIndex) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "StreamIndex", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "StreamIndex", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Fields, nil @@ -14005,34 +11323,32 @@ func (ec *executionContext) _StreamIndex_fields(ctx context.Context, field graph return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalNString2ᚕstring(ctx, field.Selections, res) + fc.Result = res + return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _StreamIndex_primary(ctx context.Context, field graphql.CollectedField, obj *entity.StreamIndex) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _StreamIndex_primary(ctx context.Context, field graphql.CollectedField, obj *models.StreamIndex) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "StreamIndex", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "StreamIndex", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Primary, nil @@ -14042,34 +11358,32 @@ func (ec *executionContext) _StreamIndex_primary(ctx context.Context, field grap return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _StreamIndex_normalize(ctx context.Context, field graphql.CollectedField, obj *entity.StreamIndex) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _StreamIndex_normalize(ctx context.Context, field graphql.CollectedField, obj *models.StreamIndex) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "StreamIndex", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "StreamIndex", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Normalize, nil @@ -14079,34 +11393,32 @@ func (ec *executionContext) _StreamIndex_normalize(ctx context.Context, field gr return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _StreamInstance_streamInstanceID(ctx context.Context, field graphql.CollectedField, obj *entity.StreamInstance) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _StreamInstance_streamInstanceID(ctx context.Context, field graphql.CollectedField, obj *models.StreamInstance) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "StreamInstance", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "StreamInstance", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.StreamInstance().StreamInstanceID(rctx, obj) @@ -14116,34 +11428,32 @@ func (ec *executionContext) _StreamInstance_streamInstanceID(ctx context.Context return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _StreamInstance_streamID(ctx context.Context, field graphql.CollectedField, obj *entity.StreamInstance) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _StreamInstance_streamID(ctx context.Context, field graphql.CollectedField, obj *models.StreamInstance) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "StreamInstance", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "StreamInstance", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.StreamID, nil @@ -14153,34 +11463,32 @@ func (ec *executionContext) _StreamInstance_streamID(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(uuid.UUID) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, field.Selections, res) } -func (ec *executionContext) _StreamInstance_version(ctx context.Context, field graphql.CollectedField, obj *entity.StreamInstance) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _StreamInstance_version(ctx context.Context, field graphql.CollectedField, obj *models.StreamInstance) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "StreamInstance", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "StreamInstance", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Version, nil @@ -14190,34 +11498,32 @@ func (ec *executionContext) _StreamInstance_version(ctx context.Context, field g return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(int) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _StreamInstance_createdOn(ctx context.Context, field graphql.CollectedField, obj *entity.StreamInstance) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _StreamInstance_createdOn(ctx context.Context, field graphql.CollectedField, obj *models.StreamInstance) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "StreamInstance", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "StreamInstance", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.CreatedOn, nil @@ -14227,34 +11533,32 @@ func (ec *executionContext) _StreamInstance_createdOn(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _StreamInstance_madePrimaryOn(ctx context.Context, field graphql.CollectedField, obj *entity.StreamInstance) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _StreamInstance_madePrimaryOn(ctx context.Context, field graphql.CollectedField, obj *models.StreamInstance) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "StreamInstance", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "StreamInstance", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.MadePrimaryOn, nil @@ -14267,28 +11571,26 @@ func (ec *executionContext) _StreamInstance_madePrimaryOn(ctx context.Context, f return graphql.Null } res := resTmp.(*time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _StreamInstance_madeFinalOn(ctx context.Context, field graphql.CollectedField, obj *entity.StreamInstance) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _StreamInstance_madeFinalOn(ctx context.Context, field graphql.CollectedField, obj *models.StreamInstance) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "StreamInstance", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "StreamInstance", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.MadeFinalOn, nil @@ -14300,27 +11602,40 @@ func (ec *executionContext) _StreamInstance_madeFinalOn(ctx context.Context, fie if resTmp == nil { return graphql.Null } - res := resTmp.(*time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) -} + res := resTmp.(*time.Time) + fc.Result = res + return ec.marshalOTime2ᚖtimeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _Subscription_empty(ctx context.Context, field graphql.CollectedField) (ret func() graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + fc := &graphql.FieldContext{ + Object: "Subscription", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } -func (ec *executionContext) _Subscription_empty(ctx context.Context, field graphql.CollectedField) func() graphql.Marshaler { - ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ - Field: field, - Args: nil, + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Subscription().Empty(rctx) }) - // FIXME: subscriptions are missing request middleware stack https://github.com/99designs/gqlgen/issues/259 - // and Tracer stack - rctx := ctx - results, err := ec.resolvers.Subscription().Empty(rctx) if err != nil { ec.Error(ctx, err) return nil } + if resTmp == nil { + return nil + } return func() graphql.Marshaler { - res, ok := <-results + res, ok := <-resTmp.(<-chan *string) if !ok { return nil } @@ -14334,23 +11649,22 @@ func (ec *executionContext) _Subscription_empty(ctx context.Context, field graph } } -func (ec *executionContext) _UserSecret_userSecretID(ctx context.Context, field graphql.CollectedField, obj *entity.UserSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _UserSecret_userSecretID(ctx context.Context, field graphql.CollectedField, obj *models.UserSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "UserSecret", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "UserSecret", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return ec.resolvers.UserSecret().UserSecretID(rctx, obj) @@ -14360,34 +11674,32 @@ func (ec *executionContext) _UserSecret_userSecretID(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _UserSecret_prefix(ctx context.Context, field graphql.CollectedField, obj *entity.UserSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _UserSecret_prefix(ctx context.Context, field graphql.CollectedField, obj *models.UserSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "UserSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "UserSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Prefix, nil @@ -14397,34 +11709,32 @@ func (ec *executionContext) _UserSecret_prefix(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _UserSecret_description(ctx context.Context, field graphql.CollectedField, obj *entity.UserSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _UserSecret_description(ctx context.Context, field graphql.CollectedField, obj *models.UserSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "UserSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "UserSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil @@ -14434,34 +11744,32 @@ func (ec *executionContext) _UserSecret_description(ctx context.Context, field g return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _UserSecret_readOnly(ctx context.Context, field graphql.CollectedField, obj *entity.UserSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _UserSecret_readOnly(ctx context.Context, field graphql.CollectedField, obj *models.UserSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "UserSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "UserSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.ReadOnly, nil @@ -14471,34 +11779,32 @@ func (ec *executionContext) _UserSecret_readOnly(ctx context.Context, field grap return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _UserSecret_publicOnly(ctx context.Context, field graphql.CollectedField, obj *entity.UserSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _UserSecret_publicOnly(ctx context.Context, field graphql.CollectedField, obj *models.UserSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "UserSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "UserSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PublicOnly, nil @@ -14508,34 +11814,32 @@ func (ec *executionContext) _UserSecret_publicOnly(ctx context.Context, field gr return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _UserSecret_createdOn(ctx context.Context, field graphql.CollectedField, obj *entity.UserSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _UserSecret_createdOn(ctx context.Context, field graphql.CollectedField, obj *models.UserSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "UserSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "UserSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.CreatedOn, nil @@ -14545,34 +11849,32 @@ func (ec *executionContext) _UserSecret_createdOn(ctx context.Context, field gra return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _UserSecret_updatedOn(ctx context.Context, field graphql.CollectedField, obj *entity.UserSecret) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) +func (ec *executionContext) _UserSecret_updatedOn(ctx context.Context, field graphql.CollectedField, obj *models.UserSecret) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "UserSecret", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "UserSecret", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.UpdatedOn, nil @@ -14582,34 +11884,32 @@ func (ec *executionContext) _UserSecret_updatedOn(ctx context.Context, field gra return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(time.Time) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Directive", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil @@ -14619,34 +11919,32 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Directive", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil @@ -14659,28 +11957,26 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Directive", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Locations, nil @@ -14690,34 +11986,32 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalN__DirectiveLocation2ᚕstring(ctx, field.Selections, res) + fc.Result = res + return ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Directive", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Args, nil @@ -14727,34 +12021,32 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]introspection.InputValue) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, field.Selections, res) + fc.Result = res + return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__EnumValue", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil @@ -14764,34 +12056,32 @@ func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__EnumValue", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil @@ -14804,28 +12094,26 @@ func (ec *executionContext) ___EnumValue_description(ctx context.Context, field return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__EnumValue", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.IsDeprecated(), nil @@ -14835,34 +12123,32 @@ func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__EnumValue", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.DeprecationReason(), nil @@ -14875,28 +12161,26 @@ func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, return graphql.Null } res := resTmp.(*string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Field", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil @@ -14906,34 +12190,32 @@ func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.Col return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Field", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil @@ -14946,28 +12228,26 @@ func (ec *executionContext) ___Field_description(ctx context.Context, field grap return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Field", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Args, nil @@ -14977,34 +12257,32 @@ func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.Col return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]introspection.InputValue) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, field.Selections, res) + fc.Result = res + return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Field", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Type, nil @@ -15014,34 +12292,32 @@ func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.Col return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(*introspection.Type) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Field", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.IsDeprecated(), nil @@ -15051,34 +12327,32 @@ func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field gra return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(bool) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNBoolean2bool(ctx, field.Selections, res) } func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Field", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.DeprecationReason(), nil @@ -15091,28 +12365,26 @@ func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, fiel return graphql.Null } res := resTmp.(*string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__InputValue", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name, nil @@ -15122,34 +12394,32 @@ func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalNString2string(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__InputValue", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description, nil @@ -15162,28 +12432,26 @@ func (ec *executionContext) ___InputValue_description(ctx context.Context, field return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__InputValue", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Type, nil @@ -15193,34 +12461,32 @@ func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(*introspection.Type) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__InputValue", - Field: field, - Args: nil, - IsMethod: false, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.DefaultValue, nil @@ -15233,28 +12499,26 @@ func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, fiel return graphql.Null } res := resTmp.(*string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Schema", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Types(), nil @@ -15264,34 +12528,32 @@ func (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.C return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]introspection.Type) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) + fc.Result = res + return ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Schema", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.QueryType(), nil @@ -15301,34 +12563,32 @@ func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graph return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(*introspection.Type) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Schema", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.MutationType(), nil @@ -15341,28 +12601,26 @@ func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field gr return graphql.Null } res := resTmp.(*introspection.Type) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Schema", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.SubscriptionType(), nil @@ -15375,28 +12633,26 @@ func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, fiel return graphql.Null } res := resTmp.(*introspection.Type) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } func (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Schema", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Directives(), nil @@ -15406,34 +12662,32 @@ func (ec *executionContext) ___Schema_directives(ctx context.Context, field grap return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.([]introspection.Directive) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, field.Selections, res) + fc.Result = res + return ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Type", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Kind(), nil @@ -15443,34 +12697,32 @@ func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.Coll return graphql.Null } if resTmp == nil { - if !ec.HasError(rctx) { + if !graphql.HasFieldError(ctx, fc) { ec.Errorf(ctx, "must not be null") } return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalN__TypeKind2string(ctx, field.Selections, res) } func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Type", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Name(), nil @@ -15483,28 +12735,26 @@ func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.Coll return graphql.Null } res := resTmp.(*string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Type", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Description(), nil @@ -15517,35 +12767,33 @@ func (ec *executionContext) ___Type_description(ctx context.Context, field graph return graphql.Null } res := resTmp.(string) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) + fc.Result = res return ec.marshalOString2string(ctx, field.Selections, res) } func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Type", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field___Type_fields_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Fields(args["includeDeprecated"].(bool)), nil @@ -15558,28 +12806,26 @@ func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.Co return graphql.Null } res := resTmp.([]introspection.Field) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, field.Selections, res) + fc.Result = res + return ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Type", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.Interfaces(), nil @@ -15592,28 +12838,26 @@ func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphq return graphql.Null } res := resTmp.([]introspection.Type) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) + fc.Result = res + return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Type", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.PossibleTypes(), nil @@ -15626,35 +12870,33 @@ func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field gra return graphql.Null } res := resTmp.([]introspection.Type) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) + fc.Result = res + return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Type", - Field: field, - Args: nil, - IsMethod: true, + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, } - ctx = graphql.WithResolverContext(ctx, rctx) + + ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) args, err := ec.field___Type_enumValues_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null } - rctx.Args = args - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children return obj.EnumValues(args["includeDeprecated"].(bool)), nil @@ -15667,65 +12909,29 @@ func (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphq return graphql.Null } res := resTmp.([]introspection.EnumValue) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, field.Selections, res) + fc.Result = res + return ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res) } func (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) ret = graphql.Null } - ec.Tracer.EndFieldExecution(ctx) }() - rctx := &graphql.ResolverContext{ - Object: "__Type", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.InputFields(), nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, } - res := resTmp.([]introspection.InputValue) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, field.Selections, res) -} -func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { - ctx = ec.Tracer.StartFieldExecution(ctx, field) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - ec.Tracer.EndFieldExecution(ctx) - }() - rctx := &graphql.ResolverContext{ - Object: "__Type", - Field: field, - Args: nil, - IsMethod: true, - } - ctx = graphql.WithResolverContext(ctx, rctx) - ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.OfType(), nil + return obj.InputFields(), nil }) if err != nil { ec.Error(ctx, err) @@ -15734,403 +12940,80 @@ func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.Co if resTmp == nil { return graphql.Null } - res := resTmp.(*introspection.Type) - rctx.Result = res - ctx = ec.Tracer.StartFieldChildExecution(ctx) - return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) -} - -// endregion **************************** field.gotpl ***************************** - -// region **************************** input.gotpl ***************************** - -// endregion **************************** input.gotpl ***************************** - -// region ************************** interface.gotpl *************************** - -func (ec *executionContext) _Organization(ctx context.Context, sel ast.SelectionSet, obj *Organization) graphql.Marshaler { - switch obj := (*obj).(type) { - case nil: - return graphql.Null - case *entity.Organization: - return ec._PublicOrganization(ctx, sel, obj) - case PrivateOrganization: - return ec._PrivateOrganization(ctx, sel, &obj) - case *PrivateOrganization: - return ec._PrivateOrganization(ctx, sel, obj) - default: - panic(fmt.Errorf("unexpected type %T", obj)) - } -} - -// endregion ************************** interface.gotpl *************************** - -// region **************************** object.gotpl **************************** - -var billedResourceImplementors = []string{"BilledResource"} - -func (ec *executionContext) _BilledResource(ctx context.Context, sel ast.SelectionSet, obj *entity.BilledResource) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, billedResourceImplementors) - - out := graphql.NewFieldSet(fields) - var invalids uint32 - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("BilledResource") - case "billedResourceID": - out.Values[i] = ec._BilledResource_billedResourceID(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "organizationID": - out.Values[i] = ec._BilledResource_organizationID(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "billingTime": - out.Values[i] = ec._BilledResource_billingTime(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "entityID": - out.Values[i] = ec._BilledResource_entityID(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "entityKind": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._BilledResource_entityKind(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - case "startTime": - out.Values[i] = ec._BilledResource_startTime(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "endTime": - out.Values[i] = ec._BilledResource_endTime(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "product": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._BilledResource_product(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - case "quantity": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._BilledResource_quantity(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - case "totalPriceCents": - out.Values[i] = ec._BilledResource_totalPriceCents(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "currency": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._BilledResource_currency(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - case "createdOn": - out.Values[i] = ec._BilledResource_createdOn(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "updatedOn": - out.Values[i] = ec._BilledResource_updatedOn(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch() - if invalids > 0 { - return graphql.Null - } - return out -} - -var billingInfoImplementors = []string{"BillingInfo"} - -func (ec *executionContext) _BillingInfo(ctx context.Context, sel ast.SelectionSet, obj *entity.BillingInfo) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, billingInfoImplementors) - - out := graphql.NewFieldSet(fields) - var invalids uint32 - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("BillingInfo") - case "organizationID": - out.Values[i] = ec._BillingInfo_organizationID(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } - case "billingMethod": - out.Values[i] = ec._BillingInfo_billingMethod(ctx, field, obj) - case "billingPlan": - out.Values[i] = ec._BillingInfo_billingPlan(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } - case "country": - out.Values[i] = ec._BillingInfo_country(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } - case "region": - out.Values[i] = ec._BillingInfo_region(ctx, field, obj) - case "companyName": - out.Values[i] = ec._BillingInfo_companyName(ctx, field, obj) - case "taxNumber": - out.Values[i] = ec._BillingInfo_taxNumber(ctx, field, obj) - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch() - if invalids > 0 { - return graphql.Null - } - return out + res := resTmp.([]introspection.InputValue) + fc.Result = res + return ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) } -var billingMethodImplementors = []string{"BillingMethod"} - -func (ec *executionContext) _BillingMethod(ctx context.Context, sel ast.SelectionSet, obj *entity.BillingMethod) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, billingMethodImplementors) - - out := graphql.NewFieldSet(fields) - var invalids uint32 - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("BillingMethod") - case "billingMethodID": - out.Values[i] = ec._BillingMethod_billingMethodID(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "organizationID": - out.Values[i] = ec._BillingMethod_organizationID(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "paymentsDriver": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._BillingMethod_paymentsDriver(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - case "driverPayload": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._BillingMethod_driverPayload(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - default: - panic("unknown field " + strconv.Quote(field.Name)) +func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, } - out.Dispatch() - if invalids > 0 { + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.OfType(), nil + }) + if err != nil { + ec.Error(ctx, err) return graphql.Null } - return out + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } -var billingPlanImplementors = []string{"BillingPlan"} +// endregion **************************** field.gotpl ***************************** -func (ec *executionContext) _BillingPlan(ctx context.Context, sel ast.SelectionSet, obj *entity.BillingPlan) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, billingPlanImplementors) +// region **************************** input.gotpl ***************************** - out := graphql.NewFieldSet(fields) - var invalids uint32 - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("BillingPlan") - case "billingPlanID": - out.Values[i] = ec._BillingPlan_billingPlanID(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "default": - out.Values[i] = ec._BillingPlan_default(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "description": - out.Values[i] = ec._BillingPlan_description(ctx, field, obj) - case "currency": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._BillingPlan_currency(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - case "period": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._BillingPlan_period(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - case "seatPriceCents": - out.Values[i] = ec._BillingPlan_seatPriceCents(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "seatReadQuota": - out.Values[i] = ec._BillingPlan_seatReadQuota(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "seatWriteQuota": - out.Values[i] = ec._BillingPlan_seatWriteQuota(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "seatScanQuota": - out.Values[i] = ec._BillingPlan_seatScanQuota(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "readOveragePriceCents": - out.Values[i] = ec._BillingPlan_readOveragePriceCents(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "writeOveragePriceCents": - out.Values[i] = ec._BillingPlan_writeOveragePriceCents(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "scanOveragePriceCents": - out.Values[i] = ec._BillingPlan_scanOveragePriceCents(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "baseReadQuota": - out.Values[i] = ec._BillingPlan_baseReadQuota(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "baseWriteQuota": - out.Values[i] = ec._BillingPlan_baseWriteQuota(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "baseScanQuota": - out.Values[i] = ec._BillingPlan_baseScanQuota(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "readQuota": - out.Values[i] = ec._BillingPlan_readQuota(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "writeQuota": - out.Values[i] = ec._BillingPlan_writeQuota(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "scanQuota": - out.Values[i] = ec._BillingPlan_scanQuota(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "availableInUI": - out.Values[i] = ec._BillingPlan_availableInUI(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch() - if invalids > 0 { +// endregion **************************** input.gotpl ***************************** + +// region ************************** interface.gotpl *************************** + +func (ec *executionContext) _Organization(ctx context.Context, sel ast.SelectionSet, obj Organization) graphql.Marshaler { + switch obj := (obj).(type) { + case nil: return graphql.Null + case *models.Organization: + if obj == nil { + return graphql.Null + } + return ec._PublicOrganization(ctx, sel, obj) + case PrivateOrganization: + return ec._PrivateOrganization(ctx, sel, &obj) + case *PrivateOrganization: + if obj == nil { + return graphql.Null + } + return ec._PrivateOrganization(ctx, sel, obj) + default: + panic(fmt.Errorf("unexpected type %T", obj)) } - return out } +// endregion ************************** interface.gotpl *************************** + +// region **************************** object.gotpl **************************** + var metricsImplementors = []string{"Metrics"} func (ec *executionContext) _Metrics(ctx context.Context, sel ast.SelectionSet, obj *Metrics) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, metricsImplementors) + fields := graphql.CollectFields(ec.OperationContext, sel, metricsImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -16207,9 +13090,9 @@ func (ec *executionContext) _Metrics(ctx context.Context, sel ast.SelectionSet, var mutationImplementors = []string{"Mutation"} func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, mutationImplementors) + fields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors) - ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ Object: "Mutation", }) @@ -16221,11 +13104,6 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) out.Values[i] = graphql.MarshalString("Mutation") case "empty": out.Values[i] = ec._Mutation_empty(ctx, field) - case "updateBillingInfo": - out.Values[i] = ec._Mutation_updateBillingInfo(ctx, field) - if out.Values[i] == graphql.Null { - invalids++ - } case "createOrganization": out.Values[i] = ec._Mutation_createOrganization(ctx, field) if out.Values[i] == graphql.Null { @@ -16365,7 +13243,7 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) var newServiceSecretImplementors = []string{"NewServiceSecret"} func (ec *executionContext) _NewServiceSecret(ctx context.Context, sel ast.SelectionSet, obj *NewServiceSecret) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, newServiceSecretImplementors) + fields := graphql.CollectFields(ec.OperationContext, sel, newServiceSecretImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -16397,7 +13275,7 @@ func (ec *executionContext) _NewServiceSecret(ctx context.Context, sel ast.Selec var newUserSecretImplementors = []string{"NewUserSecret"} func (ec *executionContext) _NewUserSecret(ctx context.Context, sel ast.SelectionSet, obj *NewUserSecret) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, newUserSecretImplementors) + fields := graphql.CollectFields(ec.OperationContext, sel, newUserSecretImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -16428,8 +13306,8 @@ func (ec *executionContext) _NewUserSecret(ctx context.Context, sel ast.Selectio var organizationMemberImplementors = []string{"OrganizationMember"} -func (ec *executionContext) _OrganizationMember(ctx context.Context, sel ast.SelectionSet, obj *entity.OrganizationMember) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, organizationMemberImplementors) +func (ec *executionContext) _OrganizationMember(ctx context.Context, sel ast.SelectionSet, obj *models.OrganizationMember) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, organizationMemberImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -16516,8 +13394,8 @@ func (ec *executionContext) _OrganizationMember(ctx context.Context, sel ast.Sel var permissionsServicesStreamsImplementors = []string{"PermissionsServicesStreams"} -func (ec *executionContext) _PermissionsServicesStreams(ctx context.Context, sel ast.SelectionSet, obj *entity.PermissionsServicesStreams) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, permissionsServicesStreamsImplementors) +func (ec *executionContext) _PermissionsServicesStreams(ctx context.Context, sel ast.SelectionSet, obj *models.PermissionsServicesStreams) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, permissionsServicesStreamsImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -16558,8 +13436,8 @@ func (ec *executionContext) _PermissionsServicesStreams(ctx context.Context, sel var permissionsUsersOrganizationsImplementors = []string{"PermissionsUsersOrganizations"} -func (ec *executionContext) _PermissionsUsersOrganizations(ctx context.Context, sel ast.SelectionSet, obj *entity.PermissionsUsersOrganizations) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, permissionsUsersOrganizationsImplementors) +func (ec *executionContext) _PermissionsUsersOrganizations(ctx context.Context, sel ast.SelectionSet, obj *models.PermissionsUsersOrganizations) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, permissionsUsersOrganizationsImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -16605,8 +13483,8 @@ func (ec *executionContext) _PermissionsUsersOrganizations(ctx context.Context, var permissionsUsersProjectsImplementors = []string{"PermissionsUsersProjects"} -func (ec *executionContext) _PermissionsUsersProjects(ctx context.Context, sel ast.SelectionSet, obj *entity.PermissionsUsersProjects) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, permissionsUsersProjectsImplementors) +func (ec *executionContext) _PermissionsUsersProjects(ctx context.Context, sel ast.SelectionSet, obj *models.PermissionsUsersProjects) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, permissionsUsersProjectsImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -16653,7 +13531,7 @@ func (ec *executionContext) _PermissionsUsersProjects(ctx context.Context, sel a var privateOrganizationImplementors = []string{"PrivateOrganization", "Organization"} func (ec *executionContext) _PrivateOrganization(ctx context.Context, sel ast.SelectionSet, obj *PrivateOrganization) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, privateOrganizationImplementors) + fields := graphql.CollectFields(ec.OperationContext, sel, privateOrganizationImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -16744,8 +13622,8 @@ func (ec *executionContext) _PrivateOrganization(ctx context.Context, sel ast.Se var privateUserImplementors = []string{"PrivateUser"} -func (ec *executionContext) _PrivateUser(ctx context.Context, sel ast.SelectionSet, obj *entity.User) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, privateUserImplementors) +func (ec *executionContext) _PrivateUser(ctx context.Context, sel ast.SelectionSet, obj *models.User) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, privateUserImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -16821,8 +13699,8 @@ func (ec *executionContext) _PrivateUser(ctx context.Context, sel ast.SelectionS var projectImplementors = []string{"Project"} -func (ec *executionContext) _Project(ctx context.Context, sel ast.SelectionSet, obj *entity.Project) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, projectImplementors) +func (ec *executionContext) _Project(ctx context.Context, sel ast.SelectionSet, obj *models.Project) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, projectImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -16908,8 +13786,8 @@ func (ec *executionContext) _Project(ctx context.Context, sel ast.SelectionSet, var projectMemberImplementors = []string{"ProjectMember"} -func (ec *executionContext) _ProjectMember(ctx context.Context, sel ast.SelectionSet, obj *entity.ProjectMember) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, projectMemberImplementors) +func (ec *executionContext) _ProjectMember(ctx context.Context, sel ast.SelectionSet, obj *models.ProjectMember) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, projectMemberImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -16985,8 +13863,8 @@ func (ec *executionContext) _ProjectMember(ctx context.Context, sel ast.Selectio var publicOrganizationImplementors = []string{"PublicOrganization", "Organization"} -func (ec *executionContext) _PublicOrganization(ctx context.Context, sel ast.SelectionSet, obj *entity.Organization) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, publicOrganizationImplementors) +func (ec *executionContext) _PublicOrganization(ctx context.Context, sel ast.SelectionSet, obj *models.Organization) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, publicOrganizationImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -17021,94 +13899,18 @@ func (ec *executionContext) _PublicOrganization(ctx context.Context, sel ast.Sel case "description": out.Values[i] = ec._PublicOrganization_description(ctx, field, obj) case "photoURL": - out.Values[i] = ec._PublicOrganization_photoURL(ctx, field, obj) - case "createdOn": - out.Values[i] = ec._PublicOrganization_createdOn(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "projects": - out.Values[i] = ec._PublicOrganization_projects(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "personalUserID": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._PublicOrganization_personalUserID(ctx, field, obj) - return res - }) - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch() - if invalids > 0 { - return graphql.Null - } - return out -} - -var queryImplementors = []string{"Query"} - -func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, queryImplementors) - - ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ - Object: "Query", - }) - - out := graphql.NewFieldSet(fields) - var invalids uint32 - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("Query") - case "empty": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_empty(ctx, field) - return res - }) - case "ping": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_ping(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - case "billedResources": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_billedResources(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - case "billingInfo": + out.Values[i] = ec._PublicOrganization_photoURL(ctx, field, obj) + case "createdOn": + out.Values[i] = ec._PublicOrganization_createdOn(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "projects": + out.Values[i] = ec._PublicOrganization_projects(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "personalUserID": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { @@ -17116,13 +13918,36 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_billingInfo(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } + res = ec._PublicOrganization_personalUserID(ctx, field, obj) return res }) - case "billingMethods": + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var queryImplementors = []string{"Query"} + +func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, queryImplementors) + + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Query", + }) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Query") + case "empty": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { @@ -17130,13 +13955,10 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_billingMethods(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } + res = ec._Query_empty(ctx, field) return res }) - case "billingPlans": + case "ping": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { @@ -17144,7 +13966,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_billingPlans(ctx, field) + res = ec._Query_ping(ctx, field) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } @@ -17494,8 +14316,8 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr var serviceImplementors = []string{"Service"} -func (ec *executionContext) _Service(ctx context.Context, sel ast.SelectionSet, obj *entity.Service) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, serviceImplementors) +func (ec *executionContext) _Service(ctx context.Context, sel ast.SelectionSet, obj *models.Service) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, serviceImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -17551,8 +14373,8 @@ func (ec *executionContext) _Service(ctx context.Context, sel ast.SelectionSet, var serviceSecretImplementors = []string{"ServiceSecret"} -func (ec *executionContext) _ServiceSecret(ctx context.Context, sel ast.SelectionSet, obj *entity.ServiceSecret) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, serviceSecretImplementors) +func (ec *executionContext) _ServiceSecret(ctx context.Context, sel ast.SelectionSet, obj *models.ServiceSecret) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, serviceSecretImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -17612,8 +14434,8 @@ func (ec *executionContext) _ServiceSecret(ctx context.Context, sel ast.Selectio var streamImplementors = []string{"Stream"} -func (ec *executionContext) _Stream(ctx context.Context, sel ast.SelectionSet, obj *entity.Stream) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, streamImplementors) +func (ec *executionContext) _Stream(ctx context.Context, sel ast.SelectionSet, obj *models.Stream) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, streamImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -17759,8 +14581,8 @@ func (ec *executionContext) _Stream(ctx context.Context, sel ast.SelectionSet, o var streamIndexImplementors = []string{"StreamIndex"} -func (ec *executionContext) _StreamIndex(ctx context.Context, sel ast.SelectionSet, obj *entity.StreamIndex) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, streamIndexImplementors) +func (ec *executionContext) _StreamIndex(ctx context.Context, sel ast.SelectionSet, obj *models.StreamIndex) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, streamIndexImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -17810,8 +14632,8 @@ func (ec *executionContext) _StreamIndex(ctx context.Context, sel ast.SelectionS var streamInstanceImplementors = []string{"StreamInstance"} -func (ec *executionContext) _StreamInstance(ctx context.Context, sel ast.SelectionSet, obj *entity.StreamInstance) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, streamInstanceImplementors) +func (ec *executionContext) _StreamInstance(ctx context.Context, sel ast.SelectionSet, obj *models.StreamInstance) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, streamInstanceImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -17866,8 +14688,8 @@ func (ec *executionContext) _StreamInstance(ctx context.Context, sel ast.Selecti var subscriptionImplementors = []string{"Subscription"} func (ec *executionContext) _Subscription(ctx context.Context, sel ast.SelectionSet) func() graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, subscriptionImplementors) - ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{ + fields := graphql.CollectFields(ec.OperationContext, sel, subscriptionImplementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ Object: "Subscription", }) if len(fields) != 1 { @@ -17885,8 +14707,8 @@ func (ec *executionContext) _Subscription(ctx context.Context, sel ast.Selection var userSecretImplementors = []string{"UserSecret"} -func (ec *executionContext) _UserSecret(ctx context.Context, sel ast.SelectionSet, obj *entity.UserSecret) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, userSecretImplementors) +func (ec *executionContext) _UserSecret(ctx context.Context, sel ast.SelectionSet, obj *models.UserSecret) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, userSecretImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -17952,7 +14774,7 @@ func (ec *executionContext) _UserSecret(ctx context.Context, sel ast.SelectionSe var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, __DirectiveImplementors) + fields := graphql.CollectFields(ec.OperationContext, sel, __DirectiveImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -17991,7 +14813,7 @@ func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionS var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, __EnumValueImplementors) + fields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -18027,7 +14849,7 @@ func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionS var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, __FieldImplementors) + fields := graphql.CollectFields(ec.OperationContext, sel, __FieldImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -18073,7 +14895,7 @@ func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, __InputValueImplementors) + fields := graphql.CollectFields(ec.OperationContext, sel, __InputValueImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -18109,7 +14931,7 @@ func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.Selection var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, __SchemaImplementors) + fields := graphql.CollectFields(ec.OperationContext, sel, __SchemaImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -18150,7 +14972,7 @@ func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { - fields := graphql.CollectFields(ec.RequestContext, sel, __TypeImplementors) + fields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 @@ -18194,218 +15016,40 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o // region ***************************** type.gotpl ***************************** -func (ec *executionContext) marshalNBilledResource2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBilledResource(ctx context.Context, sel ast.SelectionSet, v entity.BilledResource) graphql.Marshaler { - return ec._BilledResource(ctx, sel, &v) -} - -func (ec *executionContext) marshalNBilledResource2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBilledResource(ctx context.Context, sel ast.SelectionSet, v []*entity.BilledResource) graphql.Marshaler { - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - rctx := &graphql.ResolverContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithResolverContext(ctx, rctx) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNBilledResource2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBilledResource(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - return ret -} - -func (ec *executionContext) marshalNBilledResource2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBilledResource(ctx context.Context, sel ast.SelectionSet, v *entity.BilledResource) graphql.Marshaler { - if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - return ec._BilledResource(ctx, sel, v) -} - -func (ec *executionContext) marshalNBillingInfo2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingInfo(ctx context.Context, sel ast.SelectionSet, v entity.BillingInfo) graphql.Marshaler { - return ec._BillingInfo(ctx, sel, &v) -} - -func (ec *executionContext) marshalNBillingInfo2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingInfo(ctx context.Context, sel ast.SelectionSet, v *entity.BillingInfo) graphql.Marshaler { - if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - return ec._BillingInfo(ctx, sel, v) -} - -func (ec *executionContext) marshalNBillingMethod2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingMethod(ctx context.Context, sel ast.SelectionSet, v entity.BillingMethod) graphql.Marshaler { - return ec._BillingMethod(ctx, sel, &v) -} - -func (ec *executionContext) marshalNBillingMethod2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingMethod(ctx context.Context, sel ast.SelectionSet, v []*entity.BillingMethod) graphql.Marshaler { - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - rctx := &graphql.ResolverContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithResolverContext(ctx, rctx) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNBillingMethod2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingMethod(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - return ret -} - -func (ec *executionContext) marshalNBillingMethod2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingMethod(ctx context.Context, sel ast.SelectionSet, v *entity.BillingMethod) graphql.Marshaler { - if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - return ec._BillingMethod(ctx, sel, v) -} - -func (ec *executionContext) marshalNBillingPlan2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingPlan(ctx context.Context, sel ast.SelectionSet, v entity.BillingPlan) graphql.Marshaler { - return ec._BillingPlan(ctx, sel, &v) -} - -func (ec *executionContext) marshalNBillingPlan2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingPlan(ctx context.Context, sel ast.SelectionSet, v []*entity.BillingPlan) graphql.Marshaler { - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - rctx := &graphql.ResolverContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithResolverContext(ctx, rctx) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNBillingPlan2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingPlan(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - return ret -} - -func (ec *executionContext) marshalNBillingPlan2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingPlan(ctx context.Context, sel ast.SelectionSet, v *entity.BillingPlan) graphql.Marshaler { - if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - return ec._BillingPlan(ctx, sel, v) -} - func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) { - return graphql.UnmarshalBoolean(v) + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { res := graphql.MarshalBoolean(v) if res == graphql.Null { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } return res } -func (ec *executionContext) unmarshalNEntityKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐEntityKind(ctx context.Context, v interface{}) (EntityKind, error) { +func (ec *executionContext) unmarshalNEntityKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐEntityKind(ctx context.Context, v interface{}) (EntityKind, error) { var res EntityKind - return res, res.UnmarshalGQL(v) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNEntityKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐEntityKind(ctx context.Context, sel ast.SelectionSet, v EntityKind) graphql.Marshaler { +func (ec *executionContext) marshalNEntityKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐEntityKind(ctx context.Context, sel ast.SelectionSet, v EntityKind) graphql.Marshaler { return v } -func (ec *executionContext) unmarshalNFloat2float64(ctx context.Context, v interface{}) (float64, error) { - return graphql.UnmarshalFloat(v) -} - -func (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.SelectionSet, v float64) graphql.Marshaler { - res := graphql.MarshalFloat(v) - if res == graphql.Null { - if !ec.HasError(graphql.GetResolverContext(ctx)) { - ec.Errorf(ctx, "must not be null") - } - } - return res -} - func (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) { - return graphql.UnmarshalID(v) + res, err := graphql.UnmarshalID(v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { res := graphql.MarshalID(v) if res == graphql.Null { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } @@ -18413,13 +15057,14 @@ func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.Selec } func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) { - return graphql.UnmarshalInt(v) + res, err := graphql.UnmarshalInt(v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { res := graphql.MarshalInt(v) if res == graphql.Null { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } @@ -18427,38 +15072,21 @@ func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.Selecti } func (ec *executionContext) unmarshalNInt2int32(ctx context.Context, v interface{}) (int32, error) { - return graphql.UnmarshalInt32(v) + res, err := graphql.UnmarshalInt32(v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalNInt2int32(ctx context.Context, sel ast.SelectionSet, v int32) graphql.Marshaler { res := graphql.MarshalInt32(v) if res == graphql.Null { - if !ec.HasError(graphql.GetResolverContext(ctx)) { - ec.Errorf(ctx, "must not be null") - } - } - return res -} - -func (ec *executionContext) unmarshalNInt2int64(ctx context.Context, v interface{}) (int64, error) { - return graphql.UnmarshalInt64(v) -} - -func (ec *executionContext) marshalNInt2int64(ctx context.Context, sel ast.SelectionSet, v int64) graphql.Marshaler { - res := graphql.MarshalInt64(v) - if res == graphql.Null { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } return res } -func (ec *executionContext) marshalNMetrics2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐMetrics(ctx context.Context, sel ast.SelectionSet, v Metrics) graphql.Marshaler { - return ec._Metrics(ctx, sel, &v) -} - -func (ec *executionContext) marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐMetrics(ctx context.Context, sel ast.SelectionSet, v []*Metrics) graphql.Marshaler { +func (ec *executionContext) marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐMetricsᚄ(ctx context.Context, sel ast.SelectionSet, v []*Metrics) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -18467,11 +15095,11 @@ func (ec *executionContext) marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋ } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -18482,7 +15110,7 @@ func (ec *executionContext) marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋ if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNMetrics2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐMetrics(ctx, sel, v[i]) + ret[i] = ec.marshalNMetrics2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐMetrics(ctx, sel, v[i]) } if isLen1 { f(i) @@ -18495,9 +15123,9 @@ func (ec *executionContext) marshalNMetrics2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋ return ret } -func (ec *executionContext) marshalNMetrics2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐMetrics(ctx context.Context, sel ast.SelectionSet, v *Metrics) graphql.Marshaler { +func (ec *executionContext) marshalNMetrics2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐMetrics(ctx context.Context, sel ast.SelectionSet, v *Metrics) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18505,13 +15133,13 @@ func (ec *executionContext) marshalNMetrics2ᚖgitlabᚗcomᚋbeneathᚑhqᚋben return ec._Metrics(ctx, sel, v) } -func (ec *executionContext) marshalNNewServiceSecret2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐNewServiceSecret(ctx context.Context, sel ast.SelectionSet, v NewServiceSecret) graphql.Marshaler { +func (ec *executionContext) marshalNNewServiceSecret2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐNewServiceSecret(ctx context.Context, sel ast.SelectionSet, v NewServiceSecret) graphql.Marshaler { return ec._NewServiceSecret(ctx, sel, &v) } -func (ec *executionContext) marshalNNewServiceSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐNewServiceSecret(ctx context.Context, sel ast.SelectionSet, v *NewServiceSecret) graphql.Marshaler { +func (ec *executionContext) marshalNNewServiceSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐNewServiceSecret(ctx context.Context, sel ast.SelectionSet, v *NewServiceSecret) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18519,13 +15147,13 @@ func (ec *executionContext) marshalNNewServiceSecret2ᚖgitlabᚗcomᚋbeneath return ec._NewServiceSecret(ctx, sel, v) } -func (ec *executionContext) marshalNNewUserSecret2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐNewUserSecret(ctx context.Context, sel ast.SelectionSet, v NewUserSecret) graphql.Marshaler { +func (ec *executionContext) marshalNNewUserSecret2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐNewUserSecret(ctx context.Context, sel ast.SelectionSet, v NewUserSecret) graphql.Marshaler { return ec._NewUserSecret(ctx, sel, &v) } -func (ec *executionContext) marshalNNewUserSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐNewUserSecret(ctx context.Context, sel ast.SelectionSet, v *NewUserSecret) graphql.Marshaler { +func (ec *executionContext) marshalNNewUserSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐNewUserSecret(ctx context.Context, sel ast.SelectionSet, v *NewUserSecret) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18533,15 +15161,17 @@ func (ec *executionContext) marshalNNewUserSecret2ᚖgitlabᚗcomᚋbeneathᚑhq return ec._NewUserSecret(ctx, sel, v) } -func (ec *executionContext) marshalNOrganization2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐOrganization(ctx context.Context, sel ast.SelectionSet, v Organization) graphql.Marshaler { - return ec._Organization(ctx, sel, &v) -} - -func (ec *executionContext) marshalNOrganizationMember2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐOrganizationMember(ctx context.Context, sel ast.SelectionSet, v entity.OrganizationMember) graphql.Marshaler { - return ec._OrganizationMember(ctx, sel, &v) +func (ec *executionContext) marshalNOrganization2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐOrganization(ctx context.Context, sel ast.SelectionSet, v Organization) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._Organization(ctx, sel, v) } -func (ec *executionContext) marshalNOrganizationMember2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐOrganizationMember(ctx context.Context, sel ast.SelectionSet, v []*entity.OrganizationMember) graphql.Marshaler { +func (ec *executionContext) marshalNOrganizationMember2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐOrganizationMemberᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.OrganizationMember) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -18550,11 +15180,11 @@ func (ec *executionContext) marshalNOrganizationMember2ᚕᚖgitlabᚗcomᚋbene } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -18565,7 +15195,7 @@ func (ec *executionContext) marshalNOrganizationMember2ᚕᚖgitlabᚗcomᚋbene if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNOrganizationMember2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐOrganizationMember(ctx, sel, v[i]) + ret[i] = ec.marshalNOrganizationMember2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐOrganizationMember(ctx, sel, v[i]) } if isLen1 { f(i) @@ -18578,9 +15208,9 @@ func (ec *executionContext) marshalNOrganizationMember2ᚕᚖgitlabᚗcomᚋbene return ret } -func (ec *executionContext) marshalNOrganizationMember2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐOrganizationMember(ctx context.Context, sel ast.SelectionSet, v *entity.OrganizationMember) graphql.Marshaler { +func (ec *executionContext) marshalNOrganizationMember2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐOrganizationMember(ctx context.Context, sel ast.SelectionSet, v *models.OrganizationMember) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18588,13 +15218,13 @@ func (ec *executionContext) marshalNOrganizationMember2ᚖgitlabᚗcomᚋbeneath return ec._OrganizationMember(ctx, sel, v) } -func (ec *executionContext) marshalNPermissionsServicesStreams2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐPermissionsServicesStreams(ctx context.Context, sel ast.SelectionSet, v entity.PermissionsServicesStreams) graphql.Marshaler { +func (ec *executionContext) marshalNPermissionsServicesStreams2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐPermissionsServicesStreams(ctx context.Context, sel ast.SelectionSet, v models.PermissionsServicesStreams) graphql.Marshaler { return ec._PermissionsServicesStreams(ctx, sel, &v) } -func (ec *executionContext) marshalNPermissionsServicesStreams2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐPermissionsServicesStreams(ctx context.Context, sel ast.SelectionSet, v *entity.PermissionsServicesStreams) graphql.Marshaler { +func (ec *executionContext) marshalNPermissionsServicesStreams2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐPermissionsServicesStreams(ctx context.Context, sel ast.SelectionSet, v *models.PermissionsServicesStreams) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18602,13 +15232,13 @@ func (ec *executionContext) marshalNPermissionsServicesStreams2ᚖgitlabᚗcom return ec._PermissionsServicesStreams(ctx, sel, v) } -func (ec *executionContext) marshalNPermissionsUsersOrganizations2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐPermissionsUsersOrganizations(ctx context.Context, sel ast.SelectionSet, v entity.PermissionsUsersOrganizations) graphql.Marshaler { +func (ec *executionContext) marshalNPermissionsUsersOrganizations2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐPermissionsUsersOrganizations(ctx context.Context, sel ast.SelectionSet, v models.PermissionsUsersOrganizations) graphql.Marshaler { return ec._PermissionsUsersOrganizations(ctx, sel, &v) } -func (ec *executionContext) marshalNPermissionsUsersOrganizations2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐPermissionsUsersOrganizations(ctx context.Context, sel ast.SelectionSet, v *entity.PermissionsUsersOrganizations) graphql.Marshaler { +func (ec *executionContext) marshalNPermissionsUsersOrganizations2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐPermissionsUsersOrganizations(ctx context.Context, sel ast.SelectionSet, v *models.PermissionsUsersOrganizations) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18616,13 +15246,13 @@ func (ec *executionContext) marshalNPermissionsUsersOrganizations2ᚖgitlabᚗco return ec._PermissionsUsersOrganizations(ctx, sel, v) } -func (ec *executionContext) marshalNPermissionsUsersProjects2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐPermissionsUsersProjects(ctx context.Context, sel ast.SelectionSet, v entity.PermissionsUsersProjects) graphql.Marshaler { +func (ec *executionContext) marshalNPermissionsUsersProjects2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐPermissionsUsersProjects(ctx context.Context, sel ast.SelectionSet, v models.PermissionsUsersProjects) graphql.Marshaler { return ec._PermissionsUsersProjects(ctx, sel, &v) } -func (ec *executionContext) marshalNPermissionsUsersProjects2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐPermissionsUsersProjects(ctx context.Context, sel ast.SelectionSet, v *entity.PermissionsUsersProjects) graphql.Marshaler { +func (ec *executionContext) marshalNPermissionsUsersProjects2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐPermissionsUsersProjects(ctx context.Context, sel ast.SelectionSet, v *models.PermissionsUsersProjects) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18630,13 +15260,13 @@ func (ec *executionContext) marshalNPermissionsUsersProjects2ᚖgitlabᚗcomᚋb return ec._PermissionsUsersProjects(ctx, sel, v) } -func (ec *executionContext) marshalNPrivateOrganization2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐPrivateOrganization(ctx context.Context, sel ast.SelectionSet, v PrivateOrganization) graphql.Marshaler { +func (ec *executionContext) marshalNPrivateOrganization2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐPrivateOrganization(ctx context.Context, sel ast.SelectionSet, v PrivateOrganization) graphql.Marshaler { return ec._PrivateOrganization(ctx, sel, &v) } -func (ec *executionContext) marshalNPrivateOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐPrivateOrganization(ctx context.Context, sel ast.SelectionSet, v *PrivateOrganization) graphql.Marshaler { +func (ec *executionContext) marshalNPrivateOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐPrivateOrganization(ctx context.Context, sel ast.SelectionSet, v *PrivateOrganization) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18644,13 +15274,13 @@ func (ec *executionContext) marshalNPrivateOrganization2ᚖgitlabᚗcomᚋbeneat return ec._PrivateOrganization(ctx, sel, v) } -func (ec *executionContext) marshalNPrivateUser2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUser(ctx context.Context, sel ast.SelectionSet, v entity.User) graphql.Marshaler { +func (ec *executionContext) marshalNPrivateUser2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐUser(ctx context.Context, sel ast.SelectionSet, v models.User) graphql.Marshaler { return ec._PrivateUser(ctx, sel, &v) } -func (ec *executionContext) marshalNPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUser(ctx context.Context, sel ast.SelectionSet, v *entity.User) graphql.Marshaler { +func (ec *executionContext) marshalNPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐUser(ctx context.Context, sel ast.SelectionSet, v *models.User) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18658,11 +15288,11 @@ func (ec *executionContext) marshalNPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhq return ec._PrivateUser(ctx, sel, v) } -func (ec *executionContext) marshalNProject2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx context.Context, sel ast.SelectionSet, v entity.Project) graphql.Marshaler { +func (ec *executionContext) marshalNProject2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProject(ctx context.Context, sel ast.SelectionSet, v models.Project) graphql.Marshaler { return ec._Project(ctx, sel, &v) } -func (ec *executionContext) marshalNProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx context.Context, sel ast.SelectionSet, v []*entity.Project) graphql.Marshaler { +func (ec *executionContext) marshalNProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProjectᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.Project) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -18671,11 +15301,11 @@ func (ec *executionContext) marshalNProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋ } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -18686,7 +15316,7 @@ func (ec *executionContext) marshalNProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋ if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx, sel, v[i]) + ret[i] = ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProject(ctx, sel, v[i]) } if isLen1 { f(i) @@ -18699,9 +15329,9 @@ func (ec *executionContext) marshalNProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋ return ret } -func (ec *executionContext) marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx context.Context, sel ast.SelectionSet, v *entity.Project) graphql.Marshaler { +func (ec *executionContext) marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProject(ctx context.Context, sel ast.SelectionSet, v *models.Project) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18709,11 +15339,7 @@ func (ec *executionContext) marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋben return ec._Project(ctx, sel, v) } -func (ec *executionContext) marshalNProjectMember2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProjectMember(ctx context.Context, sel ast.SelectionSet, v entity.ProjectMember) graphql.Marshaler { - return ec._ProjectMember(ctx, sel, &v) -} - -func (ec *executionContext) marshalNProjectMember2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProjectMember(ctx context.Context, sel ast.SelectionSet, v []*entity.ProjectMember) graphql.Marshaler { +func (ec *executionContext) marshalNProjectMember2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProjectMemberᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.ProjectMember) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -18722,11 +15348,11 @@ func (ec *executionContext) marshalNProjectMember2ᚕᚖgitlabᚗcomᚋbeneath } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -18737,7 +15363,7 @@ func (ec *executionContext) marshalNProjectMember2ᚕᚖgitlabᚗcomᚋbeneath if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNProjectMember2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProjectMember(ctx, sel, v[i]) + ret[i] = ec.marshalNProjectMember2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProjectMember(ctx, sel, v[i]) } if isLen1 { f(i) @@ -18750,9 +15376,9 @@ func (ec *executionContext) marshalNProjectMember2ᚕᚖgitlabᚗcomᚋbeneath return ret } -func (ec *executionContext) marshalNProjectMember2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProjectMember(ctx context.Context, sel ast.SelectionSet, v *entity.ProjectMember) graphql.Marshaler { +func (ec *executionContext) marshalNProjectMember2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProjectMember(ctx context.Context, sel ast.SelectionSet, v *models.ProjectMember) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18760,13 +15386,9 @@ func (ec *executionContext) marshalNProjectMember2ᚖgitlabᚗcomᚋbeneathᚑhq return ec._ProjectMember(ctx, sel, v) } -func (ec *executionContext) marshalNPublicOrganization2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐOrganization(ctx context.Context, sel ast.SelectionSet, v entity.Organization) graphql.Marshaler { - return ec._PublicOrganization(ctx, sel, &v) -} - -func (ec *executionContext) marshalNPublicOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐOrganization(ctx context.Context, sel ast.SelectionSet, v *entity.Organization) graphql.Marshaler { +func (ec *executionContext) marshalNPublicOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐOrganization(ctx context.Context, sel ast.SelectionSet, v *models.Organization) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18774,11 +15396,11 @@ func (ec *executionContext) marshalNPublicOrganization2ᚖgitlabᚗcomᚋbeneath return ec._PublicOrganization(ctx, sel, v) } -func (ec *executionContext) marshalNService2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐService(ctx context.Context, sel ast.SelectionSet, v entity.Service) graphql.Marshaler { +func (ec *executionContext) marshalNService2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐService(ctx context.Context, sel ast.SelectionSet, v models.Service) graphql.Marshaler { return ec._Service(ctx, sel, &v) } -func (ec *executionContext) marshalNService2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐService(ctx context.Context, sel ast.SelectionSet, v []*entity.Service) graphql.Marshaler { +func (ec *executionContext) marshalNService2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐServiceᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.Service) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -18787,11 +15409,11 @@ func (ec *executionContext) marshalNService2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋ } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -18802,7 +15424,7 @@ func (ec *executionContext) marshalNService2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋ if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐService(ctx, sel, v[i]) + ret[i] = ec.marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐService(ctx, sel, v[i]) } if isLen1 { f(i) @@ -18815,9 +15437,9 @@ func (ec *executionContext) marshalNService2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋ return ret } -func (ec *executionContext) marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐService(ctx context.Context, sel ast.SelectionSet, v *entity.Service) graphql.Marshaler { +func (ec *executionContext) marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐService(ctx context.Context, sel ast.SelectionSet, v *models.Service) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18825,11 +15447,7 @@ func (ec *executionContext) marshalNService2ᚖgitlabᚗcomᚋbeneathᚑhqᚋben return ec._Service(ctx, sel, v) } -func (ec *executionContext) marshalNServiceSecret2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐServiceSecret(ctx context.Context, sel ast.SelectionSet, v entity.ServiceSecret) graphql.Marshaler { - return ec._ServiceSecret(ctx, sel, &v) -} - -func (ec *executionContext) marshalNServiceSecret2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐServiceSecret(ctx context.Context, sel ast.SelectionSet, v []*entity.ServiceSecret) graphql.Marshaler { +func (ec *executionContext) marshalNServiceSecret2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐServiceSecretᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.ServiceSecret) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -18838,11 +15456,11 @@ func (ec *executionContext) marshalNServiceSecret2ᚕᚖgitlabᚗcomᚋbeneath } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -18853,7 +15471,7 @@ func (ec *executionContext) marshalNServiceSecret2ᚕᚖgitlabᚗcomᚋbeneath if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNServiceSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐServiceSecret(ctx, sel, v[i]) + ret[i] = ec.marshalNServiceSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐServiceSecret(ctx, sel, v[i]) } if isLen1 { f(i) @@ -18866,9 +15484,9 @@ func (ec *executionContext) marshalNServiceSecret2ᚕᚖgitlabᚗcomᚋbeneath return ret } -func (ec *executionContext) marshalNServiceSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐServiceSecret(ctx context.Context, sel ast.SelectionSet, v *entity.ServiceSecret) graphql.Marshaler { +func (ec *executionContext) marshalNServiceSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐServiceSecret(ctx context.Context, sel ast.SelectionSet, v *models.ServiceSecret) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18876,11 +15494,11 @@ func (ec *executionContext) marshalNServiceSecret2ᚖgitlabᚗcomᚋbeneathᚑhq return ec._ServiceSecret(ctx, sel, v) } -func (ec *executionContext) marshalNStream2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStream(ctx context.Context, sel ast.SelectionSet, v entity.Stream) graphql.Marshaler { +func (ec *executionContext) marshalNStream2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStream(ctx context.Context, sel ast.SelectionSet, v models.Stream) graphql.Marshaler { return ec._Stream(ctx, sel, &v) } -func (ec *executionContext) marshalNStream2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStream(ctx context.Context, sel ast.SelectionSet, v []*entity.Stream) graphql.Marshaler { +func (ec *executionContext) marshalNStream2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.Stream) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -18889,11 +15507,11 @@ func (ec *executionContext) marshalNStream2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋb } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -18904,7 +15522,7 @@ func (ec *executionContext) marshalNStream2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋb if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNStream2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStream(ctx, sel, v[i]) + ret[i] = ec.marshalNStream2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStream(ctx, sel, v[i]) } if isLen1 { f(i) @@ -18917,9 +15535,9 @@ func (ec *executionContext) marshalNStream2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋb return ret } -func (ec *executionContext) marshalNStream2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStream(ctx context.Context, sel ast.SelectionSet, v *entity.Stream) graphql.Marshaler { +func (ec *executionContext) marshalNStream2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStream(ctx context.Context, sel ast.SelectionSet, v *models.Stream) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18927,11 +15545,7 @@ func (ec *executionContext) marshalNStream2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbene return ec._Stream(ctx, sel, v) } -func (ec *executionContext) marshalNStreamIndex2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamIndex(ctx context.Context, sel ast.SelectionSet, v entity.StreamIndex) graphql.Marshaler { - return ec._StreamIndex(ctx, sel, &v) -} - -func (ec *executionContext) marshalNStreamIndex2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamIndex(ctx context.Context, sel ast.SelectionSet, v []*entity.StreamIndex) graphql.Marshaler { +func (ec *executionContext) marshalNStreamIndex2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamIndexᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.StreamIndex) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -18940,11 +15554,11 @@ func (ec *executionContext) marshalNStreamIndex2ᚕᚖgitlabᚗcomᚋbeneathᚑh } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -18955,7 +15569,7 @@ func (ec *executionContext) marshalNStreamIndex2ᚕᚖgitlabᚗcomᚋbeneathᚑh if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNStreamIndex2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamIndex(ctx, sel, v[i]) + ret[i] = ec.marshalNStreamIndex2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamIndex(ctx, sel, v[i]) } if isLen1 { f(i) @@ -18968,9 +15582,9 @@ func (ec *executionContext) marshalNStreamIndex2ᚕᚖgitlabᚗcomᚋbeneathᚑh return ret } -func (ec *executionContext) marshalNStreamIndex2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamIndex(ctx context.Context, sel ast.SelectionSet, v *entity.StreamIndex) graphql.Marshaler { +func (ec *executionContext) marshalNStreamIndex2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamIndex(ctx context.Context, sel ast.SelectionSet, v *models.StreamIndex) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -18978,11 +15592,11 @@ func (ec *executionContext) marshalNStreamIndex2ᚖgitlabᚗcomᚋbeneathᚑhq return ec._StreamIndex(ctx, sel, v) } -func (ec *executionContext) marshalNStreamInstance2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamInstance(ctx context.Context, sel ast.SelectionSet, v entity.StreamInstance) graphql.Marshaler { +func (ec *executionContext) marshalNStreamInstance2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamInstance(ctx context.Context, sel ast.SelectionSet, v models.StreamInstance) graphql.Marshaler { return ec._StreamInstance(ctx, sel, &v) } -func (ec *executionContext) marshalNStreamInstance2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamInstance(ctx context.Context, sel ast.SelectionSet, v []*entity.StreamInstance) graphql.Marshaler { +func (ec *executionContext) marshalNStreamInstance2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamInstanceᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.StreamInstance) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -18991,11 +15605,11 @@ func (ec *executionContext) marshalNStreamInstance2ᚕᚖgitlabᚗcomᚋbeneath } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -19006,7 +15620,7 @@ func (ec *executionContext) marshalNStreamInstance2ᚕᚖgitlabᚗcomᚋbeneath if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamInstance(ctx, sel, v[i]) + ret[i] = ec.marshalNStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamInstance(ctx, sel, v[i]) } if isLen1 { f(i) @@ -19019,9 +15633,9 @@ func (ec *executionContext) marshalNStreamInstance2ᚕᚖgitlabᚗcomᚋbeneath return ret } -func (ec *executionContext) marshalNStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamInstance(ctx context.Context, sel ast.SelectionSet, v *entity.StreamInstance) graphql.Marshaler { +func (ec *executionContext) marshalNStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamInstance(ctx context.Context, sel ast.SelectionSet, v *models.StreamInstance) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -19029,15 +15643,16 @@ func (ec *executionContext) marshalNStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑh return ec._StreamInstance(ctx, sel, v) } -func (ec *executionContext) unmarshalNStreamSchemaKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamSchemaKind(ctx context.Context, v interface{}) (entity.StreamSchemaKind, error) { +func (ec *executionContext) unmarshalNStreamSchemaKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamSchemaKind(ctx context.Context, v interface{}) (models.StreamSchemaKind, error) { tmp, err := graphql.UnmarshalString(v) - return entity.StreamSchemaKind(tmp), err + res := models.StreamSchemaKind(tmp) + return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNStreamSchemaKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamSchemaKind(ctx context.Context, sel ast.SelectionSet, v entity.StreamSchemaKind) graphql.Marshaler { +func (ec *executionContext) marshalNStreamSchemaKind2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamSchemaKind(ctx context.Context, sel ast.SelectionSet, v models.StreamSchemaKind) graphql.Marshaler { res := graphql.MarshalString(string(v)) if res == graphql.Null { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } @@ -19045,20 +15660,21 @@ func (ec *executionContext) marshalNStreamSchemaKind2gitlabᚗcomᚋbeneathᚑhq } func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) { - return graphql.UnmarshalString(v) + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { res := graphql.MarshalString(v) if res == graphql.Null { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } return res } -func (ec *executionContext) unmarshalNString2ᚕstring(ctx context.Context, v interface{}) ([]string, error) { +func (ec *executionContext) unmarshalNString2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { var vSlice []interface{} if v != nil { if tmp1, ok := v.([]interface{}); ok { @@ -19070,6 +15686,7 @@ func (ec *executionContext) unmarshalNString2ᚕstring(ctx context.Context, v in var err error res := make([]string, len(vSlice)) for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) res[i], err = ec.unmarshalNString2string(ctx, vSlice[i]) if err != nil { return nil, err @@ -19078,7 +15695,7 @@ func (ec *executionContext) unmarshalNString2ᚕstring(ctx context.Context, v in return res, nil } -func (ec *executionContext) marshalNString2ᚕstring(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { +func (ec *executionContext) marshalNString2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { ret := make(graphql.Array, len(v)) for i := range v { ret[i] = ec.marshalNString2string(ctx, sel, v[i]) @@ -19088,13 +15705,14 @@ func (ec *executionContext) marshalNString2ᚕstring(ctx context.Context, sel as } func (ec *executionContext) unmarshalNTime2timeᚐTime(ctx context.Context, v interface{}) (time.Time, error) { - return graphql.UnmarshalTime(v) + res, err := graphql.UnmarshalTime(v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalNTime2timeᚐTime(ctx context.Context, sel ast.SelectionSet, v time.Time) graphql.Marshaler { res := graphql.MarshalTime(v) if res == graphql.Null { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } @@ -19102,24 +15720,21 @@ func (ec *executionContext) marshalNTime2timeᚐTime(ctx context.Context, sel as } func (ec *executionContext) unmarshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx context.Context, v interface{}) (uuid.UUID, error) { - return UnmarshalUUID(v) + res, err := UnmarshalUUID(v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalNUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx context.Context, sel ast.SelectionSet, v uuid.UUID) graphql.Marshaler { res := MarshalUUID(v) if res == graphql.Null { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } return res } -func (ec *executionContext) marshalNUserSecret2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUserSecret(ctx context.Context, sel ast.SelectionSet, v entity.UserSecret) graphql.Marshaler { - return ec._UserSecret(ctx, sel, &v) -} - -func (ec *executionContext) marshalNUserSecret2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUserSecret(ctx context.Context, sel ast.SelectionSet, v []*entity.UserSecret) graphql.Marshaler { +func (ec *executionContext) marshalNUserSecret2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐUserSecretᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.UserSecret) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -19128,11 +15743,11 @@ func (ec *executionContext) marshalNUserSecret2ᚕᚖgitlabᚗcomᚋbeneathᚑhq } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -19143,7 +15758,7 @@ func (ec *executionContext) marshalNUserSecret2ᚕᚖgitlabᚗcomᚋbeneathᚑhq if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNUserSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUserSecret(ctx, sel, v[i]) + ret[i] = ec.marshalNUserSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐUserSecret(ctx, sel, v[i]) } if isLen1 { f(i) @@ -19156,9 +15771,9 @@ func (ec *executionContext) marshalNUserSecret2ᚕᚖgitlabᚗcomᚋbeneathᚑhq return ret } -func (ec *executionContext) marshalNUserSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUserSecret(ctx context.Context, sel ast.SelectionSet, v *entity.UserSecret) graphql.Marshaler { +func (ec *executionContext) marshalNUserSecret2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐUserSecret(ctx context.Context, sel ast.SelectionSet, v *models.UserSecret) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -19170,7 +15785,7 @@ func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlge return ec.___Directive(ctx, sel, &v) } -func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler { +func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -19179,11 +15794,11 @@ func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgq } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -19208,20 +15823,21 @@ func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgq } func (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) { - return graphql.UnmarshalString(v) + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { res := graphql.MarshalString(v) if res == graphql.Null { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } return res } -func (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstring(ctx context.Context, v interface{}) ([]string, error) { +func (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { var vSlice []interface{} if v != nil { if tmp1, ok := v.([]interface{}); ok { @@ -19233,6 +15849,7 @@ func (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstring(ctx context. var err error res := make([]string, len(vSlice)) for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) res[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i]) if err != nil { return nil, err @@ -19241,7 +15858,7 @@ func (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstring(ctx context. return res, nil } -func (ec *executionContext) marshalN__DirectiveLocation2ᚕstring(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { +func (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -19250,11 +15867,11 @@ func (ec *executionContext) marshalN__DirectiveLocation2ᚕstring(ctx context.Co } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -19290,7 +15907,7 @@ func (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlg return ec.___InputValue(ctx, sel, &v) } -func (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { +func (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -19299,11 +15916,11 @@ func (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋg } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -19331,7 +15948,7 @@ func (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋg return ec.___Type(ctx, sel, &v) } -func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { +func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -19340,11 +15957,11 @@ func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgen } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -19370,7 +15987,7 @@ func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgen func (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { if v == nil { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } return graphql.Null @@ -19379,32 +15996,23 @@ func (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgen } func (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) { - return graphql.UnmarshalString(v) + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { res := graphql.MarshalString(v) if res == graphql.Null { - if !ec.HasError(graphql.GetResolverContext(ctx)) { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") } } return res } -func (ec *executionContext) marshalOBillingMethod2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingMethod(ctx context.Context, sel ast.SelectionSet, v entity.BillingMethod) graphql.Marshaler { - return ec._BillingMethod(ctx, sel, &v) -} - -func (ec *executionContext) marshalOBillingMethod2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐBillingMethod(ctx context.Context, sel ast.SelectionSet, v *entity.BillingMethod) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._BillingMethod(ctx, sel, v) -} - func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { - return graphql.UnmarshalBoolean(v) + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { @@ -19415,86 +16023,62 @@ func (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v int if v == nil { return nil, nil } - res, err := ec.unmarshalOBoolean2bool(ctx, v) - return &res, err + res, err := graphql.UnmarshalBoolean(v) + return &res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler { if v == nil { return graphql.Null } - return ec.marshalOBoolean2bool(ctx, sel, *v) -} - -func (ec *executionContext) unmarshalOInt2int(ctx context.Context, v interface{}) (int, error) { - return graphql.UnmarshalInt(v) -} - -func (ec *executionContext) marshalOInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { - return graphql.MarshalInt(v) -} - -func (ec *executionContext) unmarshalOInt2int64(ctx context.Context, v interface{}) (int64, error) { - return graphql.UnmarshalInt64(v) -} - -func (ec *executionContext) marshalOInt2int64(ctx context.Context, sel ast.SelectionSet, v int64) graphql.Marshaler { - return graphql.MarshalInt64(v) + return graphql.MarshalBoolean(*v) } func (ec *executionContext) unmarshalOInt2ᚖint(ctx context.Context, v interface{}) (*int, error) { if v == nil { return nil, nil } - res, err := ec.unmarshalOInt2int(ctx, v) - return &res, err + res, err := graphql.UnmarshalInt(v) + return &res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.SelectionSet, v *int) graphql.Marshaler { if v == nil { return graphql.Null } - return ec.marshalOInt2int(ctx, sel, *v) + return graphql.MarshalInt(*v) } func (ec *executionContext) unmarshalOInt2ᚖint64(ctx context.Context, v interface{}) (*int64, error) { if v == nil { return nil, nil } - res, err := ec.unmarshalOInt2int64(ctx, v) - return &res, err + res, err := graphql.UnmarshalInt64(v) + return &res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalOInt2ᚖint64(ctx context.Context, sel ast.SelectionSet, v *int64) graphql.Marshaler { if v == nil { return graphql.Null } - return ec.marshalOInt2int64(ctx, sel, *v) -} - -func (ec *executionContext) marshalOPrivateOrganization2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐPrivateOrganization(ctx context.Context, sel ast.SelectionSet, v PrivateOrganization) graphql.Marshaler { - return ec._PrivateOrganization(ctx, sel, &v) + return graphql.MarshalInt64(*v) } -func (ec *executionContext) marshalOPrivateOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋgqlᚐPrivateOrganization(ctx context.Context, sel ast.SelectionSet, v *PrivateOrganization) graphql.Marshaler { +func (ec *executionContext) marshalOPrivateOrganization2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋserverᚋcontrolᚋgqlᚐPrivateOrganization(ctx context.Context, sel ast.SelectionSet, v *PrivateOrganization) graphql.Marshaler { if v == nil { return graphql.Null } return ec._PrivateOrganization(ctx, sel, v) } -func (ec *executionContext) marshalOPrivateUser2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUser(ctx context.Context, sel ast.SelectionSet, v entity.User) graphql.Marshaler { - return ec._PrivateUser(ctx, sel, &v) -} - -func (ec *executionContext) marshalOPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐUser(ctx context.Context, sel ast.SelectionSet, v *entity.User) graphql.Marshaler { +func (ec *executionContext) marshalOPrivateUser2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐUser(ctx context.Context, sel ast.SelectionSet, v *models.User) graphql.Marshaler { if v == nil { return graphql.Null } return ec._PrivateUser(ctx, sel, v) } -func (ec *executionContext) marshalOProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx context.Context, sel ast.SelectionSet, v []*entity.Project) graphql.Marshaler { +func (ec *executionContext) marshalOProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProjectᚄ(ctx context.Context, sel ast.SelectionSet, v []*models.Project) graphql.Marshaler { if v == nil { return graphql.Null } @@ -19506,11 +16090,11 @@ func (ec *executionContext) marshalOProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋ } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -19521,7 +16105,7 @@ func (ec *executionContext) marshalOProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋ if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐProject(ctx, sel, v[i]) + ret[i] = ec.marshalNProject2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐProject(ctx, sel, v[i]) } if isLen1 { f(i) @@ -19534,11 +16118,7 @@ func (ec *executionContext) marshalOProject2ᚕᚖgitlabᚗcomᚋbeneathᚑhqᚋ return ret } -func (ec *executionContext) marshalOStreamInstance2gitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamInstance(ctx context.Context, sel ast.SelectionSet, v entity.StreamInstance) graphql.Marshaler { - return ec._StreamInstance(ctx, sel, &v) -} - -func (ec *executionContext) marshalOStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋcontrolᚋentityᚐStreamInstance(ctx context.Context, sel ast.SelectionSet, v *entity.StreamInstance) graphql.Marshaler { +func (ec *executionContext) marshalOStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑhqᚋbeneathᚋmodelsᚐStreamInstance(ctx context.Context, sel ast.SelectionSet, v *models.StreamInstance) graphql.Marshaler { if v == nil { return graphql.Null } @@ -19546,7 +16126,8 @@ func (ec *executionContext) marshalOStreamInstance2ᚖgitlabᚗcomᚋbeneathᚑh } func (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) { - return graphql.UnmarshalString(v) + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { @@ -19557,64 +16138,48 @@ func (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v in if v == nil { return nil, nil } - res, err := ec.unmarshalOString2string(ctx, v) - return &res, err + res, err := graphql.UnmarshalString(v) + return &res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { if v == nil { return graphql.Null } - return ec.marshalOString2string(ctx, sel, *v) -} - -func (ec *executionContext) unmarshalOTime2timeᚐTime(ctx context.Context, v interface{}) (time.Time, error) { - return graphql.UnmarshalTime(v) -} - -func (ec *executionContext) marshalOTime2timeᚐTime(ctx context.Context, sel ast.SelectionSet, v time.Time) graphql.Marshaler { - return graphql.MarshalTime(v) + return graphql.MarshalString(*v) } func (ec *executionContext) unmarshalOTime2ᚖtimeᚐTime(ctx context.Context, v interface{}) (*time.Time, error) { if v == nil { return nil, nil } - res, err := ec.unmarshalOTime2timeᚐTime(ctx, v) - return &res, err + res, err := graphql.UnmarshalTime(v) + return &res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalOTime2ᚖtimeᚐTime(ctx context.Context, sel ast.SelectionSet, v *time.Time) graphql.Marshaler { if v == nil { return graphql.Null } - return ec.marshalOTime2timeᚐTime(ctx, sel, *v) -} - -func (ec *executionContext) unmarshalOUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx context.Context, v interface{}) (uuid.UUID, error) { - return UnmarshalUUID(v) -} - -func (ec *executionContext) marshalOUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx context.Context, sel ast.SelectionSet, v uuid.UUID) graphql.Marshaler { - return MarshalUUID(v) + return graphql.MarshalTime(*v) } func (ec *executionContext) unmarshalOUUID2ᚖgithubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx context.Context, v interface{}) (*uuid.UUID, error) { if v == nil { return nil, nil } - res, err := ec.unmarshalOUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, v) - return &res, err + res, err := UnmarshalUUID(v) + return &res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalOUUID2ᚖgithubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx context.Context, sel ast.SelectionSet, v *uuid.UUID) graphql.Marshaler { if v == nil { return graphql.Null } - return ec.marshalOUUID2githubᚗcomᚋsatoriᚋgoᚗuuidᚐUUID(ctx, sel, *v) + return MarshalUUID(*v) } -func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler { +func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler { if v == nil { return graphql.Null } @@ -19626,11 +16191,11 @@ func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgq } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -19654,7 +16219,7 @@ func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgq return ret } -func (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler { +func (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler { if v == nil { return graphql.Null } @@ -19666,11 +16231,11 @@ func (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgen } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -19694,7 +16259,7 @@ func (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgen return ret } -func (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { +func (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { if v == nil { return graphql.Null } @@ -19706,11 +16271,11 @@ func (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋg } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { @@ -19734,10 +16299,6 @@ func (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋg return ret } -func (ec *executionContext) marshalO__Schema2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v introspection.Schema) graphql.Marshaler { - return ec.___Schema(ctx, sel, &v) -} - func (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler { if v == nil { return graphql.Null @@ -19745,11 +16306,7 @@ func (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlge return ec.___Schema(ctx, sel, v) } -func (ec *executionContext) marshalO__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler { - return ec.___Type(ctx, sel, &v) -} - -func (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { +func (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { if v == nil { return graphql.Null } @@ -19761,11 +16318,11 @@ func (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgen } for i := range v { i := i - rctx := &graphql.ResolverContext{ + fc := &graphql.FieldContext{ Index: &i, Result: &v[i], } - ctx := graphql.WithResolverContext(ctx, rctx) + ctx := graphql.WithFieldContext(ctx, fc) f := func(i int) { defer func() { if r := recover(); r != nil { diff --git a/control/gql/uuid.go b/server/control/gql/uuid.go similarity index 100% rename from control/gql/uuid.go rename to server/control/gql/uuid.go diff --git a/control/resolver/memberships.go b/server/control/resolver/memberships.go similarity index 75% rename from control/resolver/memberships.go rename to server/control/resolver/memberships.go index b535de1a..76971f48 100644 --- a/control/resolver/memberships.go +++ b/server/control/resolver/memberships.go @@ -3,8 +3,8 @@ package resolver import ( "context" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/control/gql" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/server/control/gql" ) // ProjectMember returns the ProjectMemberResolver @@ -14,11 +14,11 @@ func (r *Resolver) ProjectMember() gql.ProjectMemberResolver { type projectMemberResolver struct{ *Resolver } -func (r *projectMemberResolver) ProjectID(ctx context.Context, obj *entity.ProjectMember) (string, error) { +func (r *projectMemberResolver) ProjectID(ctx context.Context, obj *models.ProjectMember) (string, error) { return obj.ProjectID.String(), nil } -func (r *projectMemberResolver) UserID(ctx context.Context, obj *entity.ProjectMember) (string, error) { +func (r *projectMemberResolver) UserID(ctx context.Context, obj *models.ProjectMember) (string, error) { return obj.UserID.String(), nil } @@ -29,10 +29,10 @@ func (r *Resolver) OrganizationMember() gql.OrganizationMemberResolver { type organizationMemberResolver struct{ *Resolver } -func (r *organizationMemberResolver) OrganizationID(ctx context.Context, obj *entity.OrganizationMember) (string, error) { +func (r *organizationMemberResolver) OrganizationID(ctx context.Context, obj *models.OrganizationMember) (string, error) { return obj.OrganizationID.String(), nil } -func (r *organizationMemberResolver) UserID(ctx context.Context, obj *entity.OrganizationMember) (string, error) { +func (r *organizationMemberResolver) UserID(ctx context.Context, obj *models.OrganizationMember) (string, error) { return obj.UserID.String(), nil } diff --git a/control/resolver/metrics.go b/server/control/resolver/metrics.go similarity index 77% rename from control/resolver/metrics.go rename to server/control/resolver/metrics.go index 4169213b..e39b97d5 100644 --- a/control/resolver/metrics.go +++ b/server/control/resolver/metrics.go @@ -6,14 +6,12 @@ import ( "time" uuid "github.com/satori/go.uuid" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/gqlerror" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/control/gql" - "gitlab.com/beneath-hq/beneath/internal/metrics" - "gitlab.com/beneath-hq/beneath/internal/middleware" "gitlab.com/beneath-hq/beneath/pkg/mathutil" "gitlab.com/beneath-hq/beneath/pkg/timeutil" + "gitlab.com/beneath-hq/beneath/server/control/gql" + "gitlab.com/beneath-hq/beneath/services/middleware" ) func (r *queryResolver) GetMetrics(ctx context.Context, entityKind gql.EntityKind, entityID uuid.UUID, period string, from time.Time, until *time.Time) ([]*gql.Metrics, error) { @@ -34,77 +32,77 @@ func (r *queryResolver) GetMetrics(ctx context.Context, entityKind gql.EntityKin func (r *queryResolver) GetOrganizationMetrics(ctx context.Context, organizationID uuid.UUID, period string, from time.Time, until *time.Time) ([]*gql.Metrics, error) { secret := middleware.GetSecret(ctx) - perms := secret.OrganizationPermissions(ctx, organizationID) + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, organizationID) if !perms.View { return nil, gqlerror.Errorf("you do not have permission to view this organization's metrics") } - return getUsage(ctx, organizationID, period, from, until) + return r.getUsage(ctx, organizationID, period, from, until) } func (r *queryResolver) GetServiceMetrics(ctx context.Context, serviceID uuid.UUID, period string, from time.Time, until *time.Time) ([]*gql.Metrics, error) { - service := entity.FindService(ctx, serviceID) + service := r.Services.FindService(ctx, serviceID) if service == nil { return nil, gqlerror.Errorf("service not found") } secret := middleware.GetSecret(ctx) - perms := secret.ProjectPermissions(ctx, service.ProjectID, service.Project.Public) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, service.ProjectID, service.Project.Public) if !perms.View { return nil, gqlerror.Errorf("you do not have permission to view this service's metrics") } - return getUsage(ctx, serviceID, period, from, until) + return r.getUsage(ctx, serviceID, period, from, until) } func (r *queryResolver) GetStreamInstanceMetrics(ctx context.Context, streamInstanceID uuid.UUID, period string, from time.Time, until *time.Time) ([]*gql.Metrics, error) { - stream := entity.FindCachedStreamByCurrentInstanceID(ctx, streamInstanceID) + stream := r.Streams.FindCachedInstance(ctx, streamInstanceID) if stream == nil { return nil, gqlerror.Errorf("Stream for instance %s not found", streamInstanceID.String()) } secret := middleware.GetSecret(ctx) - perms := secret.StreamPermissions(ctx, stream.StreamID, stream.ProjectID, stream.Public) + perms := r.Permissions.StreamPermissionsForSecret(ctx, secret, stream.StreamID, stream.ProjectID, stream.Public) if !perms.Read { return nil, gqlerror.Errorf("you do not have permission to view this stream's metrics") } - return getUsage(ctx, streamInstanceID, period, from, until) + return r.getUsage(ctx, streamInstanceID, period, from, until) } func (r *queryResolver) GetStreamMetrics(ctx context.Context, streamID uuid.UUID, period string, from time.Time, until *time.Time) ([]*gql.Metrics, error) { - stream := entity.FindStream(ctx, streamID) + stream := r.Streams.FindStream(ctx, streamID) if stream == nil { return nil, gqlerror.Errorf("Stream %s not found", streamID.String()) } secret := middleware.GetSecret(ctx) - perms := secret.StreamPermissions(ctx, streamID, stream.ProjectID, stream.Project.Public) + perms := r.Permissions.StreamPermissionsForSecret(ctx, secret, streamID, stream.ProjectID, stream.Project.Public) if !perms.Read { return nil, gqlerror.Errorf("you do not have permission to view this stream's metrics") } - return getUsage(ctx, stream.StreamID, period, from, until) + return r.getUsage(ctx, stream.StreamID, period, from, until) } func (r *queryResolver) GetUserMetrics(ctx context.Context, userID uuid.UUID, period string, from time.Time, until *time.Time) ([]*gql.Metrics, error) { secret := middleware.GetSecret(ctx) if secret.GetOwnerID() != userID { - user := entity.FindUser(ctx, userID) + user := r.Users.FindUser(ctx, userID) if user == nil { return nil, gqlerror.Errorf("user not found") } - perms := secret.OrganizationPermissions(ctx, user.BillingOrganizationID) + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, user.BillingOrganizationID) if !perms.View { return nil, gqlerror.Errorf("you do not have permission to view this user's metrics") } } - return getUsage(ctx, userID, period, from, until) + return r.getUsage(ctx, userID, period, from, until) } -func getUsage(ctx context.Context, entityID uuid.UUID, period string, from time.Time, until *time.Time) ([]*gql.Metrics, error) { +func (r *queryResolver) getUsage(ctx context.Context, entityID uuid.UUID, period string, from time.Time, until *time.Time) ([]*gql.Metrics, error) { // if until is not provided, set to the empty time (metrics.GetUsage then defaults to current time) if until == nil { until = &time.Time{} @@ -116,7 +114,7 @@ func getUsage(ctx context.Context, entityID uuid.UUID, period string, from time. return nil, gqlerror.Errorf("%v", err.Error()) } - times, usages, err := metrics.GetHistoricalUsage(ctx, entityID, p, from, *until) + times, usages, err := r.Metrics.GetHistoricalUsage(ctx, entityID, p, from, *until) if err != nil { return nil, gqlerror.Errorf("couldn't get usage: %v", err) } diff --git a/control/resolver/metrics_test.go b/server/control/resolver/metrics_test.go similarity index 97% rename from control/resolver/metrics_test.go rename to server/control/resolver/metrics_test.go index 497381ef..599db7da 100644 --- a/control/resolver/metrics_test.go +++ b/server/control/resolver/metrics_test.go @@ -5,7 +5,7 @@ import ( "time" "github.com/stretchr/testify/assert" - "gitlab.com/beneath-hq/beneath/control/gql" + "gitlab.com/beneath-hq/beneath/server/control/gql" ) func TestAddMetrics(t *testing.T) { diff --git a/control/resolver/organization.go b/server/control/resolver/organization.go similarity index 66% rename from control/resolver/organization.go rename to server/control/resolver/organization.go index 7e9b9137..690df185 100644 --- a/control/resolver/organization.go +++ b/server/control/resolver/organization.go @@ -6,12 +6,12 @@ import ( "github.com/99designs/gqlgen/graphql" uuid "github.com/satori/go.uuid" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/control/gql" - "gitlab.com/beneath-hq/beneath/internal/metrics" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/server/control/gql" + "gitlab.com/beneath-hq/beneath/services/middleware" ) // PublicOrganization returns the gql.PublicOrganizationResolver @@ -21,11 +21,11 @@ func (r *Resolver) PublicOrganization() gql.PublicOrganizationResolver { type publicOrganizationResolver struct{ *Resolver } -func (r *publicOrganizationResolver) OrganizationID(ctx context.Context, obj *entity.Organization) (string, error) { +func (r *publicOrganizationResolver) OrganizationID(ctx context.Context, obj *models.Organization) (string, error) { return obj.OrganizationID.String(), nil } -func (r *publicOrganizationResolver) PersonalUserID(ctx context.Context, obj *entity.Organization) (*uuid.UUID, error) { +func (r *publicOrganizationResolver) PersonalUserID(ctx context.Context, obj *models.Organization) (*uuid.UUID, error) { return obj.UserID, nil } @@ -35,12 +35,12 @@ func (r *queryResolver) Me(ctx context.Context) (*gql.PrivateOrganization, error return nil, MakeUnauthenticatedError("Must be authenticated with a personal key to call 'Me'") } - org := entity.FindOrganizationByUserID(ctx, secret.GetOwnerID()) + org := r.Organizations.FindOrganizationByUserID(ctx, secret.GetOwnerID()) if org == nil { return nil, gqlerror.Errorf("Couldn't find user! This is highly irregular.") } - return organizationToPrivateOrganization(ctx, org, entity.OrganizationPermissions{ + return r.organizationToPrivateOrganization(ctx, org, models.OrganizationPermissions{ View: true, Create: true, Admin: true, @@ -48,64 +48,64 @@ func (r *queryResolver) Me(ctx context.Context) (*gql.PrivateOrganization, error } func (r *queryResolver) OrganizationByName(ctx context.Context, name string) (gql.Organization, error) { - org := entity.FindOrganizationByName(ctx, name) + org := r.Organizations.FindOrganizationByName(ctx, name) if org == nil { return nil, gqlerror.Errorf("Organization %s not found", name) } secret := middleware.GetSecret(ctx) - perms := organizationPermissions(ctx, secret, org) + perms := r.organizationPermissions(ctx, secret, org) if !perms.View { // remove private projects and return a PublicOrganization org.StripPrivateProjects() return org, nil } - return organizationToPrivateOrganization(ctx, org, perms), nil + return r.organizationToPrivateOrganization(ctx, org, perms), nil } func (r *queryResolver) OrganizationByID(ctx context.Context, organizationID uuid.UUID) (gql.Organization, error) { - org := entity.FindOrganization(ctx, organizationID) + org := r.Organizations.FindOrganization(ctx, organizationID) if org == nil { return nil, gqlerror.Errorf("Organization %s not found", organizationID.String()) } secret := middleware.GetSecret(ctx) - perms := organizationPermissions(ctx, secret, org) + perms := r.organizationPermissions(ctx, secret, org) if !perms.View { // remove private projects and return a PublicOrganization org.StripPrivateProjects() return org, nil } - return organizationToPrivateOrganization(ctx, org, perms), nil + return r.organizationToPrivateOrganization(ctx, org, perms), nil } func (r *queryResolver) OrganizationByUserID(ctx context.Context, userID uuid.UUID) (gql.Organization, error) { - org := entity.FindOrganizationByUserID(ctx, userID) + org := r.Organizations.FindOrganizationByUserID(ctx, userID) if org == nil { return nil, gqlerror.Errorf("Organization not found for userID %s", userID.String()) } secret := middleware.GetSecret(ctx) - perms := organizationPermissions(ctx, secret, org) + perms := r.organizationPermissions(ctx, secret, org) if !perms.View { // remove private projects and return a PublicOrganization org.StripPrivateProjects() return org, nil } - return organizationToPrivateOrganization(ctx, org, perms), nil + return r.organizationToPrivateOrganization(ctx, org, perms), nil } -func (r *queryResolver) OrganizationMembers(ctx context.Context, organizationID uuid.UUID) ([]*entity.OrganizationMember, error) { +func (r *queryResolver) OrganizationMembers(ctx context.Context, organizationID uuid.UUID) ([]*models.OrganizationMember, error) { secret := middleware.GetSecret(ctx) - perms := secret.OrganizationPermissions(ctx, organizationID) + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, organizationID) if !perms.View { return nil, gqlerror.Errorf("You're not allowed to see the members of organization %s", organizationID.String()) } - return entity.FindOrganizationMembers(ctx, organizationID) + return r.Organizations.FindOrganizationMembers(ctx, organizationID) } func (r *mutationResolver) CreateOrganization(ctx context.Context, name string) (*gql.PrivateOrganization, error) { @@ -114,39 +114,38 @@ func (r *mutationResolver) CreateOrganization(ctx context.Context, name string) return nil, gqlerror.Errorf("Only Beneath masters can create new organizations") } - organization := &entity.Organization{Name: name} - err := organization.CreateWithUser(ctx, secret.GetOwnerID(), true, true, true) + organization, err := r.Organizations.CreateWithUser(ctx, name, secret.GetOwnerID(), true, true, true) if err != nil { return nil, gqlerror.Errorf("Failed to create organization: %s", err.Error()) } - perms := entity.OrganizationPermissions{ + perms := models.OrganizationPermissions{ View: true, Create: true, Admin: true, } - return organizationToPrivateOrganization(ctx, organization, perms), nil + return r.organizationToPrivateOrganization(ctx, organization, perms), nil } func (r *mutationResolver) UpdateOrganization(ctx context.Context, organizationID uuid.UUID, name *string, displayName *string, description *string, photoURL *string) (*gql.PrivateOrganization, error) { secret := middleware.GetSecret(ctx) - perms := secret.OrganizationPermissions(ctx, organizationID) + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, organizationID) if !perms.Admin { return nil, gqlerror.Errorf("Not allowed to perform admin functions in organization %s", organizationID.String()) } - organization := entity.FindOrganization(ctx, organizationID) + organization := r.Organizations.FindOrganization(ctx, organizationID) if organization == nil { return nil, gqlerror.Errorf("Organization %s not found", organizationID.String()) } - err := organization.UpdateDetails(ctx, name, displayName, description, photoURL) + err := r.Organizations.UpdateDetails(ctx, organization, name, displayName, description, photoURL) if err != nil { // specifically handle the common error that a username is already taken if strings.Contains(err.Error(), `duplicate key value violates unique constraint "organizations_name_key"`) { path := graphql.GetResolverContext(ctx).Path() - path = append(path, "name") + path = append(path, ast.PathName("name")) if organization.UserID != nil { return nil, gqlerror.ErrorPathf(path, "Username already taken") } @@ -155,11 +154,11 @@ func (r *mutationResolver) UpdateOrganization(ctx context.Context, organizationI return nil, gqlerror.Errorf("Failed to update organization: %s", err.Error()) } - return organizationToPrivateOrganization(ctx, organization, perms), nil + return r.organizationToPrivateOrganization(ctx, organization, perms), nil } func (r *mutationResolver) UpdateOrganizationQuotas(ctx context.Context, organizationID uuid.UUID, readQuota *int, writeQuota *int, scanQuota *int) (*gql.PrivateOrganization, error) { - organization := entity.FindOrganization(ctx, organizationID) + organization := r.Organizations.FindOrganization(ctx, organizationID) if organization == nil { return nil, gqlerror.Errorf("Organization %s not found", organizationID.String()) } @@ -169,17 +168,17 @@ func (r *mutationResolver) UpdateOrganizationQuotas(ctx context.Context, organiz return nil, gqlerror.Errorf("Only Beneath masters can update organization quotas directly") } - err := organization.UpdateQuotas(ctx, IntToInt64(readQuota), IntToInt64(writeQuota), IntToInt64(scanQuota)) + err := r.Organizations.UpdateQuotas(ctx, organization, IntToInt64(readQuota), IntToInt64(writeQuota), IntToInt64(scanQuota)) if err != nil { return nil, gqlerror.Errorf("Error updating quotas: %s", err.Error()) } - perms := secret.OrganizationPermissions(ctx, organizationID) - return organizationToPrivateOrganization(ctx, organization, perms), nil + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, organizationID) + return r.organizationToPrivateOrganization(ctx, organization, perms), nil } func (r *mutationResolver) InviteUserToOrganization(ctx context.Context, userID uuid.UUID, organizationID uuid.UUID, view bool, create bool, admin bool) (bool, error) { - organization := entity.FindOrganization(ctx, organizationID) + organization := r.Organizations.FindOrganization(ctx, organizationID) if organization == nil { return false, gqlerror.Errorf("Organization %s not found", organizationID.String()) } @@ -189,12 +188,12 @@ func (r *mutationResolver) InviteUserToOrganization(ctx context.Context, userID } secret := middleware.GetSecret(ctx) - perms := secret.OrganizationPermissions(ctx, organizationID) + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, organizationID) if !perms.Admin { return false, gqlerror.Errorf("Not allowed to perform admin functions on organization %s", organizationID.String()) } - user := entity.FindUser(ctx, userID) + user := r.Users.FindUser(ctx, userID) if user == nil { return false, gqlerror.Errorf("User %s not found", userID.String()) } @@ -203,14 +202,7 @@ func (r *mutationResolver) InviteUserToOrganization(ctx context.Context, userID return false, gqlerror.Errorf("User is already a member of the organization") } - invite := entity.OrganizationInvite{ - OrganizationID: organizationID, - UserID: userID, - View: view, - Create: create, - Admin: admin, - } - err := invite.Upsert(ctx) + err := r.Organizations.CreateOrUpdateInvite(ctx, organizationID, userID, view, create, admin) if err != nil { return false, gqlerror.Errorf("Couldn't create invite: %s", err.Error()) } @@ -224,22 +216,22 @@ func (r *mutationResolver) AcceptOrganizationInvite(ctx context.Context, organiz return false, MakeUnauthenticatedError("Must be authenticated with a personal key") } - invite := entity.FindOrganizationInvite(ctx, organizationID, secret.GetOwnerID()) + invite := r.Organizations.FindOrganizationInvite(ctx, organizationID, secret.GetOwnerID()) if invite == nil { return false, gqlerror.Errorf("You do not have an invitation for organization %s", organizationID.String()) } - err := invite.User.BillingOrganization.TransferUser(ctx, invite.User, invite.Organization) + err := r.Organizations.TransferUser(ctx, invite.User.BillingOrganization, invite.Organization, invite.User) if err != nil { return false, gqlerror.Errorf("Couldn't accept invite: %s", err.Error()) } // grant access permissions - puo := &entity.PermissionsUsersOrganizations{ + puo := &models.PermissionsUsersOrganizations{ UserID: invite.UserID, OrganizationID: organizationID, } - err = puo.Update(ctx, &invite.View, &invite.Create, &invite.Admin) + err = r.Permissions.UpdateUserOrganizationPermission(ctx, puo, &invite.View, &invite.Create, &invite.Admin) if err != nil { return false, gqlerror.Errorf("Couldn't grant permissions: %s", err.Error()) } @@ -247,8 +239,8 @@ func (r *mutationResolver) AcceptOrganizationInvite(ctx context.Context, organiz return true, nil } -func (r *mutationResolver) LeaveBillingOrganization(ctx context.Context, userID uuid.UUID) (*entity.User, error) { - personalOrg := entity.FindOrganizationByUserID(ctx, userID) +func (r *mutationResolver) LeaveBillingOrganization(ctx context.Context, userID uuid.UUID) (*models.User, error) { + personalOrg := r.Organizations.FindOrganizationByUserID(ctx, userID) if personalOrg == nil { return nil, gqlerror.Errorf("User not found") } @@ -260,25 +252,25 @@ func (r *mutationResolver) LeaveBillingOrganization(ctx context.Context, userID // organization admins or users themselves can trigger this secret := middleware.GetSecret(ctx) if !(secret.IsUser() && secret.GetOwnerID() == userID) { - perms := secret.OrganizationPermissions(ctx, personalOrg.User.BillingOrganizationID) + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, personalOrg.User.BillingOrganizationID) if !perms.Admin { return nil, gqlerror.Errorf("Must be authenticated as the user or an admin of its organization") } } - leavingOrg := entity.FindOrganization(ctx, personalOrg.User.BillingOrganizationID) - err := leavingOrg.TransferUser(ctx, personalOrg.User, personalOrg) + leavingOrg := r.Organizations.FindOrganization(ctx, personalOrg.User.BillingOrganizationID) + err := r.Organizations.TransferUser(ctx, leavingOrg, personalOrg, personalOrg.User) if err != nil { return nil, err } // remove access permissions falsy := false - puo := &entity.PermissionsUsersOrganizations{ + puo := &models.PermissionsUsersOrganizations{ UserID: userID, OrganizationID: leavingOrg.OrganizationID, } - err = puo.Update(ctx, &falsy, &falsy, &falsy) + err = r.Permissions.UpdateUserOrganizationPermission(ctx, puo, &falsy, &falsy, &falsy) if err != nil { return nil, gqlerror.Errorf("Couldn't remove permissions: %s", err.Error()) } @@ -286,18 +278,18 @@ func (r *mutationResolver) LeaveBillingOrganization(ctx context.Context, userID return personalOrg.User, nil } -func (r *mutationResolver) TransferProjectToOrganization(ctx context.Context, projectID uuid.UUID, organizationID uuid.UUID) (*entity.Project, error) { +func (r *mutationResolver) TransferProjectToOrganization(ctx context.Context, projectID uuid.UUID, organizationID uuid.UUID) (*models.Project, error) { secret := middleware.GetSecret(ctx) - projPerms := secret.ProjectPermissions(ctx, projectID, false) + projPerms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, projectID, false) if !projPerms.Admin { return nil, gqlerror.Errorf("Not allowed to perform admin functions in project %s", projectID.String()) } - orgPerms := secret.OrganizationPermissions(ctx, organizationID) + orgPerms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, organizationID) if !orgPerms.Create { return nil, gqlerror.Errorf("Not allowed to create resources in organization %s", organizationID.String()) } - project := entity.FindProject(ctx, projectID) + project := r.Projects.FindProject(ctx, projectID) if project == nil { return nil, gqlerror.Errorf("Project %s not found", projectID.String()) } @@ -306,12 +298,12 @@ func (r *mutationResolver) TransferProjectToOrganization(ctx context.Context, pr return nil, gqlerror.Errorf("Project %s is already in organization %s", projectID.String(), organizationID.String()) } - targetOrganization := entity.FindOrganization(ctx, organizationID) + targetOrganization := r.Organizations.FindOrganization(ctx, organizationID) if targetOrganization == nil { return nil, gqlerror.Errorf("Organization %s not found", organizationID) } - err := project.Organization.TransferProject(ctx, project, targetOrganization) + err := r.Organizations.TransferProject(ctx, project.Organization, targetOrganization, project) if err != nil { return nil, err } @@ -319,15 +311,15 @@ func (r *mutationResolver) TransferProjectToOrganization(ctx context.Context, pr return project, nil } -func organizationPermissions(ctx context.Context, secret entity.Secret, org *entity.Organization) entity.OrganizationPermissions { - perms := secret.OrganizationPermissions(ctx, org.OrganizationID) +func (r *queryResolver) organizationPermissions(ctx context.Context, secret models.Secret, org *models.Organization) models.OrganizationPermissions { + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, org.OrganizationID) // if you're not allowed to view the org if !perms.View { // but, it's the personal org of a user that's paid for by another organization if org.User != nil && org.OrganizationID != org.User.BillingOrganizationID { // and, you're the admin paying the bills - billingPerms := secret.OrganizationPermissions(ctx, org.User.BillingOrganizationID) + billingPerms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, org.User.BillingOrganizationID) if billingPerms.Admin { // you do get to take a peek perms.View = true @@ -338,7 +330,7 @@ func organizationPermissions(ctx context.Context, secret entity.Secret, org *ent return perms } -func organizationToPrivateOrganization(ctx context.Context, o *entity.Organization, p entity.OrganizationPermissions) *gql.PrivateOrganization { +func (r *Resolver) organizationToPrivateOrganization(ctx context.Context, o *models.Organization, p models.OrganizationPermissions) *gql.PrivateOrganization { po := &gql.PrivateOrganization{ OrganizationID: o.OrganizationID.String(), Name: o.Name, @@ -356,7 +348,7 @@ func organizationToPrivateOrganization(ctx context.Context, o *entity.Organizati Projects: o.Projects, } - usage := metrics.GetCurrentUsage(ctx, o.OrganizationID) + usage := r.Metrics.GetCurrentUsage(ctx, o.OrganizationID) po.ReadUsage = int(usage.ReadBytes) po.WriteUsage = int(usage.WriteBytes) po.ScanUsage = int(usage.ScanBytes) @@ -367,7 +359,7 @@ func organizationToPrivateOrganization(ctx context.Context, o *entity.Organizati } if p.View || p.Create || p.Admin { - po.Permissions = &entity.PermissionsUsersOrganizations{ + po.Permissions = &models.PermissionsUsersOrganizations{ View: p.View, Create: p.Create, Admin: p.Admin, diff --git a/control/resolver/project.go b/server/control/resolver/project.go similarity index 61% rename from control/resolver/project.go rename to server/control/resolver/project.go index e0b66307..aa61b934 100644 --- a/control/resolver/project.go +++ b/server/control/resolver/project.go @@ -5,11 +5,11 @@ import ( "fmt" uuid "github.com/satori/go.uuid" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/gqlerror" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/control/gql" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/server/control/gql" + "gitlab.com/beneath-hq/beneath/services/middleware" ) // Project returns the gql.ProjectResolver @@ -19,30 +19,30 @@ func (r *Resolver) Project() gql.ProjectResolver { type projectResolver struct{ *Resolver } -func (r *projectResolver) ProjectID(ctx context.Context, obj *entity.Project) (string, error) { +func (r *projectResolver) ProjectID(ctx context.Context, obj *models.Project) (string, error) { return obj.ProjectID.String(), nil } -func (r *queryResolver) ExploreProjects(ctx context.Context) ([]*entity.Project, error) { - return entity.ExploreProjects(ctx), nil +func (r *queryResolver) ExploreProjects(ctx context.Context) ([]*models.Project, error) { + return r.Projects.ExploreProjects(ctx), nil } -func (r *queryResolver) ProjectsForUser(ctx context.Context, userID uuid.UUID) ([]*entity.Project, error) { +func (r *queryResolver) ProjectsForUser(ctx context.Context, userID uuid.UUID) ([]*models.Project, error) { secret := middleware.GetSecret(ctx) if !(secret.IsUser() && secret.GetOwnerID() == userID) { return nil, gqlerror.Errorf("ProjectsForUser can only be called for the calling user") } - return entity.FindProjectsForUser(ctx, userID), nil + return r.Projects.FindProjectsForUser(ctx, userID), nil } -func (r *queryResolver) ProjectByOrganizationAndName(ctx context.Context, organizationName string, projectName string) (*entity.Project, error) { - project := entity.FindProjectByOrganizationAndName(ctx, organizationName, projectName) +func (r *queryResolver) ProjectByOrganizationAndName(ctx context.Context, organizationName string, projectName string) (*models.Project, error) { + project := r.Projects.FindProjectByOrganizationAndName(ctx, organizationName, projectName) if project == nil { return nil, gqlerror.Errorf("Project %s/%s not found", organizationName, projectName) } secret := middleware.GetSecret(ctx) - perms := secret.ProjectPermissions(ctx, project.ProjectID, project.Public) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, project.ProjectID, project.Public) if !perms.View { return nil, gqlerror.Errorf("Not allowed to read project %s/%s", organizationName, projectName) } @@ -50,14 +50,14 @@ func (r *queryResolver) ProjectByOrganizationAndName(ctx context.Context, organi return projectWithPermissions(project, perms), nil } -func (r *queryResolver) ProjectByID(ctx context.Context, projectID uuid.UUID) (*entity.Project, error) { - project := entity.FindProject(ctx, projectID) +func (r *queryResolver) ProjectByID(ctx context.Context, projectID uuid.UUID) (*models.Project, error) { + project := r.Projects.FindProject(ctx, projectID) if project == nil { return nil, gqlerror.Errorf("Project %s not found", projectID.String()) } secret := middleware.GetSecret(ctx) - perms := secret.ProjectPermissions(ctx, projectID, project.Public) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, projectID, project.Public) if !perms.View { return nil, gqlerror.Errorf("Not allowed to read project %s", projectID.String()) } @@ -65,33 +65,33 @@ func (r *queryResolver) ProjectByID(ctx context.Context, projectID uuid.UUID) (* return projectWithPermissions(project, perms), nil } -func (r *queryResolver) ProjectMembers(ctx context.Context, projectID uuid.UUID) ([]*entity.ProjectMember, error) { - project := entity.FindProject(ctx, projectID) +func (r *queryResolver) ProjectMembers(ctx context.Context, projectID uuid.UUID) ([]*models.ProjectMember, error) { + project := r.Projects.FindProject(ctx, projectID) if project == nil { return nil, gqlerror.Errorf("Project %s not found", projectID.String()) } secret := middleware.GetSecret(ctx) - perms := secret.ProjectPermissions(ctx, projectID, project.Public) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, projectID, project.Public) if !perms.View { return nil, gqlerror.Errorf("You're not allowed to see the members of project %s", projectID.String()) } - return entity.FindProjectMembers(ctx, projectID) + return r.Projects.FindProjectMembers(ctx, projectID) } -func (r *mutationResolver) StageProject(ctx context.Context, organizationName string, projectName string, displayName *string, public *bool, description *string, site *string, photoURL *string) (*entity.Project, error) { - var organization *entity.Organization - var project *entity.Project +func (r *mutationResolver) StageProject(ctx context.Context, organizationName string, projectName string, displayName *string, public *bool, description *string, site *string, photoURL *string) (*models.Project, error) { + var organization *models.Organization + var project *models.Project // find or prepare for creating project - project = entity.FindProjectByOrganizationAndName(ctx, organizationName, projectName) + project = r.Projects.FindProjectByOrganizationAndName(ctx, organizationName, projectName) if project == nil { - organization = entity.FindOrganizationByName(ctx, organizationName) + organization = r.Organizations.FindOrganizationByName(ctx, organizationName) if organization == nil { return nil, gqlerror.Errorf("Organization %s not found", organizationName) } - project = &entity.Project{ + project = &models.Project{ Name: projectName, OrganizationID: organization.OrganizationID, Organization: organization, @@ -104,20 +104,20 @@ func (r *mutationResolver) StageProject(ctx context.Context, organizationName st create := project.ProjectID == uuid.Nil // check permissions (on org if we're creating the project) - var perms entity.ProjectPermissions + var perms models.ProjectPermissions secret := middleware.GetSecret(ctx) if create { - orgPerms := secret.OrganizationPermissions(ctx, organization.OrganizationID) + orgPerms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, organization.OrganizationID) if !orgPerms.Create { return nil, gqlerror.Errorf("Not allowed to perform admin functions on organization %s", organizationName) } - perms = entity.ProjectPermissions{ + perms = models.ProjectPermissions{ View: true, Create: true, Admin: true, } } else { - perms = secret.ProjectPermissions(ctx, project.ProjectID, false) + perms = r.Permissions.ProjectPermissionsForSecret(ctx, secret, project.ProjectID, false) if !perms.Admin { return nil, gqlerror.Errorf("Not allowed to perform admin functions on project %s/%s", organizationName, projectName) } @@ -129,26 +129,14 @@ func (r *mutationResolver) StageProject(ctx context.Context, organizationName st public = &trueVal } - // check billing info if project is private - if public != nil && !*public { - bi := entity.FindBillingInfo(ctx, organization.OrganizationID) - if bi == nil { - return nil, gqlerror.Errorf("Could not find billing info for organization %s", organizationName) - } - - if !bi.BillingPlan.PrivateProjects { - return nil, gqlerror.Errorf("Your organization's billing plan does not permit private projects") - } - } - - err := project.StageWithUser(ctx, displayName, public, description, site, photoURL, secret.GetOwnerID(), perms) + err := r.Projects.StageWithUser(ctx, project, displayName, public, description, site, photoURL, secret.GetOwnerID(), perms) if err != nil { return nil, gqlerror.Errorf("Error staging project: %s", err.Error()) } // on create, refetching project to include user if create { - project = entity.FindProject(ctx, project.ProjectID) + project = r.Projects.FindProject(ctx, project.ProjectID) if project == nil { panic(fmt.Errorf("expected project with ID %s to exist", project.ProjectID.String())) } @@ -159,17 +147,17 @@ func (r *mutationResolver) StageProject(ctx context.Context, organizationName st func (r *mutationResolver) DeleteProject(ctx context.Context, projectID uuid.UUID) (bool, error) { secret := middleware.GetSecret(ctx) - perms := secret.ProjectPermissions(ctx, projectID, false) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, projectID, false) if !perms.Admin { return false, gqlerror.Errorf("Not allowed to perform admin functions in project %s", projectID.String()) } - project := entity.FindProject(ctx, projectID) + project := r.Projects.FindProject(ctx, projectID) if project == nil { return false, gqlerror.Errorf("Project %s not found", projectID.String()) } - err := project.Delete(ctx) + err := r.Projects.Delete(ctx, project) if err != nil { return false, gqlerror.Errorf(err.Error()) } @@ -177,9 +165,9 @@ func (r *mutationResolver) DeleteProject(ctx context.Context, projectID uuid.UUI return true, nil } -func projectWithPermissions(p *entity.Project, perms entity.ProjectPermissions) *entity.Project { +func projectWithPermissions(p *models.Project, perms models.ProjectPermissions) *models.Project { if perms.View || perms.Create || perms.Admin { - p.Permissions = &entity.PermissionsUsersProjects{ + p.Permissions = &models.PermissionsUsersProjects{ View: perms.View, Create: perms.Create, Admin: perms.Admin, diff --git a/control/resolver/resolver.go b/server/control/resolver/resolver.go similarity index 61% rename from control/resolver/resolver.go rename to server/control/resolver/resolver.go index ea40c711..3c2544db 100644 --- a/control/resolver/resolver.go +++ b/server/control/resolver/resolver.go @@ -3,11 +3,28 @@ package resolver import ( "context" - "gitlab.com/beneath-hq/beneath/control/gql" + "gitlab.com/beneath-hq/beneath/server/control/gql" + "gitlab.com/beneath-hq/beneath/services/metrics" + "gitlab.com/beneath-hq/beneath/services/organization" + "gitlab.com/beneath-hq/beneath/services/permissions" + "gitlab.com/beneath-hq/beneath/services/project" + "gitlab.com/beneath-hq/beneath/services/secret" + "gitlab.com/beneath-hq/beneath/services/service" + "gitlab.com/beneath-hq/beneath/services/stream" + "gitlab.com/beneath-hq/beneath/services/user" ) // Resolver implements gql.ResolverRoot -type Resolver struct{} +type Resolver struct { + Metrics *metrics.Broker + Organizations *organization.Service + Permissions *permissions.Service + Projects *project.Service + Secrets *secret.Service + Services *service.Service + Streams *stream.Service + Users *user.Service +} // Query returns the gql.QueryResolver func (r *Resolver) Query() gql.QueryResolver { diff --git a/control/resolver/secret.go b/server/control/resolver/secret.go similarity index 70% rename from control/resolver/secret.go rename to server/control/resolver/secret.go index 527772d3..b4b9369d 100644 --- a/control/resolver/secret.go +++ b/server/control/resolver/secret.go @@ -4,11 +4,11 @@ import ( "context" uuid "github.com/satori/go.uuid" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/gqlerror" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/control/gql" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/server/control/gql" + "gitlab.com/beneath-hq/beneath/services/middleware" ) // ServiceSecret returns the gql.ServiceSecretResolver @@ -18,7 +18,7 @@ func (r *Resolver) ServiceSecret() gql.ServiceSecretResolver { type serviceSecretResolver struct{ *Resolver } -func (r *serviceSecretResolver) ServiceSecretID(ctx context.Context, obj *entity.ServiceSecret) (string, error) { +func (r *serviceSecretResolver) ServiceSecretID(ctx context.Context, obj *models.ServiceSecret) (string, error) { return obj.ServiceSecretID.String(), nil } @@ -29,32 +29,32 @@ func (r *Resolver) UserSecret() gql.UserSecretResolver { type userSecretResolver struct{ *Resolver } -func (r *userSecretResolver) UserSecretID(ctx context.Context, obj *entity.UserSecret) (string, error) { +func (r *userSecretResolver) UserSecretID(ctx context.Context, obj *models.UserSecret) (string, error) { return obj.UserSecretID.String(), nil } -func (r *queryResolver) SecretsForUser(ctx context.Context, userID uuid.UUID) ([]*entity.UserSecret, error) { +func (r *queryResolver) SecretsForUser(ctx context.Context, userID uuid.UUID) ([]*models.UserSecret, error) { secret := middleware.GetSecret(ctx) if secret.GetOwnerID() != userID { return nil, MakeUnauthenticatedError("Must be authenticated as userID") } - return entity.FindUserSecrets(ctx, userID), nil + return r.Secrets.FindUserSecrets(ctx, userID), nil } -func (r *queryResolver) SecretsForService(ctx context.Context, serviceID uuid.UUID) ([]*entity.ServiceSecret, error) { - service := entity.FindService(ctx, serviceID) +func (r *queryResolver) SecretsForService(ctx context.Context, serviceID uuid.UUID) ([]*models.ServiceSecret, error) { + service := r.Services.FindService(ctx, serviceID) if service == nil { return nil, gqlerror.Errorf("Service not found") } secret := middleware.GetSecret(ctx) - perms := secret.ProjectPermissions(ctx, service.ProjectID, false) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, service.ProjectID, false) if !perms.View { return nil, gqlerror.Errorf("Not allowed to read service secrets") } - return entity.FindServiceSecrets(ctx, serviceID), nil + return r.Secrets.FindServiceSecrets(ctx, serviceID), nil } func (r *mutationResolver) IssueUserSecret(ctx context.Context, description string, readOnly bool, publicOnly bool) (*gql.NewUserSecret, error) { @@ -63,7 +63,7 @@ func (r *mutationResolver) IssueUserSecret(ctx context.Context, description stri return nil, MakeUnauthenticatedError("Must be authenticated with a personal secret") } - secret, err := entity.CreateUserSecret(ctx, authSecret.GetOwnerID(), description, publicOnly, readOnly) + secret, err := r.Secrets.CreateUserSecret(ctx, authSecret.GetOwnerID(), description, publicOnly, readOnly) if err != nil { return nil, gqlerror.Errorf(err.Error()) } @@ -75,18 +75,18 @@ func (r *mutationResolver) IssueUserSecret(ctx context.Context, description stri } func (r *mutationResolver) IssueServiceSecret(ctx context.Context, serviceID uuid.UUID, description string) (*gql.NewServiceSecret, error) { - service := entity.FindService(ctx, serviceID) + service := r.Services.FindService(ctx, serviceID) if service == nil { return nil, gqlerror.Errorf("Service not found") } authSecret := middleware.GetSecret(ctx) - perms := authSecret.ProjectPermissions(ctx, service.ProjectID, false) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, authSecret, service.ProjectID, false) if !perms.Create { return nil, gqlerror.Errorf("Not allowed to perform create functions in the organization") } - secret, err := entity.CreateServiceSecret(ctx, serviceID, description) + secret, err := r.Secrets.CreateServiceSecret(ctx, serviceID, description) if err != nil { return nil, gqlerror.Errorf(err.Error()) } @@ -103,22 +103,22 @@ func (r *mutationResolver) RevokeServiceSecret(ctx context.Context, secretID uui return false, gqlerror.Errorf("Not allowed to edit secret") } - secret := entity.FindServiceSecret(ctx, secretID) + secret := r.Secrets.FindServiceSecret(ctx, secretID) if secret == nil { return false, gqlerror.Errorf("Secret not found") } - service := entity.FindService(ctx, secret.ServiceID) + service := r.Services.FindService(ctx, secret.ServiceID) if service == nil { return false, gqlerror.Errorf("Service not found") } - perms := authSecret.ProjectPermissions(ctx, service.ProjectID, false) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, authSecret, service.ProjectID, false) if !perms.Create { return false, gqlerror.Errorf("Not allowed to edit service") } - secret.Revoke(ctx) + r.Secrets.RevokeServiceSecret(ctx, secret) return true, nil } @@ -128,7 +128,7 @@ func (r *mutationResolver) RevokeUserSecret(ctx context.Context, secretID uuid.U return false, gqlerror.Errorf("Not allowed to edit secret") } - secret := entity.FindUserSecret(ctx, secretID) + secret := r.Secrets.FindUserSecret(ctx, secretID) if secret == nil { return false, gqlerror.Errorf("Secret not found") } @@ -137,6 +137,6 @@ func (r *mutationResolver) RevokeUserSecret(ctx context.Context, secretID uuid.U return false, gqlerror.Errorf("Not allowed to edit secret") } - secret.Revoke(ctx) + r.Secrets.RevokeUserSecret(ctx, secret) return true, nil } diff --git a/control/resolver/service.go b/server/control/resolver/service.go similarity index 59% rename from control/resolver/service.go rename to server/control/resolver/service.go index aeabada0..01f7a922 100644 --- a/control/resolver/service.go +++ b/server/control/resolver/service.go @@ -4,20 +4,20 @@ import ( "context" uuid "github.com/satori/go.uuid" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/gqlerror" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/services/middleware" ) -func (r *queryResolver) ServiceByID(ctx context.Context, serviceID uuid.UUID) (*entity.Service, error) { - service := entity.FindService(ctx, serviceID) +func (r *queryResolver) ServiceByID(ctx context.Context, serviceID uuid.UUID) (*models.Service, error) { + service := r.Services.FindService(ctx, serviceID) if service == nil { return nil, gqlerror.Errorf("Service %s not found", serviceID.String()) } secret := middleware.GetSecret(ctx) - perms := secret.ProjectPermissions(ctx, service.ProjectID, service.Project.Public) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, service.ProjectID, service.Project.Public) if !perms.View { return nil, gqlerror.Errorf("You are not allowed to view organization resources") } @@ -25,8 +25,8 @@ func (r *queryResolver) ServiceByID(ctx context.Context, serviceID uuid.UUID) (* return service, nil } -func (r *queryResolver) ServiceByOrganizationProjectAndName(ctx context.Context, organizationName string, projectName string, serviceName string) (*entity.Service, error) { - service := entity.FindServiceByOrganizationProjectAndName(ctx, organizationName, projectName, serviceName) +func (r *queryResolver) ServiceByOrganizationProjectAndName(ctx context.Context, organizationName string, projectName string, serviceName string) (*models.Service, error) { + service := r.Services.FindServiceByOrganizationProjectAndName(ctx, organizationName, projectName, serviceName) if service == nil { return nil, gqlerror.Errorf("Service %s/%s/%s not found", organizationName, projectName, serviceName) } @@ -34,7 +34,7 @@ func (r *queryResolver) ServiceByOrganizationProjectAndName(ctx context.Context, secret := middleware.GetSecret(ctx) selfFind := secret.IsService() && secret.GetOwnerID() == service.ServiceID if !selfFind { - perms := secret.ProjectPermissions(ctx, service.ProjectID, service.Project.Public) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, service.ProjectID, service.Project.Public) if !perms.View { return nil, gqlerror.Errorf("You are not allowed to view organization resources") } @@ -43,18 +43,19 @@ func (r *queryResolver) ServiceByOrganizationProjectAndName(ctx context.Context, return service, nil } -func (r *mutationResolver) StageService(ctx context.Context, organizationName string, projectName string, serviceName string, description *string, sourceURL *string, readQuota *int, writeQuota *int, scanQuota *int) (*entity.Service, error) { - var project *entity.Project - var service *entity.Service +func (r *mutationResolver) StageService(ctx context.Context, organizationName string, projectName string, serviceName string, description *string, sourceURL *string, readQuota *int, writeQuota *int, scanQuota *int) (*models.Service, error) { + var project *models.Project + var service *models.Service - service = entity.FindServiceByOrganizationProjectAndName(ctx, organizationName, projectName, serviceName) + service = r.Services.FindServiceByOrganizationProjectAndName(ctx, organizationName, projectName, serviceName) if service == nil { - project = entity.FindProjectByOrganizationAndName(ctx, organizationName, projectName) + project = r.Projects.FindProjectByOrganizationAndName(ctx, organizationName, projectName) if project == nil { return nil, gqlerror.Errorf("Project %s/%s not found", organizationName, projectName) } - service = &entity.Service{ + service = &models.Service{ Name: serviceName, + Project: project, ProjectID: project.ProjectID, } } else { @@ -62,12 +63,12 @@ func (r *mutationResolver) StageService(ctx context.Context, organizationName st } secret := middleware.GetSecret(ctx) - perms := secret.ProjectPermissions(ctx, project.ProjectID, project.Public) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, project.ProjectID, project.Public) if !perms.Create { return nil, gqlerror.Errorf("Not allowed to create or modify resources in project %s/%s", organizationName, projectName) } - err := service.Stage(ctx, description, sourceURL, IntToInt64(readQuota), IntToInt64(writeQuota), IntToInt64(scanQuota)) + err := r.Services.Stage(ctx, service, description, sourceURL, IntToInt64(readQuota), IntToInt64(writeQuota), IntToInt64(scanQuota)) if err != nil { return nil, gqlerror.Errorf("Error staging service: %s", err.Error()) } @@ -75,37 +76,37 @@ func (r *mutationResolver) StageService(ctx context.Context, organizationName st return service, nil } -func (r *mutationResolver) UpdateServiceStreamPermissions(ctx context.Context, serviceID uuid.UUID, streamID uuid.UUID, read *bool, write *bool) (*entity.PermissionsServicesStreams, error) { - service := entity.FindService(ctx, serviceID) +func (r *mutationResolver) UpdateServiceStreamPermissions(ctx context.Context, serviceID uuid.UUID, streamID uuid.UUID, read *bool, write *bool) (*models.PermissionsServicesStreams, error) { + service := r.Services.FindService(ctx, serviceID) if service == nil { return nil, gqlerror.Errorf("Service %s not found", serviceID.String()) } secret := middleware.GetSecret(ctx) - projPerms := secret.ProjectPermissions(ctx, service.ProjectID, false) + projPerms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, service.ProjectID, false) if !projPerms.Create { return nil, gqlerror.Errorf("Not allowed to edit the service") } - stream := entity.FindStream(ctx, streamID) + stream := r.Streams.FindStream(ctx, streamID) if stream == nil { return nil, gqlerror.Errorf("Stream %s not found", streamID.String()) } - streamProjectPerms := secret.ProjectPermissions(ctx, stream.ProjectID, false) + streamProjectPerms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, stream.ProjectID, false) if !streamProjectPerms.Create { return nil, gqlerror.Errorf("Not allowed to access stream") } - pss := entity.FindPermissionsServicesStreams(ctx, serviceID, streamID) + pss := r.Permissions.FindPermissionsServicesStreams(ctx, serviceID, streamID) if pss == nil { - pss = &entity.PermissionsServicesStreams{ + pss = &models.PermissionsServicesStreams{ ServiceID: serviceID, StreamID: streamID, } } - err := pss.Update(ctx, read, write) + err := r.Permissions.UpdateServiceStreamPermission(ctx, pss, read, write) if err != nil { return nil, err } @@ -114,18 +115,18 @@ func (r *mutationResolver) UpdateServiceStreamPermissions(ctx context.Context, s } func (r *mutationResolver) DeleteService(ctx context.Context, serviceID uuid.UUID) (bool, error) { - service := entity.FindService(ctx, serviceID) + service := r.Services.FindService(ctx, serviceID) if service == nil { return false, gqlerror.Errorf("Service %s not found", serviceID.String()) } secret := middleware.GetSecret(ctx) - perms := secret.ProjectPermissions(ctx, service.ProjectID, false) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, service.ProjectID, false) if !perms.Create { return false, gqlerror.Errorf("Not allowed to edit organization resources") } - err := service.Delete(ctx) + err := r.Services.Delete(ctx, service) if err != nil { return false, gqlerror.Errorf("Failed deleting service: %s", err.Error()) } diff --git a/server/control/resolver/stream.go b/server/control/resolver/stream.go new file mode 100644 index 00000000..d40b64de --- /dev/null +++ b/server/control/resolver/stream.go @@ -0,0 +1,268 @@ +package resolver + +import ( + "context" + + uuid "github.com/satori/go.uuid" + "github.com/vektah/gqlparser/v2/gqlerror" + + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/server/control/gql" + "gitlab.com/beneath-hq/beneath/services/middleware" +) + +// Stream returns the gql.StreamResolver +func (r *Resolver) Stream() gql.StreamResolver { + return &streamResolver{r} +} + +type streamResolver struct{ *Resolver } + +func (r *streamResolver) StreamID(ctx context.Context, obj *models.Stream) (string, error) { + return obj.StreamID.String(), nil +} + +func (r *queryResolver) StreamByID(ctx context.Context, streamID uuid.UUID) (*models.Stream, error) { + stream := r.Streams.FindStream(ctx, streamID) + if stream == nil { + return nil, gqlerror.Errorf("Stream with ID %s not found", streamID.String()) + } + + secret := middleware.GetSecret(ctx) + perms := r.Permissions.StreamPermissionsForSecret(ctx, secret, stream.StreamID, stream.ProjectID, stream.Project.Public) + if !perms.Read { + return nil, gqlerror.Errorf("Not allowed to read stream with ID %s", streamID.String()) + } + + return stream, nil +} + +func (r *queryResolver) StreamByOrganizationProjectAndName(ctx context.Context, organizationName string, projectName string, streamName string) (*models.Stream, error) { + stream := r.Streams.FindStreamByOrganizationProjectAndName(ctx, organizationName, projectName, streamName) + if stream == nil { + return nil, gqlerror.Errorf("Stream %s/%s/%s not found", organizationName, projectName, streamName) + } + + secret := middleware.GetSecret(ctx) + perms := r.Permissions.StreamPermissionsForSecret(ctx, secret, stream.StreamID, stream.ProjectID, stream.Project.Public) + if !perms.Read && !perms.Write { + return nil, gqlerror.Errorf("Not allowed to find stream %s/%s/%s", organizationName, projectName, streamName) + } + + return stream, nil +} + +func (r *queryResolver) StreamInstancesForStream(ctx context.Context, streamID uuid.UUID) ([]*models.StreamInstance, error) { + stream := r.Streams.FindStream(ctx, streamID) + if stream == nil { + return nil, gqlerror.Errorf("Stream with ID %s not found", streamID.String()) + } + + secret := middleware.GetSecret(ctx) + perms := r.Permissions.StreamPermissionsForSecret(ctx, secret, stream.StreamID, stream.ProjectID, stream.Project.Public) + if !perms.Read { + return nil, gqlerror.Errorf("Not allowed to read stream with ID %s", streamID.String()) + } + + instances := r.Streams.FindStreamInstances(ctx, streamID, nil, nil) + return instances, nil +} + +func (r *queryResolver) StreamInstancesByOrganizationProjectAndStreamName(ctx context.Context, organizationName string, projectName string, streamName string) ([]*models.StreamInstance, error) { + stream := r.Streams.FindStreamByOrganizationProjectAndName(ctx, organizationName, projectName, streamName) + if stream == nil { + return nil, gqlerror.Errorf("Stream %s/%s/%s not found", organizationName, projectName, streamName) + } + + secret := middleware.GetSecret(ctx) + perms := r.Permissions.StreamPermissionsForSecret(ctx, secret, stream.StreamID, stream.ProjectID, stream.Project.Public) + if !perms.Read { + return nil, gqlerror.Errorf("Not allowed to read stream with ID %s", stream.StreamID.String()) + } + + instances := r.Streams.FindStreamInstances(ctx, stream.StreamID, nil, nil) + return instances, nil +} + +func (r *mutationResolver) StageStream(ctx context.Context, organizationName string, projectName string, streamName string, schemaKind models.StreamSchemaKind, schema string, indexes *string, description *string, allowManualWrites *bool, useLog *bool, useIndex *bool, useWarehouse *bool, logRetentionSeconds *int, indexRetentionSeconds *int, warehouseRetentionSeconds *int) (*models.Stream, error) { + var project *models.Project + var stream *models.Stream + + secret := middleware.GetSecret(ctx) + + stream = r.Streams.FindStreamByOrganizationProjectAndName(ctx, organizationName, projectName, streamName) + if stream != nil { + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, stream.ProjectID, false) + if !perms.Create { + return nil, gqlerror.Errorf("Not allowed to create or modify resources in project %s/%s", organizationName, projectName) + } + + err := r.Streams.UpdateStream(ctx, &models.UpdateStreamCommand{ + Stream: stream, + SchemaKind: &schemaKind, + Schema: &schema, + Description: description, + AllowManualWrites: allowManualWrites, + }) + if err != nil { + return nil, gqlerror.Errorf("Error updating stream: %s", err.Error()) + } + return stream, nil + } + + project = r.Projects.FindProjectByOrganizationAndName(ctx, organizationName, projectName) + if project == nil { + return nil, gqlerror.Errorf("Project %s/%s not found", organizationName, projectName) + } + + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, project.ProjectID, project.Public) + if !perms.Create { + return nil, gqlerror.Errorf("Not allowed to create or modify resources in project %s/%s", organizationName, projectName) + } + + stream, err := r.Streams.CreateStream(ctx, &models.CreateStreamCommand{ + Project: project, + Name: streamName, + SchemaKind: schemaKind, + Schema: schema, + Indexes: indexes, + Description: description, + AllowManualWrites: allowManualWrites, + UseLog: useLog, + UseIndex: useIndex, + UseWarehouse: useWarehouse, + LogRetentionSeconds: logRetentionSeconds, + IndexRetentionSeconds: indexRetentionSeconds, + WarehouseRetentionSeconds: warehouseRetentionSeconds, + }) + if err != nil { + return nil, gqlerror.Errorf("Error creating stream: %s", err.Error()) + } + + _, err = r.Streams.CreateStreamInstance(ctx, stream, 0, true) + if err != nil { + return nil, gqlerror.Errorf("Error creating first instance: %s", err.Error()) + } + + return stream, nil +} + +func (r *mutationResolver) DeleteStream(ctx context.Context, streamID uuid.UUID) (bool, error) { + stream := r.Streams.FindStream(ctx, streamID) + if stream == nil { + return false, gqlerror.Errorf("Stream %s not found", streamID.String()) + } + + secret := middleware.GetSecret(ctx) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, stream.ProjectID, false) + if !perms.Create { + return false, gqlerror.Errorf("Not allowed to perform admin functions in project %s", stream.Project.Name) + } + + err := r.Streams.DeleteStream(ctx, stream) + if err != nil { + return false, gqlerror.Errorf("%s", err.Error()) + } + + return true, nil +} + +// MaxInstancesPerStream sets a limit for the number of instances for a stream at any given time +const MaxInstancesPerStream = 25 + +func (r *mutationResolver) StageStreamInstance(ctx context.Context, streamID uuid.UUID, version int, makeFinal *bool, makePrimary *bool) (*models.StreamInstance, error) { + falseVal := false + if makeFinal == nil { + makeFinal = &falseVal + } + if makePrimary == nil { + makePrimary = &falseVal + } + + secret := middleware.GetSecret(ctx) + + instance := r.Streams.FindStreamInstanceByVersion(ctx, streamID, version) + if instance != nil { + perms := r.Permissions.StreamPermissionsForSecret(ctx, secret, instance.Stream.StreamID, instance.Stream.ProjectID, false) + if !perms.Write { + return nil, gqlerror.Errorf("Not allowed to write to stream %s/%s", instance.Stream.Name, instance.Stream.Project.Name) + } + + err := r.Streams.UpdateStreamInstance(ctx, instance.Stream, instance, *makeFinal, *makePrimary) + if err != nil { + return nil, err + } + + return instance, nil + } + + stream := r.Streams.FindStream(ctx, streamID) + if stream == nil { + return nil, gqlerror.Errorf("Stream %s not found", streamID.String()) + } + + // check not too many instances + if stream.InstancesCreatedCount-stream.InstancesDeletedCount >= MaxInstancesPerStream { + return nil, gqlerror.Errorf("You cannot have more than %d instances per stream. Delete an existing instance to make room for more.", MaxInstancesPerStream) + } + + perms := r.Permissions.StreamPermissionsForSecret(ctx, secret, stream.StreamID, stream.ProjectID, stream.Project.Public) + if !perms.Write { + return nil, gqlerror.Errorf("Not allowed to write to stream %s/%s", stream.Name, stream.Project.Name) + } + + si, err := r.Streams.CreateStreamInstance(ctx, stream, version, *makePrimary) + if err != nil { + return nil, err + } + + return si, nil +} + +func (r *mutationResolver) UpdateStreamInstance(ctx context.Context, instanceID uuid.UUID, makeFinal *bool, makePrimary *bool) (*models.StreamInstance, error) { + instance := r.Streams.FindStreamInstance(ctx, instanceID) + if instance == nil { + return nil, gqlerror.Errorf("Stream instance '%s' not found", instanceID.String()) + } + + secret := middleware.GetSecret(ctx) + perms := r.Permissions.StreamPermissionsForSecret(ctx, secret, instance.Stream.StreamID, instance.Stream.ProjectID, false) + if !perms.Write { + return nil, gqlerror.Errorf("Not allowed to write to instance %s", instanceID.String()) + } + + falseVal := false + if makeFinal == nil { + makeFinal = &falseVal + } + if makePrimary == nil { + makePrimary = &falseVal + } + + err := r.Streams.UpdateStreamInstance(ctx, instance.Stream, instance, *makeFinal, *makePrimary) + if err != nil { + return nil, gqlerror.Errorf("Error updating stream instance: %s", err.Error()) + } + + return instance, nil +} + +func (r *mutationResolver) DeleteStreamInstance(ctx context.Context, instanceID uuid.UUID) (bool, error) { + instance := r.Streams.FindStreamInstance(ctx, instanceID) + if instance == nil { + return false, gqlerror.Errorf("Stream instance '%s' not found", instanceID.String()) + } + + secret := middleware.GetSecret(ctx) + perms := r.Permissions.StreamPermissionsForSecret(ctx, secret, instance.Stream.StreamID, instance.Stream.ProjectID, false) + if !perms.Write { + return false, gqlerror.Errorf("Not allowed to write to instance %s", instanceID.String()) + } + + err := r.Streams.DeleteStreamInstance(ctx, instance.Stream, instance) + if err != nil { + return false, gqlerror.Errorf("Couldn't delete stream instance: %s", err.Error()) + } + + return true, nil +} diff --git a/control/resolver/stream_index.go b/server/control/resolver/stream_index.go similarity index 72% rename from control/resolver/stream_index.go rename to server/control/resolver/stream_index.go index 14efdaa2..698c9d46 100644 --- a/control/resolver/stream_index.go +++ b/server/control/resolver/stream_index.go @@ -3,8 +3,8 @@ package resolver import ( "context" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/control/gql" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/server/control/gql" ) // StreamIndex returns the gql.StreamIndexResolver @@ -14,6 +14,6 @@ func (r *Resolver) StreamIndex() gql.StreamIndexResolver { type streamIndexResolver struct{ *Resolver } -func (r *streamIndexResolver) IndexID(ctx context.Context, obj *entity.StreamIndex) (string, error) { +func (r *streamIndexResolver) IndexID(ctx context.Context, obj *models.StreamIndex) (string, error) { return obj.StreamIndexID.String(), nil } diff --git a/control/resolver/stream_instance.go b/server/control/resolver/stream_instance.go similarity index 71% rename from control/resolver/stream_instance.go rename to server/control/resolver/stream_instance.go index 08e30d37..596e972c 100644 --- a/control/resolver/stream_instance.go +++ b/server/control/resolver/stream_instance.go @@ -3,8 +3,8 @@ package resolver import ( "context" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/control/gql" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/server/control/gql" ) // StreamInstance returns the gql.StreamInstanceResolver @@ -14,6 +14,6 @@ func (r *Resolver) StreamInstance() gql.StreamInstanceResolver { type streamInstanceResolver struct{ *Resolver } -func (r *streamInstanceResolver) StreamInstanceID(ctx context.Context, obj *entity.StreamInstance) (string, error) { +func (r *streamInstanceResolver) StreamInstanceID(ctx context.Context, obj *models.StreamInstance) (string, error) { return obj.StreamInstanceID.String(), nil } diff --git a/control/resolver/user.go b/server/control/resolver/user.go similarity index 62% rename from control/resolver/user.go rename to server/control/resolver/user.go index 54983b25..861b0cd3 100644 --- a/control/resolver/user.go +++ b/server/control/resolver/user.go @@ -4,11 +4,11 @@ import ( "context" uuid "github.com/satori/go.uuid" - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/gqlerror" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/control/gql" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/server/control/gql" + "gitlab.com/beneath-hq/beneath/services/middleware" ) // PrivateUser returns the gql.UserResolver @@ -18,22 +18,22 @@ func (r *Resolver) PrivateUser() gql.PrivateUserResolver { type privateUserResolver struct{ *Resolver } -func (r *privateUserResolver) UserID(ctx context.Context, obj *entity.User) (string, error) { +func (r *privateUserResolver) UserID(ctx context.Context, obj *models.User) (string, error) { return obj.UserID.String(), nil } -func (r *mutationResolver) RegisterUserConsent(ctx context.Context, userID uuid.UUID, terms *bool, newsletter *bool) (*entity.User, error) { +func (r *mutationResolver) RegisterUserConsent(ctx context.Context, userID uuid.UUID, terms *bool, newsletter *bool) (*models.User, error) { secret := middleware.GetSecret(ctx) if !(secret.IsUser() && secret.GetOwnerID() == userID) { return nil, gqlerror.Errorf("You can only register consent for yourself") } - user := entity.FindUser(ctx, userID) + user := r.Users.FindUser(ctx, userID) if user == nil { return nil, gqlerror.Errorf("Couldn't find user with ID %s", userID.String()) } - err := user.RegisterConsent(ctx, terms, newsletter) + err := r.Users.UpdateConsent(ctx, user, terms, newsletter) if err != nil { return nil, gqlerror.Errorf("Error: %s", err.Error()) } @@ -41,8 +41,8 @@ func (r *mutationResolver) RegisterUserConsent(ctx context.Context, userID uuid. return user, nil } -func (r *mutationResolver) UpdateUserQuotas(ctx context.Context, userID uuid.UUID, readQuota *int, writeQuota *int, scanQuota *int) (*entity.User, error) { - org := entity.FindOrganizationByUserID(ctx, userID) +func (r *mutationResolver) UpdateUserQuotas(ctx context.Context, userID uuid.UUID, readQuota *int, writeQuota *int, scanQuota *int) (*models.User, error) { + org := r.Organizations.FindOrganizationByUserID(ctx, userID) if org == nil { return nil, gqlerror.Errorf("User %s not found", userID.String()) } @@ -52,12 +52,12 @@ func (r *mutationResolver) UpdateUserQuotas(ctx context.Context, userID uuid.UUI } secret := middleware.GetSecret(ctx) - perms := secret.OrganizationPermissions(ctx, org.User.BillingOrganizationID) + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, org.User.BillingOrganizationID) if !perms.Admin { return nil, gqlerror.Errorf("Not allowed to perform admin functions in organization %s", org.User.BillingOrganizationID.String()) } - err := org.User.UpdateQuotas(ctx, IntToInt64(readQuota), IntToInt64(writeQuota), IntToInt64(scanQuota)) + err := r.Users.UpdateQuotas(ctx, org.User, IntToInt64(readQuota), IntToInt64(writeQuota), IntToInt64(scanQuota)) if err != nil { return nil, gqlerror.Errorf("Error updating quotas: %s", err.Error()) } @@ -65,22 +65,22 @@ func (r *mutationResolver) UpdateUserQuotas(ctx context.Context, userID uuid.UUI return org.User, nil } -func (r *mutationResolver) UpdateUserProjectPermissions(ctx context.Context, userID uuid.UUID, projectID uuid.UUID, view *bool, create *bool, admin *bool) (*entity.PermissionsUsersProjects, error) { +func (r *mutationResolver) UpdateUserProjectPermissions(ctx context.Context, userID uuid.UUID, projectID uuid.UUID, view *bool, create *bool, admin *bool) (*models.PermissionsUsersProjects, error) { secret := middleware.GetSecret(ctx) - perms := secret.ProjectPermissions(ctx, projectID, false) + perms := r.Permissions.ProjectPermissionsForSecret(ctx, secret, projectID, false) if !perms.Admin { return nil, gqlerror.Errorf("Not allowed to perform admin functions in project %s", projectID.String()) } - pup := entity.FindPermissionsUsersProjects(ctx, userID, projectID) + pup := r.Permissions.FindPermissionsUsersProjects(ctx, userID, projectID) if pup == nil { - pup = &entity.PermissionsUsersProjects{ + pup = &models.PermissionsUsersProjects{ UserID: userID, ProjectID: projectID, } } - err := pup.Update(ctx, view, create, admin) + err := r.Permissions.UpdateUserProjectPermission(ctx, pup, view, create, admin) if err != nil { return nil, err } @@ -88,14 +88,14 @@ func (r *mutationResolver) UpdateUserProjectPermissions(ctx context.Context, use return pup, nil } -func (r *mutationResolver) UpdateUserOrganizationPermissions(ctx context.Context, userID uuid.UUID, organizationID uuid.UUID, view *bool, create *bool, admin *bool) (*entity.PermissionsUsersOrganizations, error) { +func (r *mutationResolver) UpdateUserOrganizationPermissions(ctx context.Context, userID uuid.UUID, organizationID uuid.UUID, view *bool, create *bool, admin *bool) (*models.PermissionsUsersOrganizations, error) { secret := middleware.GetSecret(ctx) - perms := secret.OrganizationPermissions(ctx, organizationID) + perms := r.Permissions.OrganizationPermissionsForSecret(ctx, secret, organizationID) if !perms.Admin { return nil, gqlerror.Errorf("Not allowed to perform admin functions in organization %s", organizationID.String()) } - organization := entity.FindOrganization(ctx, organizationID) + organization := r.Organizations.FindOrganization(ctx, organizationID) if organization == nil { return nil, gqlerror.Errorf("Organization not found") } @@ -104,15 +104,15 @@ func (r *mutationResolver) UpdateUserOrganizationPermissions(ctx context.Context return nil, gqlerror.Errorf("Cannot edit permissions of personal organization") } - puo := entity.FindPermissionsUsersOrganizations(ctx, userID, organizationID) + puo := r.Permissions.FindPermissionsUsersOrganizations(ctx, userID, organizationID) if puo == nil { - puo = &entity.PermissionsUsersOrganizations{ + puo = &models.PermissionsUsersOrganizations{ UserID: userID, OrganizationID: organizationID, } } - err := puo.Update(ctx, view, create, admin) + err := r.Permissions.UpdateUserOrganizationPermission(ctx, puo, view, create, admin) if err != nil { return nil, err } diff --git a/control/resolver/util.go b/server/control/resolver/util.go similarity index 95% rename from control/resolver/util.go rename to server/control/resolver/util.go index f144771b..e70ba9cc 100644 --- a/control/resolver/util.go +++ b/server/control/resolver/util.go @@ -1,7 +1,7 @@ package resolver import ( - "github.com/vektah/gqlparser/gqlerror" + "github.com/vektah/gqlparser/v2/gqlerror" ) // DereferenceString does what it says it does diff --git a/control/gql/schema/base.graphql b/server/control/schema/base.graphql similarity index 100% rename from control/gql/schema/base.graphql rename to server/control/schema/base.graphql diff --git a/control/gql/schema/metrics.graphql b/server/control/schema/metrics.graphql similarity index 100% rename from control/gql/schema/metrics.graphql rename to server/control/schema/metrics.graphql diff --git a/control/gql/schema/organizations.graphql b/server/control/schema/organizations.graphql similarity index 100% rename from control/gql/schema/organizations.graphql rename to server/control/schema/organizations.graphql diff --git a/control/gql/schema/projects.graphql b/server/control/schema/projects.graphql similarity index 100% rename from control/gql/schema/projects.graphql rename to server/control/schema/projects.graphql diff --git a/control/gql/schema/secrets.graphql b/server/control/schema/secrets.graphql similarity index 100% rename from control/gql/schema/secrets.graphql rename to server/control/schema/secrets.graphql diff --git a/control/gql/schema/services.graphql b/server/control/schema/services.graphql similarity index 100% rename from control/gql/schema/services.graphql rename to server/control/schema/services.graphql diff --git a/control/gql/schema/streams.graphql b/server/control/schema/streams.graphql similarity index 100% rename from control/gql/schema/streams.graphql rename to server/control/schema/streams.graphql diff --git a/control/gql/schema/users.graphql b/server/control/schema/users.graphql similarity index 100% rename from control/gql/schema/users.graphql rename to server/control/schema/users.graphql diff --git a/server/control/server.go b/server/control/server.go new file mode 100644 index 00000000..f874dc50 --- /dev/null +++ b/server/control/server.go @@ -0,0 +1,204 @@ +package control + +import ( + "context" + "fmt" + "net/http" + "time" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/playground" + "github.com/go-chi/chi" + chimiddleware "github.com/go-chi/chi/middleware" + "github.com/rs/cors" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" + + "gitlab.com/beneath-hq/beneath/pkg/httputil" + "gitlab.com/beneath-hq/beneath/pkg/log" + "gitlab.com/beneath-hq/beneath/server/control/gql" + "gitlab.com/beneath-hq/beneath/server/control/resolver" + "gitlab.com/beneath-hq/beneath/services/metrics" + "gitlab.com/beneath-hq/beneath/services/middleware" + "gitlab.com/beneath-hq/beneath/services/organization" + "gitlab.com/beneath-hq/beneath/services/permissions" + "gitlab.com/beneath-hq/beneath/services/project" + "gitlab.com/beneath-hq/beneath/services/secret" + "gitlab.com/beneath-hq/beneath/services/service" + "gitlab.com/beneath-hq/beneath/services/stream" + "gitlab.com/beneath-hq/beneath/services/user" +) + +// ServerOptions are the options for creating a control server +type ServerOptions struct { + Host string + Port int + FrontendHost string `mapstructure:"frontend_host"` + SessionSecret string `mapstructure:"session_secret"` + Auth AuthOptions +} + +// Server is the control server +type Server struct { + Router *chi.Mux + Options *ServerOptions + + Metrics *metrics.Broker + Organizations *organization.Service + Permissions *permissions.Service + Projects *project.Service + Secrets *secret.Service + Services *service.Service + Streams *stream.Service + Users *user.Service +} + +// NewServer returns a new control server +func NewServer( + opts *ServerOptions, + metrics *metrics.Broker, + middleware *middleware.Service, + organization *organization.Service, + permissions *permissions.Service, + project *project.Service, + secret *secret.Service, + service *service.Service, + stream *stream.Service, + user *user.Service, +) *Server { + router := chi.NewRouter() + server := &Server{ + Router: router, + Options: opts, + Metrics: metrics, + Organizations: organization, + Permissions: permissions, + Projects: project, + Secrets: secret, + Services: service, + Streams: stream, + Users: user, + } + + corsOptions := cors.Options{ + AllowedOrigins: []string{ + opts.Host, + opts.FrontendHost, + }, + AllowedHeaders: []string{"*"}, + AllowCredentials: true, + Debug: false, + } + + router.Use(chimiddleware.RealIP) + router.Use(chimiddleware.DefaultCompress) + router.Use(cors.New(corsOptions).Handler) + router.Use(middleware.InjectTagsMiddleware) + router.Use(middleware.LoggerMiddleware) + router.Use(middleware.RecovererMiddleware) + router.Use(middleware.AuthMiddleware) + router.Use(middleware.IPRateLimitMiddleware) + + // Add health check + router.Get("/", server.healthCheck) + router.Get("/healthz", server.healthCheck) + + // Register auth endpoints + server.initGoth() + server.registerAuth() + + // Add error testing + router.Get("/error", func(w http.ResponseWriter, r *http.Request) { + panic(fmt.Errorf("Testing error at %v", time.Now())) + }) + + // Add playground + router.Handle("/playground", playground.Handler("Beneath", "/graphql")) + + // Add graphql server + gqlHandler := handler.New(server.makeExecutableSchema()) + gqlHandler.AroundResponses(graphqlQueryLoggingMiddleware) + gqlHandler.SetErrorPresenter(graphqlErrorPresenter) + gqlHandler.SetRecoverFunc(func(ctx context.Context, err interface{}) error { + panic(err) + }) + + return server +} + +// Run starts the control server +func (s *Server) Run(ctx context.Context) error { + log.S.Infof("serving control server on port %d", s.Options.Port) + httpServer := &http.Server{Handler: s.Router} + return httputil.ListenAndServeContext(ctx, httpServer, s.Options.Port) +} + +func (s *Server) healthCheck(w http.ResponseWriter, r *http.Request) { + healthy := true // TODO + if healthy { + w.WriteHeader(http.StatusOK) + w.Write([]byte(http.StatusText(http.StatusOK))) + } else { + log.S.Errorf("Control database health check failed") + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + } +} + +func (s *Server) makeExecutableSchema() graphql.ExecutableSchema { + return gql.NewExecutableSchema(gql.Config{Resolvers: &resolver.Resolver{ + Metrics: s.Metrics, + Organizations: s.Organizations, + Permissions: s.Permissions, + Projects: s.Projects, + Secrets: s.Secrets, + Services: s.Services, + Streams: s.Streams, + Users: s.Users, + }}) +} + +type gqlLog struct { + Op string `json:"op"` + Name string `json:"name,omitempty"` + Field string `json:"field"` + Error error `json:"error,omitempty"` + Vars map[string]interface{} `json:"vars,omitempty"` +} + +func graphqlErrorPresenter(ctx context.Context, err error) *gqlerror.Error { + tags := middleware.GetTags(ctx) + if q, ok := tags.Payload.(gqlLog); ok { + q.Error = err + } + // Uncomment this line to print resolver error details in the console + // fmt.Printf("Error in GraphQL Resolver: %s", err.Error()) + return graphql.DefaultErrorPresenter(ctx, err) +} + +func graphqlQueryLoggingMiddleware(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { + reqCtx := graphql.GetRequestContext(ctx) + middleware.SetTagsPayload(ctx, logInfoFromRequestContext(reqCtx)) + return next(ctx) +} + +func logInfoFromRequestContext(ctx *graphql.RequestContext) interface{} { + var queries []gqlLog + for _, op := range ctx.Doc.Operations { + for _, sel := range op.SelectionSet { + if field, ok := sel.(*ast.Field); ok { + name := op.Name + if name == "" { + name = "Unnamed" + } + queries = append(queries, gqlLog{ + Op: string(op.Operation), + Name: name, + Field: field.Name, + Vars: ctx.Variables, + }) + } + } + } + return queries +} diff --git a/gateway/README.md b/server/data/README.md similarity index 100% rename from gateway/README.md rename to server/data/README.md diff --git a/gateway/grpc/ping.go b/server/data/grpc/ping.go similarity index 71% rename from gateway/grpc/ping.go rename to server/data/grpc/ping.go index 9e9aa669..e978a99d 100644 --- a/gateway/grpc/ping.go +++ b/server/data/grpc/ping.go @@ -3,12 +3,12 @@ package grpc import ( "context" - "gitlab.com/beneath-hq/beneath/gateway/api" - pb "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" + pb "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" + "gitlab.com/beneath-hq/beneath/services/data" ) func (s *gRPCServer) Ping(ctx context.Context, req *pb.PingRequest) (*pb.PingResponse, error) { - res, err := api.HandlePing(ctx, &api.PingRequest{ + res, err := s.Service.HandlePing(ctx, &data.PingRequest{ ClientID: req.ClientId, ClientVersion: req.ClientVersion, }) diff --git a/gateway/grpc/proto/gateway.pb.go b/server/data/grpc/proto/gateway.pb.go similarity index 85% rename from gateway/grpc/proto/gateway.pb.go rename to server/data/grpc/proto/gateway.pb.go index 3e3954f5..eb85c397 100644 --- a/gateway/grpc/proto/gateway.pb.go +++ b/server/data/grpc/proto/gateway.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: gateway/grpc/proto/gateway.proto +// source: server/data/grpc/proto/gateway.proto package proto @@ -49,7 +49,7 @@ func (x WarehouseJob_Status) String() string { } func (WarehouseJob_Status) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{2, 0} + return fileDescriptor_7bc7b0f3637317a2, []int{2, 0} } type Record struct { @@ -64,7 +64,7 @@ func (m *Record) Reset() { *m = Record{} } func (m *Record) String() string { return proto.CompactTextString(m) } func (*Record) ProtoMessage() {} func (*Record) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{0} + return fileDescriptor_7bc7b0f3637317a2, []int{0} } func (m *Record) XXX_Unmarshal(b []byte) error { @@ -111,7 +111,7 @@ func (m *InstanceRecords) Reset() { *m = InstanceRecords{} } func (m *InstanceRecords) String() string { return proto.CompactTextString(m) } func (*InstanceRecords) ProtoMessage() {} func (*InstanceRecords) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{1} + return fileDescriptor_7bc7b0f3637317a2, []int{1} } func (m *InstanceRecords) XXX_Unmarshal(b []byte) error { @@ -165,7 +165,7 @@ func (m *WarehouseJob) Reset() { *m = WarehouseJob{} } func (m *WarehouseJob) String() string { return proto.CompactTextString(m) } func (*WarehouseJob) ProtoMessage() {} func (*WarehouseJob) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{2} + return fileDescriptor_7bc7b0f3637317a2, []int{2} } func (m *WarehouseJob) XXX_Unmarshal(b []byte) error { @@ -261,7 +261,7 @@ func (m *PingRequest) Reset() { *m = PingRequest{} } func (m *PingRequest) String() string { return proto.CompactTextString(m) } func (*PingRequest) ProtoMessage() {} func (*PingRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{3} + return fileDescriptor_7bc7b0f3637317a2, []int{3} } func (m *PingRequest) XXX_Unmarshal(b []byte) error { @@ -309,7 +309,7 @@ func (m *PingResponse) Reset() { *m = PingResponse{} } func (m *PingResponse) String() string { return proto.CompactTextString(m) } func (*PingResponse) ProtoMessage() {} func (*PingResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{4} + return fileDescriptor_7bc7b0f3637317a2, []int{4} } func (m *PingResponse) XXX_Unmarshal(b []byte) error { @@ -362,7 +362,7 @@ func (m *WriteRequest) Reset() { *m = WriteRequest{} } func (m *WriteRequest) String() string { return proto.CompactTextString(m) } func (*WriteRequest) ProtoMessage() {} func (*WriteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{5} + return fileDescriptor_7bc7b0f3637317a2, []int{5} } func (m *WriteRequest) XXX_Unmarshal(b []byte) error { @@ -401,7 +401,7 @@ func (m *WriteResponse) Reset() { *m = WriteResponse{} } func (m *WriteResponse) String() string { return proto.CompactTextString(m) } func (*WriteResponse) ProtoMessage() {} func (*WriteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{6} + return fileDescriptor_7bc7b0f3637317a2, []int{6} } func (m *WriteResponse) XXX_Unmarshal(b []byte) error { @@ -442,7 +442,7 @@ func (m *QueryLogRequest) Reset() { *m = QueryLogRequest{} } func (m *QueryLogRequest) String() string { return proto.CompactTextString(m) } func (*QueryLogRequest) ProtoMessage() {} func (*QueryLogRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{7} + return fileDescriptor_7bc7b0f3637317a2, []int{7} } func (m *QueryLogRequest) XXX_Unmarshal(b []byte) error { @@ -496,7 +496,7 @@ func (m *QueryLogResponse) Reset() { *m = QueryLogResponse{} } func (m *QueryLogResponse) String() string { return proto.CompactTextString(m) } func (*QueryLogResponse) ProtoMessage() {} func (*QueryLogResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{8} + return fileDescriptor_7bc7b0f3637317a2, []int{8} } func (m *QueryLogResponse) XXX_Unmarshal(b []byte) error { @@ -544,7 +544,7 @@ func (m *QueryIndexRequest) Reset() { *m = QueryIndexRequest{} } func (m *QueryIndexRequest) String() string { return proto.CompactTextString(m) } func (*QueryIndexRequest) ProtoMessage() {} func (*QueryIndexRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{9} + return fileDescriptor_7bc7b0f3637317a2, []int{9} } func (m *QueryIndexRequest) XXX_Unmarshal(b []byte) error { @@ -598,7 +598,7 @@ func (m *QueryIndexResponse) Reset() { *m = QueryIndexResponse{} } func (m *QueryIndexResponse) String() string { return proto.CompactTextString(m) } func (*QueryIndexResponse) ProtoMessage() {} func (*QueryIndexResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{10} + return fileDescriptor_7bc7b0f3637317a2, []int{10} } func (m *QueryIndexResponse) XXX_Unmarshal(b []byte) error { @@ -648,7 +648,7 @@ func (m *QueryWarehouseRequest) Reset() { *m = QueryWarehouseRequest{} } func (m *QueryWarehouseRequest) String() string { return proto.CompactTextString(m) } func (*QueryWarehouseRequest) ProtoMessage() {} func (*QueryWarehouseRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{11} + return fileDescriptor_7bc7b0f3637317a2, []int{11} } func (m *QueryWarehouseRequest) XXX_Unmarshal(b []byte) error { @@ -715,7 +715,7 @@ func (m *QueryWarehouseResponse) Reset() { *m = QueryWarehouseResponse{} func (m *QueryWarehouseResponse) String() string { return proto.CompactTextString(m) } func (*QueryWarehouseResponse) ProtoMessage() {} func (*QueryWarehouseResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{12} + return fileDescriptor_7bc7b0f3637317a2, []int{12} } func (m *QueryWarehouseResponse) XXX_Unmarshal(b []byte) error { @@ -754,7 +754,7 @@ func (m *PollWarehouseJobRequest) Reset() { *m = PollWarehouseJobRequest func (m *PollWarehouseJobRequest) String() string { return proto.CompactTextString(m) } func (*PollWarehouseJobRequest) ProtoMessage() {} func (*PollWarehouseJobRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{13} + return fileDescriptor_7bc7b0f3637317a2, []int{13} } func (m *PollWarehouseJobRequest) XXX_Unmarshal(b []byte) error { @@ -793,7 +793,7 @@ func (m *PollWarehouseJobResponse) Reset() { *m = PollWarehouseJobRespon func (m *PollWarehouseJobResponse) String() string { return proto.CompactTextString(m) } func (*PollWarehouseJobResponse) ProtoMessage() {} func (*PollWarehouseJobResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{14} + return fileDescriptor_7bc7b0f3637317a2, []int{14} } func (m *PollWarehouseJobResponse) XXX_Unmarshal(b []byte) error { @@ -833,7 +833,7 @@ func (m *ReadRequest) Reset() { *m = ReadRequest{} } func (m *ReadRequest) String() string { return proto.CompactTextString(m) } func (*ReadRequest) ProtoMessage() {} func (*ReadRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{15} + return fileDescriptor_7bc7b0f3637317a2, []int{15} } func (m *ReadRequest) XXX_Unmarshal(b []byte) error { @@ -880,7 +880,7 @@ func (m *ReadResponse) Reset() { *m = ReadResponse{} } func (m *ReadResponse) String() string { return proto.CompactTextString(m) } func (*ReadResponse) ProtoMessage() {} func (*ReadResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{16} + return fileDescriptor_7bc7b0f3637317a2, []int{16} } func (m *ReadResponse) XXX_Unmarshal(b []byte) error { @@ -926,7 +926,7 @@ func (m *SubscribeRequest) Reset() { *m = SubscribeRequest{} } func (m *SubscribeRequest) String() string { return proto.CompactTextString(m) } func (*SubscribeRequest) ProtoMessage() {} func (*SubscribeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{17} + return fileDescriptor_7bc7b0f3637317a2, []int{17} } func (m *SubscribeRequest) XXX_Unmarshal(b []byte) error { @@ -965,7 +965,7 @@ func (m *SubscribeResponse) Reset() { *m = SubscribeResponse{} } func (m *SubscribeResponse) String() string { return proto.CompactTextString(m) } func (*SubscribeResponse) ProtoMessage() {} func (*SubscribeResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1fb7a2419213bb16, []int{18} + return fileDescriptor_7bc7b0f3637317a2, []int{18} } func (m *SubscribeResponse) XXX_Unmarshal(b []byte) error { @@ -1016,76 +1016,78 @@ func init() { proto.RegisterType((*SubscribeResponse)(nil), "gateway.v1.SubscribeResponse") } -func init() { proto.RegisterFile("gateway/grpc/proto/gateway.proto", fileDescriptor_1fb7a2419213bb16) } - -var fileDescriptor_1fb7a2419213bb16 = []byte{ - // 1045 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x6f, 0x4f, 0x1b, 0xc7, - 0x13, 0xc6, 0xf8, 0xff, 0xd8, 0x06, 0xb3, 0xbf, 0x00, 0x17, 0x27, 0x24, 0xfe, 0x5d, 0x52, 0x09, - 0x21, 0x6a, 0x53, 0x2a, 0xb5, 0x2f, 0x90, 0x2a, 0x95, 0x90, 0x20, 0x57, 0x09, 0x25, 0x8b, 0x9a, - 0xa8, 0x95, 0xaa, 0xcb, 0xde, 0xdd, 0x82, 0x8f, 0xda, 0xb7, 0x66, 0x77, 0x8f, 0xe0, 0x7c, 0x86, - 0x7e, 0x98, 0xf6, 0x43, 0xf5, 0x7b, 0x54, 0xb7, 0xbb, 0x77, 0xbe, 0xb3, 0x21, 0x48, 0x55, 0xfb, - 0x0a, 0xcf, 0x33, 0xcf, 0xce, 0xcc, 0xce, 0xcc, 0x3e, 0x07, 0x74, 0x2f, 0x88, 0xa4, 0x1f, 0xc9, - 0xb4, 0x7f, 0xc1, 0x27, 0x5e, 0x7f, 0xc2, 0x99, 0x64, 0x7d, 0x03, 0xf5, 0x94, 0x85, 0x20, 0x31, - 0xaf, 0xbf, 0xb2, 0x5f, 0x40, 0x05, 0x53, 0x8f, 0x71, 0x1f, 0x3d, 0x82, 0x3a, 0xb9, 0xe6, 0xcc, - 0xf1, 0x89, 0x24, 0x56, 0xa1, 0x5b, 0xd8, 0x6e, 0xe2, 0x5a, 0x0c, 0x1c, 0x11, 0x49, 0xd0, 0x63, - 0xa8, 0xcb, 0x60, 0x4c, 0x85, 0x24, 0xe3, 0x89, 0xb5, 0xdc, 0x2d, 0x6c, 0x17, 0xf1, 0x0c, 0xb0, - 0x3f, 0xc0, 0xea, 0x20, 0x14, 0x92, 0x84, 0x1e, 0xd5, 0xc1, 0x04, 0x7a, 0x0a, 0x8d, 0xc0, 0x40, - 0x4e, 0xe0, 0x9b, 0x78, 0x90, 0x40, 0x03, 0x1f, 0xed, 0x42, 0x95, 0x6b, 0xae, 0xb5, 0xdc, 0x2d, - 0x6e, 0x37, 0xf6, 0x51, 0x6f, 0x56, 0x56, 0x4f, 0x87, 0xc1, 0x09, 0xc5, 0xfe, 0xa3, 0x08, 0xcd, - 0xf7, 0x84, 0xd3, 0x21, 0x8b, 0x04, 0xfd, 0x81, 0xb9, 0x68, 0x1d, 0x2a, 0x97, 0xcc, 0x9d, 0x85, - 0x2e, 0x5f, 0x32, 0x77, 0xe0, 0xa3, 0x6f, 0xa1, 0x22, 0x24, 0x91, 0x91, 0x50, 0x45, 0xae, 0xec, - 0x3f, 0xcd, 0x06, 0xcd, 0x06, 0xe8, 0x9d, 0x29, 0x1a, 0x36, 0x74, 0xf4, 0x00, 0xca, 0x94, 0x73, - 0xc6, 0xad, 0x62, 0xb7, 0xb0, 0x5d, 0xc7, 0xda, 0x40, 0xbb, 0x80, 0x38, 0x15, 0xd1, 0x48, 0x3a, - 0xaa, 0x35, 0xc2, 0x1b, 0xd2, 0x31, 0xb1, 0x4a, 0x8a, 0xd2, 0xd6, 0x9e, 0xef, 0xaf, 0x39, 0x3b, - 0x53, 0x38, 0xfa, 0x02, 0x56, 0x38, 0x9d, 0x8c, 0xc8, 0xd4, 0xf1, 0x22, 0x2e, 0x18, 0x17, 0x56, - 0xb9, 0x5b, 0xdc, 0x6e, 0xe2, 0x96, 0x46, 0x5f, 0x68, 0x10, 0x7d, 0x03, 0x9b, 0x9c, 0x9e, 0x53, - 0x4e, 0x43, 0x8f, 0xfa, 0x4e, 0xa6, 0x4b, 0xc2, 0xaa, 0x28, 0xfe, 0xfa, 0xcc, 0x3d, 0x48, 0x1b, - 0x26, 0xd0, 0x33, 0x68, 0xb9, 0x53, 0x49, 0x85, 0x23, 0x3c, 0x12, 0x86, 0xd4, 0xb7, 0xaa, 0x6a, - 0x0e, 0x4d, 0x05, 0x9e, 0x69, 0x0c, 0xed, 0xc0, 0x9a, 0xa9, 0x58, 0x04, 0x9f, 0xa8, 0xa3, 0x7c, - 0x56, 0x4d, 0x11, 0x57, 0xb5, 0xe3, 0x2c, 0xf8, 0x44, 0x0f, 0x63, 0x18, 0xf5, 0xe0, 0x7f, 0x59, - 0x6e, 0x32, 0x8e, 0xba, 0x62, 0xaf, 0xcd, 0xd8, 0x66, 0xa6, 0xf6, 0x2e, 0x54, 0x74, 0xd7, 0x50, - 0x03, 0xaa, 0xa7, 0x2f, 0x4f, 0x8e, 0x06, 0x27, 0xc7, 0xed, 0xa5, 0xd8, 0xc0, 0x3f, 0x9d, 0x9c, - 0xc4, 0x46, 0x01, 0xd5, 0xa0, 0x74, 0xf4, 0xe3, 0xc9, 0xcb, 0xf6, 0xb2, 0xfd, 0x16, 0x1a, 0xa7, - 0x41, 0x78, 0x81, 0xe9, 0x55, 0x44, 0x85, 0x8c, 0xd7, 0xcb, 0x1b, 0x05, 0x34, 0x94, 0xc9, 0xcc, - 0xea, 0xb8, 0xa6, 0x81, 0x81, 0x1f, 0x77, 0xce, 0x38, 0xaf, 0x29, 0x17, 0x01, 0x0b, 0xd5, 0xf8, - 0xea, 0xb8, 0xa5, 0xd1, 0x77, 0x1a, 0xb4, 0x7f, 0x2f, 0x40, 0x53, 0xc7, 0x14, 0x13, 0x16, 0x0a, - 0x8a, 0x9e, 0x43, 0x8b, 0x44, 0x72, 0x48, 0x43, 0x19, 0x78, 0x44, 0x52, 0x1d, 0xb8, 0x86, 0xf3, - 0x60, 0x1c, 0xdd, 0x84, 0x75, 0x32, 0xcb, 0x51, 0xc7, 0x2d, 0x83, 0x9a, 0x4b, 0xf5, 0xe3, 0x76, - 0x78, 0x6c, 0x3c, 0xa6, 0xa1, 0x4f, 0xfd, 0xb4, 0x12, 0xbd, 0x10, 0x28, 0xe3, 0x4a, 0xca, 0x79, - 0x07, 0xcd, 0xf7, 0x3c, 0x90, 0x34, 0xb9, 0xe2, 0x2b, 0x68, 0xa7, 0xd3, 0x4c, 0x9a, 0x59, 0x50, - 0xbb, 0xfd, 0x28, 0xbb, 0x86, 0x73, 0x4f, 0x05, 0xaf, 0x06, 0x79, 0xc0, 0xde, 0x81, 0x96, 0x89, - 0x6b, 0xae, 0xf9, 0x10, 0x6a, 0x1f, 0x63, 0x60, 0xb6, 0xee, 0x55, 0x65, 0x0f, 0x7c, 0xfb, 0x1c, - 0x56, 0xdf, 0x46, 0x94, 0x4f, 0x5f, 0xb3, 0xb4, 0xd3, 0xf7, 0x3e, 0xbd, 0x27, 0x00, 0x13, 0xc2, - 0x65, 0x20, 0x03, 0x16, 0xea, 0x5e, 0x94, 0x71, 0x06, 0x41, 0x08, 0x4a, 0x13, 0x4a, 0x7f, 0x53, - 0x37, 0xaf, 0x61, 0xf5, 0xdb, 0xfe, 0x00, 0xed, 0x59, 0x1e, 0x53, 0xd6, 0xe2, 0xbe, 0x17, 0x6e, - 0xdb, 0xf7, 0x78, 0xb8, 0x43, 0x12, 0x5e, 0xd0, 0x94, 0xb6, 0xac, 0x69, 0x1a, 0x35, 0x34, 0x7b, - 0x04, 0x6b, 0x2a, 0xc3, 0x20, 0xf4, 0xe9, 0xcd, 0xbf, 0x76, 0x97, 0x0d, 0xa8, 0x9c, 0x07, 0x23, - 0x49, 0x93, 0x87, 0x6d, 0x2c, 0xdb, 0x05, 0x94, 0xcd, 0xf6, 0x9f, 0xdc, 0xe8, 0xcf, 0x02, 0xac, - 0xab, 0x24, 0xa9, 0xf0, 0x24, 0xd7, 0x7a, 0x00, 0xe5, 0xab, 0xd8, 0x61, 0x1e, 0x82, 0x36, 0xee, - 0xbd, 0xcb, 0x26, 0x54, 0x7d, 0x3e, 0x75, 0x78, 0x14, 0x9a, 0xd1, 0x54, 0x7c, 0x3e, 0xc5, 0x51, - 0x88, 0xb6, 0x00, 0x62, 0x31, 0x66, 0x91, 0x74, 0xc6, 0x42, 0xc9, 0x53, 0x59, 0xcb, 0x33, 0x8b, - 0xe4, 0x1b, 0x11, 0x6b, 0xc2, 0x98, 0xdc, 0x38, 0x79, 0xf1, 0x28, 0x6b, 0x4d, 0x18, 0x93, 0x9b, - 0xc3, 0x8c, 0x7e, 0xd8, 0x47, 0xb0, 0x31, 0x5f, 0xb2, 0xe9, 0xcd, 0x0e, 0x14, 0x2f, 0x99, 0xab, - 0x2a, 0x6e, 0xec, 0x5b, 0x77, 0xe9, 0x2a, 0x8e, 0x49, 0xf6, 0x1e, 0x6c, 0x9e, 0xb2, 0xd1, 0x28, - 0xe7, 0x30, 0x57, 0xbf, 0x5d, 0xb8, 0xed, 0x57, 0x60, 0x2d, 0x9e, 0xf8, 0x07, 0x99, 0x0f, 0xa0, - 0x81, 0x29, 0xf1, 0x93, 0x6c, 0x1b, 0x50, 0xd1, 0x23, 0x52, 0xed, 0x6c, 0x62, 0x63, 0xc5, 0x03, - 0x18, 0x05, 0xe3, 0x40, 0xaa, 0x46, 0x96, 0xb1, 0x36, 0xec, 0x5f, 0xa1, 0xa9, 0x0f, 0x9b, 0xc4, - 0x99, 0x6f, 0x54, 0xe1, 0xde, 0x6f, 0x54, 0xbc, 0xab, 0x21, 0xbd, 0x91, 0x4e, 0x2e, 0x21, 0xc4, - 0x90, 0x5e, 0x08, 0x7b, 0x07, 0xda, 0x67, 0x91, 0x2b, 0x3c, 0x1e, 0xb8, 0xf4, 0x9e, 0x02, 0xed, - 0x1e, 0xac, 0x65, 0xb8, 0xf7, 0xea, 0xc0, 0xfe, 0x5f, 0x25, 0xa8, 0x1e, 0xeb, 0xda, 0xd0, 0x01, - 0x94, 0x62, 0x95, 0x44, 0x9b, 0xd9, 0x6a, 0x33, 0x5a, 0xdc, 0xb1, 0x16, 0x1d, 0x3a, 0x83, 0xbd, - 0x84, 0xbe, 0x83, 0xb2, 0x12, 0x1f, 0x94, 0x6f, 0x74, 0x46, 0xe7, 0x3a, 0x0f, 0x6f, 0xf1, 0xa4, - 0xe7, 0x8f, 0xa1, 0x96, 0x08, 0x05, 0xca, 0xc9, 0xde, 0x9c, 0x4c, 0x75, 0x1e, 0xdf, 0xee, 0x4c, - 0x03, 0xbd, 0x01, 0x98, 0xbd, 0x50, 0xb4, 0xb5, 0xc0, 0xce, 0xea, 0x44, 0xe7, 0xc9, 0x5d, 0xee, - 0x34, 0xdc, 0xcf, 0xb0, 0x92, 0x5f, 0x6c, 0xf4, 0xff, 0x85, 0x33, 0xf3, 0xef, 0xb4, 0x63, 0x7f, - 0x8e, 0x92, 0x86, 0x76, 0xa0, 0x3d, 0xbf, 0xbb, 0xe8, 0x59, 0xae, 0xc5, 0xb7, 0xbf, 0x85, 0xce, - 0xf3, 0xcf, 0x93, 0xd2, 0x04, 0x07, 0x50, 0x8a, 0xf7, 0x32, 0x3f, 0xd0, 0xcc, 0x9a, 0xe7, 0x07, - 0x9a, 0x5d, 0x61, 0x7b, 0x09, 0xbd, 0x86, 0x7a, 0xba, 0x49, 0x28, 0xd7, 0xf4, 0xf9, 0x65, 0xec, - 0x6c, 0xdd, 0xe1, 0x4d, 0x62, 0xed, 0x15, 0x0e, 0xf7, 0x7f, 0xd9, 0xbb, 0x08, 0xe4, 0x88, 0xb8, - 0x3d, 0x8f, 0x8d, 0xfb, 0x2e, 0x0d, 0x29, 0x91, 0xc3, 0x2f, 0x87, 0x57, 0xc9, 0xcf, 0xfe, 0xe2, - 0x7f, 0x9f, 0x6e, 0x45, 0xfd, 0xf9, 0xfa, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xab, 0x6f, 0xc9, - 0xe3, 0x9a, 0x0a, 0x00, 0x00, +func init() { + proto.RegisterFile("server/data/grpc/proto/gateway.proto", fileDescriptor_7bc7b0f3637317a2) +} + +var fileDescriptor_7bc7b0f3637317a2 = []byte{ + // 1050 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xff, 0x4e, 0xdc, 0x46, + 0x10, 0xc6, 0xdc, 0xef, 0xb9, 0x3b, 0x38, 0xb6, 0x01, 0x9c, 0x4b, 0x48, 0xa8, 0x43, 0x25, 0x84, + 0xe8, 0x5d, 0x4a, 0xab, 0xf4, 0x0f, 0xa4, 0x4a, 0x25, 0x24, 0xe8, 0xaa, 0x84, 0x92, 0x45, 0x4d, + 0xd4, 0x4a, 0x95, 0xb3, 0xb6, 0x17, 0xce, 0xf4, 0xec, 0x3d, 0x76, 0xd7, 0x84, 0xcb, 0x33, 0xf4, + 0x61, 0xda, 0x87, 0xea, 0x7b, 0x54, 0xde, 0xb5, 0x7d, 0xf6, 0x71, 0x04, 0xa9, 0x6a, 0xfe, 0xe2, + 0xe6, 0x9b, 0x6f, 0x67, 0x66, 0x67, 0x66, 0x3f, 0x03, 0x5b, 0x82, 0xf2, 0x2b, 0xca, 0xfb, 0x1e, + 0x91, 0xa4, 0x7f, 0xce, 0xc7, 0x6e, 0x7f, 0xcc, 0x99, 0x64, 0xfd, 0x73, 0x22, 0xe9, 0x07, 0x32, + 0xe9, 0x29, 0x0b, 0x41, 0x6a, 0x5e, 0x7d, 0x63, 0x3d, 0x87, 0x2a, 0xa6, 0x2e, 0xe3, 0x1e, 0x7a, + 0x00, 0x0d, 0x72, 0xc5, 0x99, 0x1d, 0x9f, 0x35, 0x8d, 0x4d, 0x63, 0xbb, 0x85, 0xeb, 0x31, 0x70, + 0x48, 0x24, 0x41, 0x0f, 0xa1, 0x21, 0xfd, 0x80, 0x0a, 0x49, 0x82, 0xb1, 0xb9, 0xb8, 0x69, 0x6c, + 0x97, 0xf0, 0x14, 0xb0, 0xde, 0xc3, 0xf2, 0x20, 0x14, 0x92, 0x84, 0x2e, 0xd5, 0xc1, 0x04, 0x7a, + 0x0c, 0x4d, 0x3f, 0x81, 0x6c, 0xdf, 0x4b, 0xe2, 0x41, 0x0a, 0x0d, 0x3c, 0xb4, 0x0b, 0x35, 0xae, + 0xb9, 0xe6, 0xe2, 0x66, 0x69, 0xbb, 0xb9, 0x87, 0x7a, 0xd3, 0xb2, 0x7a, 0x3a, 0x0c, 0x4e, 0x29, + 0xd6, 0x5f, 0x25, 0x68, 0xbd, 0x23, 0x9c, 0x0e, 0x59, 0x24, 0xe8, 0x4f, 0xcc, 0x41, 0xab, 0x50, + 0xbd, 0x60, 0xce, 0x34, 0x74, 0xe5, 0x82, 0x39, 0x03, 0x0f, 0x7d, 0x0f, 0x55, 0x21, 0x89, 0x8c, + 0x84, 0x2a, 0x72, 0x69, 0xef, 0x71, 0x3e, 0x68, 0x3e, 0x40, 0xef, 0x54, 0xd1, 0x70, 0x42, 0x47, + 0xf7, 0xa0, 0x42, 0x39, 0x67, 0xdc, 0x2c, 0x6d, 0x1a, 0xdb, 0x0d, 0xac, 0x0d, 0xb4, 0x0b, 0x88, + 0x53, 0x11, 0x8d, 0xa4, 0xad, 0x5a, 0x23, 0xdc, 0x21, 0x0d, 0x88, 0x59, 0x56, 0x94, 0x8e, 0xf6, + 0xfc, 0x78, 0xc5, 0xd9, 0xa9, 0xc2, 0xd1, 0x57, 0xb0, 0xc4, 0xe9, 0x78, 0x44, 0x26, 0xb6, 0x1b, + 0x71, 0xc1, 0xb8, 0x30, 0x2b, 0x9b, 0xa5, 0xed, 0x16, 0x6e, 0x6b, 0xf4, 0xb9, 0x06, 0xd1, 0x33, + 0x58, 0xe7, 0xf4, 0x8c, 0x72, 0x1a, 0xba, 0xd4, 0xb3, 0x73, 0x5d, 0x12, 0x66, 0x55, 0xf1, 0x57, + 0xa7, 0xee, 0x41, 0xd6, 0x30, 0x81, 0x9e, 0x40, 0xdb, 0x99, 0x48, 0x2a, 0x6c, 0xe1, 0x92, 0x30, + 0xa4, 0x9e, 0x59, 0x53, 0x73, 0x68, 0x29, 0xf0, 0x54, 0x63, 0x68, 0x07, 0x56, 0x92, 0x8a, 0x85, + 0xff, 0x91, 0xda, 0xca, 0x67, 0xd6, 0x15, 0x71, 0x59, 0x3b, 0x4e, 0xfd, 0x8f, 0xf4, 0x20, 0x86, + 0x51, 0x0f, 0xbe, 0xc8, 0x73, 0xd3, 0x71, 0x34, 0x14, 0x7b, 0x65, 0xca, 0x4e, 0x66, 0x6a, 0xed, + 0x42, 0x55, 0x77, 0x0d, 0x35, 0xa1, 0x76, 0xf2, 0xe2, 0xf8, 0x70, 0x70, 0x7c, 0xd4, 0x59, 0x88, + 0x0d, 0xfc, 0xcb, 0xf1, 0x71, 0x6c, 0x18, 0xa8, 0x0e, 0xe5, 0xc3, 0x9f, 0x8f, 0x5f, 0x74, 0x16, + 0xad, 0x37, 0xd0, 0x3c, 0xf1, 0xc3, 0x73, 0x4c, 0x2f, 0x23, 0x2a, 0x64, 0xbc, 0x5e, 0xee, 0xc8, + 0xa7, 0xa1, 0x4c, 0x67, 0xd6, 0xc0, 0x75, 0x0d, 0x0c, 0xbc, 0xb8, 0x73, 0x89, 0xf3, 0x8a, 0x72, + 0xe1, 0xb3, 0x50, 0x8d, 0xaf, 0x81, 0xdb, 0x1a, 0x7d, 0xab, 0x41, 0xeb, 0x4f, 0x03, 0x5a, 0x3a, + 0xa6, 0x18, 0xb3, 0x50, 0x50, 0xb4, 0x05, 0x6d, 0x12, 0xc9, 0x21, 0x0d, 0xa5, 0xef, 0x12, 0x49, + 0x75, 0xe0, 0x3a, 0x2e, 0x82, 0x71, 0xf4, 0x24, 0xac, 0x9d, 0x5b, 0x8e, 0x06, 0x6e, 0x27, 0x68, + 0x72, 0xa9, 0x7e, 0xdc, 0x0e, 0x97, 0x05, 0x01, 0x0d, 0x3d, 0xea, 0x65, 0x95, 0xe8, 0x85, 0x40, + 0x39, 0x57, 0x5a, 0xce, 0x5b, 0x68, 0xbd, 0xe3, 0xbe, 0xa4, 0xe9, 0x15, 0x5f, 0x42, 0x27, 0x9b, + 0x66, 0xda, 0x4c, 0x43, 0xed, 0xf6, 0x83, 0xfc, 0x1a, 0xce, 0x3c, 0x15, 0xbc, 0xec, 0x17, 0x01, + 0x6b, 0x07, 0xda, 0x49, 0xdc, 0xe4, 0x9a, 0xf7, 0xa1, 0xfe, 0x21, 0x06, 0xa6, 0xeb, 0x5e, 0x53, + 0xf6, 0xc0, 0xb3, 0xce, 0x60, 0xf9, 0x4d, 0x44, 0xf9, 0xe4, 0x15, 0xcb, 0x3a, 0x7d, 0xe7, 0xd3, + 0x7b, 0x04, 0x30, 0x26, 0x5c, 0xfa, 0xd2, 0x67, 0xa1, 0xee, 0x45, 0x05, 0xe7, 0x10, 0x84, 0xa0, + 0x3c, 0xa6, 0xf4, 0x0f, 0x75, 0xf3, 0x3a, 0x56, 0xbf, 0xad, 0xf7, 0xd0, 0x99, 0xe6, 0x49, 0xca, + 0xba, 0xb9, 0xef, 0xc6, 0xbc, 0x7d, 0x8f, 0x87, 0x3b, 0x24, 0xe1, 0x39, 0xcd, 0x68, 0x8b, 0x9a, + 0xa6, 0xd1, 0x84, 0x66, 0x8d, 0x60, 0x45, 0x65, 0x18, 0x84, 0x1e, 0xbd, 0xfe, 0xdf, 0xee, 0xb2, + 0x06, 0xd5, 0x33, 0x7f, 0x24, 0x69, 0xfa, 0xb0, 0x13, 0xcb, 0x72, 0x00, 0xe5, 0xb3, 0x7d, 0x96, + 0x1b, 0xfd, 0x6d, 0xc0, 0xaa, 0x4a, 0x92, 0x09, 0x4f, 0x7a, 0xad, 0x7b, 0x50, 0xb9, 0x8c, 0x1d, + 0xc9, 0x43, 0xd0, 0xc6, 0x9d, 0x77, 0x59, 0x87, 0x9a, 0xc7, 0x27, 0x36, 0x8f, 0xc2, 0x64, 0x34, + 0x55, 0x8f, 0x4f, 0x70, 0x14, 0xa2, 0x0d, 0x80, 0x58, 0x8c, 0x59, 0x24, 0xed, 0x40, 0x28, 0x79, + 0xaa, 0x68, 0x79, 0x66, 0x91, 0x7c, 0x2d, 0x62, 0x4d, 0x08, 0xc8, 0xb5, 0x5d, 0x14, 0x8f, 0x8a, + 0xd6, 0x84, 0x80, 0x5c, 0x1f, 0xe4, 0xf4, 0xc3, 0x3a, 0x84, 0xb5, 0xd9, 0x92, 0x93, 0xde, 0xec, + 0x40, 0xe9, 0x82, 0x39, 0xaa, 0xe2, 0xe6, 0x9e, 0x79, 0x9b, 0xae, 0xe2, 0x98, 0x64, 0x3d, 0x85, + 0xf5, 0x13, 0x36, 0x1a, 0x15, 0x1c, 0xc9, 0xd5, 0xe7, 0x0b, 0xb7, 0xf5, 0x12, 0xcc, 0x9b, 0x27, + 0xfe, 0x43, 0xe6, 0x7d, 0x68, 0x62, 0x4a, 0xbc, 0x34, 0xdb, 0x1a, 0x54, 0xf5, 0x88, 0x54, 0x3b, + 0x5b, 0x38, 0xb1, 0xe2, 0x01, 0x8c, 0xfc, 0xc0, 0x97, 0xaa, 0x91, 0x15, 0xac, 0x0d, 0xeb, 0x77, + 0x68, 0xe9, 0xc3, 0x49, 0xe2, 0xdc, 0x37, 0xca, 0xb8, 0xf3, 0x1b, 0x15, 0xef, 0x6a, 0x48, 0xaf, + 0xa5, 0x5d, 0x48, 0x08, 0x31, 0xa4, 0x17, 0xc2, 0xda, 0x81, 0xce, 0x69, 0xe4, 0x08, 0x97, 0xfb, + 0x0e, 0xbd, 0xa3, 0x40, 0xab, 0x07, 0x2b, 0x39, 0xee, 0x9d, 0x3a, 0xb0, 0xf7, 0x4f, 0x19, 0x6a, + 0x47, 0xba, 0x36, 0xb4, 0x0f, 0xe5, 0x58, 0x25, 0xd1, 0x7a, 0xbe, 0xda, 0x9c, 0x16, 0x77, 0xcd, + 0x9b, 0x0e, 0x9d, 0xc1, 0x5a, 0x40, 0x3f, 0x40, 0x45, 0x89, 0x0f, 0x2a, 0x36, 0x3a, 0xa7, 0x73, + 0xdd, 0xfb, 0x73, 0x3c, 0xd9, 0xf9, 0x23, 0xa8, 0xa7, 0x42, 0x81, 0x0a, 0xb2, 0x37, 0x23, 0x53, + 0xdd, 0x87, 0xf3, 0x9d, 0x59, 0xa0, 0xd7, 0x00, 0xd3, 0x17, 0x8a, 0x36, 0x6e, 0xb0, 0xf3, 0x3a, + 0xd1, 0x7d, 0x74, 0x9b, 0x3b, 0x0b, 0xf7, 0x2b, 0x2c, 0x15, 0x17, 0x1b, 0x7d, 0x79, 0xe3, 0xcc, + 0xec, 0x3b, 0xed, 0x5a, 0x9f, 0xa2, 0x64, 0xa1, 0x6d, 0xe8, 0xcc, 0xee, 0x2e, 0x7a, 0x52, 0x68, + 0xf1, 0xfc, 0xb7, 0xd0, 0xdd, 0xfa, 0x34, 0x29, 0x4b, 0xb0, 0x0f, 0xe5, 0x78, 0x2f, 0x8b, 0x03, + 0xcd, 0xad, 0x79, 0x71, 0xa0, 0xf9, 0x15, 0xb6, 0x16, 0xd0, 0x2b, 0x68, 0x64, 0x9b, 0x84, 0x0a, + 0x4d, 0x9f, 0x5d, 0xc6, 0xee, 0xc6, 0x2d, 0xde, 0x34, 0xd6, 0x53, 0xe3, 0xe0, 0xd9, 0x6f, 0xdf, + 0x9d, 0xfb, 0x72, 0x44, 0x9c, 0x9e, 0xcb, 0x82, 0xbe, 0x43, 0x43, 0x4a, 0xe4, 0xf0, 0xeb, 0xe1, + 0x65, 0xfa, 0xb3, 0x3f, 0xff, 0x3f, 0x50, 0xa7, 0xaa, 0xfe, 0x7c, 0xfb, 0x6f, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x14, 0x18, 0xee, 0x6e, 0xa2, 0x0a, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1445,5 +1447,5 @@ var _Gateway_serviceDesc = grpc.ServiceDesc{ ServerStreams: true, }, }, - Metadata: "gateway/grpc/proto/gateway.proto", + Metadata: "server/data/grpc/proto/gateway.proto", } diff --git a/gateway/grpc/proto/gateway.proto b/server/data/grpc/proto/gateway.proto similarity index 96% rename from gateway/grpc/proto/gateway.proto rename to server/data/grpc/proto/gateway.proto index 8d69a167..aa677950 100644 --- a/gateway/grpc/proto/gateway.proto +++ b/server/data/grpc/proto/gateway.proto @@ -1,5 +1,5 @@ syntax = "proto3"; -option go_package = "gitlab.com/beneath-hq/beneath/gateway/grpc/proto"; +option go_package = "gitlab.com/beneath-hq/beneath/server/data/grpc/proto"; package gateway.v1; message Record { diff --git a/gateway/grpc/query.go b/server/data/grpc/query.go similarity index 83% rename from gateway/grpc/query.go rename to server/data/grpc/query.go index 902fa754..4ba46cd6 100644 --- a/gateway/grpc/query.go +++ b/server/data/grpc/query.go @@ -7,8 +7,8 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "gitlab.com/beneath-hq/beneath/gateway/api" - pb "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" + "gitlab.com/beneath-hq/beneath/services/data" + pb "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" ) func (s *gRPCServer) QueryLog(ctx context.Context, req *pb.QueryLogRequest) (*pb.QueryLogResponse, error) { @@ -19,7 +19,7 @@ func (s *gRPCServer) QueryLog(ctx context.Context, req *pb.QueryLogRequest) (*pb } // handle - res, err := api.HandleQueryLog(ctx, &api.QueryLogRequest{ + res, err := s.Service.HandleQueryLog(ctx, &data.QueryLogRequest{ InstanceID: instanceID, Partitions: req.Partitions, Peek: req.Peek, @@ -43,7 +43,7 @@ func (s *gRPCServer) QueryIndex(ctx context.Context, req *pb.QueryIndexRequest) } // handle - res, err := api.HandleQueryIndex(ctx, &api.QueryIndexRequest{ + res, err := s.Service.HandleQueryIndex(ctx, &data.QueryIndexRequest{ InstanceID: instanceID, Partitions: req.Partitions, Filter: req.Filter, diff --git a/gateway/grpc/read.go b/server/data/grpc/read.go similarity index 67% rename from gateway/grpc/read.go rename to server/data/grpc/read.go index 91f15536..e3e74de5 100644 --- a/gateway/grpc/read.go +++ b/server/data/grpc/read.go @@ -3,12 +3,12 @@ package grpc import ( "context" - "gitlab.com/beneath-hq/beneath/gateway/api" - pb "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" + "gitlab.com/beneath-hq/beneath/services/data" + pb "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" ) func (s *gRPCServer) Read(ctx context.Context, req *pb.ReadRequest) (*pb.ReadResponse, error) { - res, err := api.HandleRead(ctx, &api.ReadRequest{ + res, err := s.Service.HandleRead(ctx, &data.ReadRequest{ Cursor: req.Cursor, Limit: req.Limit, ReturnPB: true, diff --git a/gateway/grpc/server.go b/server/data/grpc/server.go similarity index 72% rename from gateway/grpc/server.go rename to server/data/grpc/server.go index eb62245c..1dabb83b 100644 --- a/gateway/grpc/server.go +++ b/server/data/grpc/server.go @@ -5,8 +5,9 @@ import ( grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth" "google.golang.org/grpc" - pb "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" - "gitlab.com/beneath-hq/beneath/internal/middleware" + pb "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" + "gitlab.com/beneath-hq/beneath/services/data" + "gitlab.com/beneath-hq/beneath/services/middleware" // see https://github.com/grpc/grpc-go/blob/master/Documentation/encoding.md#using-a-compressor _ "google.golang.org/grpc/encoding/gzip" @@ -18,10 +19,12 @@ const ( ) // gRPCServer implements pb.GatewayServer -type gRPCServer struct{} +type gRPCServer struct { + Service *data.Service +} -// Server returns the gateway GRPC server -func Server() *grpc.Server { +// NewServer creates and returns the data GRPC server +func NewServer(data *data.Service, middleware *middleware.Service) *grpc.Server { server := grpc.NewServer( grpc.MaxRecvMsgSize(maxRecvMsgSize), grpc.MaxSendMsgSize(maxSendMsgSize), @@ -38,6 +41,8 @@ func Server() *grpc.Server { middleware.RecovererStreamServerInterceptor(), ), ) - pb.RegisterGatewayServer(server, &gRPCServer{}) + pb.RegisterGatewayServer(server, &gRPCServer{ + Service: data, + }) return server } diff --git a/server/data/grpc/subscription.go b/server/data/grpc/subscription.go new file mode 100644 index 00000000..d32a27f5 --- /dev/null +++ b/server/data/grpc/subscription.go @@ -0,0 +1,45 @@ +package grpc + +import ( + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + + pb "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" + "gitlab.com/beneath-hq/beneath/services/data" + "gitlab.com/beneath-hq/beneath/services/middleware" +) + +func (s *gRPCServer) Subscribe(req *pb.SubscribeRequest, ss pb.Gateway_SubscribeServer) error { + // get auth + secret := middleware.GetSecret(ss.Context()) + if secret == nil { + return grpc.Errorf(codes.PermissionDenied, "not authenticated") + } + + // get subscription channel + ch := make(chan data.SubscriptionMessage) + res, err := s.Service.HandleSubscribe(ss.Context(), &data.SubscribeRequest{ + Secret: secret, + Cursor: req.Cursor, + Cb: func(msg data.SubscriptionMessage) { + ch <- msg + }, + }) + if err != nil { + return err + } + defer res.Cancel() + + // read messages until disconnect + for { + select { + case <-ss.Context().Done(): + return nil + case _ = <-ch: + err := ss.Send(&pb.SubscribeResponse{}) + if err != nil { + return err + } + } + } +} diff --git a/gateway/grpc/warehouse.go b/server/data/grpc/warehouse.go similarity index 83% rename from gateway/grpc/warehouse.go rename to server/data/grpc/warehouse.go index e0b67c2a..c6146e3c 100644 --- a/gateway/grpc/warehouse.go +++ b/server/data/grpc/warehouse.go @@ -8,13 +8,13 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "gitlab.com/beneath-hq/beneath/engine/driver" - "gitlab.com/beneath-hq/beneath/gateway/api" - pb "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" + "gitlab.com/beneath-hq/beneath/services/data" + pb "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" ) func (s *gRPCServer) QueryWarehouse(ctx context.Context, req *pb.QueryWarehouseRequest) (*pb.QueryWarehouseResponse, error) { - res, err := api.HandleQueryWarehouse(ctx, &api.QueryWarehouseRequest{ + res, err := s.Service.HandleQueryWarehouse(ctx, &data.QueryWarehouseRequest{ Query: req.Query, Partitions: req.Partitions, DryRun: req.DryRun, @@ -36,7 +36,7 @@ func (s *gRPCServer) PollWarehouseJob(ctx context.Context, req *pb.PollWarehouse return nil, status.Error(codes.InvalidArgument, "job_id not valid UUID") } - res, err := api.HandlePollWarehouse(ctx, &api.PollWarehouseRequest{ + res, err := s.Service.HandlePollWarehouse(ctx, &data.PollWarehouseRequest{ JobID: jobID, }) if err != nil { @@ -48,7 +48,7 @@ func (s *gRPCServer) PollWarehouseJob(ctx context.Context, req *pb.PollWarehouse }, nil } -func makeWarehouseJobPB(job *api.WarehouseJob) *pb.WarehouseJob { +func makeWarehouseJobPB(job *data.WarehouseJob) *pb.WarehouseJob { var status pb.WarehouseJob_Status switch job.Status { case driver.PendingWarehouseJobStatus: diff --git a/gateway/grpc/write.go b/server/data/grpc/write.go similarity index 70% rename from gateway/grpc/write.go rename to server/data/grpc/write.go index fad1a04b..97e4533f 100644 --- a/gateway/grpc/write.go +++ b/server/data/grpc/write.go @@ -7,13 +7,13 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "gitlab.com/beneath-hq/beneath/gateway/api" - pb "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" + "gitlab.com/beneath-hq/beneath/services/data" + pb "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" ) func (s *gRPCServer) Write(ctx context.Context, req *pb.WriteRequest) (*pb.WriteResponse, error) { // build instanceRecords - instanceRecords := make(map[uuid.UUID]*api.WriteRecords) + instanceRecords := make(map[uuid.UUID]*data.WriteRecords) for _, ir := range req.InstanceRecords { instanceID := uuid.FromBytesOrNil(ir.InstanceId) if instanceID == uuid.Nil { @@ -22,11 +22,11 @@ func (s *gRPCServer) Write(ctx context.Context, req *pb.WriteRequest) (*pb.Write if instanceRecords[instanceID] != nil { return nil, status.Errorf(codes.InvalidArgument, "found two InstanceRecords for instance_id=%s", instanceID.String()) } - instanceRecords[instanceID] = &api.WriteRecords{PB: ir.Records} + instanceRecords[instanceID] = &data.WriteRecords{PB: ir.Records} } // call write - res, err := api.HandleWrite(ctx, &api.WriteRequest{InstanceRecords: instanceRecords}) + res, err := s.Service.HandleWrite(ctx, &data.WriteRequest{InstanceRecords: instanceRecords}) if err != nil { return nil, err.GRPC() } diff --git a/gateway/http/ping.go b/server/data/http/ping.go similarity index 81% rename from gateway/http/ping.go rename to server/data/http/ping.go index 82cdb0bf..1317426f 100644 --- a/gateway/http/ping.go +++ b/server/data/http/ping.go @@ -3,8 +3,8 @@ package http import ( "net/http" - "gitlab.com/beneath-hq/beneath/gateway/api" "gitlab.com/beneath-hq/beneath/pkg/jsonutil" + "gitlab.com/beneath-hq/beneath/services/data" ) type pingArgs struct { @@ -12,14 +12,14 @@ type pingArgs struct { ClientVersion string } -func getPing(w http.ResponseWriter, r *http.Request) error { +func (a *app) getPing(w http.ResponseWriter, r *http.Request) error { // parse args args := pingArgs{} args.ClientID = r.URL.Query().Get("client_id") args.ClientVersion = r.URL.Query().Get("client_version") // handle - res, errr := api.HandlePing(r.Context(), &api.PingRequest{ + res, errr := a.DataService.HandlePing(r.Context(), &data.PingRequest{ ClientID: args.ClientID, ClientVersion: args.ClientVersion, }) diff --git a/gateway/http/query.go b/server/data/http/query.go similarity index 80% rename from gateway/http/query.go rename to server/data/http/query.go index e81fad64..4bc6625f 100644 --- a/gateway/http/query.go +++ b/server/data/http/query.go @@ -7,9 +7,8 @@ import ( "github.com/go-chi/chi" uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/gateway/api" "gitlab.com/beneath-hq/beneath/pkg/httputil" + "gitlab.com/beneath-hq/beneath/services/data" ) type queryArgsType string @@ -26,10 +25,10 @@ type queryArgs struct { Peek bool } -func getFromOrganizationAndProjectAndStream(w http.ResponseWriter, r *http.Request) error { +func (a *app) getFromOrganizationAndProjectAndStream(w http.ResponseWriter, r *http.Request) error { // if cursor is set, go straight to fetching from cursor (the instance ID is backed into the cursor) if r.URL.Query().Get("cursor") != "" { - return getFromCursor(w, r) + return a.getFromCursor(w, r) } // parse url params @@ -38,19 +37,19 @@ func getFromOrganizationAndProjectAndStream(w http.ResponseWriter, r *http.Reque streamName := toBackendName(chi.URLParam(r, "streamName")) // find primary instance ID for stream - instanceID := entity.FindInstanceIDByOrganizationProjectAndName(r.Context(), organizationName, projectName, streamName) + instanceID := a.StreamService.FindPrimaryInstanceIDByOrganizationProjectAndName(r.Context(), organizationName, projectName, streamName) if instanceID == uuid.Nil { return httputil.NewError(404, "instance for stream not found") } // run query - return handleQuery(w, r, instanceID) + return a.handleQuery(w, r, instanceID) } -func getFromInstance(w http.ResponseWriter, r *http.Request) error { +func (a *app) getFromInstance(w http.ResponseWriter, r *http.Request) error { // if cursor is set, go straight to fetching from cursor (the instance ID is backed into the cursor) if r.URL.Query().Get("cursor") != "" { - return getFromCursor(w, r) + return a.getFromCursor(w, r) } // parse instance ID @@ -60,10 +59,10 @@ func getFromInstance(w http.ResponseWriter, r *http.Request) error { } // run query - return handleQuery(w, r, instanceID) + return a.handleQuery(w, r, instanceID) } -func handleQuery(w http.ResponseWriter, r *http.Request, instanceID uuid.UUID) error { +func (a *app) handleQuery(w http.ResponseWriter, r *http.Request, instanceID uuid.UUID) error { // read body args, err := parseQueryArgs(r) if err != nil { @@ -74,7 +73,7 @@ func handleQuery(w http.ResponseWriter, r *http.Request, instanceID uuid.UUID) e var replayCursors, changeCursors [][]byte switch args.Type { case queryArgsTypeIndex: - res, err := api.HandleQueryIndex(r.Context(), &api.QueryIndexRequest{ + res, err := a.DataService.HandleQueryIndex(r.Context(), &data.QueryIndexRequest{ InstanceID: instanceID, Partitions: 1, Filter: args.Filter, @@ -85,7 +84,7 @@ func handleQuery(w http.ResponseWriter, r *http.Request, instanceID uuid.UUID) e replayCursors = res.ReplayCursors changeCursors = res.ChangeCursors case queryArgsTypeLog: - res, err := api.HandleQueryLog(r.Context(), &api.QueryLogRequest{ + res, err := a.DataService.HandleQueryLog(r.Context(), &data.QueryLogRequest{ InstanceID: instanceID, Partitions: 1, Peek: args.Peek, @@ -107,7 +106,7 @@ func handleQuery(w http.ResponseWriter, r *http.Request, instanceID uuid.UUID) e } // run a read - return handleRead(w, r, replayCursor, args.Limit, changeCursor) + return a.handleRead(w, r, replayCursor, args.Limit, changeCursor) } func parseQueryArgs(r *http.Request) (queryArgs, error) { diff --git a/gateway/http/read.go b/server/data/http/read.go similarity index 83% rename from gateway/http/read.go rename to server/data/http/read.go index be2dfe57..53fad970 100644 --- a/gateway/http/read.go +++ b/server/data/http/read.go @@ -6,7 +6,7 @@ import ( "github.com/mr-tron/base58" uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/gateway/api" + "gitlab.com/beneath-hq/beneath/services/data" "gitlab.com/beneath-hq/beneath/pkg/httputil" "gitlab.com/beneath-hq/beneath/pkg/jsonutil" ) @@ -16,17 +16,17 @@ type readArgs struct { Limit int } -func getFromCursor(w http.ResponseWriter, r *http.Request) error { +func (a *app) getFromCursor(w http.ResponseWriter, r *http.Request) error { args, err := parseReadArgs(r) if err != nil { return err } - return handleRead(w, r, args.Cursor, args.Limit, nil) + return a.handleRead(w, r, args.Cursor, args.Limit, nil) } -func handleRead(w http.ResponseWriter, r *http.Request, cursor []byte, limit int, passChangeCursor []byte) error { - res, errr := api.HandleRead(r.Context(), &api.ReadRequest{ +func (a *app) handleRead(w http.ResponseWriter, r *http.Request, cursor []byte, limit int, passChangeCursor []byte) error { + res, errr := a.DataService.HandleRead(r.Context(), &data.ReadRequest{ Cursor: cursor, Limit: int32(limit), ReturnJSON: true, diff --git a/server/data/http/server.go b/server/data/http/server.go new file mode 100644 index 00000000..47c4c664 --- /dev/null +++ b/server/data/http/server.go @@ -0,0 +1,122 @@ +package http + +import ( + "fmt" + "net/http" + "strconv" + "strings" + + "github.com/go-chi/chi" + chimiddleware "github.com/go-chi/chi/middleware" + "github.com/rs/cors" + + "gitlab.com/beneath-hq/beneath/pkg/httputil" + "gitlab.com/beneath-hq/beneath/pkg/log" + "gitlab.com/beneath-hq/beneath/pkg/ws" + "gitlab.com/beneath-hq/beneath/services/data" + "gitlab.com/beneath-hq/beneath/services/middleware" + "gitlab.com/beneath-hq/beneath/services/secret" + "gitlab.com/beneath-hq/beneath/services/stream" +) + +type app struct { + DataService *data.Service + SecretService *secret.Service + StreamService *stream.Service +} + +// NewServer creates and returns the data HTTP server +func NewServer(data *data.Service, middleware *middleware.Service, secret *secret.Service, stream *stream.Service) *http.Server { + app := &app{ + DataService: data, + SecretService: secret, + StreamService: stream, + } + router := chi.NewRouter() + + corsOptions := cors.Options{ + AllowedOrigins: []string{"*"}, + AllowedHeaders: []string{"*"}, + AllowCredentials: true, + MaxAge: 7200, + Debug: false, + } + + router.Use(chimiddleware.RealIP) + router.Use(chimiddleware.DefaultCompress) + router.Use(cors.New(corsOptions).Handler) + router.Use(middleware.InjectTagsMiddleware) + router.Use(middleware.LoggerMiddleware) + router.Use(middleware.RecovererMiddleware) + router.Use(middleware.AuthMiddleware) + router.Use(middleware.IPRateLimitMiddleware) + + // Add health check + router.Get("/", app.healthCheck) + router.Get("/healthz", app.healthCheck) + + // Add ping + router.Method("GET", "/v1/-/ping", httputil.AppHandler(app.getPing)) + + // index and log endpoints + router.Method("GET", "/v1/{organizationName}/{projectName}/{streamName}", httputil.AppHandler(app.getFromOrganizationAndProjectAndStream)) + router.Method("GET", "/v1/-/instances/{instanceID}", httputil.AppHandler(app.getFromInstance)) + + // write endpoint + router.Method("POST", "/v1/{organizationName}/{projectName}/{streamName}", httputil.AppHandler(app.postToOrganizationAndProjectAndStream)) + router.Method("POST", "/v1/-/instances/{instanceID}", httputil.AppHandler(app.postToInstance)) + + // warehouse job endpoints + router.Method("GET", "/v1/-/warehouse/{jobID}", httputil.AppHandler(app.getFromWarehouseJob)) + router.Method("POST", "/v1/-/warehouse", httputil.AppHandler(app.postToWarehouseJob)) + + // read endpoint + router.Method("GET", "/v1/-/cursor", httputil.AppHandler(app.getFromCursor)) + + // create websocket broker and start accepting new connections on /ws + wss := ws.NewBroker(app) + router.Method("GET", "/v1/-/ws", httputil.AppHandler(wss.HTTPHandler)) + + return &http.Server{ + Handler: router, + } +} + +func (a *app) healthCheck(w http.ResponseWriter, r *http.Request) { + if true { // TODO + w.WriteHeader(http.StatusOK) + w.Write([]byte(http.StatusText(http.StatusOK))) + } else { + log.S.Errorf("Gateway database health check failed") + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + } +} + +func parseBoolParam(name string, val string) (bool, error) { + if val == "" { + return false, nil + } else if val == "true" { + return true, nil + } else if val == "false" { + return false, nil + } + + return false, fmt.Errorf("expected '%s' parameter to be 'true' or 'false'", name) +} + +func parseIntParam(name string, val string) (int, error) { + if val == "" { + return 0, nil + } + + res, err := strconv.Atoi(val) + if err != nil { + return 0, fmt.Errorf("couldn't parse '%s' as integer", name) + } + + return res, nil +} + +func toBackendName(s string) string { + return strings.ToLower(strings.ReplaceAll(s, "-", "_")) +} diff --git a/server/data/http/subscription.go b/server/data/http/subscription.go new file mode 100644 index 00000000..2722d978 --- /dev/null +++ b/server/data/http/subscription.go @@ -0,0 +1,153 @@ +package http + +import ( + "context" + "fmt" + "time" + + "github.com/mr-tron/base58" + + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/pkg/log" + "gitlab.com/beneath-hq/beneath/pkg/secrettoken" + "gitlab.com/beneath-hq/beneath/pkg/ws" + "gitlab.com/beneath-hq/beneath/services/data" +) + +// KeepAlive implements ws.Server +func (a *app) KeepAlive(numClients int, elapsed time.Duration) { + // log state + log.S.Infow( + "ws keepalive", + "clients", numClients, + "elapsed", elapsed, + ) +} + +// InitClient implements ws.Server +func (a *app) InitClient(client *ws.Client, payload map[string]interface{}) error { + // get secret + var secret models.Secret + tokenStr, ok := payload["secret"].(string) + if ok { + // parse token + token, err := secrettoken.FromString(tokenStr) + if err != nil { + return fmt.Errorf("malformed secret") + } + + // authenticate + secret = a.SecretService.AuthenticateWithToken(client.Context, token) + if secret == nil { + return fmt.Errorf("couldn't authenticate secret") + } + } + + if secret == nil { + secret = &models.AnonymousSecret{} + } + + // set secret as state + client.SetState(secret) + + // log + a.logWithSecret(secret, "ws init client", + "ip", client.GetRemoteAddr(), + ) + + return nil +} + +// CloseClient implements ws.Server +func (a *app) CloseClient(client *ws.Client) { + // the client state is the secret + secret := client.GetState().(models.Secret) + + // log + a.logWithSecret(secret, "ws close client", + "ip", client.GetRemoteAddr(), + "reads", client.MessagesRead, + "bytes_read", client.BytesRead, + "writes", client.MessagesWritten, + "bytes_written", client.BytesWritten, + "elapsed", time.Since(client.StartTime), + "error", client.Err, + ) +} + +// StartQuery implements ws.Server +func (a *app) StartQuery(client *ws.Client, id ws.QueryID, payload map[string]interface{}) error { + // get secret + secret := client.GetState().(models.Secret) + + // get cursor bytes + cursorStr, ok := payload["cursor"].(string) + if !ok { + return fmt.Errorf("payload must contain key 'cursor'") + } + cursorBytes, err := base58.Decode(cursorStr) + if err != nil { + return fmt.Errorf("payload key 'cursor' must contain a base58-encoded cursor") + } + + // start subscription + res, err := a.DataService.HandleSubscribe(client.Context, &data.SubscribeRequest{ + Secret: secret, + Cursor: cursorBytes, + Cb: func(msg data.SubscriptionMessage) { + // TODO: For now, just sending empty messages + client.SendData(id, "") + }, + }) + if err != nil { + return err + } + + // set cancel as query state + client.SetQueryState(id, res.Cancel) + + // log + a.logWithSecret(secret, "ws start query", + "ip", client.GetRemoteAddr(), + "id", id, + "instance", res.InstanceID.String(), + ) + + return nil +} + +// StopQuery implements ws.Server +func (a *app) StopQuery(client *ws.Client, id ws.QueryID) error { + // the query state is the cancel func + cancel := client.GetQueryState(id).(context.CancelFunc) + cancel() + + // the client state is the secret + secret := client.GetState().(models.Secret) + + // log + a.logWithSecret(secret, "ws stop query", + "ip", client.GetRemoteAddr(), + "id", id, + ) + + return nil +} + +func (a *app) logWithSecret(sec models.Secret, msg string, keysAndValues ...interface{}) { + l := log.S + + if sec.IsUser() { + l = l.With( + "secret", sec.GetSecretID().String(), + "user", sec.GetOwnerID().String(), + ) + } else if sec.IsService() { + l = l.With( + "secret", sec.GetSecretID().String(), + "service", sec.GetOwnerID().String(), + ) + } + + l.Infow(msg, keysAndValues...) +} diff --git a/gateway/http/warehouse.go b/server/data/http/warehouse.go similarity index 84% rename from gateway/http/warehouse.go rename to server/data/http/warehouse.go index 50fc32d9..30a86c9b 100644 --- a/gateway/http/warehouse.go +++ b/server/data/http/warehouse.go @@ -8,8 +8,8 @@ import ( "github.com/mr-tron/base58" uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/engine/driver" - "gitlab.com/beneath-hq/beneath/gateway/api" + "gitlab.com/beneath-hq/beneath/services/data" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" "gitlab.com/beneath-hq/beneath/pkg/httputil" "gitlab.com/beneath-hq/beneath/pkg/jsonutil" ) @@ -33,13 +33,13 @@ type warehouseJob struct { ResultSizeRecords int64 `json:"result_size_records,omitempty"` } -func postToWarehouseJob(w http.ResponseWriter, r *http.Request) error { +func (a *app) postToWarehouseJob(w http.ResponseWriter, r *http.Request) error { args, err := parseQueryWarehouseArgs(r) if err != nil { return err } - res, errr := api.HandleQueryWarehouse(r.Context(), &api.QueryWarehouseRequest{ + res, errr := a.DataService.HandleQueryWarehouse(r.Context(), &data.QueryWarehouseRequest{ Query: args.Query, Partitions: 1, DryRun: args.DryRun, @@ -53,13 +53,13 @@ func postToWarehouseJob(w http.ResponseWriter, r *http.Request) error { return handleWarehouseJob(w, res.Job) } -func getFromWarehouseJob(w http.ResponseWriter, r *http.Request) error { +func (a *app) getFromWarehouseJob(w http.ResponseWriter, r *http.Request) error { jobID, err := uuid.FromString(chi.URLParam(r, "jobID")) if err != nil { return httputil.NewError(404, "job_id not found or not a valid UUID") } - res, errr := api.HandlePollWarehouse(r.Context(), &api.PollWarehouseRequest{ + res, errr := a.DataService.HandlePollWarehouse(r.Context(), &data.PollWarehouseRequest{ JobID: jobID, }) if errr != nil { @@ -79,7 +79,7 @@ func parseQueryWarehouseArgs(r *http.Request) (queryWarehouseArgs, error) { return args, nil } -func handleWarehouseJob(w http.ResponseWriter, job *api.WarehouseJob) error { +func handleWarehouseJob(w http.ResponseWriter, job *data.WarehouseJob) error { encode := warehouseJob{ ResultAvroSchema: job.ResultAvroSchema, ReferencedInstances: job.ReferencedInstances, diff --git a/gateway/http/write.go b/server/data/http/write.go similarity index 67% rename from gateway/http/write.go rename to server/data/http/write.go index 59fa49e2..6316f01f 100644 --- a/gateway/http/write.go +++ b/server/data/http/write.go @@ -6,35 +6,34 @@ import ( "github.com/go-chi/chi" uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/gateway/api" "gitlab.com/beneath-hq/beneath/pkg/httputil" "gitlab.com/beneath-hq/beneath/pkg/jsonutil" + "gitlab.com/beneath-hq/beneath/services/data" ) -func postToOrganizationAndProjectAndStream(w http.ResponseWriter, r *http.Request) error { +func (a *app) postToOrganizationAndProjectAndStream(w http.ResponseWriter, r *http.Request) error { organizationName := toBackendName(chi.URLParam(r, "organizationName")) projectName := toBackendName(chi.URLParam(r, "projectName")) streamName := toBackendName(chi.URLParam(r, "streamName")) - instanceID := entity.FindInstanceIDByOrganizationProjectAndName(r.Context(), organizationName, projectName, streamName) + instanceID := a.StreamService.FindPrimaryInstanceIDByOrganizationProjectAndName(r.Context(), organizationName, projectName, streamName) if instanceID == uuid.Nil { return httputil.NewError(404, "instance for stream not found") } - return handleWrite(w, r, instanceID) + return a.handleWrite(w, r, instanceID) } -func postToInstance(w http.ResponseWriter, r *http.Request) error { +func (a *app) postToInstance(w http.ResponseWriter, r *http.Request) error { instanceID, err := uuid.FromString(chi.URLParam(r, "instanceID")) if err != nil { return httputil.NewError(404, "instance not found -- malformed ID") } - return handleWrite(w, r, instanceID) + return a.handleWrite(w, r, instanceID) } -func handleWrite(w http.ResponseWriter, r *http.Request, instanceID uuid.UUID) error { +func (a *app) handleWrite(w http.ResponseWriter, r *http.Request, instanceID uuid.UUID) error { // decode json body var body interface{} err := jsonutil.Unmarshal(r.Body, &body) @@ -54,9 +53,9 @@ func handleWrite(w http.ResponseWriter, r *http.Request, instanceID uuid.UUID) e } // call write - res, errr := api.HandleWrite(r.Context(), &api.WriteRequest{ - InstanceRecords: map[uuid.UUID]*api.WriteRecords{ - instanceID: &api.WriteRecords{JSON: objects}, + res, errr := a.DataService.HandleWrite(r.Context(), &data.WriteRequest{ + InstanceRecords: map[uuid.UUID]*data.WriteRecords{ + instanceID: &data.WriteRecords{JSON: objects}, }, }) if errr != nil { diff --git a/server/data/server.go b/server/data/server.go new file mode 100644 index 00000000..44eaf7d5 --- /dev/null +++ b/server/data/server.go @@ -0,0 +1,65 @@ +package data + +import ( + "context" + "net/http" + + "golang.org/x/sync/errgroup" + "google.golang.org/grpc" + + "gitlab.com/beneath-hq/beneath/pkg/grpcutil" + "gitlab.com/beneath-hq/beneath/pkg/httputil" + "gitlab.com/beneath-hq/beneath/pkg/log" + gwgrpc "gitlab.com/beneath-hq/beneath/server/data/grpc" + gwhttp "gitlab.com/beneath-hq/beneath/server/data/http" + "gitlab.com/beneath-hq/beneath/services/data" + "gitlab.com/beneath-hq/beneath/services/middleware" + "gitlab.com/beneath-hq/beneath/services/secret" + "gitlab.com/beneath-hq/beneath/services/stream" +) + +// ServerOptions are the options for creating a data server +type ServerOptions struct { + HTTPPort int `mapstructure:"http_port"` + GRPCPort int `mapstructure:"grpc_port"` +} + +// Server is the data server +type Server struct { + Opts *ServerOptions + DataService *data.Service + HTTP *http.Server + GRPC *grpc.Server +} + +// NewServer initializes a new data-plane server that supports HTTP and GRPC +func NewServer(opts *ServerOptions, data *data.Service, middleware *middleware.Service, secret *secret.Service, stream *stream.Service) *Server { + s := &Server{ + Opts: opts, + DataService: data, + GRPC: gwgrpc.NewServer(data, middleware), + HTTP: gwhttp.NewServer(data, middleware, secret, stream), + } + + return s +} + +// Run starts serving on HTTP and GRPC +func (s *Server) Run(ctx context.Context) error { + group, cctx := errgroup.WithContext(ctx) + + group.Go(func() error { + return httputil.ListenAndServeContext(cctx, s.HTTP, s.Opts.HTTPPort) + }) + + group.Go(func() error { + return grpcutil.ListenAndServeContext(cctx, s.GRPC, s.Opts.GRPCPort) + }) + + group.Go(func() error { + return s.DataService.ServeSubscriptions(cctx) + }) + + log.S.Infof("serving data server on http port %d and grpc port %d", s.Opts.HTTPPort, s.Opts.GRPCPort) + return group.Wait() +} diff --git a/gateway/clientversion/clientversion.go b/services/data/clientversion/clientversion.go similarity index 100% rename from gateway/clientversion/clientversion.go rename to services/data/clientversion/clientversion.go diff --git a/gateway/util/cursor.go b/services/data/cursor.go similarity index 78% rename from gateway/util/cursor.go rename to services/data/cursor.go index 023462b2..1b964470 100644 --- a/gateway/util/cursor.go +++ b/services/data/cursor.go @@ -1,4 +1,4 @@ -package util +package data import ( "fmt" @@ -82,3 +82,20 @@ func (c Cursor) GetID() uuid.UUID { func (c Cursor) GetPayload() []byte { return c[(cursorTypeSize + uuid.Size):] } + +// utility to wrap an engine cursor with Cursor +func wrapCursor(cursorType CursorType, id uuid.UUID, engineCursor []byte) []byte { + if len(engineCursor) == 0 { + return engineCursor + } + return NewCursor(cursorType, id, engineCursor).GetBytes() +} + +// utility to making multiple wrapCursor calls +func wrapCursors(cursorType CursorType, id uuid.UUID, engineCursors [][]byte) [][]byte { + wrapped := make([][]byte, len(engineCursors)) + for idx, engineCursor := range engineCursors { + wrapped[idx] = wrapCursor(cursorType, id, engineCursor) + } + return wrapped +} diff --git a/services/data/data.go b/services/data/data.go new file mode 100644 index 00000000..37fa2966 --- /dev/null +++ b/services/data/data.go @@ -0,0 +1,44 @@ +package data + +import ( + "gitlab.com/beneath-hq/beneath/infrastructure/engine" + "gitlab.com/beneath-hq/beneath/infrastructure/mq" + "gitlab.com/beneath-hq/beneath/services/metrics" + "gitlab.com/beneath-hq/beneath/services/permissions" + "gitlab.com/beneath-hq/beneath/services/stream" +) + +// Service implements the data-plane functionality for handling requests +// (in a protocol-agnostic way used by the http and grpc interfaces), and for +// processing records in the background. +type Service struct { + MQ mq.MessageQueue + Engine *engine.Engine + Metrics *metrics.Broker + Permissions *permissions.Service + Streams *stream.Service + + // manages real-time push (for websockets/streaming grpc clients) + subscriptions subscriptions +} + +// New returns a new data service instance +func New(mq mq.MessageQueue, engine *engine.Engine, metrics *metrics.Broker, permissions *permissions.Service, streams *stream.Service) (*Service, error) { + err := mq.RegisterTopic(writeRequestsTopic) + if err != nil { + return nil, err + } + + err = mq.RegisterTopic(writeReportsTopic) + if err != nil { + return nil, err + } + + return &Service{ + MQ: mq, + Engine: engine, + Metrics: metrics, + Permissions: permissions, + Streams: streams, + }, nil +} diff --git a/gateway/api/index.go b/services/data/handle_index.go similarity index 66% rename from gateway/api/index.go rename to services/data/handle_index.go index 712e4d7e..545e5eae 100644 --- a/gateway/api/index.go +++ b/services/data/handle_index.go @@ -1,4 +1,4 @@ -package api +package data import ( "context" @@ -6,11 +6,9 @@ import ( uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/gateway/util" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/models" "gitlab.com/beneath-hq/beneath/pkg/queryparse" + "gitlab.com/beneath-hq/beneath/services/middleware" ) // QueryIndexRequest is a request to HandleQueryIndex @@ -33,7 +31,7 @@ type queryIndexTags struct { } // HandleQueryIndex handles an index query request -func HandleQueryIndex(ctx context.Context, req *QueryIndexRequest) (*QueryIndexResponse, *Error) { +func (s *Service) HandleQueryIndex(ctx context.Context, req *QueryIndexRequest) (*QueryIndexResponse, *Error) { // get auth secret := middleware.GetSecret(ctx) if secret == nil { @@ -49,13 +47,13 @@ func HandleQueryIndex(ctx context.Context, req *QueryIndexRequest) (*QueryIndexR middleware.SetTagsPayload(ctx, payload) // get cached stream - stream := entity.FindCachedStreamByCurrentInstanceID(ctx, req.InstanceID) + stream := s.Streams.FindCachedInstance(ctx, req.InstanceID) if stream == nil { return nil, newErrorf(http.StatusNotFound, "stream not found") } // check permissions - perms := secret.StreamPermissions(ctx, stream.StreamID, stream.ProjectID, stream.Public) + perms := s.Permissions.StreamPermissionsForSecret(ctx, secret, stream.StreamID, stream.ProjectID, stream.Public) if !perms.Read { return nil, newErrorf(http.StatusForbidden, "token doesn't grant right to read this stream") } @@ -67,14 +65,14 @@ func HandleQueryIndex(ctx context.Context, req *QueryIndexRequest) (*QueryIndexR } // run query - replayCursors, changeCursors, err := hub.Engine.Lookup.ParseQuery(ctx, stream, stream, entity.EfficientStreamInstance(req.InstanceID), where, true, int(req.Partitions)) + replayCursors, changeCursors, err := s.Engine.Lookup.ParseQuery(ctx, stream, stream, models.EfficientStreamInstance(req.InstanceID), where, true, int(req.Partitions)) if err != nil { return nil, newErrorf(http.StatusBadRequest, "error parsing query: %s", err.Error()) } // done return &QueryIndexResponse{ - ReplayCursors: wrapCursors(util.IndexCursorType, req.InstanceID, replayCursors), - ChangeCursors: wrapCursors(util.LogCursorType, req.InstanceID, changeCursors), + ReplayCursors: wrapCursors(IndexCursorType, req.InstanceID, replayCursors), + ChangeCursors: wrapCursors(LogCursorType, req.InstanceID, changeCursors), }, nil } diff --git a/gateway/api/log.go b/services/data/handle_log.go similarity index 60% rename from gateway/api/log.go rename to services/data/handle_log.go index 3837b0a4..d494e7aa 100644 --- a/gateway/api/log.go +++ b/services/data/handle_log.go @@ -1,4 +1,4 @@ -package api +package data import ( "context" @@ -6,10 +6,8 @@ import ( uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/gateway/util" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/services/middleware" ) // QueryLogRequest is a request to HandleQueryLog @@ -32,7 +30,7 @@ type queryLogTags struct { } // HandleQueryLog handles a log query request -func HandleQueryLog(ctx context.Context, req *QueryLogRequest) (*QueryLogResponse, *Error) { +func (s *Service) HandleQueryLog(ctx context.Context, req *QueryLogRequest) (*QueryLogResponse, *Error) { // get auth secret := middleware.GetSecret(ctx) if secret == nil { @@ -48,13 +46,13 @@ func HandleQueryLog(ctx context.Context, req *QueryLogRequest) (*QueryLogRespons middleware.SetTagsPayload(ctx, payload) // get cached stream - stream := entity.FindCachedStreamByCurrentInstanceID(ctx, req.InstanceID) + stream := s.Streams.FindCachedInstance(ctx, req.InstanceID) if stream == nil { return nil, newErrorf(http.StatusNotFound, "stream not found") } // check permissions - perms := secret.StreamPermissions(ctx, stream.StreamID, stream.ProjectID, stream.Public) + perms := s.Permissions.StreamPermissionsForSecret(ctx, secret, stream.StreamID, stream.ProjectID, stream.Public) if !perms.Read { return nil, newErrorf(http.StatusForbidden, "token doesn't grant right to read this stream") } @@ -67,27 +65,27 @@ func HandleQueryLog(ctx context.Context, req *QueryLogRequest) (*QueryLogRespons } // run query - replayCursor, changeCursor, err := hub.Engine.Lookup.Peek(ctx, stream, stream, entity.EfficientStreamInstance(req.InstanceID)) + replayCursor, changeCursor, err := s.Engine.Lookup.Peek(ctx, stream, stream, models.EfficientStreamInstance(req.InstanceID)) if err != nil { return nil, newErrorf(http.StatusBadRequest, "error parsing query: %s", err.Error()) } // done return &QueryLogResponse{ - ReplayCursors: [][]byte{wrapCursor(util.LogCursorType, req.InstanceID, replayCursor)}, - ChangeCursors: [][]byte{wrapCursor(util.LogCursorType, req.InstanceID, changeCursor)}, + ReplayCursors: [][]byte{wrapCursor(LogCursorType, req.InstanceID, replayCursor)}, + ChangeCursors: [][]byte{wrapCursor(LogCursorType, req.InstanceID, changeCursor)}, }, nil } // run normal query - replayCursors, changeCursors, err := hub.Engine.Lookup.ParseQuery(ctx, stream, stream, entity.EfficientStreamInstance(req.InstanceID), nil, false, int(req.Partitions)) + replayCursors, changeCursors, err := s.Engine.Lookup.ParseQuery(ctx, stream, stream, models.EfficientStreamInstance(req.InstanceID), nil, false, int(req.Partitions)) if err != nil { return nil, newErrorf(http.StatusBadRequest, "error parsing query: %s", err.Error()) } // done return &QueryLogResponse{ - ReplayCursors: wrapCursors(util.LogCursorType, req.InstanceID, replayCursors), - ChangeCursors: wrapCursors(util.LogCursorType, req.InstanceID, changeCursors), + ReplayCursors: wrapCursors(LogCursorType, req.InstanceID, replayCursors), + ChangeCursors: wrapCursors(LogCursorType, req.InstanceID, changeCursors), }, nil } diff --git a/gateway/api/ping.go b/services/data/handle_ping.go similarity index 85% rename from gateway/api/ping.go rename to services/data/handle_ping.go index cec7649d..c659a1aa 100644 --- a/gateway/api/ping.go +++ b/services/data/handle_ping.go @@ -1,4 +1,4 @@ -package api +package data import ( "context" @@ -6,8 +6,8 @@ import ( version "github.com/hashicorp/go-version" - "gitlab.com/beneath-hq/beneath/gateway/clientversion" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/services/middleware" + "gitlab.com/beneath-hq/beneath/services/data/clientversion" ) // PingRequest is a request to HandlePing @@ -29,7 +29,7 @@ type pingTags struct { } // HandlePing handles a ping request from a client library -func HandlePing(ctx context.Context, req *PingRequest) (*PingResponse, *Error) { +func (s *Service) HandlePing(ctx context.Context, req *PingRequest) (*PingResponse, *Error) { middleware.SetTagsPayload(ctx, pingTags{ ClientID: req.ClientID, ClientVersion: req.ClientVersion, diff --git a/gateway/api/read.go b/services/data/handle_read.go similarity index 76% rename from gateway/api/read.go rename to services/data/handle_read.go index 3f2e46e0..109b776b 100644 --- a/gateway/api/read.go +++ b/services/data/handle_read.go @@ -1,4 +1,4 @@ -package api +package data import ( "context" @@ -7,13 +7,11 @@ import ( uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/engine/driver" - pb "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" - "gitlab.com/beneath-hq/beneath/gateway/util" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" + "gitlab.com/beneath-hq/beneath/models" "gitlab.com/beneath-hq/beneath/pkg/timeutil" + pb "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" + "gitlab.com/beneath-hq/beneath/services/middleware" ) // ReadRequest is a request to HandleRead @@ -48,7 +46,7 @@ const ( ) // HandleRead handles a read request -func HandleRead(ctx context.Context, req *ReadRequest) (*ReadResponse, *Error) { +func (s *Service) HandleRead(ctx context.Context, req *ReadRequest) (*ReadResponse, *Error) { // get auth secret := middleware.GetSecret(ctx) if secret == nil { @@ -63,7 +61,7 @@ func HandleRead(ctx context.Context, req *ReadRequest) (*ReadResponse, *Error) { middleware.SetTagsPayload(ctx, payload) // parse cursor - cursor, err := util.CursorFromBytes(req.Cursor) + cursor, err := CursorFromBytes(req.Cursor) if err != nil { return nil, newErrorf(http.StatusBadRequest, "%s", err.Error()) } @@ -76,7 +74,7 @@ func HandleRead(ctx context.Context, req *ReadRequest) (*ReadResponse, *Error) { } // check quota - err = util.CheckReadQuota(ctx, secret) + err = s.CheckReadQuota(ctx, secret) if err != nil { return nil, newError(http.StatusTooManyRequests, err.Error()) } @@ -89,7 +87,7 @@ func HandleRead(ctx context.Context, req *ReadRequest) (*ReadResponse, *Error) { streamID := uuid.Nil instanceID := uuid.Nil - if cursor.GetType() == util.LogCursorType || cursor.GetType() == util.IndexCursorType { + if cursor.GetType() == LogCursorType || cursor.GetType() == IndexCursorType { // get instanceID instanceID = cursor.GetID() resp.InstanceID = instanceID @@ -99,24 +97,24 @@ func HandleRead(ctx context.Context, req *ReadRequest) (*ReadResponse, *Error) { middleware.SetTagsPayload(ctx, payload) // get cached stream - stream := entity.FindCachedStreamByCurrentInstanceID(ctx, instanceID) + stream := s.Streams.FindCachedInstance(ctx, instanceID) if stream == nil { return nil, newError(http.StatusNotFound, "stream not found") } streamID = stream.StreamID // check permissions - perms := secret.StreamPermissions(ctx, stream.StreamID, stream.ProjectID, stream.Public) + perms := s.Permissions.StreamPermissionsForSecret(ctx, secret, stream.StreamID, stream.ProjectID, stream.Public) if !perms.Read { return nil, newErrorf(http.StatusForbidden, "token doesn't grant right to read this stream") } // get it - it, err = hub.Engine.Lookup.ReadCursor(ctx, stream, stream, entity.EfficientStreamInstance(instanceID), cursor.GetPayload(), int(req.Limit)) + it, err = s.Engine.Lookup.ReadCursor(ctx, stream, stream, models.EfficientStreamInstance(instanceID), cursor.GetPayload(), int(req.Limit)) if err != nil { return nil, newErrorf(http.StatusBadRequest, "%s", err.Error()) } - } else if cursor.GetType() == util.WarehouseCursorType { + } else if cursor.GetType() == WarehouseCursorType { // get jobID jobID := cursor.GetID() resp.JobID = jobID @@ -126,7 +124,7 @@ func HandleRead(ctx context.Context, req *ReadRequest) (*ReadResponse, *Error) { middleware.SetTagsPayload(ctx, payload) // get it - it, err = hub.Engine.Warehouse.ReadWarehouseCursor(ctx, cursor.GetPayload(), int(req.Limit)) + it, err = s.Engine.Warehouse.ReadWarehouseCursor(ctx, cursor.GetPayload(), int(req.Limit)) if err != nil { return nil, newErrorf(http.StatusBadRequest, "%s", err.Error()) } @@ -158,7 +156,7 @@ func HandleRead(ctx context.Context, req *ReadRequest) (*ReadResponse, *Error) { avro := record.GetAvro() // to calculate bytes read data := record.GetJSON() - if cursor.GetType() == util.WarehouseCursorType { + if cursor.GetType() == WarehouseCursorType { data["@meta"] = map[string]interface{}{ "timestamp": timeutil.UnixMilli(record.GetTimestamp()), } @@ -180,7 +178,7 @@ func HandleRead(ctx context.Context, req *ReadRequest) (*ReadResponse, *Error) { resp.NextCursor = wrapCursor(cursor.GetType(), cursor.GetID(), it.NextCursor()) // track read metrics - util.TrackRead(ctx, secret, streamID, instanceID, int64(nrecords), int64(nbytes)) + s.TrackRead(ctx, secret, streamID, instanceID, int64(nrecords), int64(nbytes)) // update log message payload.BytesRead = nbytes diff --git a/services/data/handle_subscribe.go b/services/data/handle_subscribe.go new file mode 100644 index 00000000..0739a6cd --- /dev/null +++ b/services/data/handle_subscribe.go @@ -0,0 +1,71 @@ +package data + +import ( + "context" + "net/http" + + uuid "github.com/satori/go.uuid" + + "gitlab.com/beneath-hq/beneath/models" +) + +// SubscribeRequest is a request to HandleSubscribe +type SubscribeRequest struct { + Secret models.Secret + Cursor []byte + Cb func(msg SubscriptionMessage) +} + +// SubscribeResponse is a result from HandleSubscribe +type SubscribeResponse struct { + InstanceID uuid.UUID + Cancel context.CancelFunc +} + +// HandleSubscribe starts a new subscription. +// Note: Basically just packaging a bunch of things the HTTP and GRPC servers need to +// do before calling s.Subscribe. +func (s *Service) HandleSubscribe(ctx context.Context, req *SubscribeRequest) (*SubscribeResponse, error) { + // parse cursor + cursor, err := CursorFromBytes(req.Cursor) + if err != nil { + return nil, newError(http.StatusBadRequest, err.Error()) + } + + // ensure log cursor + if cursor.GetType() != LogCursorType { + return nil, newErrorf(http.StatusBadRequest, "cannot subscribe to non-log cursor") + } + + // read instanceID + instanceID := cursor.GetID() + + // get cached stream + stream := s.Streams.FindCachedInstance(ctx, instanceID) + if stream == nil { + return nil, newErrorf(http.StatusNotFound, "stream not found") + } + + // check permissions + perms := s.Permissions.StreamPermissionsForSecret(ctx, req.Secret, stream.StreamID, stream.ProjectID, stream.Public) + if !perms.Read { + return nil, newErrorf(http.StatusForbidden, "token doesn't grant right to read this stream") + } + + // check usage + err = s.CheckReadQuota(ctx, req.Secret) + if err != nil { + return nil, newError(http.StatusTooManyRequests, err.Error()) + } + + // start subscription + cancel, err := s.Subscribe(instanceID, cursor.GetPayload(), req.Cb) + if err != nil { + return nil, err + } + + return &SubscribeResponse{ + InstanceID: instanceID, + Cancel: cancel, + }, nil +} diff --git a/gateway/api/warehouse.go b/services/data/handle_warehouse.go similarity index 80% rename from gateway/api/warehouse.go rename to services/data/handle_warehouse.go index 8b25b34f..0665bd42 100644 --- a/gateway/api/warehouse.go +++ b/services/data/handle_warehouse.go @@ -1,4 +1,4 @@ -package api +package data import ( "context" @@ -6,11 +6,9 @@ import ( uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/engine/driver" - "gitlab.com/beneath-hq/beneath/gateway/util" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/internal/middleware" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/services/middleware" ) // QueryWarehouseRequest is a request to HandleQueryWarehouse @@ -67,7 +65,7 @@ type pollWarehouseTags struct { } // HandleQueryWarehouse handles a warehouse query request -func HandleQueryWarehouse(ctx context.Context, req *QueryWarehouseRequest) (*QueryWarehouseResponse, *Error) { +func (s *Service) HandleQueryWarehouse(ctx context.Context, req *QueryWarehouseRequest) (*QueryWarehouseResponse, *Error) { // get auth secret := middleware.GetSecret(ctx) if secret == nil || secret.IsAnonymous() { @@ -90,27 +88,27 @@ func HandleQueryWarehouse(ctx context.Context, req *QueryWarehouseRequest) (*Que } // expand query - query, err := hub.Engine.ExpandWarehouseQuery(ctx, req.Query, func(ctx context.Context, organizationName, projectName, streamName string) (driver.Project, driver.Stream, driver.StreamInstance, error) { + query, err := s.Engine.ExpandWarehouseQuery(ctx, req.Query, func(ctx context.Context, organizationName, projectName, streamName string) (driver.Project, driver.Stream, driver.StreamInstance, error) { // get instance ID - instanceID := entity.FindInstanceIDByOrganizationProjectAndName(ctx, organizationName, projectName, streamName) + instanceID := s.Streams.FindPrimaryInstanceIDByOrganizationProjectAndName(ctx, organizationName, projectName, streamName) if instanceID == uuid.Nil { return nil, nil, nil, newErrorf(http.StatusNotFound, "instance not found for stream '%s/%s/%s'", organizationName, projectName, streamName) } // get stream - stream := entity.FindCachedStreamByCurrentInstanceID(ctx, instanceID) + stream := s.Streams.FindCachedInstance(ctx, instanceID) if stream == nil { return nil, nil, nil, newErrorf(http.StatusNotFound, "stream '%s/%s/%s' not found", organizationName, projectName, streamName) } // check permissions - perms := secret.StreamPermissions(ctx, stream.StreamID, stream.ProjectID, stream.Public) + perms := s.Permissions.StreamPermissionsForSecret(ctx, secret, stream.StreamID, stream.ProjectID, stream.Public) if !perms.Read { return nil, nil, nil, newErrorf(http.StatusForbidden, "token doesn't grant right to read stream '%s/%s/%s'", organizationName, projectName, streamName) } // success - return stream, stream, entity.EfficientStreamInstance(instanceID), nil + return stream, stream, models.EfficientStreamInstance(instanceID), nil }) if err != nil { if errr, ok := err.(*Error); ok { @@ -120,7 +118,7 @@ func HandleQueryWarehouse(ctx context.Context, req *QueryWarehouseRequest) (*Que } // analyze query - analyzeJob, err := hub.Engine.Warehouse.AnalyzeWarehouseQuery(ctx, query) + analyzeJob, err := s.Engine.Warehouse.AnalyzeWarehouseQuery(ctx, query) if err != nil { return nil, newErrorf(http.StatusBadRequest, "error during query analysis: %s", err.Error()) } @@ -137,14 +135,14 @@ func HandleQueryWarehouse(ctx context.Context, req *QueryWarehouseRequest) (*Que } // check quota - err = util.CheckScanQuota(ctx, secret, estimatedBytesScanned) + err = s.CheckScanQuota(ctx, secret, estimatedBytesScanned) if err != nil { return nil, newError(http.StatusTooManyRequests, err.Error()) } // run real job jobID := uuid.NewV4() - job, err := hub.Engine.Warehouse.RunWarehouseQuery(ctx, jobID, query, int(req.Partitions), int(req.TimeoutMs), int(req.MaxBytesScanned)) + job, err := s.Engine.Warehouse.RunWarehouseQuery(ctx, jobID, query, int(req.Partitions), int(req.TimeoutMs), int(req.MaxBytesScanned)) if err != nil { return nil, newErrorf(http.StatusBadRequest, "error running query: %s", err.Error()) } @@ -156,20 +154,20 @@ func HandleQueryWarehouse(ctx context.Context, req *QueryWarehouseRequest) (*Que middleware.SetTagsPayload(ctx, payload) // track read metrics - util.TrackScan(ctx, secret, estimatedBytesScanned) + s.TrackScan(ctx, secret, estimatedBytesScanned) return &QueryWarehouseResponse{Job: wrapWarehouseJob(job, analyzeJob)}, nil } // HandlePollWarehouse handles a warehouse poll request -func HandlePollWarehouse(ctx context.Context, req *PollWarehouseRequest) (*PollWarehouseResponse, *Error) { +func (s *Service) HandlePollWarehouse(ctx context.Context, req *PollWarehouseRequest) (*PollWarehouseResponse, *Error) { // set payload payload := pollWarehouseTags{ JobID: req.JobID, } middleware.SetTagsPayload(ctx, payload) - job, err := hub.Engine.Warehouse.PollWarehouseJob(ctx, req.JobID) + job, err := s.Engine.Warehouse.PollWarehouseJob(ctx, req.JobID) if err != nil { return nil, newErrorf(http.StatusBadRequest, "error polling job: %s", err.Error()) } @@ -187,7 +185,7 @@ func HandlePollWarehouse(ctx context.Context, req *PollWarehouseRequest) (*PollW func wrapWarehouseJob(job driver.WarehouseJob, analyzeJob driver.WarehouseJob) *WarehouseJob { var cursors [][]byte for _, engineCursor := range job.GetReplayCursors() { - cursors = append(cursors, wrapCursor(util.WarehouseCursorType, job.GetJobID(), engineCursor)) + cursors = append(cursors, wrapCursor(WarehouseCursorType, job.GetJobID(), engineCursor)) } // coalesce GetReferencedInstances with analyzeJob diff --git a/gateway/api/write.go b/services/data/handle_write.go similarity index 81% rename from gateway/api/write.go rename to services/data/handle_write.go index 8781f30e..e5844ba6 100644 --- a/gateway/api/write.go +++ b/services/data/handle_write.go @@ -1,4 +1,4 @@ -package api +package data import ( "context" @@ -9,14 +9,12 @@ import ( uuid "github.com/satori/go.uuid" "golang.org/x/sync/errgroup" - "gitlab.com/beneath-hq/beneath/control/entity" - pb_engine "gitlab.com/beneath-hq/beneath/engine/proto" - pb "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" - "gitlab.com/beneath-hq/beneath/gateway/util" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/internal/middleware" + pb_engine "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" + "gitlab.com/beneath-hq/beneath/models" "gitlab.com/beneath-hq/beneath/pkg/jsonutil" "gitlab.com/beneath-hq/beneath/pkg/timeutil" + pb "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" + "gitlab.com/beneath-hq/beneath/services/middleware" ) // WriteRequest is a request to HandleWrite @@ -45,7 +43,7 @@ type writeMetrics struct { } // HandleWrite handles a write request -func HandleWrite(ctx context.Context, req *WriteRequest) (*WriteResponse, *Error) { +func (s *Service) HandleWrite(ctx context.Context, req *WriteRequest) (*WriteResponse, *Error) { // get auth secret := middleware.GetSecret(ctx) if secret == nil { @@ -53,7 +51,7 @@ func HandleWrite(ctx context.Context, req *WriteRequest) (*WriteResponse, *Error } // check quota - err := util.CheckWriteQuota(ctx, secret) + err := s.CheckWriteQuota(ctx, secret) if err != nil { return nil, newError(http.StatusTooManyRequests, err.Error()) } @@ -65,7 +63,7 @@ func HandleWrite(ctx context.Context, req *WriteRequest) (*WriteResponse, *Error // get instances concurrently mu := &sync.Mutex{} - instances := make(map[uuid.UUID]*entity.CachedStream, len(req.InstanceRecords)) + instances := make(map[uuid.UUID]*models.CachedInstance, len(req.InstanceRecords)) group, cctx := errgroup.WithContext(ctx) for instanceID, records := range req.InstanceRecords { instanceID := instanceID // see https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables @@ -77,7 +75,7 @@ func HandleWrite(ctx context.Context, req *WriteRequest) (*WriteResponse, *Error } // get stream info - stream := entity.FindCachedStreamByCurrentInstanceID(cctx, instanceID) + stream := s.Streams.FindCachedInstance(cctx, instanceID) if stream == nil { return newErrorf(http.StatusNotFound, "stream not found for instance_id=%s", instanceID.String()) } @@ -88,7 +86,7 @@ func HandleWrite(ctx context.Context, req *WriteRequest) (*WriteResponse, *Error } // check permissions - perms := secret.StreamPermissions(cctx, stream.StreamID, stream.ProjectID, stream.Public) + perms := s.Permissions.StreamPermissionsForSecret(cctx, secret, stream.StreamID, stream.ProjectID, stream.Public) if !perms.Write { return newErrorf(http.StatusForbidden, "secret doesn't grant right to write to stream_id=%s", stream.StreamID.String()) } @@ -113,14 +111,14 @@ func HandleWrite(ctx context.Context, req *WriteRequest) (*WriteResponse, *Error instanceMetrics := make([]writeMetrics, 0, len(req.InstanceRecords)) for instanceID, records := range req.InstanceRecords { // check the batch length is valid - err = hub.Engine.CheckBatchLength(records.Len()) + err = s.Engine.CheckBatchLength(records.Len()) if err != nil { return nil, newError(http.StatusBadRequest, err.Error()) } // check records stream := instances[instanceID] - pbs, bytes, err := records.prepare(instanceID, stream) + pbs, bytes, err := records.prepare(s, instanceID, stream) if err != nil { return nil, err } @@ -139,7 +137,7 @@ func HandleWrite(ctx context.Context, req *WriteRequest) (*WriteResponse, *Error // write request to engine writeID := uuid.NewV4() - err = hub.Engine.QueueWriteRequest(ctx, &pb_engine.WriteRequest{ + err = s.QueueWriteRequest(ctx, &pb_engine.WriteRequest{ WriteId: writeID.Bytes(), InstanceRecords: instanceRecords, }) @@ -150,7 +148,7 @@ func HandleWrite(ctx context.Context, req *WriteRequest) (*WriteResponse, *Error // track write metrics for _, im := range instanceMetrics { stream := instances[im.InstanceID] - util.TrackWrite(ctx, secret, stream.StreamID, im.InstanceID, int64(im.RecordsCount), int64(im.BytesWritten)) + s.TrackWrite(ctx, secret, stream.StreamID, im.InstanceID, int64(im.RecordsCount), int64(im.BytesWritten)) } // set log payload @@ -178,14 +176,14 @@ func (r *WriteRecords) Len() int { } // prepares for writing -func (r *WriteRecords) prepare(instanceID uuid.UUID, stream *entity.CachedStream) ([]*pb.Record, int, *Error) { +func (r *WriteRecords) prepare(s *Service, instanceID uuid.UUID, stream *models.CachedInstance) ([]*pb.Record, int, *Error) { if r.PB != nil { - return r.preparePB(instanceID, stream) + return r.preparePB(s, instanceID, stream) } - return r.prepareJSON(instanceID, stream) + return r.prepareJSON(s, instanceID, stream) } -func (r *WriteRecords) preparePB(instanceID uuid.UUID, stream *entity.CachedStream) ([]*pb.Record, int, *Error) { +func (r *WriteRecords) preparePB(s *Service, instanceID uuid.UUID, stream *models.CachedInstance) ([]*pb.Record, int, *Error) { // validate each record bytes := 0 for i, record := range r.PB { @@ -201,7 +199,7 @@ func (r *WriteRecords) preparePB(instanceID uuid.UUID, stream *entity.CachedStre } // check record size - err = hub.Engine.CheckRecordSize(stream, structured, len(record.AvroData)) + err = s.Engine.CheckRecordSize(stream, structured, len(record.AvroData)) if err != nil { return nil, 0, newErrorf(http.StatusBadRequest, "error for instance_id=%s, record at index %d: %v", instanceID.String(), i, err.Error()) } @@ -213,7 +211,7 @@ func (r *WriteRecords) preparePB(instanceID uuid.UUID, stream *entity.CachedStre return r.PB, bytes, nil } -func (r *WriteRecords) prepareJSON(instanceID uuid.UUID, stream *entity.CachedStream) ([]*pb.Record, int, *Error) { +func (r *WriteRecords) prepareJSON(s *Service, instanceID uuid.UUID, stream *models.CachedInstance) ([]*pb.Record, int, *Error) { // convert objects into records records := make([]*pb.Record, len(r.JSON)) bytesWritten := 0 @@ -250,7 +248,7 @@ func (r *WriteRecords) prepareJSON(instanceID uuid.UUID, stream *entity.CachedSt return nil, 0, newErrorf(http.StatusBadRequest, "error encoding record at index %d for instance %s: %s", idx, instanceID.String(), err.Error()) } - err = hub.Engine.CheckRecordSize(stream, native, len(avroData)) + err = s.Engine.CheckRecordSize(stream, native, len(avroData)) if err != nil { return nil, 0, newErrorf(http.StatusBadRequest, "error encoding record at index %d for instance %s: %s", idx, instanceID.String(), err.Error()) } diff --git a/engine/writes.go b/services/data/mq.go similarity index 60% rename from engine/writes.go rename to services/data/mq.go index 6fb4cf8b..69d775c8 100644 --- a/engine/writes.go +++ b/services/data/mq.go @@ -1,4 +1,4 @@ -package engine +package data import ( "context" @@ -6,7 +6,7 @@ import ( "github.com/golang/protobuf/proto" - pb "gitlab.com/beneath-hq/beneath/engine/proto" + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" ) const ( @@ -19,20 +19,20 @@ const ( // QueueWriteRequest queues a write request -- concretely, it results in // the write request being written to Pubsub, then from there read by // the data processing pipeline and written to BigTable and BigQuery -func (e *Engine) QueueWriteRequest(ctx context.Context, req *pb.WriteRequest) error { +func (s *Service) QueueWriteRequest(ctx context.Context, req *pb.WriteRequest) error { msg, err := proto.Marshal(req) if err != nil { - panic(err) + return err } - if len(msg) > e.MQ.MaxMessageSize() { - return fmt.Errorf("total write size <%d bytes> exceeds maximum <%d bytes>", len(msg), e.MQ.MaxMessageSize()) + if len(msg) > s.MQ.MaxMessageSize() { + return fmt.Errorf("total write size <%d bytes> exceeds maximum <%d bytes>", len(msg), s.MQ.MaxMessageSize()) } - return e.MQ.Publish(ctx, writeRequestsTopic, msg) + return s.MQ.Publish(ctx, writeRequestsTopic, msg) } // ReadWriteRequests triggers fn for every WriteRecordsRequest that's written with QueueWriteRequest -func (e *Engine) ReadWriteRequests(ctx context.Context, fn func(context.Context, *pb.WriteRequest) error) error { - return e.MQ.Subscribe(ctx, writeRequestsTopic, writeRequestsSubscription, true, func(ctx context.Context, msg []byte) error { +func (s *Service) ReadWriteRequests(ctx context.Context, fn func(context.Context, *pb.WriteRequest) error) error { + return s.MQ.Subscribe(ctx, writeRequestsTopic, writeRequestsSubscription, true, func(ctx context.Context, msg []byte) error { req := &pb.WriteRequest{} err := proto.Unmarshal(msg, req) if err != nil { @@ -43,20 +43,20 @@ func (e *Engine) ReadWriteRequests(ctx context.Context, fn func(context.Context, } // QueueWriteReport publishes a WriteReport (used to notify of completed processing of a WriteRequest) -func (e *Engine) QueueWriteReport(ctx context.Context, rep *pb.WriteReport) error { +func (s *Service) QueueWriteReport(ctx context.Context, rep *pb.WriteReport) error { msg, err := proto.Marshal(rep) if err != nil { panic(err) } - if len(msg) > e.MQ.MaxMessageSize() { - return fmt.Errorf("total write report size <%d bytes> exceeds maximum <%d bytes>", len(msg), e.MQ.MaxMessageSize()) + if len(msg) > s.MQ.MaxMessageSize() { + return fmt.Errorf("total write report size <%d bytes> exceeds maximum <%d bytes>", len(msg), s.MQ.MaxMessageSize()) } - return e.MQ.Publish(ctx, writeReportsTopic, msg) + return s.MQ.Publish(ctx, writeReportsTopic, msg) } // ReadWriteReports reads messages published with QueueWriteReport -func (e *Engine) ReadWriteReports(ctx context.Context, fn func(context.Context, *pb.WriteReport) error) error { - return e.MQ.Subscribe(ctx, writeReportsTopic, writeReportsSubscription, false, func(ctx context.Context, msg []byte) error { +func (s *Service) ReadWriteReports(ctx context.Context, fn func(context.Context, *pb.WriteReport) error) error { + return s.MQ.Subscribe(ctx, writeReportsTopic, writeReportsSubscription, false, func(ctx context.Context, msg []byte) error { rep := &pb.WriteReport{} err := proto.Unmarshal(msg, rep) if err != nil { diff --git a/services/data/subscriptions.go b/services/data/subscriptions.go new file mode 100644 index 00000000..63276c03 --- /dev/null +++ b/services/data/subscriptions.go @@ -0,0 +1,119 @@ +package data + +import ( + "context" + "fmt" + "sync" + "time" + + uuid "github.com/satori/go.uuid" + + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" + "gitlab.com/beneath-hq/beneath/pkg/log" +) + +// SubscriptionMessage encapsulates a subscription update dispatched by a Broker +type SubscriptionMessage struct { + Iterator driver.RecordsIterator + PrevCursor []byte +} + +// subscriptions manages a map of instances to subscription callbacks +type subscriptions struct { + sync.RWMutex + i int + m map[uuid.UUID]*callbacks + open bool +} + +// callbacks manages a set of subscription callbacks +type callbacks struct { + sync.RWMutex + m map[int]func(SubscriptionMessage) +} + +// ServeSubscriptions brokers subscriptions until ctx is cancelled or an error occurs +func (s *Service) ServeSubscriptions(ctx context.Context) error { + s.subscriptions = subscriptions{ + m: make(map[uuid.UUID]*callbacks), + open: true, + } + + err := s.ReadWriteReports(ctx, s.handleWriteReport) + if err != nil { + return err + } + + // TODO: gracefully shutdown subscriptions + + s.subscriptions.open = false + log.S.Infow("subscriptions broker shutdown gracefully") + return nil +} + +// Subscribe opens a new subscription on an instance +func (s *Service) Subscribe(instanceID uuid.UUID, cursor []byte, cb func(SubscriptionMessage)) (context.CancelFunc, error) { + if !s.subscriptions.open { + return nil, fmt.Errorf("Cannot handle Subscribe because Service isn't serving subscriptions") + } + + s.subscriptions.Lock() + cbs := s.subscriptions.m[instanceID] + if cbs == nil { + cbs = &callbacks{m: make(map[int]func(SubscriptionMessage))} + s.subscriptions.m[instanceID] = cbs + } + s.subscriptions.i++ + cbID := s.subscriptions.i + s.subscriptions.Unlock() + + cbs.Lock() + cbs.m[cbID] = cb + cbs.Unlock() + + cancel := func() { + cbs.Lock() + delete(cbs.m, cbID) + cbs.Unlock() + } + return cancel, nil +} + +// handleWriteReport processes a write report +func (s *Service) handleWriteReport(ctx context.Context, rep *pb.WriteReport) error { + startTime := time.Now() + + instanceID := uuid.FromBytesOrNil(rep.InstanceId) + + s.subscriptions.RLock() + cbs := s.subscriptions.m[instanceID] + s.subscriptions.RUnlock() + + if cbs == nil { + return nil + } + + cbs.RLock() + n := len(cbs.m) + if n == 0 { + cbs.RUnlock() + return nil + } + + msg := SubscriptionMessage{} + for _, cb := range cbs.m { + cb(msg) + } + + cbs.RUnlock() + + log.S.Infow( + "subscription dispatch", + "instance", instanceID.String(), + "clients", n, + "elapsed", time.Since(startTime), + ) + + return nil +} diff --git a/gateway/util/usage.go b/services/data/usage.go similarity index 59% rename from gateway/util/usage.go rename to services/data/usage.go index 51c0978a..33b41e29 100644 --- a/gateway/util/usage.go +++ b/services/data/usage.go @@ -1,4 +1,4 @@ -package util +package data import ( "context" @@ -6,8 +6,7 @@ import ( uuid "github.com/satori/go.uuid" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/gateway" + "gitlab.com/beneath-hq/beneath/models" ) const ( @@ -17,55 +16,55 @@ const ( ) // TrackRead is a helper to track read usage for a secret from an instance -func TrackRead(ctx context.Context, secret entity.Secret, streamID uuid.UUID, instanceID uuid.UUID, nrecords int64, nbytes int64) { +func (s *Service) TrackRead(ctx context.Context, secret models.Secret, streamID uuid.UUID, instanceID uuid.UUID, nrecords int64, nbytes int64) { if streamID != uuid.Nil { - gateway.Metrics.TrackRead(streamID, nrecords, nbytes) + s.Metrics.TrackRead(streamID, nrecords, nbytes) } if instanceID != uuid.Nil { - gateway.Metrics.TrackRead(instanceID, nrecords, nbytes) + s.Metrics.TrackRead(instanceID, nrecords, nbytes) } if !secret.IsAnonymous() { if nbytes < minReadBytesBilled { nbytes = minReadBytesBilled } - gateway.Metrics.TrackRead(secret.GetOwnerID(), nrecords, nbytes) - gateway.Metrics.TrackRead(secret.GetBillingOrganizationID(), nrecords, nbytes) + s.Metrics.TrackRead(secret.GetOwnerID(), nrecords, nbytes) + s.Metrics.TrackRead(secret.GetBillingOrganizationID(), nrecords, nbytes) } } // TrackWrite is a helper to track write usage for a secret to an instance -func TrackWrite(ctx context.Context, secret entity.Secret, streamID uuid.UUID, instanceID uuid.UUID, nrecords int64, nbytes int64) { - gateway.Metrics.TrackWrite(streamID, nrecords, nbytes) - gateway.Metrics.TrackWrite(instanceID, nrecords, nbytes) +func (s *Service) TrackWrite(ctx context.Context, secret models.Secret, streamID uuid.UUID, instanceID uuid.UUID, nrecords int64, nbytes int64) { + s.Metrics.TrackWrite(streamID, nrecords, nbytes) + s.Metrics.TrackWrite(instanceID, nrecords, nbytes) if !secret.IsAnonymous() { if nbytes < minWriteBytesBilled { nbytes = minWriteBytesBilled } - gateway.Metrics.TrackWrite(secret.GetOwnerID(), nrecords, nbytes) - gateway.Metrics.TrackWrite(secret.GetBillingOrganizationID(), nrecords, nbytes) + s.Metrics.TrackWrite(secret.GetOwnerID(), nrecords, nbytes) + s.Metrics.TrackWrite(secret.GetBillingOrganizationID(), nrecords, nbytes) } } // TrackScan is a helper to track scan usage for a secret to an instance -func TrackScan(ctx context.Context, secret entity.Secret, nbytes int64) { +func (s *Service) TrackScan(ctx context.Context, secret models.Secret, nbytes int64) { if !secret.IsAnonymous() { if nbytes < minScanBytesBilled { nbytes = minScanBytesBilled } - gateway.Metrics.TrackScan(secret.GetOwnerID(), nbytes) - gateway.Metrics.TrackScan(secret.GetBillingOrganizationID(), nbytes) + s.Metrics.TrackScan(secret.GetOwnerID(), nbytes) + s.Metrics.TrackScan(secret.GetBillingOrganizationID(), nbytes) } } // CheckReadQuota checks that the secret is within its quotas to trigger a read -func CheckReadQuota(ctx context.Context, secret entity.Secret) error { +func (s *Service) CheckReadQuota(ctx context.Context, secret models.Secret) error { if secret.IsAnonymous() { return nil } brq := secret.GetBillingReadQuota() if brq != nil { - usage := gateway.Metrics.GetCurrentUsage(ctx, secret.GetBillingOrganizationID()) + usage := s.Metrics.GetCurrentUsage(ctx, secret.GetBillingOrganizationID()) if usage.ReadBytes >= *brq { return fmt.Errorf("your organization has exhausted its monthly read quota") } @@ -73,7 +72,7 @@ func CheckReadQuota(ctx context.Context, secret entity.Secret) error { orq := secret.GetOwnerReadQuota() if orq != nil { - usage := gateway.Metrics.GetCurrentUsage(ctx, secret.GetOwnerID()) + usage := s.Metrics.GetCurrentUsage(ctx, secret.GetOwnerID()) if usage.ReadBytes >= *orq { return fmt.Errorf("you have exhausted your monthly read quota") } @@ -83,14 +82,14 @@ func CheckReadQuota(ctx context.Context, secret entity.Secret) error { } // CheckWriteQuota checks that the secret is within its quotas to trigger a write -func CheckWriteQuota(ctx context.Context, secret entity.Secret) error { +func (s *Service) CheckWriteQuota(ctx context.Context, secret models.Secret) error { if secret.IsAnonymous() { return nil } bwq := secret.GetBillingWriteQuota() if bwq != nil { - usage := gateway.Metrics.GetCurrentUsage(ctx, secret.GetBillingOrganizationID()) + usage := s.Metrics.GetCurrentUsage(ctx, secret.GetBillingOrganizationID()) if usage.WriteBytes >= *bwq { return fmt.Errorf("your organization has exhausted its monthly write quota") } @@ -98,7 +97,7 @@ func CheckWriteQuota(ctx context.Context, secret entity.Secret) error { owq := secret.GetOwnerWriteQuota() if owq != nil { - usage := gateway.Metrics.GetCurrentUsage(ctx, secret.GetOwnerID()) + usage := s.Metrics.GetCurrentUsage(ctx, secret.GetOwnerID()) if usage.WriteBytes >= *owq { return fmt.Errorf("you have exhausted your monthly write quota") } @@ -108,14 +107,14 @@ func CheckWriteQuota(ctx context.Context, secret entity.Secret) error { } // CheckScanQuota checks that secret is within its quotas to trigger a warehouse query -func CheckScanQuota(ctx context.Context, secret entity.Secret, estimatedScanBytes int64) error { +func (s *Service) CheckScanQuota(ctx context.Context, secret models.Secret, estimatedScanBytes int64) error { if secret.IsAnonymous() { return fmt.Errorf("anonymous users cannot run warehouse queries") } bsq := secret.GetBillingScanQuota() if bsq != nil { - usage := gateway.Metrics.GetCurrentUsage(ctx, secret.GetBillingOrganizationID()) + usage := s.Metrics.GetCurrentUsage(ctx, secret.GetBillingOrganizationID()) if usage.ScanBytes >= *bsq { return fmt.Errorf("your organization has exhausted its monthly warehouse scan quota") } else if usage.ScanBytes+estimatedScanBytes > *bsq { @@ -125,7 +124,7 @@ func CheckScanQuota(ctx context.Context, secret entity.Secret, estimatedScanByte osq := secret.GetOwnerScanQuota() if osq != nil { - usage := gateway.Metrics.GetCurrentUsage(ctx, secret.GetOwnerID()) + usage := s.Metrics.GetCurrentUsage(ctx, secret.GetOwnerID()) if usage.ScanBytes >= *osq { return fmt.Errorf("you have exhausted your monthly warehouse scan quota") } else if usage.ScanBytes+estimatedScanBytes > *osq { diff --git a/gateway/api/util.go b/services/data/util.go similarity index 64% rename from gateway/api/util.go rename to services/data/util.go index e3875612..4a353ff7 100644 --- a/gateway/api/util.go +++ b/services/data/util.go @@ -1,32 +1,15 @@ -package api +package data import ( "fmt" "net/http" - uuid "github.com/satori/go.uuid" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "gitlab.com/beneath-hq/beneath/gateway/util" "gitlab.com/beneath-hq/beneath/pkg/httputil" ) -func wrapCursor(cursorType util.CursorType, id uuid.UUID, engineCursor []byte) []byte { - if len(engineCursor) == 0 { - return engineCursor - } - return util.NewCursor(cursorType, id, engineCursor).GetBytes() -} - -func wrapCursors(cursorType util.CursorType, id uuid.UUID, engineCursors [][]byte) [][]byte { - wrapped := make([][]byte, len(engineCursors)) - for idx, engineCursor := range engineCursors { - wrapped[idx] = wrapCursor(cursorType, id, engineCursor) - } - return wrapped -} - // Error represents a generalized GRPC and HTTP error type Error struct { httpStatus int diff --git a/gateway/pipeline/pipeline.go b/services/data/worker.go similarity index 76% rename from gateway/pipeline/pipeline.go rename to services/data/worker.go index cc3ec9db..da487f15 100644 --- a/gateway/pipeline/pipeline.go +++ b/services/data/worker.go @@ -1,4 +1,4 @@ -package pipeline +package data import ( "context" @@ -9,23 +9,22 @@ import ( uuid "github.com/satori/go.uuid" "golang.org/x/sync/errgroup" - "gitlab.com/beneath-hq/beneath/control/entity" - "gitlab.com/beneath-hq/beneath/engine/driver" - pb "gitlab.com/beneath-hq/beneath/engine/proto" - pbgw "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" - "gitlab.com/beneath-hq/beneath/hub" + "gitlab.com/beneath-hq/beneath/infrastructure/engine/driver" + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" + "gitlab.com/beneath-hq/beneath/models" "gitlab.com/beneath-hq/beneath/pkg/log" "gitlab.com/beneath-hq/beneath/pkg/timeutil" + pbgw "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" ) -// Run subscribes to new write requests and stores data in derived systems. +// RunWorker subscribes to new write requests and stores data in derived systems. // It runs forever unless an error occcurs. -func Run(ctx context.Context) error { - return hub.Engine.ReadWriteRequests(ctx, processWriteRequest) +func (s *Service) RunWorker(ctx context.Context) error { + return s.ReadWriteRequests(ctx, s.processWriteRequest) } // ProcessWriteRequest persists a write request -func processWriteRequest(ctx context.Context, req *pb.WriteRequest) error { +func (s *Service) processWriteRequest(ctx context.Context, req *pb.WriteRequest) error { // metrics to track start := time.Now() bytesTotal := 0 @@ -46,7 +45,7 @@ func processWriteRequest(ctx context.Context, req *pb.WriteRequest) error { ir := req.InstanceRecords[idx] // see https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables group.Go(func() error { // process - bytesWritten, err := processInstanceRecords(cctx, req.WriteId, ir) + bytesWritten, err := s.processInstanceRecords(cctx, req.WriteId, ir) if err != nil { return err } @@ -82,10 +81,10 @@ func processWriteRequest(ctx context.Context, req *pb.WriteRequest) error { return nil } -func processInstanceRecords(ctx context.Context, writeID []byte, ir *pbgw.InstanceRecords) (int, error) { +func (s *Service) processInstanceRecords(ctx context.Context, writeID []byte, ir *pbgw.InstanceRecords) (int, error) { // lookup stream instanceID := uuid.FromBytesOrNil(ir.InstanceId) - stream := entity.FindCachedStreamByCurrentInstanceID(ctx, instanceID) + stream := s.Streams.FindCachedInstance(ctx, instanceID) if stream == nil { // TODO: use dead letter queue that retries log.S.Errorw("instance not found", "instance", instanceID.String(), "records", ir.Records) @@ -105,12 +104,12 @@ func processInstanceRecords(ctx context.Context, writeID []byte, ir *pbgw.Instan group, cctx := errgroup.WithContext(ctx) group.Go(func() error { - return hub.Engine.Lookup.WriteRecords(cctx, stream, stream, entity.EfficientStreamInstance(instanceID), records) + return s.Engine.Lookup.WriteRecords(cctx, stream, stream, models.EfficientStreamInstance(instanceID), records) }) if stream.UseWarehouse { group.Go(func() error { - return hub.Engine.Warehouse.WriteToWarehouse(cctx, stream, stream, entity.EfficientStreamInstance(instanceID), records) + return s.Engine.Warehouse.WriteToWarehouse(cctx, stream, stream, models.EfficientStreamInstance(instanceID), records) }) } @@ -120,7 +119,7 @@ func processInstanceRecords(ctx context.Context, writeID []byte, ir *pbgw.Instan } // publish write report (used for streaming updates) - err = hub.Engine.QueueWriteReport(ctx, &pb.WriteReport{ + err = s.QueueWriteReport(ctx, &pb.WriteReport{ WriteId: writeID, InstanceId: ir.InstanceId, RecordsCount: int32(len(ir.Records)), diff --git a/services/metrics/broker.go b/services/metrics/broker.go new file mode 100644 index 00000000..93f7d011 --- /dev/null +++ b/services/metrics/broker.go @@ -0,0 +1,53 @@ +package metrics + +import ( + "sync" + "time" + + "github.com/bluele/gcache" + uuid "github.com/satori/go.uuid" + + "gitlab.com/beneath-hq/beneath/infrastructure/engine" + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" +) + +// Options for creating a metrics broker +type Options struct { + CacheSize int + CommitInterval time.Duration +} + +// Broker reads and writes metrics. For writes, it buffers updates and flushes them in the background. +type Broker struct { + opts *Options + engine *engine.Engine + + running bool + buffer map[uuid.UUID]pb.QuotaUsage // accumulates metrics to commit + mu sync.RWMutex // for buffer + commitTicker *time.Ticker // periodically triggers a commit to BigTable + + usageCache gcache.Cache +} + +// OpType defines a read or write operation +type OpType int + +// OpType enum definition +const ( + OpTypeRead OpType = iota + OpTypeWrite + OpTypeScan +) + +// New initializes the Broker +func New(opts *Options, e *engine.Engine) *Broker { + // create the Broker + b := &Broker{ + opts: opts, + engine: e, + } + + // done + return b +} diff --git a/services/metrics/reading.go b/services/metrics/reading.go new file mode 100644 index 00000000..bcd254d3 --- /dev/null +++ b/services/metrics/reading.go @@ -0,0 +1,109 @@ +package metrics + +import ( + "context" + "fmt" + "time" + + "github.com/bluele/gcache" + uuid "github.com/satori/go.uuid" + + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" + "gitlab.com/beneath-hq/beneath/pkg/bytesutil" + "gitlab.com/beneath-hq/beneath/pkg/timeutil" +) + +const ( + maxPeriods = 175 // roughly one week on an hourly basis +) + +// GetHistoricalUsage returns usage info for the given length of time +func (b *Broker) GetHistoricalUsage(ctx context.Context, entityID uuid.UUID, period timeutil.Period, from time.Time, until time.Time) ([]time.Time, []pb.QuotaUsage, error) { + // check is supported period + if period != timeutil.PeriodHour && period != timeutil.PeriodMonth { + return nil, nil, fmt.Errorf("usage is calculated only in hourly and monthly periods") + } + + // if "until" is 0, set it to the current time + if until.IsZero() { + until = timeutil.Floor(time.Now(), period) + } + + // check that the provided time range corresponds to keys in the table + if from != timeutil.Floor(from, period) || until != timeutil.Floor(until, period) { + return nil, nil, fmt.Errorf("from and until must exactly match period beginnings") + } + + // prevent the retrieval of too many rows at once + if period.Count(from, until) > maxPeriods { + return nil, nil, fmt.Errorf("time span too long") + } + + // read usage table and collect usage metrics + var times []time.Time + var usages []pb.QuotaUsage + err := b.engine.ReadUsage(ctx, entityID, period, from, until, func(ts time.Time, usage pb.QuotaUsage) error { + times = append(times, ts) + usages = append(usages, usage) + return nil + }) + if err != nil { + panic(fmt.Errorf("error reading from metrics table: %s", err.Error())) + } + + return times, usages, nil +} + +// GetCurrentUsage returns an ID's usage for the current monthly or hourly period +func (b *Broker) GetCurrentUsage(ctx context.Context, entityID uuid.UUID) pb.QuotaUsage { + if !b.running { + return b.loadCurrentUsage(ctx, entityID) + } + + // create cache key + timeBytes := bytesutil.IntToBytes(timeutil.Floor(time.Now(), timeutil.PeriodMonth).Unix()) + cacheKey := string(append(entityID.Bytes(), timeBytes...)) + + // first, check cache for usage else get usage from store + var usage pb.QuotaUsage + val, err := b.usageCache.Get(cacheKey) + if err == nil { + // use cached value + usage = val.(pb.QuotaUsage) + } else if err != gcache.KeyNotFoundError { + // unexpected + panic(err) + } else { + // load from store + usage = b.loadCurrentUsage(ctx, entityID) + + // write back to cache + b.usageCache.Set(cacheKey, usage) + } + + // add buffer to quota + b.mu.RLock() + usageBuf := b.buffer[entityID] + b.mu.RUnlock() + usage.ReadOps += usageBuf.ReadOps + usage.ReadRecords += usageBuf.ReadRecords + usage.ReadBytes += usageBuf.ReadBytes + usage.WriteOps += usageBuf.WriteOps + usage.WriteRecords += usageBuf.WriteRecords + usage.WriteBytes += usageBuf.WriteBytes + usage.ScanOps += usageBuf.ScanOps + usage.ScanBytes += usageBuf.ScanBytes + + return usage +} + +// LoadCurrentUsage returns an ID's usage for the current monthly period +func (b *Broker) loadCurrentUsage(ctx context.Context, entityID uuid.UUID) pb.QuotaUsage { + // load from bigtable + usage, err := b.engine.ReadSingleUsage(ctx, entityID, timeutil.PeriodMonth, time.Now()) + if err != nil { + panic(fmt.Errorf("error reading metrics: %s", err.Error())) + } + + return usage +} diff --git a/internal/metrics/broker.go b/services/metrics/writing.go similarity index 52% rename from internal/metrics/broker.go rename to services/metrics/writing.go index ce1c6dbf..266ca5d6 100644 --- a/internal/metrics/broker.go +++ b/services/metrics/writing.go @@ -3,66 +3,28 @@ package metrics import ( "context" "fmt" - "sync" "time" "github.com/bluele/gcache" uuid "github.com/satori/go.uuid" "golang.org/x/sync/semaphore" - pb "gitlab.com/beneath-hq/beneath/engine/proto" - "gitlab.com/beneath-hq/beneath/hub" - "gitlab.com/beneath-hq/beneath/pkg/bytesutil" + pb "gitlab.com/beneath-hq/beneath/infrastructure/engine/proto" "gitlab.com/beneath-hq/beneath/pkg/log" "gitlab.com/beneath-hq/beneath/pkg/timeutil" ) -// Broker coordinates the buffer and ticker -type Broker struct { - // options set by NewBroker - cacheSize int - commitInterval time.Duration - - // accumulates metrics to commit - buffer map[uuid.UUID]pb.QuotaUsage - - // periodically triggers a commit to BigTable - commitTicker *time.Ticker - - // Lock - mu sync.RWMutex - - // usage cache - usageCache gcache.Cache -} - -// OpType defines a read or write operation -type OpType int - -// OpType enum definition -const ( - OpTypeRead OpType = iota - OpTypeWrite - OpTypeScan -) - -// NewBroker initializes the Broker -func NewBroker(cacheSize int, commitInterval time.Duration) *Broker { - // create the Broker - b := &Broker{ - cacheSize: cacheSize, - commitInterval: commitInterval, - buffer: make(map[uuid.UUID]pb.QuotaUsage, cacheSize), - commitTicker: time.NewTicker(commitInterval), - usageCache: gcache.New(cacheSize).LRU().Build(), +// Run sets the broker to periodically commit buffered metrics until ctx is cancelled or an error occurs +func (b *Broker) Run(ctx context.Context) error { + if b.running { + panic(fmt.Errorf("Cannot call RunForever twice")) } - // done - return b -} + b.running = true + b.buffer = make(map[uuid.UUID]pb.QuotaUsage, b.opts.CacheSize) + b.commitTicker = time.NewTicker(b.opts.CommitInterval) + b.usageCache = gcache.New(b.opts.CacheSize).LRU().Build() -// RunForever sets the broker to periodically commit buffered metrics until ctx is cancelled or an error occurs -func (b *Broker) RunForever(ctx context.Context) { for { select { case <-b.commitTicker.C: @@ -70,8 +32,9 @@ func (b *Broker) RunForever(ctx context.Context) { case <-ctx.Done(): b.commitTicker.Stop() b.commitToTable() + b.running = false log.S.Infow("metrics committed before stopping") - return + return nil } } } @@ -87,7 +50,7 @@ func (b *Broker) commitToTable() error { b.mu.Lock() buf := b.buffer - b.buffer = make(map[uuid.UUID]pb.QuotaUsage, b.cacheSize) + b.buffer = make(map[uuid.UUID]pb.QuotaUsage, b.opts.CacheSize) b.mu.Unlock() // skip if nothing to upload @@ -108,13 +71,13 @@ func (b *Broker) commitToTable() error { defer sem.Release(1) // commit metrics to monthly count - err := hub.Engine.CommitUsage(ctx, id, timeutil.PeriodMonth, ts, usage) + err := b.engine.CommitUsage(ctx, id, timeutil.PeriodMonth, ts, usage) if err != nil { return err } // commit metrics to hourly count - err = hub.Engine.CommitUsage(ctx, id, timeutil.PeriodHour, ts, usage) + err = b.engine.CommitUsage(ctx, id, timeutil.PeriodHour, ts, usage) if err != nil { return err } @@ -183,42 +146,3 @@ func (b *Broker) trackOp(op OpType, id uuid.UUID, nrecords int64, nbytes int64) b.buffer[id] = u b.mu.Unlock() } - -// GetCurrentUsage returns an ID's usage for the current monthly or hourly period -func (b *Broker) GetCurrentUsage(ctx context.Context, entityID uuid.UUID) pb.QuotaUsage { - // create cache key - timeBytes := bytesutil.IntToBytes(timeutil.Floor(time.Now(), timeutil.PeriodMonth).Unix()) - cacheKey := string(append(entityID.Bytes(), timeBytes...)) - - // first, check cache for usage else get usage from store - var usage pb.QuotaUsage - val, err := b.usageCache.Get(cacheKey) - if err == nil { - // use cached value - usage = val.(pb.QuotaUsage) - } else if err != gcache.KeyNotFoundError { - // unexpected - panic(err) - } else { - // load from store - usage = GetCurrentUsage(ctx, entityID) - - // write back to cache - b.usageCache.Set(cacheKey, usage) - } - - // add buffer to quota - b.mu.RLock() - usageBuf := b.buffer[entityID] - b.mu.RUnlock() - usage.ReadOps += usageBuf.ReadOps - usage.ReadRecords += usageBuf.ReadRecords - usage.ReadBytes += usageBuf.ReadBytes - usage.WriteOps += usageBuf.WriteOps - usage.WriteRecords += usageBuf.WriteRecords - usage.WriteBytes += usageBuf.WriteBytes - usage.ScanOps += usageBuf.ScanOps - usage.ScanBytes += usageBuf.ScanBytes - - return usage -} diff --git a/internal/middleware/auth.go b/services/middleware/auth.go similarity index 72% rename from internal/middleware/auth.go rename to services/middleware/auth.go index 2f9506a8..c02afa64 100644 --- a/internal/middleware/auth.go +++ b/services/middleware/auth.go @@ -7,28 +7,28 @@ import ( "reflect" "strings" + grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth" + uuid "github.com/satori/go.uuid" "google.golang.org/grpc" "google.golang.org/grpc/codes" - "gitlab.com/beneath-hq/beneath/control/entity" + "gitlab.com/beneath-hq/beneath/models" "gitlab.com/beneath-hq/beneath/pkg/httputil" "gitlab.com/beneath-hq/beneath/pkg/secrettoken" - grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth" - uuid "github.com/satori/go.uuid" ) // GetSecret extracts the auth object from ctx -func GetSecret(ctx context.Context) entity.Secret { +func GetSecret(ctx context.Context) models.Secret { tags := GetTags(ctx) return tags.Secret } -// Auth reads bearer token and injects auth into the context of an HTTP request -// Sets ContextKey to nil if no authorization passed (contrary to gRPC) -func Auth(next http.Handler) http.Handler { +// AuthMiddleware reads bearer token and injects auth into the context of an HTTP request. +// Sets authenticated secret to AnonymousSecret if no token is provided (contrary to GRPC). +func (s *Service) AuthMiddleware(next http.Handler) http.Handler { return httputil.AppHandler(func(w http.ResponseWriter, r *http.Request) error { - var secret entity.Secret - secret = &entity.AnonymousSecret{} + var secret models.Secret + secret = &models.AnonymousSecret{} header := r.Header.Get("Authorization") if header != "" { @@ -42,7 +42,7 @@ func Auth(next http.Handler) http.Handler { return httputil.NewError(400, fmt.Sprintf("authentication error: %v", err.Error())) } - secret = entity.AuthenticateWithToken(r.Context(), token) + secret = s.SecretService.AuthenticateWithToken(r.Context(), token) if secret == nil || reflect.ValueOf(secret).IsNil() { return httputil.NewError(400, "authentication error: token not found") } @@ -57,9 +57,9 @@ func Auth(next http.Handler) http.Handler { }) } -// AuthInterceptor reads bearer token and injects auth into the context of a gRPC call -// Errors if no authorization passed (contrary to HTTP) -func AuthInterceptor(ctx context.Context) (context.Context, error) { +// AuthInterceptor reads bearer token and injects auth into the context of a gRPC call. +// Errors if no authorization passed (contrary to HTTP). +func (s *Service) AuthInterceptor(ctx context.Context) (context.Context, error) { tokenStr, err := grpc_auth.AuthFromMD(ctx, "bearer") if err != nil { return nil, grpc.Errorf(codes.Unauthenticated, "authentication error: %v", err) @@ -70,7 +70,7 @@ func AuthInterceptor(ctx context.Context) (context.Context, error) { return nil, grpc.Errorf(codes.Unauthenticated, "authentication error: %v", err) } - secret := entity.AuthenticateWithToken(ctx, token) + secret := s.SecretService.AuthenticateWithToken(ctx, token) if secret == nil { return nil, grpc.Errorf(codes.Unauthenticated, "authentication error: secret not found") } diff --git a/internal/middleware/ipratelimiting.go b/services/middleware/ipratelimiting.go similarity index 55% rename from internal/middleware/ipratelimiting.go rename to services/middleware/ipratelimiting.go index 463030cc..1b1e8bb1 100644 --- a/internal/middleware/ipratelimiting.go +++ b/services/middleware/ipratelimiting.go @@ -17,58 +17,48 @@ import ( "gitlab.com/beneath-hq/beneath/pkg/httputil" ) -var ( - limiter *redis_rate.Limiter -) - -func initLimiter() *redis_rate.Limiter { - if limiter == nil { - limiter = redis_rate.NewLimiter(hub.Redis, &redis_rate.Limit{ - Burst: 20, - Rate: 20, - Period: time.Second * 15, - }) - } - return limiter +func (s *Service) initRateLimiter() { + s.limiter = redis_rate.NewLimiter(hub.Redis, &redis_rate.Limit{ + Burst: 20, + Rate: 20, + Period: time.Second * 15, + }) } -// IPRateLimit is an HTTP middleware that checks the ipaddress for rate limiting -func IPRateLimit() func(http.Handler) http.Handler { - initLimiter() - return func(next http.Handler) http.Handler { - return httputil.AppHandler(func(w http.ResponseWriter, r *http.Request) error { - secret := GetSecret(r.Context()) - if secret == nil { // if any issues, add this back: " || reflect.ValueOf(secret).IsNil()" - // check rate limit - ip, _, err := net.SplitHostPort(r.RemoteAddr) - if err != nil { - ip = r.RemoteAddr - } +// IPRateLimitMiddleware is a HTTP middleware that uses the ipaddress for rate limiting. +// It skips rate limit checks if secret is nil. +func (s *Service) IPRateLimitMiddleware(next http.Handler) http.Handler { + return httputil.AppHandler(func(w http.ResponseWriter, r *http.Request) error { + secret := GetSecret(r.Context()) + if secret.IsAnonymous() { + // check rate limit + ip, _, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + ip = r.RemoteAddr + } - res, err := limiter.Allow(ip) - if err != nil { - panic(err) - } + res, err := s.limiter.Allow(ip) + if err != nil { + panic(err) + } - if !res.Allowed { - return httputil.NewError(http.StatusTooManyRequests, http.StatusText(http.StatusTooManyRequests)) - } + if !res.Allowed { + return httputil.NewError(http.StatusTooManyRequests, http.StatusText(http.StatusTooManyRequests)) } - next.ServeHTTP(w, r) - return nil - }) - } + } + next.ServeHTTP(w, r) + return nil + }) } // IPRateLimitUnaryServerInterceptor is like IPRateLimit, but for unary gRPC calls -func IPRateLimitUnaryServerInterceptor() grpc.UnaryServerInterceptor { - initLimiter() +func (s *Service) IPRateLimitUnaryServerInterceptor() grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { secret := GetSecret(ctx) - if secret == nil { + if secret.IsAnonymous() { // check rate limit ip := gRPCRealIP(ctx) - res, err := limiter.Allow(ip) + res, err := s.limiter.Allow(ip) if err != nil { panic(err) } @@ -82,15 +72,14 @@ func IPRateLimitUnaryServerInterceptor() grpc.UnaryServerInterceptor { } // IPRateLimitStreamServerInterceptor is like IPRateLimit, but for streaming gRPC calls -func IPRateLimitStreamServerInterceptor() grpc.StreamServerInterceptor { - initLimiter() +func (s *Service) IPRateLimitStreamServerInterceptor() grpc.StreamServerInterceptor { return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { secret := GetSecret(ss.Context()) - if secret == nil { + if secret.IsAnonymous() { // check rate limit ip := gRPCRealIP(ss.Context()) - res, err := limiter.Allow(ip) + res, err := s.limiter.Allow(ip) if err != nil { panic(err) } diff --git a/internal/middleware/logger.go b/services/middleware/logger.go similarity index 86% rename from internal/middleware/logger.go rename to services/middleware/logger.go index 4c905950..356d3886 100644 --- a/internal/middleware/logger.go +++ b/services/middleware/logger.go @@ -15,9 +15,9 @@ import ( "gitlab.com/beneath-hq/beneath/pkg/log" ) -// Logger is a middleware that logs each request, along with some useful data about what -// was requested, what the response status was, and how long it took to return. -func Logger(next http.Handler) http.Handler { +// LoggerMiddleware is a HTTP middleware that logs each request, along with some useful data +// about what was requested, what the response status was, and how long it took to return. +func (s *Service) LoggerMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { t1 := time.Now() @@ -56,7 +56,7 @@ func Logger(next http.Handler) http.Handler { } // LoggerUnaryServerInterceptor is a gRPC interceptor that logs each request -func LoggerUnaryServerInterceptor() grpc.UnaryServerInterceptor { +func (s *Service) LoggerUnaryServerInterceptor() grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { t1 := time.Now() resp, err := handler(ctx, req) @@ -77,7 +77,7 @@ func LoggerUnaryServerInterceptor() grpc.UnaryServerInterceptor { } // LoggerStreamServerInterceptor is a gRPC interceptor that logs each streaming request -func LoggerStreamServerInterceptor() grpc.StreamServerInterceptor { +func (s *Service) LoggerStreamServerInterceptor() grpc.StreamServerInterceptor { return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { t1 := time.Now() err := handler(srv, ss) diff --git a/services/middleware/middleware.go b/services/middleware/middleware.go new file mode 100644 index 00000000..417527be --- /dev/null +++ b/services/middleware/middleware.go @@ -0,0 +1,25 @@ +package middleware + +import ( + "github.com/go-redis/redis/v7" + "github.com/go-redis/redis_rate/v8" + "gitlab.com/beneath-hq/beneath/services/secret" +) + +// Service provides various useful HTTP and GRPC middlewares, eg. for authentication and rate limiting +type Service struct { + Redis *redis.Client + SecretService *secret.Service + + limiter *redis_rate.Limiter +} + +// New creates a new middleware service +func New(redis *redis.Client, secretService *secret.Service) *Service { + s := &Service{ + Redis: redis, + SecretService: secretService, + } + s.initRateLimiter() + return s +} diff --git a/internal/middleware/recoverer.go b/services/middleware/recoverer.go similarity index 80% rename from internal/middleware/recoverer.go rename to services/middleware/recoverer.go index 8e2d0422..d2646a3b 100644 --- a/internal/middleware/recoverer.go +++ b/services/middleware/recoverer.go @@ -12,9 +12,9 @@ import ( "gitlab.com/beneath-hq/beneath/pkg/log" ) -// Recoverer is a middleware that catches any downstream panic calls, and logs them without -// halting execution of the entire process -func Recoverer(next http.Handler) http.Handler { +// RecovererMiddleware is a HTTP middleware that catches any downstream panic calls, and +// logs them without halting execution of the entire process +func (s *Service) RecovererMiddleware(next http.Handler) http.Handler { return httputil.AppHandler(func(w http.ResponseWriter, r *http.Request) (httpErr error) { defer func() { if r := recover(); r != nil { @@ -32,7 +32,7 @@ func Recoverer(next http.Handler) http.Handler { } // RecovererUnaryServerInterceptor is a gRPC interceptor similar to Recoverer -func RecovererUnaryServerInterceptor() grpc.UnaryServerInterceptor { +func (s *Service) RecovererUnaryServerInterceptor() grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (_ interface{}, err error) { defer func() { if r := recover(); r != nil { @@ -49,7 +49,7 @@ func RecovererUnaryServerInterceptor() grpc.UnaryServerInterceptor { } // RecovererStreamServerInterceptor is a gRPC interceptor similar to Recoverer -func RecovererStreamServerInterceptor() grpc.StreamServerInterceptor { +func (s *Service) RecovererStreamServerInterceptor() grpc.StreamServerInterceptor { return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) (err error) { defer func() { if r := recover(); r != nil { diff --git a/internal/middleware/tags.go b/services/middleware/tags.go similarity index 82% rename from internal/middleware/tags.go rename to services/middleware/tags.go index daedce53..61326a64 100644 --- a/internal/middleware/tags.go +++ b/services/middleware/tags.go @@ -9,7 +9,7 @@ import ( uuid "github.com/satori/go.uuid" "google.golang.org/grpc" - "gitlab.com/beneath-hq/beneath/control/entity" + "gitlab.com/beneath-hq/beneath/models" ) // Tags represents annotations on a request made available both up and down the @@ -17,15 +17,35 @@ import ( // to logging middleware at the top of the chain). type Tags struct { AnonymousID uuid.UUID - Secret entity.Secret + Secret models.Secret Payload interface{} } // TagsContextKey is the request context key for the request's Tags object type TagsContextKey struct{} -// InjectTags is an HTTP middleware that injects Tags into into the request context -func InjectTags(next http.Handler) http.Handler { +// GetTags extracts the tags object from ctx +func GetTags(ctx context.Context) *Tags { + tags, ok := ctx.Value(TagsContextKey{}).(*Tags) + if !ok { + panic(fmt.Errorf("couldn't get tags from context")) + } + + return tags +} + +// SetTagsPayload sets the Payload field of middleware.GetTags(ctx) +func SetTagsPayload(ctx context.Context, payload interface{}) { + if payload == nil { + return + } + + tags := GetTags(ctx) + tags.Payload = payload +} + +// InjectTagsMiddleware is an HTTP middleware that injects Tags into into the request context +func (s *Service) InjectTagsMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { tags := &Tags{} ctx := context.WithValue(r.Context(), TagsContextKey{}, tags) @@ -34,7 +54,7 @@ func InjectTags(next http.Handler) http.Handler { } // InjectTagsUnaryServerInterceptor is like InjectTags, but for unary gRPC calls -func InjectTagsUnaryServerInterceptor() grpc.UnaryServerInterceptor { +func (s *Service) InjectTagsUnaryServerInterceptor() grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { tags := &Tags{} newCtx := context.WithValue(ctx, TagsContextKey{}, tags) @@ -43,7 +63,7 @@ func InjectTagsUnaryServerInterceptor() grpc.UnaryServerInterceptor { } // InjectTagsStreamServerInterceptor is like InjectTags, but for streaming gRPC calls -func InjectTagsStreamServerInterceptor() grpc.StreamServerInterceptor { +func (s *Service) InjectTagsStreamServerInterceptor() grpc.StreamServerInterceptor { return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { tags := &Tags{} newCtx := context.WithValue(ss.Context(), TagsContextKey{}, tags) @@ -53,23 +73,3 @@ func InjectTagsStreamServerInterceptor() grpc.StreamServerInterceptor { return handler(srv, wrapped) } } - -// GetTags extracts the tags object from ctx -func GetTags(ctx context.Context) *Tags { - tags, ok := ctx.Value(TagsContextKey{}).(*Tags) - if !ok { - panic(fmt.Errorf("couldn't get tags from context")) - } - - return tags -} - -// SetTagsPayload sets the Payload field of middleware.GetTags(ctx) -func SetTagsPayload(ctx context.Context, payload interface{}) { - if payload == nil { - return - } - - tags := GetTags(ctx) - tags.Payload = payload -} diff --git a/services/organization/crud.go b/services/organization/crud.go new file mode 100644 index 00000000..f8756e36 --- /dev/null +++ b/services/organization/crud.go @@ -0,0 +1,149 @@ +package organization + +import ( + "context" + "time" + + uuid "github.com/satori/go.uuid" + "gitlab.com/beneath-hq/beneath/models" +) + +// CreateWithUser creates an organization and makes user a member +func (s *Service) CreateWithUser(ctx context.Context, name string, userID uuid.UUID, view bool, create bool, admin bool) (*models.Organization, error) { + // validate name + org := &models.Organization{Name: name} + err := org.Validate() + if err != nil { + return nil, err + } + + // create in tx + err = s.DB.InTransaction(ctx, func(ctx context.Context) error { + tx := s.DB.GetDB(ctx) + + // insert org + _, err := tx.Model(org).Insert() + if err != nil { + return err + } + + // connect to user + err = tx.Insert(&models.PermissionsUsersOrganizations{ + UserID: userID, + OrganizationID: org.OrganizationID, + View: view, + Create: create, + Admin: admin, + }) + if err != nil { + return err + } + + // send event + err = s.Bus.Publish(ctx, &models.OrganizationCreatedEvent{ + Organization: org, + }) + if err != nil { + return err + } + + return nil + }) + if err != nil { + return nil, err + } + + return org, nil +} + +// UpdateDetails updates the organization's name, display name, description and/or photo +func (s *Service) UpdateDetails(ctx context.Context, o *models.Organization, name *string, displayName *string, description *string, photoURL *string) error { + if name != nil { + o.Name = *name + } + if displayName != nil { + o.DisplayName = *displayName + } + if description != nil { + o.Description = *description + } + if photoURL != nil { + o.PhotoURL = *photoURL + } + + err := o.Validate() + if err != nil { + return err + } + + o.UpdatedOn = time.Now() + _, err = s.DB.GetDB(ctx).ModelContext(ctx, o). + Column( + "name", + "display_name", + "description", + "photo_url", + "updated_on", + ).WherePK().Update() + if err != nil { + return err + } + + // send event + err = s.Bus.Publish(ctx, &models.OrganizationUpdatedEvent{ + Organization: o, + }) + if err != nil { + return err + } + + return nil +} + +// UpdateQuotas updates the quotas enforced upon the organization +func (s *Service) UpdateQuotas(ctx context.Context, o *models.Organization, readQuota *int64, writeQuota *int64, scanQuota *int64) error { + // set fields + o.ReadQuota = readQuota + o.WriteQuota = writeQuota + o.ScanQuota = scanQuota + + // validate + err := o.Validate() + if err != nil { + return err + } + + // update + o.UpdatedOn = time.Now() + _, err = s.DB.GetDB(ctx).ModelContext(ctx, o). + Column("read_quota", "write_quota", "scan_quota", "updated_on"). + WherePK(). + Update() + if err != nil { + return err + } + + // send event + err = s.Bus.Publish(ctx, &models.OrganizationUpdatedEvent{ + Organization: o, + }) + if err != nil { + return err + } + + return nil +} + +// Delete deletes the organization. It fails if there are any users, services, or projects +// that are still tied to the organization. +func (s *Service) Delete(ctx context.Context, o *models.Organization) error { + // NOTE: effectively, this resolver doesn't work, as there will always be one admin member. + // TODO: check it's empty and has just one admin user, trigger bill, make the admin leave, delete org. + + _, err := s.DB.GetDB(ctx).ModelContext(ctx, o).Delete() + if err != nil { + return err + } + + return nil +} diff --git a/services/organization/invites.go b/services/organization/invites.go new file mode 100644 index 00000000..1ea41ebc --- /dev/null +++ b/services/organization/invites.go @@ -0,0 +1,59 @@ +package organization + +import ( + "context" + + uuid "github.com/satori/go.uuid" + "gitlab.com/beneath-hq/beneath/infrastructure/db" + "gitlab.com/beneath-hq/beneath/models" +) + +// An invite procedure is required for organizations since there's mutual costs and benefits: a) The inviter +// proposes to cover the invitees bills, but b) the invitee is subjected to quotas set by +// from the inviter (as well as more intrusive oversight). +// Don't confuse changing billing organizations with simply granted organization permissions to someone, +// which doesn't imply a change in billing or quotas. + +// FindOrganizationInvite finds an existing invitation +func (s *Service) FindOrganizationInvite(ctx context.Context, organizationID uuid.UUID, userID uuid.UUID) *models.OrganizationInvite { + invite := &models.OrganizationInvite{} + err := s.DB.GetDB(ctx).ModelContext(ctx, invite). + Column("organization_invite.*", "Organization", "User", "User.BillingOrganization"). + Where("organization_invite.organization_id = ?", organizationID). + Where("organization_invite.user_id = ?", userID). + Select() + if !db.AssertFoundOne(err) { + return nil + } + return invite +} + +// CreateOrUpdateInvite creates or updates the organization invite +func (s *Service) CreateOrUpdateInvite(ctx context.Context, organizationID uuid.UUID, userID uuid.UUID, view, create, admin bool) error { + invite := &models.OrganizationInvite{ + OrganizationID: organizationID, + UserID: userID, + View: view, + Create: create, + Admin: admin, + } + + err := invite.Validate() + if err != nil { + return err + } + + // build upsert + q := s.DB.GetDB(ctx).ModelContext(ctx, invite).OnConflict("(organization_id, user_id) DO UPDATE") + q.Set("view = EXCLUDED.view") + q.Set(`"create" = EXCLUDED."create"`) + q.Set("admin = EXCLUDED.admin") + + // run upsert + _, err = q.Insert() + if err != nil { + return err + } + + return nil +} diff --git a/services/organization/organization.go b/services/organization/organization.go new file mode 100644 index 00000000..ff7c4223 --- /dev/null +++ b/services/organization/organization.go @@ -0,0 +1,116 @@ +package organization + +import ( + "context" + + "github.com/go-pg/pg" + uuid "github.com/satori/go.uuid" + + "gitlab.com/beneath-hq/beneath/bus" + "gitlab.com/beneath-hq/beneath/infrastructure/db" + "gitlab.com/beneath-hq/beneath/models" +) + +// Service encapsulates behavior for dealing with organizations +type Service struct { + Bus *bus.Bus + DB db.DB +} + +// New creates a new Service +func New(bus *bus.Bus, db db.DB) *Service { + return &Service{ + Bus: bus, + DB: db, + } +} + +// FindOrganization finds a organization by ID +func (s *Service) FindOrganization(ctx context.Context, organizationID uuid.UUID) *models.Organization { + organization := &models.Organization{ + OrganizationID: organizationID, + } + err := s.DB.GetDB(ctx).ModelContext(ctx, organization). + WherePK(). + Column("organization.*", "User", "User.BillingOrganization", "Projects"). + Select() + if !db.AssertFoundOne(err) { + return nil + } + return organization +} + +// FindOrganizationByName finds a organization by name +func (s *Service) FindOrganizationByName(ctx context.Context, name string) *models.Organization { + organization := &models.Organization{} + err := s.DB.GetDB(ctx).ModelContext(ctx, organization). + Where("lower(organization.name) = lower(?)", name). + Column( + "organization.*", + "User", + "User.BillingOrganization", + "Projects", + ).Select() + if !db.AssertFoundOne(err) { + return nil + } + return organization +} + +// FindOrganizationByUserID finds an organization by its personal user ID (if set) +func (s *Service) FindOrganizationByUserID(ctx context.Context, userID uuid.UUID) *models.Organization { + organization := &models.Organization{} + err := s.DB.GetDB(ctx).ModelContext(ctx, organization). + Where("organization.user_id = ?", userID). + Column( + "organization.*", + "User", + "User.BillingOrganization", + "Projects", + ).Select() + if !db.AssertFoundOne(err) { + return nil + } + return organization +} + +// FindAllOrganizations returns all active organizations +func (s *Service) FindAllOrganizations(ctx context.Context) []*models.Organization { + var organizations []*models.Organization + err := s.DB.GetDB(ctx).ModelContext(ctx, &organizations). + Column("organization.*"). + Select() + if err != nil { + panic(err) + } + return organizations +} + +// FindOrganizationMembers finds useful information about the organization's members, represented in +// the structure of OrganizationMember (includes both people with and without billing affiliation) +func (s *Service) FindOrganizationMembers(ctx context.Context, organizationID uuid.UUID) ([]*models.OrganizationMember, error) { + var result []*models.OrganizationMember + _, err := s.DB.GetDB(ctx).QueryContext(ctx, &result, ` + select + p.organization_id, + p.user_id, + u.billing_organization_id, + o.name, + o.display_name, + o.photo_url, + p.view, + p."create", + p.admin, + u.read_quota, + u.write_quota, + u.scan_quota + from permissions_users_organizations p + join organizations o on p.user_id = o.user_id + join users u on p.user_id = u.user_id + where p.organization_id = ? + `, organizationID) + if err != nil && err != pg.ErrNoRows { + return nil, err + } + return result, nil +} diff --git a/services/organization/transfer.go b/services/organization/transfer.go new file mode 100644 index 00000000..19ee6fca --- /dev/null +++ b/services/organization/transfer.go @@ -0,0 +1,87 @@ +package organization + +import ( + "context" + "fmt" + "time" + + "gitlab.com/beneath-hq/beneath/models" +) + +// TransferProject transfers a project in fromOrg to targetOrg +func (s *Service) TransferProject(ctx context.Context, fromOrg *models.Organization, targetOrg *models.Organization, project *models.Project) error { + project.Organization = targetOrg + project.OrganizationID = targetOrg.OrganizationID + project.UpdatedOn = time.Now() + _, err := s.DB.GetDB(ctx).ModelContext(ctx, project).Column("organization_id", "updated_on").WherePK().Update() + if err != nil { + return err + } + + err = s.Bus.Publish(ctx, &models.ProjectUpdatedEvent{ + Project: project, + }) + if err != nil { + return err + } + + return nil +} + +// TransferUser transfers a user in fromOrg to targetOrg. +// Can be from personal to multi, multi to personal, multi to multi. +func (s *Service) TransferUser(ctx context.Context, fromOrg *models.Organization, targetOrg *models.Organization, user *models.User) error { + // Ensure the last admin member isn't leaving a multi-user org + if fromOrg.IsMulti() { + foundRemainingAdmin := false + members, err := s.FindOrganizationMembers(ctx, fromOrg.OrganizationID) + if err != nil { + return err + } + for _, member := range members { + if member.Admin && member.UserID != user.UserID { + foundRemainingAdmin = true + break + } + } + if !foundRemainingAdmin { + return fmt.Errorf("Cannot transfer user because it would leave the organization without an admin") + } + } + + return s.DB.InTransaction(ctx, func(ctx context.Context) error { + // update user + user.BillingOrganization = targetOrg + user.BillingOrganizationID = targetOrg.OrganizationID + user.ReadQuota = nil + user.WriteQuota = nil + user.ScanQuota = nil + user.UpdatedOn = time.Now() + _, err := s.DB.GetDB(ctx).ModelContext(ctx, user). + Column("billing_organization_id", "read_quota", "write_quota", "scan_quota", "updated_on"). + WherePK(). + Update() + if err != nil { + return err + } + + // publish events + err = s.Bus.Publish(ctx, models.UserUpdatedEvent{ + User: user, + }) + if err != nil { + return err + } + + err = s.Bus.Publish(ctx, models.OrganizationTransferredUserEvent{ + Source: fromOrg, + Target: targetOrg, + User: user, + }) + if err != nil { + return err + } + + return nil + }) +} diff --git a/services/permissions/cache.go b/services/permissions/cache.go new file mode 100644 index 00000000..7a95344f --- /dev/null +++ b/services/permissions/cache.go @@ -0,0 +1,149 @@ +package permissions + +import ( + "bytes" + "context" + "encoding/gob" + "reflect" + "time" + + "github.com/go-pg/pg/v9" + "github.com/go-redis/cache/v7" + uuid "github.com/satori/go.uuid" + + "gitlab.com/beneath-hq/beneath/models" +) + +// initCaches sets up the three permissions caches +func (s *Service) initCaches() { + s.userOrganizationCache = NewCache(s, models.OrganizationPermissions{}, ` + select p.view, p.create, p.admin + from permissions_users_organizations p + where p.user_id = ? and p.organization_id = ? + `) + + s.userProjectCache = NewCache(s, models.ProjectPermissions{}, ` + select p.view, p.create, p.admin + from permissions_users_projects p + where p.user_id = ? and p.project_id = ? + `) + + s.serviceStreamCache = NewCache(s, models.StreamPermissions{}, ` + select p.read, p.write + from permissions_services_streams p + where p.service_id = ? and p.stream_id = ? + `) +} + +// CachedUserOrganizationPermissions returns organization permissions for a given owner-resource combo +func (s *Service) CachedUserOrganizationPermissions(ctx context.Context, userID uuid.UUID, organizationID uuid.UUID) models.OrganizationPermissions { + return s.userOrganizationCache.Get(ctx, userID, organizationID).(models.OrganizationPermissions) +} + +// CachedUserProjectPermissions returns project permissions for a given owner-resource combo +func (s *Service) CachedUserProjectPermissions(ctx context.Context, userID uuid.UUID, projectID uuid.UUID) models.ProjectPermissions { + return s.userProjectCache.Get(ctx, userID, projectID).(models.ProjectPermissions) +} + +// CachedServiceStreamPermissions returns stream permissions for a given owner-resource combo +func (s *Service) CachedServiceStreamPermissions(ctx context.Context, serviceID uuid.UUID, streamID uuid.UUID) models.StreamPermissions { + return s.serviceStreamCache.Get(ctx, serviceID, streamID).(models.StreamPermissions) +} + +// Cache caches an owner's permissions for a resource for fast access +type Cache struct { + service *Service + codec *cache.Codec + prototype reflect.Type + query string +} + +var permsCacheConfig = struct { + cacheTime time.Duration + cacheLRUTime time.Duration + cacheLRUSize int + redisKeyFn func(ownerID uuid.UUID, resourceID uuid.UUID) string +}{ + cacheTime: time.Hour, + cacheLRUTime: 10 * time.Second, + cacheLRUSize: 20000, + redisKeyFn: func(ownerID uuid.UUID, resourceID uuid.UUID) string { + res := append([]byte("perm:"), ownerID.Bytes()...) + res = append(res, resourceID.Bytes()...) + return string(res) + }, +} + +// NewCache initializes a PermissionCache object for a given prototype (organization/project/stream) +func NewCache(service *Service, prototype interface{}, query string) *Cache { + pm := &Cache{} + pm.service = service + pm.prototype = reflect.TypeOf(prototype) + pm.query = query + pm.codec = &cache.Codec{ + Redis: service.Redis, + Marshal: pm.marshal, + Unmarshal: pm.unmarshal, + } + pm.codec.UseLocalCache(permsCacheConfig.cacheLRUSize, permsCacheConfig.cacheLRUTime) + return pm +} + +// Get fetches permissions by applying the cached query to the given parameters +func (c *Cache) Get(ctx context.Context, ownerID uuid.UUID, resourceID uuid.UUID) interface{} { + res := reflect.New(c.prototype) + err := c.codec.Once(&cache.Item{ + Key: permsCacheConfig.redisKeyFn(ownerID, resourceID), + Object: res.Interface(), + Expiration: permsCacheConfig.cacheTime, + Func: c.getterFunc(ctx, ownerID, resourceID), + }) + if err != nil { + if ctx.Err() == context.Canceled { + return res.Elem().Interface() + } + panic(err) + } + return res.Elem().Interface() +} + +// Clear removes a key from the cache +func (c *Cache) Clear(ctx context.Context, ownerID uuid.UUID, resourceID uuid.UUID) { + err := c.codec.Delete(permsCacheConfig.redisKeyFn(ownerID, resourceID)) + if err != nil && err != cache.ErrCacheMiss { + panic(err) + } +} + +func (c *Cache) marshal(v interface{}) ([]byte, error) { + var buf bytes.Buffer + enc := gob.NewEncoder(&buf) + err := enc.Encode(v) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (c *Cache) unmarshal(b []byte, v interface{}) (err error) { + dec := gob.NewDecoder(bytes.NewReader(b)) + err = dec.Decode(v) + if err != nil { + return err + } + return nil +} + +func (c *Cache) getterFunc(ctx context.Context, ownerID uuid.UUID, resourceID uuid.UUID) func() (interface{}, error) { + return func() (interface{}, error) { + res := reflect.New(c.prototype) + _, err := c.service.DB.GetDB(ctx).QueryContext(ctx, res.Interface(), c.query, ownerID, resourceID) + if err != nil && err != pg.ErrNoRows { + if ctx.Err() == context.Canceled { + return res.Elem().Interface(), nil + } + panic(err) + } + return res.Elem().Interface(), nil + } +} diff --git a/services/permissions/permissions.go b/services/permissions/permissions.go new file mode 100644 index 00000000..7d86f10a --- /dev/null +++ b/services/permissions/permissions.go @@ -0,0 +1,205 @@ +package permissions + +import ( + "context" + + uuid "github.com/satori/go.uuid" + + "github.com/go-redis/redis/v7" + "gitlab.com/beneath-hq/beneath/bus" + "gitlab.com/beneath-hq/beneath/infrastructure/db" + "gitlab.com/beneath-hq/beneath/models" +) + +// Service provides functionality for checking users' and services' permissions for resources +type Service struct { + Bus *bus.Bus + DB db.DB + Redis *redis.Client + + userOrganizationCache *Cache + userProjectCache *Cache + serviceStreamCache *Cache +} + +// New creates a new permissions service +func New(bus *bus.Bus, db db.DB, redis *redis.Client) *Service { + s := &Service{ + Bus: bus, + DB: db, + Redis: redis, + } + s.initCaches() + return s +} + +// FindPermissionsUsersProjects finds a user's permissions for a project +func (s *Service) FindPermissionsUsersProjects(ctx context.Context, userID uuid.UUID, projectID uuid.UUID) *models.PermissionsUsersProjects { + permissions := &models.PermissionsUsersProjects{ + UserID: userID, + ProjectID: projectID, + } + err := s.DB.GetDB(ctx).ModelContext(ctx, permissions). + WherePK(). + Select() + if !db.AssertFoundOne(err) { + return nil + } + return permissions +} + +// FindPermissionsUsersOrganizations finds a user's permissions for an organization +func (s *Service) FindPermissionsUsersOrganizations(ctx context.Context, userID uuid.UUID, organizationID uuid.UUID) *models.PermissionsUsersOrganizations { + permissions := &models.PermissionsUsersOrganizations{ + UserID: userID, + OrganizationID: organizationID, + } + err := s.DB.GetDB(ctx).ModelContext(ctx, permissions). + WherePK(). + Select() + if !db.AssertFoundOne(err) { + return nil + } + return permissions +} + +// FindPermissionsServicesStreams finds a service's permissions for a stream +func (s *Service) FindPermissionsServicesStreams(ctx context.Context, serviceID uuid.UUID, streamID uuid.UUID) *models.PermissionsServicesStreams { + permissions := &models.PermissionsServicesStreams{ + ServiceID: serviceID, + StreamID: streamID, + } + err := s.DB.GetDB(ctx).ModelContext(ctx, permissions). + WherePK(). + Select() + if !db.AssertFoundOne(err) { + return nil + } + return permissions +} + +// UpdateUserProjectPermission upserts permissions (or deletes them if all are falsy) +func (s *Service) UpdateUserProjectPermission(ctx context.Context, p *models.PermissionsUsersProjects, view *bool, create *bool, admin *bool) error { + if view != nil { + p.View = *view + } + if create != nil { + p.Create = *create + } + if admin != nil { + p.Admin = *admin + } + + // if all are falsy, delete the permission (if it exists), else update + if !p.View && !p.Create && !p.Admin { + _, err := s.DB.GetDB(ctx).ModelContext(ctx, p).WherePK().Delete() + if err != nil { + return err + } + } else { + // build upsert + q := s.DB.GetDB(ctx).ModelContext(ctx, p).OnConflict("(user_id, project_id) DO UPDATE") + if view != nil { + q = q.Set("view = EXCLUDED.view") + } + if create != nil { + q = q.Set(`"create" = EXCLUDED."create"`) + } + if admin != nil { + q = q.Set("admin = EXCLUDED.admin") + } + + // run upsert + _, err := q.Insert() + if err != nil { + return err + } + } + + // clear cache + s.userProjectCache.Clear(ctx, p.UserID, p.ProjectID) + + return nil +} + +// UpdateUserOrganizationPermission upserts permissions (or deletes them if all are falsy) +func (s *Service) UpdateUserOrganizationPermission(ctx context.Context, p *models.PermissionsUsersOrganizations, view *bool, create *bool, admin *bool) error { + if view != nil { + p.View = *view + } + if create != nil { + p.Create = *create + } + if admin != nil { + p.Admin = *admin + } + + // if all are falsy, delete the permission (if it exists), else update + if !p.View && !p.Create && !p.Admin { + _, err := s.DB.GetDB(ctx).ModelContext(ctx, p).WherePK().Delete() + if err != nil { + return err + } + } else { + // build upsert + q := s.DB.GetDB(ctx).ModelContext(ctx, p).OnConflict("(user_id, organization_id) DO UPDATE") + if view != nil { + q = q.Set("view = EXCLUDED.view") + } + if create != nil { + q = q.Set(`"create" = EXCLUDED."create"`) + } + if admin != nil { + q = q.Set("admin = EXCLUDED.admin") + } + + // run upsert + _, err := q.Insert() + if err != nil { + return err + } + } + + // clear cache + s.userOrganizationCache.Clear(ctx, p.UserID, p.OrganizationID) + + return nil +} + +// UpdateServiceStreamPermission upserts permissions (or deletes them if all are falsy) +func (s *Service) UpdateServiceStreamPermission(ctx context.Context, p *models.PermissionsServicesStreams, read *bool, write *bool) error { + if read != nil { + p.Read = *read + } + if write != nil { + p.Write = *write + } + + // if all are falsy, delete the permission (if it exists), else update + if !p.Read && !p.Write { + _, err := s.DB.GetDB(ctx).ModelContext(ctx, p).WherePK().Delete() + if err != nil { + return err + } + } else { + // build upsert + q := s.DB.GetDB(ctx).ModelContext(ctx, p).OnConflict("(service_id, stream_id) DO UPDATE") + if read != nil { + q = q.Set("read = EXCLUDED.read") + } + if write != nil { + q = q.Set("write = EXCLUDED.write") + } + + // run upsert + _, err := q.Insert() + if err != nil { + return err + } + } + + // clear cache + s.serviceStreamCache.Clear(ctx, p.ServiceID, p.StreamID) + + return nil +} diff --git a/services/permissions/secrets.go b/services/permissions/secrets.go new file mode 100644 index 00000000..39c9ec24 --- /dev/null +++ b/services/permissions/secrets.go @@ -0,0 +1,91 @@ +package permissions + +import ( + "context" + "fmt" + + uuid "github.com/satori/go.uuid" + + "gitlab.com/beneath-hq/beneath/models" +) + +// StreamPermissionsForSecret gets the secret owner's permissions for a stream +func (s *Service) StreamPermissionsForSecret(ctx context.Context, secret models.Secret, streamID uuid.UUID, projectID uuid.UUID, public bool) models.StreamPermissions { + switch secret := secret.(type) { + case *models.UserSecret: + return s.streamPermissionsForUserSecret(ctx, secret, streamID, projectID, public) + case *models.ServiceSecret: + return s.streamPermissionsForServiceSecret(ctx, secret, streamID, projectID, public) + default: + panic(fmt.Errorf("unrecognized secret type %T", secret)) + } +} + +func (s *Service) streamPermissionsForUserSecret(ctx context.Context, secret *models.UserSecret, streamID uuid.UUID, projectID uuid.UUID, public bool) models.StreamPermissions { + projectPerms := s.CachedUserProjectPermissions(ctx, secret.UserID, projectID) + return models.StreamPermissions{ + Read: (projectPerms.View && !secret.PublicOnly) || public, + Write: projectPerms.Create && !secret.ReadOnly && (!secret.PublicOnly || public), + } +} + +func (s *Service) streamPermissionsForServiceSecret(ctx context.Context, secret *models.ServiceSecret, streamID uuid.UUID, projectID uuid.UUID, public bool) models.StreamPermissions { + return s.CachedServiceStreamPermissions(ctx, secret.ServiceID, streamID) +} + +// ProjectPermissionsForSecret gets the secret owner's permissions for a project +func (s *Service) ProjectPermissionsForSecret(ctx context.Context, secret models.Secret, projectID uuid.UUID, public bool) models.ProjectPermissions { + switch secret := secret.(type) { + case *models.UserSecret: + return s.projectPermissionsForUserSecret(ctx, secret, projectID, public) + case *models.ServiceSecret: + return s.projectPermissionsForServiceSecret(ctx, secret, projectID, public) + default: + panic(fmt.Errorf("unrecognized secret type %T", secret)) + } +} + +func (s *Service) projectPermissionsForUserSecret(ctx context.Context, secret *models.UserSecret, projectID uuid.UUID, public bool) models.ProjectPermissions { + if secret.PublicOnly && !public { + return models.ProjectPermissions{} + } + if secret.ReadOnly && public { + return models.ProjectPermissions{View: true} + } + perms := s.CachedUserProjectPermissions(ctx, secret.UserID, projectID) + if public { + perms.View = true + } + if secret.ReadOnly { + perms.Admin = false + perms.Create = false + } + return perms +} + +func (s *Service) projectPermissionsForServiceSecret(ctx context.Context, secret *models.ServiceSecret, projectID uuid.UUID, public bool) models.ProjectPermissions { + return models.ProjectPermissions{} +} + +// OrganizationPermissionsForSecret gets the secret owner's permissions for a organization +func (s *Service) OrganizationPermissionsForSecret(ctx context.Context, secret models.Secret, organizationID uuid.UUID) models.OrganizationPermissions { + switch secret := secret.(type) { + case *models.UserSecret: + return s.organizationPermissionsForUserSecret(ctx, secret, organizationID) + case *models.ServiceSecret: + return s.organizationPermissionsForServiceSecret(ctx, secret, organizationID) + default: + panic(fmt.Errorf("unrecognized secret type %T", secret)) + } +} + +func (s *Service) organizationPermissionsForUserSecret(ctx context.Context, secret *models.UserSecret, organizationID uuid.UUID) models.OrganizationPermissions { + if secret.ReadOnly || secret.PublicOnly { + return models.OrganizationPermissions{} + } + return s.CachedUserOrganizationPermissions(ctx, secret.UserID, organizationID) +} + +func (s *Service) organizationPermissionsForServiceSecret(ctx context.Context, secret *models.ServiceSecret, organizationID uuid.UUID) models.OrganizationPermissions { + return models.OrganizationPermissions{} +} diff --git a/services/project/project.go b/services/project/project.go new file mode 100644 index 00000000..a2423689 --- /dev/null +++ b/services/project/project.go @@ -0,0 +1,224 @@ +package project + +import ( + "context" + "time" + + "github.com/go-pg/pg/v9" + "github.com/go-pg/pg/v9/orm" + uuid "github.com/satori/go.uuid" + + "gitlab.com/beneath-hq/beneath/bus" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/infrastructure/db" +) + +// Service manages Beneath projects +type Service struct { + Bus *bus.Bus + DB db.DB +} + +// New creates a project service +func New(bus *bus.Bus, db db.DB) *Service { + s := &Service{ + Bus: bus, + DB: db, + } + bus.AddSyncListener(s.CreateUserStarterProject) + return s +} + +// FindProject finds a project by ID +func (s *Service) FindProject(ctx context.Context, projectID uuid.UUID) *models.Project { + project := &models.Project{ + ProjectID: projectID, + } + err := s.DB.GetDB(ctx).ModelContext(ctx, project). + WherePK(). + Column("project.*", "Streams", "Services", "Organization"). + Select() + if !db.AssertFoundOne(err) { + return nil + } + return project +} + +// FindProjectByOrganizationAndName finds a project by organization name and project name +func (s *Service) FindProjectByOrganizationAndName(ctx context.Context, organizationName string, projectName string) *models.Project { + project := &models.Project{} + err := s.DB.GetDB(ctx).ModelContext(ctx, project). + Relation("Organization", func(q *orm.Query) (*orm.Query, error) { + return q.Where("lower(organization.name) = lower(?)", organizationName), nil + }). + Where("lower(project.name) = lower(?)", projectName). + Column("project.*", "Streams", "Services"). + Select() + if !db.AssertFoundOne(err) { + return nil + } + return project +} + +// FindProjectsForUser finds the projects that the user has been granted access to +func (s *Service) FindProjectsForUser(ctx context.Context, userID uuid.UUID) []*models.Project { + var projects []*models.Project + err := s.DB.GetDB(ctx).ModelContext(ctx, &projects). + Relation("Organization"). + Join("JOIN permissions_users_projects AS pup ON pup.project_id = project.project_id"). + Where("pup.user_id = ?", userID). + Order("project.name"). + Limit(200). + Select() + if err != nil { + panic(err) + } + return projects +} + +// ExploreProjects returns a list of featured projects +func (s *Service) ExploreProjects(ctx context.Context) []*models.Project { + var projects []*models.Project + err := s.DB.GetDB(ctx).ModelContext(ctx, &projects). + Where("project.explore_rank IS NOT NULL"). + Limit(200). + Order("explore_rank"). + Relation("Organization"). + Select() + if err != nil { + panic(err) + } + return projects +} + +// FindProjectMembers is an effective way to get info about a project's members (represented with ProjectMember instead of User) +func (s *Service) FindProjectMembers(ctx context.Context, projectID uuid.UUID) ([]*models.ProjectMember, error) { + var result []*models.ProjectMember + _, err := s.DB.GetDB(ctx).QueryContext(ctx, &result, ` + select + p.project_id, + p.user_id, + o.name, + o.display_name, + o.photo_url, + p.view, + p."create", + p.admin + from permissions_users_projects p + join organizations o on p.user_id = o.user_id + where p.project_id = ? + `, projectID) + if err != nil && err != pg.ErrNoRows { + return nil, err + } + return result, nil +} + +// StageWithUser updates the project if it already exists or creates it with the given user as a member +func (s *Service) StageWithUser(ctx context.Context, p *models.Project, displayName *string, public *bool, description *string, site *string, photoURL *string, userID uuid.UUID, perms models.ProjectPermissions) error { + // determine whether to insert or update + update := (p.ProjectID != uuid.Nil) + + // tracks whether a save is necessary + save := !update + + if displayName != nil && p.DisplayName != *displayName { + p.DisplayName = *displayName + save = true + } + + if public != nil && p.Public != *public { + p.Public = *public + save = true + } + + if description != nil && p.Description != *description { + p.Description = *description + save = true + } + + if site != nil && p.Site != *site { + p.Site = *site + save = true + } + + if photoURL != nil && p.PhotoURL != *photoURL { + p.PhotoURL = *photoURL + save = true + } + + // quit if no changes + if !save { + return nil + } + + // validate + err := p.Validate() + if err != nil { + return err + } + + // note: if we ever support renaming projects, must invalidate stream cache for all instances in project + + err = s.DB.InTransaction(ctx, func(ctx context.Context) error { + tx := s.DB.GetDB(ctx) + if update { + // update + p.UpdatedOn = time.Now() + _, err = tx.Model(p). + Column("display_name", "public", "description", "site", "photo_url", "updated_on"). + WherePK(). + Update() + if err != nil { + return err + } + + err = s.Bus.Publish(ctx, &models.ProjectUpdatedEvent{ + Project: p, + }) + if err != nil { + return err + } + } else { + // insert + _, err := tx.Model(p).Insert() + if err != nil { + return err + } + + // connect project to userID + err = tx.Insert(&models.PermissionsUsersProjects{ + UserID: userID, + ProjectID: p.ProjectID, + View: perms.View, + Create: perms.Create, + Admin: perms.Admin, + }) + if err != nil { + return err + } + } + + return nil + }) + if err != nil { + return err + } + + return nil +} + +// Delete safely deletes the project (fails if the project still has content) +func (s *Service) Delete(ctx context.Context, project *models.Project) error { + _, err := s.DB.GetDB(ctx).ModelContext(ctx, project).Delete() + if err != nil { + return err + } + + err = s.Bus.Publish(ctx, &models.ProjectDeletedEvent{ProjectID: project.ProjectID}) + if err != nil { + return err + } + + return nil +} diff --git a/services/project/starter.go b/services/project/starter.go new file mode 100644 index 00000000..a25cb2cd --- /dev/null +++ b/services/project/starter.go @@ -0,0 +1,30 @@ +package project + +import ( + "context" + + "gitlab.com/beneath-hq/beneath/models" +) + +// CreateUserStarterProject creates a starter project when a user is created +func (s *Service) CreateUserStarterProject(ctx context.Context, msg *models.UserCreatedEvent) error { + // stage initial project + starterProject := &models.Project{ + Name: "starter_project", + DisplayName: "Starter project", + Description: "We automatically created this project for you to help you get started", + Public: true, + OrganizationID: msg.User.BillingOrganizationID, + } + + err := s.StageWithUser(ctx, starterProject, nil, nil, nil, nil, nil, msg.User.UserID, models.ProjectPermissions{ + View: true, + Create: true, + Admin: true, + }) + if err != nil { + return err + } + + return nil +} diff --git a/control/entity/secret_cache.go b/services/secret/cache.go similarity index 67% rename from control/entity/secret_cache.go rename to services/secret/cache.go index 4d8f7f02..6071bdef 100644 --- a/control/entity/secret_cache.go +++ b/services/secret/cache.go @@ -1,4 +1,4 @@ -package entity +package secret import ( "context" @@ -9,56 +9,51 @@ import ( uuid "github.com/satori/go.uuid" "github.com/vmihailenco/msgpack" - "gitlab.com/beneath-hq/beneath/hub" + "gitlab.com/beneath-hq/beneath/models" "gitlab.com/beneath-hq/beneath/pkg/secrettoken" ) -// SecretCache encapsulates a Redis cache of authenticated secrets -type SecretCache struct { - codec cache.Codec +// AuthenticateWithToken returns the secret object matching token or AnonymousSecret +func (s *Service) AuthenticateWithToken(ctx context.Context, token secrettoken.Token) models.Secret { + return s.cache.Get(ctx, token) } -var ( - // cache global - secretCache *SecretCache - - // configuration global - secretCacheConfig = struct { - cacheTime time.Duration - cacheLRUTime time.Duration - cacheLRUSize int - redisKeyFn func(hashedToken []byte) string - }{ - cacheTime: time.Hour, - cacheLRUTime: 10 * time.Second, - cacheLRUSize: 10000, - redisKeyFn: func(hashedToken []byte) string { - return string(append([]byte("scrt:"), hashedToken...)) - }, - } -) +// Cache wraps a Redis and LRU cache of authenticated secrets +type Cache struct { + codec *cache.Codec + service *Service +} -// AuthenticateWithToken returns the secret object matching token or AnonymousSecret -func AuthenticateWithToken(ctx context.Context, token secrettoken.Token) Secret { - return getSecretCache().Get(ctx, token) +// cache configuration +var secretCacheConfig = struct { + cacheTime time.Duration + cacheLRUTime time.Duration + cacheLRUSize int + redisKeyFn func(hashedToken []byte) string +}{ + cacheTime: time.Hour, + cacheLRUTime: 10 * time.Second, + cacheLRUSize: 10000, + redisKeyFn: func(hashedToken []byte) string { + return string(append([]byte("scrt:"), hashedToken...)) + }, } -func getSecretCache() *SecretCache { - if secretCache == nil { - secretCache = &SecretCache{ - codec: cache.Codec{ - Redis: hub.Redis, - Marshal: msgpack.Marshal, - Unmarshal: msgpack.Unmarshal, - }, - } - secretCache.codec.UseLocalCache(secretCacheConfig.cacheLRUSize, secretCacheConfig.cacheLRUTime) +// initializes the service's cache +func (s *Service) initCache() { + s.cache = &Cache{ + codec: &cache.Codec{ + Redis: s.Redis, + Marshal: msgpack.Marshal, + Unmarshal: msgpack.Unmarshal, + }, + service: s, } - return secretCache + s.cache.codec.UseLocalCache(secretCacheConfig.cacheLRUSize, secretCacheConfig.cacheLRUTime) } // Get returns a Secret for a token in string representation -func (c *SecretCache) Get(ctx context.Context, token secrettoken.Token) Secret { +func (c *Cache) Get(ctx context.Context, token secrettoken.Token) models.Secret { switch token.Flags() { case TokenFlagsUser: return c.userOnce(ctx, token) @@ -70,7 +65,7 @@ func (c *SecretCache) Get(ctx context.Context, token secrettoken.Token) Secret { } // Clear removes a key from the cache -func (c *SecretCache) Clear(ctx context.Context, hashedToken []byte) { +func (c *Cache) Clear(ctx context.Context, hashedToken []byte) { err := c.codec.Delete(secretCacheConfig.redisKeyFn(hashedToken)) if err != nil && err != cache.ErrCacheMiss { panic(err) @@ -78,7 +73,7 @@ func (c *SecretCache) Clear(ctx context.Context, hashedToken []byte) { } // ClearForOrganization clears all secrets for services and billing users in the org -func (c *SecretCache) ClearForOrganization(ctx context.Context, organizationID uuid.UUID) { +func (c *Cache) ClearForOrganization(ctx context.Context, organizationID uuid.UUID) { c.clearQuery(ctx, ` select ss.hashed_token from service_secrets ss @@ -94,7 +89,7 @@ func (c *SecretCache) ClearForOrganization(ctx context.Context, organizationID u } // ClearForUser clears all secrets for the user -func (c *SecretCache) ClearForUser(ctx context.Context, userID uuid.UUID) { +func (c *Cache) ClearForUser(ctx context.Context, userID uuid.UUID) { c.clearQuery(ctx, ` select us.hashed_token from user_secrets us @@ -103,7 +98,7 @@ func (c *SecretCache) ClearForUser(ctx context.Context, userID uuid.UUID) { } // ClearForService clears all secrets for the service -func (c *SecretCache) ClearForService(ctx context.Context, serviceID uuid.UUID) { +func (c *Cache) ClearForService(ctx context.Context, serviceID uuid.UUID) { c.clearQuery(ctx, ` select ss.hashed_token from service_secrets ss @@ -112,9 +107,9 @@ func (c *SecretCache) ClearForService(ctx context.Context, serviceID uuid.UUID) } // clearQuery clears hashed tokens returned by the given query and params -func (c *SecretCache) clearQuery(ctx context.Context, query string, params ...interface{}) { +func (c *Cache) clearQuery(ctx context.Context, query string, params ...interface{}) { var hashedTokens [][]byte - _, err := hub.DB.QueryContext(ctx, &hashedTokens, query, params...) + _, err := c.service.DB.GetDB(ctx).QueryContext(ctx, &hashedTokens, query, params...) if err != nil { panic(err) } @@ -123,9 +118,9 @@ func (c *SecretCache) clearQuery(ctx context.Context, query string, params ...in } } -func (c *SecretCache) userOnce(ctx context.Context, token secrettoken.Token) *UserSecret { +func (c *Cache) userOnce(ctx context.Context, token secrettoken.Token) *models.UserSecret { hashedToken := token.Hashed() - var res *UserSecret + var res *models.UserSecret err := c.codec.Once(&cache.Item{ Key: secretCacheConfig.redisKeyFn(hashedToken), Object: &res, @@ -144,9 +139,9 @@ func (c *SecretCache) userOnce(ctx context.Context, token secrettoken.Token) *Us return res } -func (c *SecretCache) serviceOnce(ctx context.Context, token secrettoken.Token) *ServiceSecret { +func (c *Cache) serviceOnce(ctx context.Context, token secrettoken.Token) *models.ServiceSecret { hashedToken := token.Hashed() - var res *ServiceSecret + var res *models.ServiceSecret err := c.codec.Once(&cache.Item{ Key: secretCacheConfig.redisKeyFn(hashedToken), Object: &res, @@ -165,10 +160,10 @@ func (c *SecretCache) serviceOnce(ctx context.Context, token secrettoken.Token) return res } -func (c *SecretCache) userGetter(ctx context.Context, hashedToken []byte) func() (interface{}, error) { +func (c *Cache) userGetter(ctx context.Context, hashedToken []byte) func() (interface{}, error) { return func() (interface{}, error) { - secret := &UserSecret{} - err := hub.DB.ModelContext(ctx, secret). + secret := &models.UserSecret{} + err := c.service.DB.GetDB(ctx).ModelContext(ctx, secret). Column( "user_secret.user_secret_id", "user_secret.read_only", @@ -202,10 +197,10 @@ func (c *SecretCache) userGetter(ctx context.Context, hashedToken []byte) func() } } -func (c *SecretCache) serviceGetter(ctx context.Context, hashedToken []byte) func() (interface{}, error) { +func (c *Cache) serviceGetter(ctx context.Context, hashedToken []byte) func() (interface{}, error) { return func() (interface{}, error) { - secret := &ServiceSecret{} - err := hub.DB.ModelContext(ctx, secret). + secret := &models.ServiceSecret{} + err := c.service.DB.GetDB(ctx).ModelContext(ctx, secret). Column( "service_secret.service_secret_id", "Service.service_id", diff --git a/services/secret/crud.go b/services/secret/crud.go new file mode 100644 index 00000000..5916b190 --- /dev/null +++ b/services/secret/crud.go @@ -0,0 +1,89 @@ +package secret + +import ( + "context" + + "github.com/go-pg/pg" + uuid "github.com/satori/go.uuid" + + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/pkg/secrettoken" +) + +// CreateUserSecret creates a new secret to manage a user +func (s *Service) CreateUserSecret(ctx context.Context, userID uuid.UUID, description string, publicOnly, readOnly bool) (*models.UserSecret, error) { + // create + secret := &models.UserSecret{} + secret.Token = secrettoken.New(TokenFlagsUser) + secret.Prefix = secret.Token.Prefix() + secret.HashedToken = secret.Token.Hashed() + secret.Description = description + secret.UserID = userID + secret.ReadOnly = readOnly + secret.PublicOnly = publicOnly + + // validate + err := secret.Validate() + if err != nil { + return nil, err + } + + // insert + _, err = s.DB.GetDB(ctx).ModelContext(ctx, secret).Insert() + if err != nil { + return nil, err + } + + // done + return secret, nil +} + +// CreateServiceSecret creates a new secret to manage a service +func (s *Service) CreateServiceSecret(ctx context.Context, serviceID uuid.UUID, description string) (*models.ServiceSecret, error) { + // create + secret := &models.ServiceSecret{} + secret.Token = secrettoken.New(TokenFlagsService) + secret.Prefix = secret.Token.Prefix() + secret.HashedToken = secret.Token.Hashed() + secret.Description = description + secret.ServiceID = serviceID + + // validate + err := secret.Validate() + if err != nil { + return nil, err + } + + // insert + _, err = s.DB.GetDB(ctx).ModelContext(ctx, secret).Insert() + if err != nil { + return nil, err + } + + // done + return secret, nil +} + +// RevokeUserSecret revokes a user secret +func (s *Service) RevokeUserSecret(ctx context.Context, secret *models.UserSecret) { + // delete from db + _, err := s.DB.GetDB(ctx).ModelContext(ctx, secret).Delete() + if err != nil && err != pg.ErrNoRows { + panic(err) + } + + // remove from redis (ignore error) + s.cache.Clear(ctx, secret.HashedToken) +} + +// RevokeServiceSecret revokes a service secret +func (s *Service) RevokeServiceSecret(ctx context.Context, secret *models.ServiceSecret) { + // delete from db + _, err := s.DB.GetDB(ctx).ModelContext(ctx, secret).Delete() + if err != nil && err != pg.ErrNoRows { + panic(err) + } + + // remove from redis (ignore error) + s.cache.Clear(ctx, secret.HashedToken) +} diff --git a/services/secret/events.go b/services/secret/events.go new file mode 100644 index 00000000..14f3a49a --- /dev/null +++ b/services/secret/events.go @@ -0,0 +1,27 @@ +package secret + +import ( + "context" + + "gitlab.com/beneath-hq/beneath/models" +) + +func (s *Service) userUpdated(ctx context.Context, msg *models.UserUpdatedEvent) error { + s.cache.ClearForUser(ctx, msg.User.UserID) + return nil +} + +func (s *Service) organizationUpdated(ctx context.Context, msg *models.OrganizationUpdatedEvent) error { + s.cache.ClearForOrganization(ctx, msg.Organization.OrganizationID) + return nil +} + +func (s *Service) serviceUpdated(ctx context.Context, msg *models.ServiceUpdatedEvent) error { + s.cache.ClearForService(ctx, msg.Service.ServiceID) + return nil +} + +func (s *Service) serviceDeleted(ctx context.Context, msg *models.ServiceDeletedEvent) error { + s.cache.ClearForService(ctx, msg.ServiceID) + return nil +} diff --git a/services/secret/secret.go b/services/secret/secret.go new file mode 100644 index 00000000..3e603b4a --- /dev/null +++ b/services/secret/secret.go @@ -0,0 +1,83 @@ +package secret + +import ( + "context" + + "github.com/go-redis/redis/v7" + uuid "github.com/satori/go.uuid" + "gitlab.com/beneath-hq/beneath/bus" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/infrastructure/db" +) + +const ( + // TokenFlagsService is used as flags byte for service secret tokens + TokenFlagsService = byte(0x80) + + // TokenFlagsUser is used as flags byte for user secret tokens + TokenFlagsUser = byte(0x81) +) + +// Service has functionality for managing user and service secrets, including authentication +type Service struct { + Bus *bus.Bus + DB db.DB + Redis *redis.Client + + cache *Cache +} + +// New creates a new user service +func New(bus *bus.Bus, db db.DB, redis *redis.Client) *Service { + s := &Service{ + Bus: bus, + DB: db, + Redis: redis, + } + s.initCache() + s.Bus.AddSyncListener(s.userUpdated) + s.Bus.AddSyncListener(s.organizationUpdated) + s.Bus.AddSyncListener(s.serviceUpdated) + s.Bus.AddSyncListener(s.serviceDeleted) + return s +} + +// FindUserSecret finds a secret +func (s *Service) FindUserSecret(ctx context.Context, secretID uuid.UUID) *models.UserSecret { + secret := &models.UserSecret{UserSecretID: secretID} + err := s.DB.GetDB(ctx).ModelContext(ctx, secret).WherePK().Select() + if !db.AssertFoundOne(err) { + return nil + } + return secret +} + +// FindUserSecrets finds all the user's secrets +func (s *Service) FindUserSecrets(ctx context.Context, userID uuid.UUID) []*models.UserSecret { + var secrets []*models.UserSecret + err := s.DB.GetDB(ctx).ModelContext(ctx, &secrets).Where("user_id = ?", userID).Limit(1000).Order("created_on DESC").Select() + if err != nil { + panic(err) + } + return secrets +} + +// FindServiceSecret finds a service secret +func (s *Service) FindServiceSecret(ctx context.Context, secretID uuid.UUID) *models.ServiceSecret { + secret := &models.ServiceSecret{ServiceSecretID: secretID} + err := s.DB.GetDB(ctx).ModelContext(ctx, secret).WherePK().Select() + if !db.AssertFoundOne(err) { + return nil + } + return secret +} + +// FindServiceSecrets finds all the service's secrets +func (s *Service) FindServiceSecrets(ctx context.Context, serviceID uuid.UUID) []*models.ServiceSecret { + var secrets []*models.ServiceSecret + err := s.DB.GetDB(ctx).ModelContext(ctx, &secrets).Where("service_id = ?", serviceID).Limit(1000).Order("created_on DESC").Select() + if err != nil { + panic(err) + } + return secrets +} diff --git a/services/service/service.go b/services/service/service.go new file mode 100644 index 00000000..ebd7766c --- /dev/null +++ b/services/service/service.go @@ -0,0 +1,161 @@ +package service + +import ( + "context" + "time" + + uuid "github.com/satori/go.uuid" + "gitlab.com/beneath-hq/beneath/bus" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/infrastructure/db" +) + +// Service contains functionality for finding and creating services. +// YES, THIS IS CONFUSING! In the codebase, a "service" wraps functionality +// for a specific domain of the app. Meanwhile in Beneath, a "service" is a +// non-user account, also known as a "service account" in eg. GCP. +type Service struct { + Bus *bus.Bus + DB db.DB +} + +// New creates a new user service +func New(bus *bus.Bus, db db.DB) *Service { + return &Service{ + Bus: bus, + DB: db, + } +} + +// FindService returns the matching service or nil +func (s *Service) FindService(ctx context.Context, serviceID uuid.UUID) *models.Service { + service := &models.Service{ + ServiceID: serviceID, + } + err := s.DB.GetDB(ctx).ModelContext(ctx, service). + Column( + "service.*", + "Project", + "Project.Organization", + ). + WherePK(). + Select() + if !db.AssertFoundOne(err) { + return nil + } + return service +} + +// FindServiceByOrganizationProjectAndName returns the matching service or nil +func (s *Service) FindServiceByOrganizationProjectAndName(ctx context.Context, organizationName, projectName, serviceName string) *models.Service { + service := &models.Service{} + err := s.DB.GetDB(ctx).ModelContext(ctx, service). + Column( + "service.*", + "Project", + "Project.Organization", + ). + Where("lower(project__organization.name) = lower(?)", organizationName). + Where("lower(project.name) = lower(?)", projectName). + Where("lower(service.name) = lower(?)", serviceName). + Select() + if !db.AssertFoundOne(err) { + return nil + } + return service +} + +// Stage creates or updates the service +func (s *Service) Stage(ctx context.Context, service *models.Service, description *string, sourceURL *string, readQuota *int64, writeQuota *int64, scanQuota *int64) error { + // determine whether to insert or update + update := (service.ServiceID != uuid.Nil) + + // tracks whether a save is necessary + save := !update + + if description != nil { + if service.Description != *description { + service.Description = *description + save = true + } + } + + if sourceURL != nil { + if service.SourceURL != *sourceURL { + service.SourceURL = *sourceURL + save = true + } + } + + if readQuota != nil { + if *readQuota == 0 { + service.ReadQuota = nil + } else { + service.ReadQuota = readQuota + } + save = true + } + + if writeQuota != nil { + if *writeQuota == 0 { + service.WriteQuota = nil + } else { + service.WriteQuota = writeQuota + } + save = true + } + + if scanQuota != nil { + if *scanQuota == 0 { + service.ScanQuota = nil + } else { + service.ScanQuota = scanQuota + } + save = true + } + + // quit if no changes + if !save { + return nil + } + + // validate + err := service.Validate() + if err != nil { + return err + } + + if update { + service.UpdatedOn = time.Now() + _, err := s.DB.GetDB(ctx).ModelContext(ctx, service).WherePK().Update() + if err != nil { + return err + } + + err = s.Bus.Publish(ctx, models.ServiceUpdatedEvent{ + Service: service, + }) + if err != nil { + return err + } + } else { + _, err := s.DB.GetDB(ctx).ModelContext(ctx, service).Insert() + if err != nil { + return err + } + } + + return nil +} + +// Delete removes a service from the database +func (s *Service) Delete(ctx context.Context, service *models.Service) error { + _, err := s.DB.GetDB(ctx).ModelContext(ctx, service).WherePK().Delete() + if err != nil { + return err + } + + return s.Bus.Publish(ctx, &models.ServiceDeletedEvent{ + ServiceID: service.ServiceID, + }) +} diff --git a/services/stream/cached_stream.go b/services/stream/cached_stream.go new file mode 100644 index 00000000..e79b1377 --- /dev/null +++ b/services/stream/cached_stream.go @@ -0,0 +1,159 @@ +package stream + +import ( + "bytes" + "encoding/gob" + + uuid "github.com/satori/go.uuid" + + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/pkg/codec" +) + +// internalCachedInstance is a serializable version of models.CachedInstance (which is not serializable because of Codec) +type internalCachedInstance struct { + StreamID uuid.UUID + Public bool + Final bool + UseLog bool + UseIndex bool + UseWarehouse bool + LogRetentionSeconds int32 + IndexRetentionSeconds int32 + WarehouseRetentionSeconds int32 + OrganizationID uuid.UUID + OrganizationName string + ProjectID uuid.UUID + ProjectName string + StreamName string + CanonicalAvroSchema string + Indexes []internalCachedInstanceIndex +} + +// internalCachedInstanceIndex represents indexes +type internalCachedInstanceIndex struct { + StreamIndexID uuid.UUID + ShortID int + Fields []string + Primary bool + Normalize bool +} + +// GetIndexID implements codec.Index +func (i internalCachedInstanceIndex) GetIndexID() uuid.UUID { + return i.StreamIndexID +} + +// GetShortID implements codec.Index +func (i internalCachedInstanceIndex) GetShortID() int { + return i.ShortID +} + +// GetFields implements codec.Index +func (i internalCachedInstanceIndex) GetFields() []string { + return i.Fields +} + +// GetNormalize implements codec.Index +func (i internalCachedInstanceIndex) GetNormalize() bool { + return i.Normalize +} + +func cachedInstanceToInternal(c *models.CachedInstance) *internalCachedInstance { + wrapped := &internalCachedInstance{ + StreamID: c.StreamID, + Public: c.Public, + Final: c.Final, + UseLog: c.UseLog, + UseIndex: c.UseIndex, + UseWarehouse: c.UseWarehouse, + LogRetentionSeconds: c.LogRetentionSeconds, + IndexRetentionSeconds: c.IndexRetentionSeconds, + WarehouseRetentionSeconds: c.WarehouseRetentionSeconds, + OrganizationID: c.OrganizationID, + OrganizationName: c.OrganizationName, + ProjectID: c.ProjectID, + ProjectName: c.ProjectName, + StreamName: c.StreamName, + } + + // necessary because we allow empty CachedInstance objects + if c.Codec != nil { + wrapped.CanonicalAvroSchema = c.Codec.AvroSchema + wrapped.Indexes = []internalCachedInstanceIndex{c.Codec.PrimaryIndex.(internalCachedInstanceIndex)} + for _, index := range c.Codec.SecondaryIndexes { + wrapped.Indexes = append(wrapped.Indexes, index.(internalCachedInstanceIndex)) + } + } + + return wrapped +} + +func internalToCachedInstance(i *internalCachedInstance) (*models.CachedInstance, error) { + c := &models.CachedInstance{} + + c.StreamID = i.StreamID + c.Public = i.Public + c.Final = i.Final + c.UseLog = i.UseLog + c.UseIndex = i.UseIndex + c.UseWarehouse = i.UseWarehouse + c.LogRetentionSeconds = i.LogRetentionSeconds + c.IndexRetentionSeconds = i.IndexRetentionSeconds + c.WarehouseRetentionSeconds = i.WarehouseRetentionSeconds + c.OrganizationID = i.OrganizationID + c.OrganizationName = i.OrganizationName + c.ProjectID = i.ProjectID + c.ProjectName = i.ProjectName + c.StreamName = i.StreamName + + // nil checks necessary because we allow empty CachedInstance objects + + if i.CanonicalAvroSchema != "" { + var primaryIndex codec.Index + var secondaryIndexes []codec.Index + for _, index := range i.Indexes { + if index.Primary { + primaryIndex = index + } else { + secondaryIndexes = append(secondaryIndexes, index) + } + } + + codec, err := codec.New(i.CanonicalAvroSchema, primaryIndex, secondaryIndexes) + if err != nil { + return nil, err + } + c.Codec = codec + } + + return c, nil +} + +func marshalCachedInstance(c *models.CachedInstance) ([]byte, error) { + internal := cachedInstanceToInternal(c) + var buf bytes.Buffer + enc := gob.NewEncoder(&buf) + err := enc.Encode(internal) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func unmarshalCachedInstance(data []byte, target *models.CachedInstance) error { + internal := internalCachedInstance{} + dec := gob.NewDecoder(bytes.NewReader(data)) + err := dec.Decode(&internal) + if err != nil { + return err + } + + cachedInstance, err := internalToCachedInstance(&internal) + if err != nil { + return err + } + + *target = *cachedInstance + return nil +} diff --git a/services/stream/compile.go b/services/stream/compile.go new file mode 100644 index 00000000..7dd5b3e6 --- /dev/null +++ b/services/stream/compile.go @@ -0,0 +1,121 @@ +package stream + +import ( + "crypto/md5" + "encoding/json" + "fmt" + "strings" + + uuid "github.com/satori/go.uuid" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/pkg/schemalang" + "gitlab.com/beneath-hq/beneath/pkg/schemalang/transpilers" +) + +// ComputeSchemaMD5 returns a non-canonical (but useful) digest of a schema and its indexes +func (s *Service) ComputeSchemaMD5(schema string, indexes *string) []byte { + input := []byte(strings.TrimSpace(schema)) + if indexes != nil { + input = append(input, []byte(strings.TrimSpace(*indexes))...) + } + digest := md5.Sum(input) + return digest[:] +} + +// CompileToStream compiles the given schema and sets relevant fields on the stream. +func (s *Service) CompileToStream(stream *models.Stream, schemaKind models.StreamSchemaKind, newSchema string, newIndexes *string, description *string) error { + // determine if we're updating an existing stream or creating a new + update := stream.StreamID != uuid.Nil + + // get schema + var schema schemalang.Schema + var indexes schemalang.Indexes + var err error + switch schemaKind { + case models.StreamSchemaKindAvro: + schema, err = transpilers.FromAvro(newSchema) + case models.StreamSchemaKindGraphQL: + schema, indexes, err = transpilers.FromGraphQL(newSchema) + default: + err = fmt.Errorf("Unsupported stream schema definition language '%s'", schemaKind) + } + if err != nil { + return err + } + + // parse newIndexes if set (overrides output from transpiler) + if newIndexes != nil { + err = json.Unmarshal([]byte(*newIndexes), &indexes) + if err != nil { + return fmt.Errorf("error parsing indexes: '%s'", err.Error()) + } + } + + // check schema + err = schemalang.Check(schema) + if err != nil { + return err + } + + // check indexes + err = indexes.Check(schema) + if err != nil { + return err + } + + // normalize indexes + canonicalIndexes := indexes.CanonicalJSON() + + // get avro schemas + canonicalAvro := transpilers.ToAvro(schema, false) + avro := transpilers.ToAvro(schema, true) + + // if update, check canonical avro is the same + if update { + if canonicalAvro != stream.CanonicalAvroSchema { + return fmt.Errorf("Unfortunately we do not currently support updating a stream's data structure; you can only edit its documentation") + } + if canonicalIndexes != stream.CanonicalIndexes { + return fmt.Errorf("Unfortunately we do not currently support updating a stream's indexes") + } + } + + // TEMPORARY: disable secondary indexes + if len(indexes) != 1 { + return fmt.Errorf("Cannot add secondary indexes to stream (a stream must have exactly one key index)") + } + + // set indexes + if !update { + s.assignIndexes(stream, indexes) + } + + // set missing stream fields + stream.SchemaKind = schemaKind + stream.Schema = newSchema + stream.AvroSchema = avro + stream.CanonicalAvroSchema = canonicalAvro + stream.CanonicalIndexes = canonicalIndexes + if description == nil { + stream.Description = schema.(*schemalang.Record).Doc + } else { + stream.Description = *description + } + + return nil +} + +// Sets StreamIndexes to new StreamIndex objects based on def. +// Doesn't execute any DB actions, so doesn't set any IDs. +func (s *Service) assignIndexes(stream *models.Stream, indexes schemalang.Indexes) { + indexes.Sort() + stream.StreamIndexes = make([]*models.StreamIndex, len(indexes)) + for idx, index := range indexes { + stream.StreamIndexes[idx] = &models.StreamIndex{ + ShortID: idx, + Fields: index.Fields, + Primary: index.Key, + Normalize: index.Normalize, + } + } +} diff --git a/services/stream/events.go b/services/stream/events.go new file mode 100644 index 00000000..f0856a6e --- /dev/null +++ b/services/stream/events.go @@ -0,0 +1,87 @@ +package stream + +import ( + "context" + "time" + + "gitlab.com/beneath-hq/beneath/models" +) + +func (s *Service) organizationUpdated(ctx context.Context, msg *models.OrganizationUpdatedEvent) error { + s.instanceCache.ClearForOrganization(ctx, msg.Organization.OrganizationID) + return nil +} + +func (s *Service) projectUpdated(ctx context.Context, msg *models.ProjectUpdatedEvent) error { + s.instanceCache.ClearForProject(ctx, msg.Project.ProjectID) + return nil +} + +func (s *Service) streamUpdated(ctx context.Context, msg *models.StreamUpdatedEvent) error { + instances := s.FindStreamInstances(ctx, msg.Stream.StreamID, nil, nil) + for _, instance := range instances { + s.instanceCache.Clear(ctx, instance.StreamInstanceID) + err := s.Engine.RegisterInstance(ctx, msg.Stream, instance) + if err != nil { + return err + } + } + return nil +} + +func (s *Service) streamDeleted(ctx context.Context, msg *models.StreamDeletedEvent) error { + err := s.Engine.ClearUsage(ctx, msg.StreamID) + if err != nil { + return err + } + return nil +} + +func (s *Service) streamInstanceCreated(ctx context.Context, msg *models.StreamInstanceCreatedEvent) error { + err := s.Engine.RegisterInstance(ctx, msg.Stream, msg.StreamInstance) + if err != nil { + return err + } + return nil +} + +func (s *Service) streamInstanceUpdated(ctx context.Context, msg *models.StreamInstanceUpdatedEvent) error { + // clear instance cache + s.instanceCache.Clear(ctx, msg.StreamInstance.StreamInstanceID) + + // clear name cache + if msg.MakePrimary { + s.nameCache.Clear(ctx, msg.OrganizationName, msg.ProjectName, msg.Stream.Name) + } + + // delete earlier versions + if msg.MakePrimary { + instances := s.FindStreamInstances(ctx, msg.Stream.StreamID, nil, &msg.StreamInstance.Version) + for _, instance := range instances { + err := s.DeleteStreamInstance(ctx, msg.Stream, instance) + if err != nil { + return err + } + } + } + + return nil +} + +func (s *Service) streamInstanceDeleted(ctx context.Context, msg *models.StreamInstanceDeletedEvent) error { + time.Sleep(s.instanceCache.cacheLRUTime()) + + s.instanceCache.Clear(ctx, msg.StreamInstance.StreamInstanceID) + + err := s.Engine.RemoveInstance(ctx, msg.Stream, msg.StreamInstance) + if err != nil { + return err + } + + err = s.Engine.ClearUsage(ctx, msg.StreamInstance.StreamInstanceID) + if err != nil { + return err + } + + return nil +} diff --git a/services/stream/instance_cache.go b/services/stream/instance_cache.go new file mode 100644 index 00000000..61a5973c --- /dev/null +++ b/services/stream/instance_cache.go @@ -0,0 +1,202 @@ +package stream + +import ( + "context" + "time" + + "github.com/bluele/gcache" + "github.com/go-pg/pg/v9" + "github.com/go-redis/cache/v7" + uuid "github.com/satori/go.uuid" + + "gitlab.com/beneath-hq/beneath/models" +) + +// FindCachedInstance returns select info about the instance and its stream (cached) +func (s *Service) FindCachedInstance(ctx context.Context, instanceID uuid.UUID) *models.CachedInstance { + return s.instanceCache.Get(ctx, instanceID) +} + +// StreamCache is a Redis and LRU based cache mapping an instance ID to a CachedStream +type instanceCache struct { + codec *cache.Codec + lru gcache.Cache + service *Service +} + +func (s *Service) initInstanceCache() { + c := &instanceCache{ + service: s, + } + c.codec = &cache.Codec{ + Redis: s.Redis, + Marshal: c.marshal, + Unmarshal: c.unmarshal, + } + c.lru = gcache.New(c.cacheLRUSize()).LRU().Build() + s.instanceCache = c +} + +// Get returns the CachedStream for the given instanceID +func (c *instanceCache) Get(ctx context.Context, instanceID uuid.UUID) *models.CachedInstance { + key := c.redisKey(instanceID) + + // lookup in lru first + value, err := c.lru.Get(key) + if err == nil { + cachedStream := value.(*models.CachedInstance) + return cachedStream + } + + // lookup in redis or db + cachedStream := &models.CachedInstance{} + err = c.codec.Once(&cache.Item{ + Key: key, + Object: cachedStream, + Expiration: c.cacheTime(), + Func: c.getterFunc(ctx, instanceID), + }) + + if err != nil { + if ctx.Err() == context.Canceled { + return nil + } + panic(err) + } + + if cachedStream.StreamID == uuid.Nil { + cachedStream = nil + } + + // set in lru + c.lru.SetWithExpire(key, cachedStream, c.cacheLRUTime()) + + return cachedStream +} + +// Clear removes any CachedStream cached for the given instanceID +func (c *instanceCache) Clear(ctx context.Context, instanceID uuid.UUID) { + key := c.redisKey(instanceID) + c.lru.Remove(key) + err := c.codec.Delete(key) + if err != nil && err != cache.ErrCacheMiss { + panic(err) + } +} + +// ClearForOrganization clears all streams in the organization +func (c *instanceCache) ClearForOrganization(ctx context.Context, organizationID uuid.UUID) { + c.clearQuery(ctx, ` + select si.stream_instance_id + from stream_instances si + join streams s on si.stream_id = s.stream_id + join projects p on s.project_id = p.project_id + where p.organization_id = ? + `, organizationID) +} + +// ClearForProject clears all streams in the project +func (c *instanceCache) ClearForProject(ctx context.Context, projectID uuid.UUID) { + c.clearQuery(ctx, ` + select si.stream_instance_id + from stream_instances si + join streams s on si.stream_id = s.stream_id + where s.project_id = ? + `, projectID) +} + +// clearQuery clears instance IDs returned by the given query and params +func (c *instanceCache) clearQuery(ctx context.Context, query string, params ...interface{}) { + var instanceIDs []uuid.UUID + _, err := c.service.DB.GetDB(ctx).QueryContext(ctx, &instanceIDs, query, params...) + if err != nil { + panic(err) + } + for _, instanceID := range instanceIDs { + c.Clear(ctx, instanceID) + } +} + +func (c *instanceCache) cacheTime() time.Duration { + return time.Hour +} + +func (c *instanceCache) cacheLRUSize() int { + return 10000 +} + +func (c *instanceCache) cacheLRUTime() time.Duration { + return 10 * time.Second +} + +func (c *instanceCache) redisKey(instanceID uuid.UUID) string { + return string(append([]byte("strm:"), instanceID.Bytes()...)) +} + +func (c *instanceCache) marshal(v interface{}) ([]byte, error) { + cachedInstance := v.(*models.CachedInstance) + return marshalCachedInstance(cachedInstance) +} + +func (c *instanceCache) unmarshal(b []byte, v interface{}) (err error) { + cachedInstance := v.(*models.CachedInstance) + return unmarshalCachedInstance(b, cachedInstance) +} + +func (c *instanceCache) getterFunc(ctx context.Context, instanceID uuid.UUID) func() (interface{}, error) { + return func() (interface{}, error) { + internalResult := &internalCachedInstance{} + _, err := c.service.DB.GetDB(ctx).QueryContext(ctx, internalResult, ` + select + s.stream_id, + p.public, + si.made_final_on is not null as final, + s.use_log, + s.use_index, + s.use_warehouse, + s.log_retention_seconds, + s.index_retention_seconds, + s.warehouse_retention_seconds, + p.organization_id, + o.name as organization_name, + s.project_id, + p.name as project_name, + s.name as stream_name, + s.canonical_avro_schema + from stream_instances si + join streams s on si.stream_id = s.stream_id + join projects p on s.project_id = p.project_id + join organizations o on p.organization_id = o.organization_id + where si.stream_instance_id = ? + `, instanceID) + + if err == pg.ErrNoRows { + return &models.CachedInstance{}, nil + } else if err != nil { + return nil, err + } + + _, err = c.service.DB.GetDB(ctx).QueryContext(ctx, &internalResult.Indexes, ` + select + stream_index_id, + short_id, + fields, + "primary", + normalize + from stream_indexes + where stream_id = ? + `, internalResult.StreamID) + if err == pg.ErrNoRows { + return &models.CachedInstance{}, nil + } else if err != nil { + return nil, err + } + + result, err := internalToCachedInstance(internalResult) + if err != nil { + return nil, err + } + + return result, nil + } +} diff --git a/services/stream/instances.go b/services/stream/instances.go new file mode 100644 index 00000000..7bf86eac --- /dev/null +++ b/services/stream/instances.go @@ -0,0 +1,239 @@ +package stream + +import ( + "context" + "fmt" + "time" + + uuid "github.com/satori/go.uuid" + "gitlab.com/beneath-hq/beneath/infrastructure/db" + "gitlab.com/beneath-hq/beneath/models" +) + +// FindStreamInstance finds an instance and related stream details +func (s *Service) FindStreamInstance(ctx context.Context, instanceID uuid.UUID) *models.StreamInstance { + si := &models.StreamInstance{StreamInstanceID: instanceID} + err := s.DB.GetDB(ctx).ModelContext(ctx, si).Column( + "stream_instance.*", + "Stream", + "Stream.StreamIndexes", + "Stream.Project", + "Stream.Project.Organization", + ).WherePK().Select() + if !db.AssertFoundOne(err) { + return nil + } + return si +} + +// FindStreamInstanceByVersion finds an instance by version in its parent stream +func (s *Service) FindStreamInstanceByVersion(ctx context.Context, streamID uuid.UUID, version int) *models.StreamInstance { + si := &models.StreamInstance{} + err := s.DB.GetDB(ctx).ModelContext(ctx, si). + Column( + "stream_instance.*", + "Stream", + "Stream.StreamIndexes", + "Stream.Project", + "Stream.Project.Organization", + ). + Where("stream_id = ?", streamID). + Where("version = ?", version). + Select() + if !db.AssertFoundOne(err) { + return nil + } + return si +} + +// FindStreamInstances finds the instances associated with the given stream +func (s *Service) FindStreamInstances(ctx context.Context, streamID uuid.UUID, fromVersion *int, toVersion *int) []*models.StreamInstance { + var res []*models.StreamInstance + + // optimization + if fromVersion != nil && toVersion != nil && *fromVersion == *toVersion { + return res + } + + // build query + query := s.DB.GetDB(ctx).ModelContext(ctx, &res).Where("stream_id = ?", streamID) + if fromVersion != nil { + query = query.Where("version >= ?", *fromVersion) + } + if toVersion != nil { + query = query.Where("version < ?", *toVersion) + } + + // select + err := query.Select() + if err != nil { + panic(fmt.Errorf("error fetching stream instances: %s", err.Error())) + } + + return res +} + +// CreateStreamInstance creates and registers a new stream instance +func (s *Service) CreateStreamInstance(ctx context.Context, stream *models.Stream, version int, makePrimary bool) (*models.StreamInstance, error) { + if version < 0 { + return nil, fmt.Errorf("Cannot create stream instance with negative version (got %d)", version) + } + + instance := &models.StreamInstance{ + StreamID: stream.StreamID, + Stream: stream, + Version: version, + } + + if makePrimary { + now := time.Now() + instance.MadePrimaryOn = &now + } + + // create in transaction + err := s.DB.InTransaction(ctx, func(ctx context.Context) error { + tx := s.DB.GetDB(ctx) + + _, err := tx.Model(instance).Insert() + if err != nil { + return err + } + + updateCountsQuery := tx.Model(stream).WherePK() + updateCountsQuery.Set("instances_created_count = instances_created_count + 1") + if makePrimary { + updateCountsQuery.Set("instances_made_primary_count = instances_made_primary_count + 1") + } + _, err = updateCountsQuery.Update() + if err != nil { + return err + } + + return nil + }) + if err != nil { + return nil, err + } + + // publish event + err = s.Bus.Publish(ctx, &models.StreamInstanceCreatedEvent{ + Stream: stream, + StreamInstance: instance, + MakePrimary: makePrimary, + }) + if err != nil { + return nil, err + } + + return instance, nil +} + +// UpdateStreamInstance makes a stream instance primary and/or final +func (s *Service) UpdateStreamInstance(ctx context.Context, stream *models.Stream, instance *models.StreamInstance, makeFinal bool, makePrimary bool) error { + // makeFinal is one-way and can be done once + // makePrimary can be done any number of times + + // bail if there's nothing to do + if (!makeFinal || instance.MadeFinalOn != nil) && !makePrimary { + return nil + } + + // run in transaction + now := time.Now() + err := s.DB.InTransaction(ctx, func(ctx context.Context) error { + tx := s.DB.GetDB(ctx) + updateStreamQuery := tx.Model(stream).WherePK() + updateInstanceQuery := tx.Model(instance).WherePK() + + // handle makeFinal + if makeFinal && instance.MadeFinalOn == nil { + updateStreamQuery.Set("instances_made_final_count = instances_made_final_count + 1") + updateInstanceQuery.Set("made_final_on = now()") + instance.MadeFinalOn = &now + } + + // handle makePrimary + if makePrimary { + updateInstanceQuery.Set("made_primary_on = now()") + instance.MadePrimaryOn = &now + updateStreamQuery.Set("primary_stream_instance_id = ?", instance.StreamInstanceID) + if instance.MadePrimaryOn == nil { + updateStreamQuery.Set("instances_made_primary_count = instances_made_primary_count + 1") + } + } + + // updated on timestamps + updateStreamQuery.Set("updated_on = now()") + updateInstanceQuery.Set("updated_on = now()") + instance.UpdatedOn = now + + // update + _, err := updateStreamQuery.Update() + if err != nil { + return err + } + _, err = updateInstanceQuery.Update() + if err != nil { + return err + } + + return nil + }) + if err != nil { + return err + } + + // publish event + err = s.Bus.Publish(ctx, &models.StreamInstanceUpdatedEvent{ + Stream: stream, + StreamInstance: instance, + MakeFinal: makeFinal, + MakePrimary: makePrimary, + OrganizationName: stream.Project.Organization.Name, + ProjectName: stream.Project.Name, + }) + if err != nil { + return err + } + + return nil +} + +// DeleteStreamInstance deletes a stream and its data +func (s *Service) DeleteStreamInstance(ctx context.Context, stream *models.Stream, instance *models.StreamInstance) error { + err := s.DB.InTransaction(ctx, func(ctx context.Context) error { + tx := s.DB.GetDB(ctx) + + err := tx.Delete(instance) + if err != nil { + return err + } + + _, err = tx.Model(stream). + WherePK(). + Set("updated_on = ?", stream.UpdatedOn). + Set("instances_deleted_count = instances_deleted_count + 1"). + Update() + if err != nil { + return err + } + + // stream.PrimaryStreamInstanceID has SET NULL constraint (so we don't have to handle it) + + return nil + }) + if err != nil { + return err + } + + // publish event + err = s.Bus.Publish(ctx, &models.StreamInstanceDeletedEvent{ + Stream: stream, + StreamInstance: instance, + }) + if err != nil { + return err + } + + return nil +} diff --git a/services/stream/name_cache.go b/services/stream/name_cache.go new file mode 100644 index 00000000..ab6ef8fa --- /dev/null +++ b/services/stream/name_cache.go @@ -0,0 +1,108 @@ +package stream + +import ( + "context" + "fmt" + "time" + + "github.com/go-pg/pg/v9" + "github.com/go-redis/cache/v7" + uuid "github.com/satori/go.uuid" +) + +// FindPrimaryInstanceIDByOrganizationProjectAndName returns the current primary instance ID of the stream +func (s *Service) FindPrimaryInstanceIDByOrganizationProjectAndName(ctx context.Context, organizationName string, projectName string, streamName string) uuid.UUID { + return s.nameCache.Get(ctx, organizationName, projectName, streamName) +} + +// nameCache is a Redis and LRU based cache mapping stream paths to the primary instance ID for that stream +type nameCache struct { + codec *cache.Codec + service *Service +} + +func (s *Service) initNameCache() { + c := &nameCache{ + service: s, + } + c.codec = &cache.Codec{ + Redis: s.Redis, + Marshal: c.marshal, + Unmarshal: c.unmarshal, + } + c.codec.UseLocalCache(c.cacheLRUSize(), c.cacheLRUTime()) + s.nameCache = c +} + +func (c *nameCache) Get(ctx context.Context, organizationName string, projectName string, streamName string) uuid.UUID { + var instanceID uuid.UUID + err := c.codec.Once(&cache.Item{ + Key: c.redisKey(organizationName, projectName, streamName), + Object: &instanceID, + Expiration: c.cacheTime(), + Func: c.getterFunc(ctx, organizationName, projectName, streamName), + }) + + if err != nil { + if ctx.Err() == context.Canceled { + return uuid.Nil + } + panic(err) + } + + return instanceID +} + +func (c *nameCache) Clear(ctx context.Context, organizationName string, projectName string, streamName string) { + err := c.codec.Delete(c.redisKey(organizationName, projectName, streamName)) + if err != nil && err != cache.ErrCacheMiss { + panic(err) + } +} + +func (c *nameCache) cacheTime() time.Duration { + return time.Hour +} + +func (c *nameCache) cacheLRUSize() int { + return 10000 +} + +func (c *nameCache) cacheLRUTime() time.Duration { + return 10 * time.Second +} + +func (c *nameCache) redisKey(organizationName string, projectName string, streamName string) string { + return fmt.Sprintf("inst:%s:%s:%s", organizationName, projectName, streamName) +} + +func (c *nameCache) marshal(v interface{}) ([]byte, error) { + instanceID := v.(uuid.UUID) + return instanceID.Bytes(), nil +} + +func (c *nameCache) unmarshal(b []byte, v interface{}) (err error) { + instanceID := v.(*uuid.UUID) + *instanceID, err = uuid.FromBytes(b) + return err +} + +func (c *nameCache) getterFunc(ctx context.Context, organizationName string, projectName string, streamName string) func() (interface{}, error) { + return func() (interface{}, error) { + res := uuid.Nil + _, err := c.service.DB.GetDB(ctx).QueryContext(ctx, pg.Scan(&res), ` + select s.primary_stream_instance_id + from streams s + join projects p on s.project_id = p.project_id + join organizations o on p.organization_id = o.organization_id + where lower(s.name) = lower(?) + and lower(p.name) = lower(?) + and lower(o.name) = lower(?) + and primary_stream_instance_id is not null + `, streamName, projectName, organizationName) + if err == pg.ErrNoRows { + return res, nil + } + return res, err + } +} diff --git a/services/stream/stream.go b/services/stream/stream.go new file mode 100644 index 00000000..8eb05222 --- /dev/null +++ b/services/stream/stream.go @@ -0,0 +1,40 @@ +package stream + +import ( + "github.com/go-redis/redis/v7" + + "gitlab.com/beneath-hq/beneath/bus" + "gitlab.com/beneath-hq/beneath/infrastructure/db" + "gitlab.com/beneath-hq/beneath/infrastructure/engine" +) + +// Service has functionality for managing user and service secrets, including authentication +type Service struct { + Bus *bus.Bus + DB db.DB + Redis *redis.Client + Engine *engine.Engine + + nameCache *nameCache + instanceCache *instanceCache +} + +// New creates a new user service +func New(bus *bus.Bus, db db.DB, redis *redis.Client, engine *engine.Engine) *Service { + s := &Service{ + Bus: bus, + DB: db, + Redis: redis, + Engine: engine, + } + s.initNameCache() + s.initInstanceCache() + s.Bus.AddSyncListener(s.organizationUpdated) + s.Bus.AddSyncListener(s.projectUpdated) + s.Bus.AddAsyncListener(s.streamUpdated) + s.Bus.AddAsyncListener(s.streamDeleted) + s.Bus.AddAsyncListener(s.streamInstanceCreated) + s.Bus.AddAsyncListener(s.streamInstanceUpdated) + s.Bus.AddAsyncListener(s.streamInstanceDeleted) + return s +} diff --git a/services/stream/streams.go b/services/stream/streams.go new file mode 100644 index 00000000..cf954638 --- /dev/null +++ b/services/stream/streams.go @@ -0,0 +1,244 @@ +package stream + +import ( + "bytes" + "context" + "fmt" + "time" + + uuid "github.com/satori/go.uuid" + "gitlab.com/beneath-hq/beneath/infrastructure/db" + "gitlab.com/beneath-hq/beneath/models" +) + +// FindStream finds a stream +func (s *Service) FindStream(ctx context.Context, streamID uuid.UUID) *models.Stream { + stream := &models.Stream{StreamID: streamID} + err := s.DB.GetDB(ctx).ModelContext(ctx, stream). + WherePK(). + Column( + "stream.*", + "Project", + "Project.Organization", + "PrimaryStreamInstance", + "StreamIndexes", + ). + Select() + if !db.AssertFoundOne(err) { + return nil + } + return stream +} + +// FindStreamByOrganizationProjectAndName finds a stream +func (s *Service) FindStreamByOrganizationProjectAndName(ctx context.Context, organizationName string, projectName string, streamName string) *models.Stream { + stream := &models.Stream{} + err := s.DB.GetDB(ctx).ModelContext(ctx, stream). + Column( + "stream.*", + "Project", + "Project.Organization", + "PrimaryStreamInstance", + "StreamIndexes", + ). + Where("lower(project__organization.name) = lower(?)", organizationName). + Where("lower(project.name) = lower(?)", projectName). + Where("lower(stream.name) = lower(?)", streamName). + Select() + if !db.AssertFoundOne(err) { + return nil + } + return stream +} + +// CreateStream compiles and creates a new stream +func (s *Service) CreateStream(ctx context.Context, msg *models.CreateStreamCommand) (*models.Stream, error) { + stream := &models.Stream{ + Name: msg.Name, + ProjectID: msg.Project.ProjectID, + } + + // compile stream + err := s.CompileToStream(stream, msg.SchemaKind, msg.Schema, msg.Indexes, msg.Description) + if err != nil { + return nil, err + } + stream.SchemaMD5 = s.ComputeSchemaMD5(msg.Schema, msg.Indexes) + + // set other values + stream.AllowManualWrites = derefBool(msg.AllowManualWrites, false) + stream.UseLog = derefBool(msg.UseLog, true) + stream.UseIndex = derefBool(msg.UseIndex, true) + stream.UseWarehouse = derefBool(msg.UseWarehouse, true) + + if msg.LogRetentionSeconds != nil { + if !stream.UseLog { + return nil, fmt.Errorf("Cannot set logRetentionSeconds on stream that doesn't have useLog=true") + } + stream.LogRetentionSeconds = int32(*msg.LogRetentionSeconds) + } + + if msg.IndexRetentionSeconds != nil { + if !stream.UseIndex { + return nil, fmt.Errorf("Cannot set indexRetentionSeconds on stream that doesn't have useIndex=true") + } + stream.IndexRetentionSeconds = int32(*msg.IndexRetentionSeconds) + } + + if msg.WarehouseRetentionSeconds != nil { + if !stream.UseWarehouse { + return nil, fmt.Errorf("Cannot set warehouseRetentionSeconds on stream that doesn't have useWarehouse=true") + } + stream.WarehouseRetentionSeconds = int32(*msg.WarehouseRetentionSeconds) + } + + // if there's a normalized index, make sure we use a non-expiring log. + // note that this is currently a little fictional, as normalized index support is pretty shaky. + for _, index := range stream.StreamIndexes { + if index.Normalize && (!stream.UseLog || stream.LogRetentionSeconds != 0) { + return nil, fmt.Errorf("Cannot use normalized indexes when useLog=false or logRetentionSeconds is set") + } + } + + // temporarily, we're going to enforce UseLog + if !stream.UseLog { + return nil, fmt.Errorf("Currently doesn't support streams with useLog=false") + } + + // validate + err = stream.Validate() + if err != nil { + return nil, err + } + + // insert stream and its indexes transactionally + err = s.DB.InTransaction(ctx, func(ctx context.Context) error { + tx := s.DB.GetDB(ctx) + + _, err := tx.Model(stream).Insert() + if err != nil { + return err + } + + for _, index := range stream.StreamIndexes { + index.StreamID = stream.StreamID + _, err := tx.Model(index).Insert() + if err != nil { + return err + } + } + + return nil + }) + if err != nil { + return nil, err + } + + // publish events + err = s.Bus.Publish(ctx, &models.StreamCreatedEvent{ + Stream: stream, + }) + if err != nil { + return nil, err + } + + return stream, nil +} + +// UpdateStream updates a streams schema (within limits) and more +func (s *Service) UpdateStream(ctx context.Context, msg *models.UpdateStreamCommand) error { + stream := msg.Stream + updateFields := []string{} + modifiedSchema := false + + // re-compile and set updates if schema changed + if msg.SchemaKind != nil && msg.Schema != nil { + schemaMD5 := s.ComputeSchemaMD5(*msg.Schema, &stream.CanonicalIndexes) + if !bytes.Equal(schemaMD5, stream.SchemaMD5) { + err := s.CompileToStream(stream, *msg.SchemaKind, *msg.Schema, &stream.CanonicalIndexes, msg.Description) + if err != nil { + return err + } + stream.SchemaMD5 = schemaMD5 + updateFields = append( + updateFields, + "schema_kind", + "schema", + "schema_md5", + "avro_schema", + "canonical_avro_schema", + "canonical_indexes", + "description", + ) + modifiedSchema = true + } + } + + // update description (you can change a description without changing the schema) + // (this steps on the former clause's toes, but the if-check here makes them mutually exclusive) + if msg.Description != nil && *msg.Description != stream.Description { + stream.Description = *msg.Description + updateFields = append(updateFields, "description") + } + + // update manual writes + if msg.AllowManualWrites != nil && *msg.AllowManualWrites != stream.AllowManualWrites { + stream.AllowManualWrites = *msg.AllowManualWrites + updateFields = append(updateFields, "allow_manual_writes") + } + + // quit if no changes + if len(updateFields) == 0 { + return nil + } + + // validate + err := stream.Validate() + if err != nil { + return err + } + + // update + stream.UpdatedOn = time.Now() + _, err = s.DB.GetDB(ctx).ModelContext(ctx, stream).WherePK().Update() + if err != nil { + return err + } + + // publish events + err = s.Bus.Publish(ctx, &models.StreamUpdatedEvent{ + Stream: stream, + ModifiedSchema: modifiedSchema, + }) + if err != nil { + return err + } + + return nil +} + +// DeleteStream deletes a stream and all its related instances +func (s *Service) DeleteStream(ctx context.Context, stream *models.Stream) error { + // delete instances + instances := s.FindStreamInstances(ctx, stream.StreamID, nil, nil) + for _, inst := range instances { + err := s.DeleteStreamInstance(ctx, stream, inst) + if err != nil { + return err + } + } + + // delete stream + _, err := s.DB.GetDB(ctx).ModelContext(ctx, stream).Delete() + if err != nil { + return err + } + + // publish event + err = s.Bus.Publish(ctx, &models.StreamDeletedEvent{StreamID: stream.StreamID}) + if err != nil { + return err + } + + return nil +} diff --git a/services/stream/util.go b/services/stream/util.go new file mode 100644 index 00000000..a4a617ce --- /dev/null +++ b/services/stream/util.go @@ -0,0 +1,8 @@ +package stream + +func derefBool(val *bool, fallback bool) bool { + if val != nil { + return *val + } + return fallback +} diff --git a/services/user/create.go b/services/user/create.go new file mode 100644 index 00000000..8012332a --- /dev/null +++ b/services/user/create.go @@ -0,0 +1,234 @@ +package user + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/go-pg/pg/v9/orm" + + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/infrastructure/db" +) + +// CreateOrUpdateUser consolidates and returns the user matching the args +func (s *Service) CreateOrUpdateUser(ctx context.Context, githubID, googleID, email, nickname, name, photoURL string) (*models.User, error) { + var createdUser *models.User + err := s.DB.InTransaction(ctx, func(ctx context.Context) error { + tx := s.DB.GetDB(ctx) + + found, user, org, err := s.getUserForCreateOrUpdate(ctx, githubID, googleID, email) + if err != nil { + return err + } + + // set fields + if githubID != "" { + user.GithubID = githubID + } + if googleID != "" { + user.GoogleID = googleID + } + if email != "" { + user.Email = email + } + if org.DisplayName == "" { + org.DisplayName = name + } + if org.PhotoURL == "" { + org.PhotoURL = photoURL + } + + // if updating, finalize and return + if found { + // validate and save user + user.UpdatedOn = time.Now() + err = user.Validate() + if err != nil { + return err + } + err = tx.Update(user) + if err != nil { + return err + } + + // validate and save org + org.UpdatedOn = time.Now() + err = org.Validate() + if err != nil { + return err + } + err = tx.Update(org) + if err != nil { + return err + } + + // publish event and commit + err := s.Bus.Publish(ctx, models.UserUpdatedEvent{ + User: user, + }) + if err != nil { + return err + } + + // commit + return nil + } + + // we're creating a new user + + // try out all possible usernames + usernameSeeds := usernameSeeds(email, name, nickname) + err = s.createWithUsernameSeeds(ctx, user, org, usernameSeeds) + if err != nil { + return err + } + + // add user to user-organization permissions table + err = tx.Insert(&models.PermissionsUsersOrganizations{ + UserID: user.UserID, + OrganizationID: org.OrganizationID, + View: true, + Create: true, + Admin: true, + }) + if err != nil { + return err + } + + // send events + err = s.Bus.Publish(ctx, &models.UserCreatedEvent{ + User: user, + }) + if err != nil { + return err + } + + err = s.Bus.Publish(ctx, &models.OrganizationCreatedEvent{ + Organization: org, + }) + if err != nil { + return err + } + + // commit + return nil + }) + if err != nil { + return nil, err + } + + return createdUser, nil +} + +func (s *Service) getUserForCreateOrUpdate(ctx context.Context, githubID, googleID, email string) (bool, *models.User, *models.Organization, error) { + tx := s.DB.GetDB(ctx) // must be run in a tx + org := &models.Organization{} + user := &models.User{} + found := true + + // create query to find by id + var userQuery *orm.Query + if githubID != "" { + userQuery = tx.Model(user).Where("github_id = ?", githubID) + } else if googleID != "" { + userQuery = tx.Model(user).Where("google_id = ?", googleID) + } else { + return false, nil, nil, fmt.Errorf("Neither githubID nor googleID set for user") + } + + // select for update + err := userQuery.For("UPDATE").Select() + if !db.AssertFoundOne(err) { + // find by email instead + err = tx.Model(user).Where("lower(email) = lower(?)", email).For("UPDATE").Select() + if !db.AssertFoundOne(err) { + found = false + } + } + + // if user found, select personal org for update + if found { + err = tx.Model(org).Where("user_id = ?", user.UserID).For("UPDATE").Select() + if err != nil { + return false, nil, nil, fmt.Errorf("Couldn't find personal organization for user: %s", err.Error()) + } + } + + // done + return found, user, org, nil +} + +func (s *Service) createWithUsernameSeeds(ctx context.Context, user *models.User, org *models.Organization, usernameSeeds []string) error { + tx := s.DB.GetDB(ctx) // must be run in a tx + created := false + for _, username := range usernameSeeds { + // update org and user + org.Name = username + + // validate org + err := org.Validate() + if err != nil { + // continue (probably username is blacklisted) + continue + } + + // savepoint in case name is taken + _, err = tx.Exec("SAVEPOINT bi") + if err != nil { + return err + } + + // insert org + err = tx.Insert(org) + if err == nil { + // insert user (with org as billing) + user.BillingOrganizationID = org.OrganizationID + err = tx.Insert(user) + if err != nil { + return err + } + + // update org with user ID + org.UserID = &user.UserID + _, err = tx.Model(org).Column("user_id").WherePK().Update() + if err != nil { + return err + } + + // success + created = true + break + } + + // failure, err != nil + + // rollback on name error + if isUniqueError(err) { + // rollback to before error, then try next username + _, err = tx.Exec("ROLLBACK TO SAVEPOINT bi") + if err != nil { + return err + } + continue + } + + // unexpected error + return err + } + + // if not created, error + if !created { + return fmt.Errorf("couldn't create user for any username seeds") + } + + return nil +} + +func isUniqueError(err error) bool { + if err == nil { + return false + } + return strings.Contains(strings.ToLower(err.Error()), "violates unique constraint") +} diff --git a/services/user/update.go b/services/user/update.go new file mode 100644 index 00000000..dc680ef8 --- /dev/null +++ b/services/user/update.go @@ -0,0 +1,76 @@ +package user + +import ( + "context" + "fmt" + "time" + + "gitlab.com/beneath-hq/beneath/models" +) + +// UpdateConsent updates the user's consent preferences +func (s *Service) UpdateConsent(ctx context.Context, u *models.User, terms *bool, newsletter *bool) error { + if !u.ConsentTerms && (terms == nil || !*terms) { + return fmt.Errorf("Cannot continue without consent to the terms of service") + } + + if terms != nil { + if !*terms { + return fmt.Errorf("You cannot withdraw consent to the terms of service; instead, delete your user") + } + u.ConsentTerms = *terms + } + + if newsletter != nil { + u.ConsentNewsletter = *newsletter + } + + // validate and save + u.UpdatedOn = time.Now() + err := u.Validate() + if err != nil { + return err + } + + _, err = s.DB.GetDB(ctx).ModelContext(ctx, u). + Column("consent_terms", "consent_newsletter", "updated_on"). + WherePK(). + Update() + if err != nil { + return err + } + + return nil +} + +// UpdateQuotas change the user's quotas +func (s *Service) UpdateQuotas(ctx context.Context, u *models.User, readQuota *int64, writeQuota *int64, scanQuota *int64) error { + // set fields + u.ReadQuota = readQuota + u.WriteQuota = writeQuota + u.ScanQuota = scanQuota + + // validate and save + u.UpdatedOn = time.Now() + err := u.Validate() + if err != nil { + return err + } + _, err = s.DB.GetDB(ctx).ModelContext(ctx, u). + Column("read_quota", "write_quota", "scan_quota", "updated_on"). + WherePK(). + Update() + if err != nil { + return err + } + + // publish event + err = s.Bus.Publish(ctx, models.UserUpdatedEvent{ + User: u, + }) + if err != nil { + return err + } + + return nil +} diff --git a/services/user/user.go b/services/user/user.go new file mode 100644 index 00000000..5e4b12e0 --- /dev/null +++ b/services/user/user.go @@ -0,0 +1,37 @@ +package user + +import ( + "context" + + uuid "github.com/satori/go.uuid" + + "gitlab.com/beneath-hq/beneath/bus" + "gitlab.com/beneath-hq/beneath/models" + "gitlab.com/beneath-hq/beneath/infrastructure/db" +) + +// Service contains functionality for finding and creating users +type Service struct { + Bus *bus.Bus + DB db.DB +} + +// New creates a new user service +func New(bus *bus.Bus, db db.DB) *Service { + return &Service{ + Bus: bus, + DB: db, + } +} + +// FindUser returns the matching user or nil +func (s *Service) FindUser(ctx context.Context, userID uuid.UUID) *models.User { + user := &models.User{ + UserID: userID, + } + err := s.DB.GetDB(ctx).ModelContext(ctx, user).WherePK().Column("user.*").Select() + if !db.AssertFoundOne(err) { + return nil + } + return user +} diff --git a/services/user/username_seeds.go b/services/user/username_seeds.go new file mode 100644 index 00000000..1d618c21 --- /dev/null +++ b/services/user/username_seeds.go @@ -0,0 +1,71 @@ +package user + +import ( + "regexp" + "strings" + "unicode" + + uuid "github.com/satori/go.uuid" +) + +const ( + usernameMinLength = 3 + usernameMaxLength = 50 +) + +var nonAlphanumericRegex = regexp.MustCompile("[^a-zA-Z0-9]+") + +func usernameSeeds(email string, name string, nickname string) []string { + // gather candidates + var seeds []string + var shortest string + + // base on nickname + username := nonAlphanumericRegex.ReplaceAllString(nickname, "") + if len(username) >= usernameMinLength { + seeds = append(seeds, finalizeUsernameSeed(username)) + shortest = username + } + if len(username) < len(shortest) { + shortest = username + } + + // base on email + username = strings.Split(email, "@")[0] + username = nonAlphanumericRegex.ReplaceAllString(username, "") + if len(username) >= usernameMinLength { + seeds = append(seeds, finalizeUsernameSeed(username)) + } + if len(username) < len(shortest) { + shortest = username + } + + // base on name + username = nonAlphanumericRegex.ReplaceAllString(name, "") + if len(username) >= usernameMinLength { + seeds = append(seeds, finalizeUsernameSeed(username)) + } + if len(username) < len(shortest) { + shortest = username + } + + // final fallback -- a uuid + username = shortest + uuid.NewV4().String()[0:8] + seeds = append(seeds, finalizeUsernameSeed(username)) + + return seeds +} + +func finalizeUsernameSeed(seed string) string { + seed = strings.ToLower(seed) + if len(seed) == (usernameMinLength-1) && seed[0] != '_' { + seed = "_" + seed + } + if unicode.IsDigit(rune(seed[0])) { + seed = "b" + seed + } + if len(seed) > usernameMaxLength { + seed = seed[0:usernameMaxLength] + } + return seed +} diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index 23153e5f..b0b63480 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -21,13 +21,13 @@ import ( "gitlab.com/beneath-hq/beneath/control/auth" "gitlab.com/beneath-hq/beneath/control/entity" "gitlab.com/beneath-hq/beneath/control/migrations" - "gitlab.com/beneath-hq/beneath/control/payments" + "gitlab.com/beneath-hq/beneath/ee/infrastructure/payments" "gitlab.com/beneath-hq/beneath/control/taskqueue/worker" - "gitlab.com/beneath-hq/beneath/gateway" - gwgrpc "gitlab.com/beneath-hq/beneath/gateway/grpc" - pb "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" - gwhttp "gitlab.com/beneath-hq/beneath/gateway/http" - "gitlab.com/beneath-hq/beneath/gateway/pipeline" + "gitlab.com/beneath-hq/beneath/server/data" + gwgrpc "gitlab.com/beneath-hq/beneath/server/data/grpc" + pb "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" + gwhttp "gitlab.com/beneath-hq/beneath/server/data/http" + "gitlab.com/beneath-hq/beneath/server/data/pipeline" "gitlab.com/beneath-hq/beneath/hub" "gitlab.com/beneath-hq/beneath/pkg/envutil" "gitlab.com/beneath-hq/beneath/pkg/log" diff --git a/test/integration/stream_create_read_write_test.go b/test/integration/stream_create_read_write_test.go index 34d7c128..c62aef21 100644 --- a/test/integration/stream_create_read_write_test.go +++ b/test/integration/stream_create_read_write_test.go @@ -18,7 +18,7 @@ import ( uuid "github.com/satori/go.uuid" assert "github.com/stretchr/testify/require" - pb "gitlab.com/beneath-hq/beneath/gateway/grpc/proto" + pb "gitlab.com/beneath-hq/beneath/server/data/grpc/proto" "gitlab.com/beneath-hq/beneath/pkg/timeutil" )