From 265331801feefd59b703923f0b905dbfd6b2d60b Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Mon, 4 Jul 2022 22:37:13 +0530 Subject: [PATCH 01/14] feat: add database models --- server/db/models/webhook.go | 14 ++++++++++++++ server/db/models/webhook_log.go | 15 +++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 server/db/models/webhook.go create mode 100644 server/db/models/webhook_log.go diff --git a/server/db/models/webhook.go b/server/db/models/webhook.go new file mode 100644 index 0000000..17d01a7 --- /dev/null +++ b/server/db/models/webhook.go @@ -0,0 +1,14 @@ +package models + +// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation + +// Webhook model for db +type Webhook struct { + Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb + ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"` + EventName string `gorm:"unique" json:"event_name" bson:"event_name" cql:"event_name"` + EndPoint string `json:"endpoint" bson:"endpoint" cql:"endpoint"` + Enabled bool `json:"enabled" bson:"enabled" cql:"enabled"` + CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"` + UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"` +} diff --git a/server/db/models/webhook_log.go b/server/db/models/webhook_log.go new file mode 100644 index 0000000..daa6fd8 --- /dev/null +++ b/server/db/models/webhook_log.go @@ -0,0 +1,15 @@ +package models + +// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation + +// WebhookLog model for db +type WebhookLog struct { + Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb + ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"` + HttpStatus int32 `json:"http_status" bson:"http_status" cql:"http_status"` + Response string `json:"response" bson:"response" cql:"response"` + Request string `json:"request" bson:"request" cql:"request"` + WebhookID string `gorm:"type:char(36),index:" json:"webhook_id" bson:"webhook_id" cql:"webhook_id"` + CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"` + UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"` +} From a8064e79a1ad97b04d2df4ce32b1bc13085d443e Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Wed, 6 Jul 2022 10:38:21 +0530 Subject: [PATCH 02/14] feat: add template for webhook db methods --- server/db/providers/arangodb/webhook.go | 36 + server/db/providers/arangodb/webhook_log.go | 16 + server/db/providers/cassandradb/webhook.go | 36 + .../db/providers/cassandradb/webhook_log.go | 16 + server/db/providers/mongodb/webhook.go | 36 + server/db/providers/mongodb/webhook_log.go | 16 + .../db/providers/provider_template/webhook.go | 36 + .../provider_template/webhook_log.go | 16 + server/db/providers/providers.go | 18 + server/db/providers/sql/webhook.go | 36 + server/db/providers/sql/webhook_log.go | 16 + server/graph/generated/generated.go | 1267 +++++++++++++++++ server/graph/model/models_gen.go | 34 + server/graph/schema.graphqls | 37 + server/graph/schema.resolvers.go | 9 + 15 files changed, 1625 insertions(+) create mode 100644 server/db/providers/arangodb/webhook.go create mode 100644 server/db/providers/arangodb/webhook_log.go create mode 100644 server/db/providers/cassandradb/webhook.go create mode 100644 server/db/providers/cassandradb/webhook_log.go create mode 100644 server/db/providers/mongodb/webhook.go create mode 100644 server/db/providers/mongodb/webhook_log.go create mode 100644 server/db/providers/provider_template/webhook.go create mode 100644 server/db/providers/provider_template/webhook_log.go create mode 100644 server/db/providers/sql/webhook.go create mode 100644 server/db/providers/sql/webhook_log.go diff --git a/server/db/providers/arangodb/webhook.go b/server/db/providers/arangodb/webhook.go new file mode 100644 index 0000000..3dd7c9e --- /dev/null +++ b/server/db/providers/arangodb/webhook.go @@ -0,0 +1,36 @@ +package arangodb + +import ( + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" +) + +// AddWebhook to add webhook +func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { + return webhook, nil +} + +// UpdateWebhook to update webhook +func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { + return webhook, nil +} + +// ListWebhooks to list webhook +func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { + return nil, nil +} + +// GetWebhookByID to get webhook by id +func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { + return models.Webhook{}, nil +} + +// GetWebhookByEvent to get webhook by event_name +func (p *provider) GetWebhookByEvent(eventName string) (models.Webhook, error) { + return models.Webhook{}, nil +} + +// DeleteWebhook to delete webhook +func (p *provider) DeleteWebhook(webhookID string) error { + return nil +} diff --git a/server/db/providers/arangodb/webhook_log.go b/server/db/providers/arangodb/webhook_log.go new file mode 100644 index 0000000..aa41366 --- /dev/null +++ b/server/db/providers/arangodb/webhook_log.go @@ -0,0 +1,16 @@ +package arangodb + +import ( + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" +) + +// AddWebhookLog to add webhook log +func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { + return webhookLog, nil +} + +// ListWebhookLogs to list webhook logs +func (p *provider) ListWebhookLogs(req model.ListWebhookLogRequest) (*model.WebhookLogs, error) { + return nil, nil +} diff --git a/server/db/providers/cassandradb/webhook.go b/server/db/providers/cassandradb/webhook.go new file mode 100644 index 0000000..79ea9a7 --- /dev/null +++ b/server/db/providers/cassandradb/webhook.go @@ -0,0 +1,36 @@ +package cassandradb + +import ( + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" +) + +// AddWebhook to add webhook +func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { + return webhook, nil +} + +// UpdateWebhook to update webhook +func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { + return webhook, nil +} + +// ListWebhooks to list webhook +func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { + return nil, nil +} + +// GetWebhookByID to get webhook by id +func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { + return models.Webhook{}, nil +} + +// GetWebhookByEvent to get webhook by event_name +func (p *provider) GetWebhookByEvent(eventName string) (models.Webhook, error) { + return models.Webhook{}, nil +} + +// DeleteWebhook to delete webhook +func (p *provider) DeleteWebhook(webhookID string) error { + return nil +} diff --git a/server/db/providers/cassandradb/webhook_log.go b/server/db/providers/cassandradb/webhook_log.go new file mode 100644 index 0000000..4ea41e2 --- /dev/null +++ b/server/db/providers/cassandradb/webhook_log.go @@ -0,0 +1,16 @@ +package cassandradb + +import ( + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" +) + +// AddWebhookLog to add webhook log +func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { + return webhookLog, nil +} + +// ListWebhookLogs to list webhook logs +func (p *provider) ListWebhookLogs(req model.ListWebhookLogRequest) (*model.WebhookLogs, error) { + return nil, nil +} diff --git a/server/db/providers/mongodb/webhook.go b/server/db/providers/mongodb/webhook.go new file mode 100644 index 0000000..5669a12 --- /dev/null +++ b/server/db/providers/mongodb/webhook.go @@ -0,0 +1,36 @@ +package mongodb + +import ( + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" +) + +// AddWebhook to add webhook +func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { + return webhook, nil +} + +// UpdateWebhook to update webhook +func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { + return webhook, nil +} + +// ListWebhooks to list webhook +func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { + return nil, nil +} + +// GetWebhookByID to get webhook by id +func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { + return models.Webhook{}, nil +} + +// GetWebhookByEvent to get webhook by event_name +func (p *provider) GetWebhookByEvent(eventName string) (models.Webhook, error) { + return models.Webhook{}, nil +} + +// DeleteWebhook to delete webhook +func (p *provider) DeleteWebhook(webhookID string) error { + return nil +} diff --git a/server/db/providers/mongodb/webhook_log.go b/server/db/providers/mongodb/webhook_log.go new file mode 100644 index 0000000..c497a4c --- /dev/null +++ b/server/db/providers/mongodb/webhook_log.go @@ -0,0 +1,16 @@ +package mongodb + +import ( + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" +) + +// AddWebhookLog to add webhook log +func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { + return webhookLog, nil +} + +// ListWebhookLogs to list webhook logs +func (p *provider) ListWebhookLogs(req model.ListWebhookLogRequest) (*model.WebhookLogs, error) { + return nil, nil +} diff --git a/server/db/providers/provider_template/webhook.go b/server/db/providers/provider_template/webhook.go new file mode 100644 index 0000000..1717ca6 --- /dev/null +++ b/server/db/providers/provider_template/webhook.go @@ -0,0 +1,36 @@ +package provider_template + +import ( + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" +) + +// AddWebhook to add webhook +func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { + return webhook, nil +} + +// UpdateWebhook to update webhook +func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { + return webhook, nil +} + +// ListWebhooks to list webhook +func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { + return nil, nil +} + +// GetWebhookByID to get webhook by id +func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { + return models.Webhook{}, nil +} + +// GetWebhookByEvent to get webhook by event_name +func (p *provider) GetWebhookByEvent(eventName string) (models.Webhook, error) { + return models.Webhook{}, nil +} + +// DeleteWebhook to delete webhook +func (p *provider) DeleteWebhook(webhookID string) error { + return nil +} diff --git a/server/db/providers/provider_template/webhook_log.go b/server/db/providers/provider_template/webhook_log.go new file mode 100644 index 0000000..860a8c0 --- /dev/null +++ b/server/db/providers/provider_template/webhook_log.go @@ -0,0 +1,16 @@ +package provider_template + +import ( + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" +) + +// AddWebhookLog to add webhook log +func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { + return webhookLog, nil +} + +// ListWebhookLogs to list webhook logs +func (p *provider) ListWebhookLogs(req model.ListWebhookLogRequest) (*model.WebhookLogs, error) { + return nil, nil +} diff --git a/server/db/providers/providers.go b/server/db/providers/providers.go index aa69c66..cb7caea 100644 --- a/server/db/providers/providers.go +++ b/server/db/providers/providers.go @@ -41,4 +41,22 @@ type Provider interface { UpdateEnv(env models.Env) (models.Env, error) // GetEnv to get environment information from database GetEnv() (models.Env, error) + + // AddWebhook to add webhook + AddWebhook(webhook models.Webhook) (models.Webhook, error) + // UpdateWebhook to update webhook + UpdateWebhook(webhook models.Webhook) (models.Webhook, error) + // ListWebhooks to list webhook + ListWebhook(pagination model.Pagination) (*model.Webhooks, error) + // GetWebhookByID to get webhook by id + GetWebhookByID(webhookID string) (models.Webhook, error) + // GetWebhookByEvent to get webhook by event_name + GetWebhookByEvent(eventName string) (models.Webhook, error) + // DeleteWebhook to delete webhook + DeleteWebhook(webhookID string) error + + // AddWebhookLog to add webhook log + AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) + // ListWebhookLogs to list webhook logs + ListWebhookLogs(req model.ListWebhookLogRequest) (*model.WebhookLogs, error) } diff --git a/server/db/providers/sql/webhook.go b/server/db/providers/sql/webhook.go new file mode 100644 index 0000000..58abee6 --- /dev/null +++ b/server/db/providers/sql/webhook.go @@ -0,0 +1,36 @@ +package sql + +import ( + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" +) + +// AddWebhook to add webhook +func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { + return webhook, nil +} + +// UpdateWebhook to update webhook +func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { + return webhook, nil +} + +// ListWebhooks to list webhook +func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { + return nil, nil +} + +// GetWebhookByID to get webhook by id +func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { + return models.Webhook{}, nil +} + +// GetWebhookByEvent to get webhook by event_name +func (p *provider) GetWebhookByEvent(eventName string) (models.Webhook, error) { + return models.Webhook{}, nil +} + +// DeleteWebhook to delete webhook +func (p *provider) DeleteWebhook(webhookID string) error { + return nil +} diff --git a/server/db/providers/sql/webhook_log.go b/server/db/providers/sql/webhook_log.go new file mode 100644 index 0000000..6f19e2a --- /dev/null +++ b/server/db/providers/sql/webhook_log.go @@ -0,0 +1,16 @@ +package sql + +import ( + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" +) + +// AddWebhookLog to add webhook log +func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { + return webhookLog, nil +} + +// ListWebhookLogs to list webhook logs +func (p *provider) ListWebhookLogs(req model.ListWebhookLogRequest) (*model.WebhookLogs, error) { + return nil, nil +} diff --git a/server/graph/generated/generated.go b/server/graph/generated/generated.go index 13421fd..da9aaa0 100644 --- a/server/graph/generated/generated.go +++ b/server/graph/generated/generated.go @@ -168,6 +168,8 @@ type ComplexityRoot struct { Users func(childComplexity int, params *model.PaginatedInput) int ValidateJwtToken func(childComplexity int, params model.ValidateJWTTokenInput) int VerificationRequests func(childComplexity int, params *model.PaginatedInput) int + WebhookLogs func(childComplexity int, params *model.ListWebhookLogRequest) int + Webhooks func(childComplexity int, params *model.PaginatedInput) int } Response struct { @@ -220,6 +222,35 @@ type ComplexityRoot struct { Pagination func(childComplexity int) int VerificationRequests func(childComplexity int) int } + + Webhook struct { + CreatedAt func(childComplexity int) int + Enabled func(childComplexity int) int + Endpoint func(childComplexity int) int + EventName func(childComplexity int) int + ID func(childComplexity int) int + UpdatedAt func(childComplexity int) int + } + + WebhookLog struct { + CreatedAt func(childComplexity int) int + HTTPStatus func(childComplexity int) int + ID func(childComplexity int) int + Request func(childComplexity int) int + Response func(childComplexity int) int + UpdatedAt func(childComplexity int) int + WebhookID func(childComplexity int) int + } + + WebhookLogs struct { + Pagination func(childComplexity int) int + WebhookLogs func(childComplexity int) int + } + + Webhooks struct { + Pagination func(childComplexity int) int + Webhooks func(childComplexity int) int + } } type MutationResolver interface { @@ -253,6 +284,8 @@ type QueryResolver interface { VerificationRequests(ctx context.Context, params *model.PaginatedInput) (*model.VerificationRequests, error) AdminSession(ctx context.Context) (*model.Response, error) Env(ctx context.Context) (*model.Env, error) + Webhooks(ctx context.Context, params *model.PaginatedInput) (*model.Webhooks, error) + WebhookLogs(ctx context.Context, params *model.ListWebhookLogRequest) (*model.WebhookLogs, error) } type executableSchema struct { @@ -1101,6 +1134,30 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.VerificationRequests(childComplexity, args["params"].(*model.PaginatedInput)), true + case "Query._webhook_logs": + if e.complexity.Query.WebhookLogs == nil { + break + } + + args, err := ec.field_Query__webhook_logs_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.WebhookLogs(childComplexity, args["params"].(*model.ListWebhookLogRequest)), true + + case "Query._webhooks": + if e.complexity.Query.Webhooks == nil { + break + } + + args, err := ec.field_Query__webhooks_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Webhooks(childComplexity, args["params"].(*model.PaginatedInput)), true + case "Response.message": if e.complexity.Response.Message == nil { break @@ -1332,6 +1389,125 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.VerificationRequests.VerificationRequests(childComplexity), true + case "Webhook.created_at": + if e.complexity.Webhook.CreatedAt == nil { + break + } + + return e.complexity.Webhook.CreatedAt(childComplexity), true + + case "Webhook.enabled": + if e.complexity.Webhook.Enabled == nil { + break + } + + return e.complexity.Webhook.Enabled(childComplexity), true + + case "Webhook.endpoint": + if e.complexity.Webhook.Endpoint == nil { + break + } + + return e.complexity.Webhook.Endpoint(childComplexity), true + + case "Webhook.event_name": + if e.complexity.Webhook.EventName == nil { + break + } + + return e.complexity.Webhook.EventName(childComplexity), true + + case "Webhook.id": + if e.complexity.Webhook.ID == nil { + break + } + + return e.complexity.Webhook.ID(childComplexity), true + + case "Webhook.updated_at": + if e.complexity.Webhook.UpdatedAt == nil { + break + } + + return e.complexity.Webhook.UpdatedAt(childComplexity), true + + case "WebhookLog.created_at": + if e.complexity.WebhookLog.CreatedAt == nil { + break + } + + return e.complexity.WebhookLog.CreatedAt(childComplexity), true + + case "WebhookLog.http_status": + if e.complexity.WebhookLog.HTTPStatus == nil { + break + } + + return e.complexity.WebhookLog.HTTPStatus(childComplexity), true + + case "WebhookLog.id": + if e.complexity.WebhookLog.ID == nil { + break + } + + return e.complexity.WebhookLog.ID(childComplexity), true + + case "WebhookLog.request": + if e.complexity.WebhookLog.Request == nil { + break + } + + return e.complexity.WebhookLog.Request(childComplexity), true + + case "WebhookLog.response": + if e.complexity.WebhookLog.Response == nil { + break + } + + return e.complexity.WebhookLog.Response(childComplexity), true + + case "WebhookLog.updated_at": + if e.complexity.WebhookLog.UpdatedAt == nil { + break + } + + return e.complexity.WebhookLog.UpdatedAt(childComplexity), true + + case "WebhookLog.webhook_id": + if e.complexity.WebhookLog.WebhookID == nil { + break + } + + return e.complexity.WebhookLog.WebhookID(childComplexity), true + + case "WebhookLogs.pagination": + if e.complexity.WebhookLogs.Pagination == nil { + break + } + + return e.complexity.WebhookLogs.Pagination(childComplexity), true + + case "WebhookLogs.webhook_logs": + if e.complexity.WebhookLogs.WebhookLogs == nil { + break + } + + return e.complexity.WebhookLogs.WebhookLogs(childComplexity), true + + case "Webhooks.pagination": + if e.complexity.Webhooks.Pagination == nil { + break + } + + return e.complexity.Webhooks.Pagination(childComplexity), true + + case "Webhooks.webhooks": + if e.complexity.Webhooks.Webhooks == nil { + break + } + + return e.complexity.Webhooks.Webhooks(childComplexity), true + } return 0, false } @@ -1400,6 +1576,7 @@ var sources = []*ast.Source{ # # https://gqlgen.com/getting-started/ scalar Int64 +scalar Int32 scalar Map scalar Any @@ -1722,6 +1899,40 @@ input GenerateJWTKeysInput { type: String! } +type Webhook { + id: ID! + event_name: String + endpoint: String + enabled: Boolean + created_at: Int64 + updated_at: Int64 +} + +type Webhooks { + pagination: Pagination! + webhooks: [Webhook!]! +} + +type WebhookLog { + id: ID! + http_status: Int32 + response: String + request: String + webhook_id: ID + created_at: Int64 + updated_at: Int64 +} + +input ListWebhookLogRequest { + pagination: PaginatedInput! + webhook_id: String +} + +type WebhookLogs { + pagination: Pagination! + webhook_logs: [WebhookLog!]! +} + type Mutation { signup(params: SignUpInput!): AuthResponse! login(params: LoginInput!): AuthResponse! @@ -1756,6 +1967,8 @@ type Query { _verification_requests(params: PaginatedInput): VerificationRequests! _admin_session: Response! _env: Env! + _webhooks(params: PaginatedInput): Webhooks! + _webhook_logs(params: ListWebhookLogRequest): WebhookLogs! } `, BuiltIn: false}, } @@ -2080,6 +2293,36 @@ func (ec *executionContext) field_Query__verification_requests_args(ctx context. return args, nil } +func (ec *executionContext) field_Query__webhook_logs_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *model.ListWebhookLogRequest + if tmp, ok := rawArgs["params"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params")) + arg0, err = ec.unmarshalOListWebhookLogRequest2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐListWebhookLogRequest(ctx, tmp) + if err != nil { + return nil, err + } + } + args["params"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query__webhooks_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *model.PaginatedInput + if tmp, ok := rawArgs["params"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params")) + arg0, err = ec.unmarshalOPaginatedInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginatedInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["params"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_session_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -5766,6 +6009,90 @@ func (ec *executionContext) _Query__env(ctx context.Context, field graphql.Colle return ec.marshalNEnv2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐEnv(ctx, field.Selections, res) } +func (ec *executionContext) _Query__webhooks(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query__webhooks_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Webhooks(rctx, args["params"].(*model.PaginatedInput)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Webhooks) + fc.Result = res + return ec.marshalNWebhooks2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhooks(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query__webhook_logs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query__webhook_logs_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().WebhookLogs(rctx, args["params"].(*model.ListWebhookLogRequest)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.WebhookLogs) + fc.Result = res + return ec.marshalNWebhookLogs2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookLogs(ctx, field.Selections, res) +} + func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -6929,6 +7256,568 @@ func (ec *executionContext) _VerificationRequests_verification_requests(ctx cont return ec.marshalNVerificationRequest2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐVerificationRequestᚄ(ctx, field.Selections, res) } +func (ec *executionContext) _Webhook_id(ctx context.Context, field graphql.CollectedField, obj *model.Webhook) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Webhook", + 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.ID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + +func (ec *executionContext) _Webhook_event_name(ctx context.Context, field graphql.CollectedField, obj *model.Webhook) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Webhook", + 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.EventName, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _Webhook_endpoint(ctx context.Context, field graphql.CollectedField, obj *model.Webhook) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Webhook", + 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.Endpoint, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _Webhook_enabled(ctx context.Context, field graphql.CollectedField, obj *model.Webhook) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Webhook", + 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.Enabled, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*bool) + fc.Result = res + return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res) +} + +func (ec *executionContext) _Webhook_created_at(ctx context.Context, field graphql.CollectedField, obj *model.Webhook) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Webhook", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.CreatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*int64) + fc.Result = res + return ec.marshalOInt642ᚖint64(ctx, field.Selections, res) +} + +func (ec *executionContext) _Webhook_updated_at(ctx context.Context, field graphql.CollectedField, obj *model.Webhook) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Webhook", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UpdatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*int64) + fc.Result = res + return ec.marshalOInt642ᚖint64(ctx, field.Selections, res) +} + +func (ec *executionContext) _WebhookLog_id(ctx context.Context, field graphql.CollectedField, obj *model.WebhookLog) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "WebhookLog", + 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.ID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + +func (ec *executionContext) _WebhookLog_http_status(ctx context.Context, field graphql.CollectedField, obj *model.WebhookLog) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "WebhookLog", + 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.HTTPStatus, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOInt322ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _WebhookLog_response(ctx context.Context, field graphql.CollectedField, obj *model.WebhookLog) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "WebhookLog", + 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.Response, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _WebhookLog_request(ctx context.Context, field graphql.CollectedField, obj *model.WebhookLog) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "WebhookLog", + 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.Request, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _WebhookLog_webhook_id(ctx context.Context, field graphql.CollectedField, obj *model.WebhookLog) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "WebhookLog", + 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.WebhookID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOID2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _WebhookLog_created_at(ctx context.Context, field graphql.CollectedField, obj *model.WebhookLog) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "WebhookLog", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.CreatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*int64) + fc.Result = res + return ec.marshalOInt642ᚖint64(ctx, field.Selections, res) +} + +func (ec *executionContext) _WebhookLog_updated_at(ctx context.Context, field graphql.CollectedField, obj *model.WebhookLog) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "WebhookLog", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.UpdatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*int64) + fc.Result = res + return ec.marshalOInt642ᚖint64(ctx, field.Selections, res) +} + +func (ec *executionContext) _WebhookLogs_pagination(ctx context.Context, field graphql.CollectedField, obj *model.WebhookLogs) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "WebhookLogs", + 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.Pagination, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Pagination) + fc.Result = res + return ec.marshalNPagination2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPagination(ctx, field.Selections, res) +} + +func (ec *executionContext) _WebhookLogs_webhook_logs(ctx context.Context, field graphql.CollectedField, obj *model.WebhookLogs) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "WebhookLogs", + 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.WebhookLogs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.WebhookLog) + fc.Result = res + return ec.marshalNWebhookLog2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookLogᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) _Webhooks_pagination(ctx context.Context, field graphql.CollectedField, obj *model.Webhooks) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Webhooks", + 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.Pagination, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Pagination) + fc.Result = res + return ec.marshalNPagination2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPagination(ctx, field.Selections, res) +} + +func (ec *executionContext) _Webhooks_webhooks(ctx context.Context, field graphql.CollectedField, obj *model.Webhooks) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Webhooks", + 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.Webhooks, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.Webhook) + fc.Result = res + return ec.marshalNWebhook2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookᚄ(ctx, field.Selections, res) +} + func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -8213,6 +9102,37 @@ func (ec *executionContext) unmarshalInputInviteMemberInput(ctx context.Context, return it, nil } +func (ec *executionContext) unmarshalInputListWebhookLogRequest(ctx context.Context, obj interface{}) (model.ListWebhookLogRequest, error) { + var it model.ListWebhookLogRequest + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "pagination": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("pagination")) + it.Pagination, err = ec.unmarshalNPaginatedInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginatedInput(ctx, v) + if err != nil { + return it, err + } + case "webhook_id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("webhook_id")) + it.WebhookID, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputLoginInput(ctx context.Context, obj interface{}) (model.LoginInput, error) { var it model.LoginInput asMap := map[string]interface{}{} @@ -9881,6 +10801,34 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } return res }) + case "_webhooks": + 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__webhooks(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "_webhook_logs": + 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__webhook_logs(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "__type": out.Values[i] = ec._Query___type(ctx, field) case "__schema": @@ -10130,6 +11078,146 @@ func (ec *executionContext) _VerificationRequests(ctx context.Context, sel ast.S return out } +var webhookImplementors = []string{"Webhook"} + +func (ec *executionContext) _Webhook(ctx context.Context, sel ast.SelectionSet, obj *model.Webhook) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, webhookImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Webhook") + case "id": + out.Values[i] = ec._Webhook_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "event_name": + out.Values[i] = ec._Webhook_event_name(ctx, field, obj) + case "endpoint": + out.Values[i] = ec._Webhook_endpoint(ctx, field, obj) + case "enabled": + out.Values[i] = ec._Webhook_enabled(ctx, field, obj) + case "created_at": + out.Values[i] = ec._Webhook_created_at(ctx, field, obj) + case "updated_at": + out.Values[i] = ec._Webhook_updated_at(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var webhookLogImplementors = []string{"WebhookLog"} + +func (ec *executionContext) _WebhookLog(ctx context.Context, sel ast.SelectionSet, obj *model.WebhookLog) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, webhookLogImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("WebhookLog") + case "id": + out.Values[i] = ec._WebhookLog_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "http_status": + out.Values[i] = ec._WebhookLog_http_status(ctx, field, obj) + case "response": + out.Values[i] = ec._WebhookLog_response(ctx, field, obj) + case "request": + out.Values[i] = ec._WebhookLog_request(ctx, field, obj) + case "webhook_id": + out.Values[i] = ec._WebhookLog_webhook_id(ctx, field, obj) + case "created_at": + out.Values[i] = ec._WebhookLog_created_at(ctx, field, obj) + case "updated_at": + out.Values[i] = ec._WebhookLog_updated_at(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var webhookLogsImplementors = []string{"WebhookLogs"} + +func (ec *executionContext) _WebhookLogs(ctx context.Context, sel ast.SelectionSet, obj *model.WebhookLogs) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, webhookLogsImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("WebhookLogs") + case "pagination": + out.Values[i] = ec._WebhookLogs_pagination(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "webhook_logs": + out.Values[i] = ec._WebhookLogs_webhook_logs(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var webhooksImplementors = []string{"Webhooks"} + +func (ec *executionContext) _Webhooks(ctx context.Context, sel ast.SelectionSet, obj *model.Webhooks) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, webhooksImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Webhooks") + case "pagination": + out.Values[i] = ec._Webhooks_pagination(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "webhooks": + out.Values[i] = ec._Webhooks_webhooks(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { @@ -10526,6 +11614,11 @@ func (ec *executionContext) unmarshalNOAuthRevokeInput2githubᚗcomᚋauthorizer return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalNPaginatedInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginatedInput(ctx context.Context, v interface{}) (*model.PaginatedInput, error) { + res, err := ec.unmarshalInputPaginatedInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalNPagination2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPagination(ctx context.Context, sel ast.SelectionSet, v *model.Pagination) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -10800,6 +11893,142 @@ func (ec *executionContext) unmarshalNVerifyEmailInput2githubᚗcomᚋauthorizer return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalNWebhook2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Webhook) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNWebhook2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhook(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNWebhook2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhook(ctx context.Context, sel ast.SelectionSet, v *model.Webhook) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._Webhook(ctx, sel, v) +} + +func (ec *executionContext) marshalNWebhookLog2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookLogᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.WebhookLog) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNWebhookLog2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookLog(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNWebhookLog2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookLog(ctx context.Context, sel ast.SelectionSet, v *model.WebhookLog) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._WebhookLog(ctx, sel, v) +} + +func (ec *executionContext) marshalNWebhookLogs2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookLogs(ctx context.Context, sel ast.SelectionSet, v model.WebhookLogs) graphql.Marshaler { + return ec._WebhookLogs(ctx, sel, &v) +} + +func (ec *executionContext) marshalNWebhookLogs2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookLogs(ctx context.Context, sel ast.SelectionSet, v *model.WebhookLogs) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._WebhookLogs(ctx, sel, v) +} + +func (ec *executionContext) marshalNWebhooks2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhooks(ctx context.Context, sel ast.SelectionSet, v model.Webhooks) graphql.Marshaler { + return ec._Webhooks(ctx, sel, &v) +} + +func (ec *executionContext) marshalNWebhooks2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhooks(ctx context.Context, sel ast.SelectionSet, v *model.Webhooks) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._Webhooks(ctx, sel, v) +} + func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { return ec.___Directive(ctx, sel, &v) } @@ -11081,6 +12310,36 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast return graphql.MarshalBoolean(*v) } +func (ec *executionContext) unmarshalOID2ᚖstring(ctx context.Context, v interface{}) (*string, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalID(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOID2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return graphql.MarshalID(*v) +} + +func (ec *executionContext) unmarshalOInt322ᚖstring(ctx context.Context, v interface{}) (*string, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalString(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOInt322ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return graphql.MarshalString(*v) +} + func (ec *executionContext) unmarshalOInt642ᚖint64(ctx context.Context, v interface{}) (*int64, error) { if v == nil { return nil, nil @@ -11096,6 +12355,14 @@ func (ec *executionContext) marshalOInt642ᚖint64(ctx context.Context, sel ast. return graphql.MarshalInt64(*v) } +func (ec *executionContext) unmarshalOListWebhookLogRequest2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐListWebhookLogRequest(ctx context.Context, v interface{}) (*model.ListWebhookLogRequest, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputListWebhookLogRequest(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOPaginatedInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginatedInput(ctx context.Context, v interface{}) (*model.PaginatedInput, error) { if v == nil { return nil, nil diff --git a/server/graph/model/models_gen.go b/server/graph/model/models_gen.go index f4c390b..803ef5e 100644 --- a/server/graph/model/models_gen.go +++ b/server/graph/model/models_gen.go @@ -100,6 +100,11 @@ type InviteMemberInput struct { RedirectURI *string `json:"redirect_uri"` } +type ListWebhookLogRequest struct { + Pagination *PaginatedInput `json:"pagination"` + WebhookID *string `json:"webhook_id"` +} + type LoginInput struct { Email string `json:"email"` Password string `json:"password"` @@ -319,3 +324,32 @@ type VerificationRequests struct { type VerifyEmailInput struct { Token string `json:"token"` } + +type Webhook struct { + ID string `json:"id"` + EventName *string `json:"event_name"` + Endpoint *string `json:"endpoint"` + Enabled *bool `json:"enabled"` + CreatedAt *int64 `json:"created_at"` + UpdatedAt *int64 `json:"updated_at"` +} + +type WebhookLog struct { + ID string `json:"id"` + HTTPStatus *string `json:"http_status"` + Response *string `json:"response"` + Request *string `json:"request"` + WebhookID *string `json:"webhook_id"` + CreatedAt *int64 `json:"created_at"` + UpdatedAt *int64 `json:"updated_at"` +} + +type WebhookLogs struct { + Pagination *Pagination `json:"pagination"` + WebhookLogs []*WebhookLog `json:"webhook_logs"` +} + +type Webhooks struct { + Pagination *Pagination `json:"pagination"` + Webhooks []*Webhook `json:"webhooks"` +} diff --git a/server/graph/schema.graphqls b/server/graph/schema.graphqls index 5855b07..032c8e5 100644 --- a/server/graph/schema.graphqls +++ b/server/graph/schema.graphqls @@ -2,6 +2,7 @@ # # https://gqlgen.com/getting-started/ scalar Int64 +scalar Int32 scalar Map scalar Any @@ -324,6 +325,40 @@ input GenerateJWTKeysInput { type: String! } +type Webhook { + id: ID! + event_name: String + endpoint: String + enabled: Boolean + created_at: Int64 + updated_at: Int64 +} + +type Webhooks { + pagination: Pagination! + webhooks: [Webhook!]! +} + +type WebhookLog { + id: ID! + http_status: Int32 + response: String + request: String + webhook_id: ID + created_at: Int64 + updated_at: Int64 +} + +input ListWebhookLogRequest { + pagination: PaginatedInput! + webhook_id: String +} + +type WebhookLogs { + pagination: Pagination! + webhook_logs: [WebhookLog!]! +} + type Mutation { signup(params: SignUpInput!): AuthResponse! login(params: LoginInput!): AuthResponse! @@ -358,4 +393,6 @@ type Query { _verification_requests(params: PaginatedInput): VerificationRequests! _admin_session: Response! _env: Env! + _webhooks(params: PaginatedInput): Webhooks! + _webhook_logs(params: ListWebhookLogRequest): WebhookLogs! } diff --git a/server/graph/schema.resolvers.go b/server/graph/schema.resolvers.go index 51b2314..5e5cbe3 100644 --- a/server/graph/schema.resolvers.go +++ b/server/graph/schema.resolvers.go @@ -5,6 +5,7 @@ package graph import ( "context" + "fmt" "github.com/authorizerdev/authorizer/server/graph/generated" "github.com/authorizerdev/authorizer/server/graph/model" @@ -123,6 +124,14 @@ func (r *queryResolver) Env(ctx context.Context) (*model.Env, error) { return resolvers.EnvResolver(ctx) } +func (r *queryResolver) Webhooks(ctx context.Context, params *model.PaginatedInput) (*model.Webhooks, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *queryResolver) WebhookLogs(ctx context.Context, params *model.ListWebhookLogRequest) (*model.WebhookLogs, error) { + panic(fmt.Errorf("not implemented")) +} + // Mutation returns generated.MutationResolver implementation. func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} } From ec62686fbcf912c4b01488eb0feab43d34a37b3a Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Fri, 8 Jul 2022 19:09:23 +0530 Subject: [PATCH 03/14] feat: add database methods for webhookLog --- server/db/models/model.go | 4 ++ server/db/models/webhook_log.go | 18 +++++- server/db/providers/arangodb/provider.go | 27 ++++++++ server/db/providers/arangodb/webhook.go | 11 ++++ server/db/providers/arangodb/webhook_log.go | 62 ++++++++++++++++++- server/db/providers/cassandradb/provider.go | 22 +++++++ server/db/providers/cassandradb/webhook.go | 11 ++++ .../db/providers/cassandradb/webhook_log.go | 57 ++++++++++++++++- server/db/providers/mongodb/provider.go | 18 ++++++ server/db/providers/mongodb/webhook.go | 11 ++++ server/db/providers/mongodb/webhook_log.go | 60 +++++++++++++++++- .../db/providers/provider_template/webhook.go | 11 ++++ .../provider_template/webhook_log.go | 12 +++- server/db/providers/providers.go | 2 +- server/db/providers/sql/provider.go | 2 +- server/db/providers/sql/webhook.go | 11 ++++ server/db/providers/sql/webhook_log.go | 55 +++++++++++++++- server/graph/generated/generated.go | 22 +------ server/graph/model/models_gen.go | 2 +- server/graph/schema.graphqls | 3 +- 20 files changed, 387 insertions(+), 34 deletions(-) diff --git a/server/db/models/model.go b/server/db/models/model.go index c9eb0b8..4dbda36 100644 --- a/server/db/models/model.go +++ b/server/db/models/model.go @@ -6,6 +6,8 @@ type CollectionList struct { VerificationRequest string Session string Env string + Webhook string + WebhookLog string } var ( @@ -17,5 +19,7 @@ var ( VerificationRequest: Prefix + "verification_requests", Session: Prefix + "sessions", Env: Prefix + "env", + Webhook: Prefix + "webhook", + WebhookLog: Prefix + "webhook_log", } ) diff --git a/server/db/models/webhook_log.go b/server/db/models/webhook_log.go index daa6fd8..c5f80bd 100644 --- a/server/db/models/webhook_log.go +++ b/server/db/models/webhook_log.go @@ -1,15 +1,31 @@ package models +import "github.com/authorizerdev/authorizer/server/graph/model" + // Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation // WebhookLog model for db type WebhookLog struct { Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"` - HttpStatus int32 `json:"http_status" bson:"http_status" cql:"http_status"` + HttpStatus int64 `json:"http_status" bson:"http_status" cql:"http_status"` Response string `json:"response" bson:"response" cql:"response"` Request string `json:"request" bson:"request" cql:"request"` WebhookID string `gorm:"type:char(36),index:" json:"webhook_id" bson:"webhook_id" cql:"webhook_id"` CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"` UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"` } + +func (w *WebhookLog) AsAPIWebhookLog() *model.WebhookLog { + createdAt := w.CreatedAt + updatedAt := w.UpdatedAt + return &model.WebhookLog{ + ID: w.ID, + HTTPStatus: &w.HttpStatus, + Response: &w.Response, + Request: &w.Request, + WebhookID: &w.WebhookID, + CreatedAt: &createdAt, + UpdatedAt: &updatedAt, + } +} diff --git a/server/db/providers/arangodb/provider.go b/server/db/providers/arangodb/provider.go index a9a8432..6207acf 100644 --- a/server/db/providers/arangodb/provider.go +++ b/server/db/providers/arangodb/provider.go @@ -107,6 +107,33 @@ func NewProvider() (*provider, error) { } } + webhookCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Webhook) + if !webhookCollectionExists { + _, err = arangodb.CreateCollection(ctx, models.Collections.Webhook, nil) + if err != nil { + return nil, err + } + } + + webhookCollection, _ := arangodb.Collection(nil, models.Collections.Webhook) + webhookCollection.EnsureHashIndex(ctx, []string{"event_name"}, &arangoDriver.EnsureHashIndexOptions{ + Unique: true, + Sparse: true, + }) + + webhookLogCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.WebhookLog) + if !webhookLogCollectionExists { + _, err = arangodb.CreateCollection(ctx, models.Collections.WebhookLog, nil) + if err != nil { + return nil, err + } + } + + webhookLogCollection, _ := arangodb.Collection(nil, models.Collections.WebhookLog) + webhookLogCollection.EnsureHashIndex(ctx, []string{"webhook_id"}, &arangoDriver.EnsureHashIndexOptions{ + Unique: true, + }) + return &provider{ db: arangodb, }, err diff --git a/server/db/providers/arangodb/webhook.go b/server/db/providers/arangodb/webhook.go index 3dd7c9e..eef4003 100644 --- a/server/db/providers/arangodb/webhook.go +++ b/server/db/providers/arangodb/webhook.go @@ -1,17 +1,28 @@ package arangodb import ( + "time" + "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/google/uuid" ) // AddWebhook to add webhook func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { + if webhook.ID == "" { + webhook.ID = uuid.New().String() + } + + webhook.Key = webhook.ID + webhook.CreatedAt = time.Now().Unix() + webhook.UpdatedAt = time.Now().Unix() return webhook, nil } // UpdateWebhook to update webhook func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { + webhook.UpdatedAt = time.Now().Unix() return webhook, nil } diff --git a/server/db/providers/arangodb/webhook_log.go b/server/db/providers/arangodb/webhook_log.go index aa41366..bfad8b6 100644 --- a/server/db/providers/arangodb/webhook_log.go +++ b/server/db/providers/arangodb/webhook_log.go @@ -1,16 +1,74 @@ package arangodb import ( + "context" + "fmt" + "time" + + "github.com/arangodb/go-driver" + arangoDriver "github.com/arangodb/go-driver" "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/google/uuid" ) // AddWebhookLog to add webhook log func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { + if webhookLog.ID == "" { + webhookLog.ID = uuid.New().String() + } + + webhookLog.Key = webhookLog.ID + webhookLog.CreatedAt = time.Now().Unix() + webhookLog.UpdatedAt = time.Now().Unix() + webhookLogCollection, _ := p.db.Collection(nil, models.Collections.WebhookLog) + _, err := webhookLogCollection.CreateDocument(nil, webhookLog) + if err != nil { + return webhookLog, err + } return webhookLog, nil } // ListWebhookLogs to list webhook logs -func (p *provider) ListWebhookLogs(req model.ListWebhookLogRequest) (*model.WebhookLogs, error) { - return nil, nil +func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { + webhookLogs := []*model.WebhookLog{} + bindVariables := map[string]interface{}{} + + query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.WebhookLog, pagination.Offset, pagination.Limit) + + if webhookID != "" { + query = fmt.Sprintf("FOR d in %s FILTER d.webhook_id == @webhookID SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.WebhookLog, pagination.Offset, pagination.Limit) + bindVariables = map[string]interface{}{ + webhookID: webhookID, + } + } + ctx := driver.WithQueryFullCount(context.Background()) + cursor, err := p.db.Query(ctx, query, bindVariables) + if err != nil { + return nil, err + } + defer cursor.Close() + + paginationClone := pagination + paginationClone.Total = cursor.Statistics().FullCount() + + for { + var webhookLog models.WebhookLog + meta, err := cursor.ReadDocument(nil, &webhookLog) + + if arangoDriver.IsNoMoreDocuments(err) { + break + } else if err != nil { + return nil, err + } + + if meta.Key != "" { + webhookLogs = append(webhookLogs, webhookLog.AsAPIWebhookLog()) + } + } + + return &model.WebhookLogs{ + Pagination: &paginationClone, + WebhookLogs: webhookLogs, + }, nil } diff --git a/server/db/providers/cassandradb/provider.go b/server/db/providers/cassandradb/provider.go index 54270a3..3d90d2a 100644 --- a/server/db/providers/cassandradb/provider.go +++ b/server/db/providers/cassandradb/provider.go @@ -177,6 +177,28 @@ func NewProvider() (*provider, error) { return nil, err } + webhookCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, event_name text, endpoint text, enabled boolean, updated_at bigint, created_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.Webhook) + err = session.Query(webhookCollectionQuery).Exec() + if err != nil { + return nil, err + } + webhookIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_webhook_event_name ON %s.%s (event_name)", KeySpace, models.Collections.Webhook) + err = session.Query(webhookIndexQuery).Exec() + if err != nil { + return nil, err + } + + webhookLogCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, http_status bigint, response text, request text, webhook_id text,updated_at bigint, created_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.WebhookLog) + err = session.Query(webhookLogCollectionQuery).Exec() + if err != nil { + return nil, err + } + webhookLogIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_webhook_log_webhook_id ON %s.%s (webhook_id)", KeySpace, models.Collections.WebhookLog) + err = session.Query(webhookLogIndexQuery).Exec() + if err != nil { + return nil, err + } + return &provider{ db: session, }, err diff --git a/server/db/providers/cassandradb/webhook.go b/server/db/providers/cassandradb/webhook.go index 79ea9a7..2e9e978 100644 --- a/server/db/providers/cassandradb/webhook.go +++ b/server/db/providers/cassandradb/webhook.go @@ -1,17 +1,28 @@ package cassandradb import ( + "time" + "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/google/uuid" ) // AddWebhook to add webhook func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { + if webhook.ID == "" { + webhook.ID = uuid.New().String() + } + + webhook.Key = webhook.ID + webhook.CreatedAt = time.Now().Unix() + webhook.UpdatedAt = time.Now().Unix() return webhook, nil } // UpdateWebhook to update webhook func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { + webhook.UpdatedAt = time.Now().Unix() return webhook, nil } diff --git a/server/db/providers/cassandradb/webhook_log.go b/server/db/providers/cassandradb/webhook_log.go index 4ea41e2..73ecd8f 100644 --- a/server/db/providers/cassandradb/webhook_log.go +++ b/server/db/providers/cassandradb/webhook_log.go @@ -1,16 +1,69 @@ package cassandradb import ( + "fmt" + "time" + "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/gocql/gocql" + "github.com/google/uuid" ) // AddWebhookLog to add webhook log func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { + if webhookLog.ID == "" { + webhookLog.ID = uuid.New().String() + } + + webhookLog.Key = webhookLog.ID + webhookLog.CreatedAt = time.Now().Unix() + webhookLog.UpdatedAt = time.Now().Unix() + + insertWebhookLogQuery := fmt.Sprintf("INSERT INTO %s (id, http_status, response, request, webhook_id, created_at, updated_at) VALUES ('%s', %d,'%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.WebhookLog, webhookLog.ID, webhookLog.HttpStatus, webhookLog.Response, webhookLog.Request, webhookLog.WebhookID, webhookLog.CreatedAt, webhookLog.UpdatedAt) + err := p.db.Query(insertWebhookLogQuery).Exec() + if err != nil { + return webhookLog, err + } return webhookLog, nil } // ListWebhookLogs to list webhook logs -func (p *provider) ListWebhookLogs(req model.ListWebhookLogRequest) (*model.WebhookLogs, error) { - return nil, nil +func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { + webhookLogs := []*model.WebhookLog{} + paginationClone := pagination + totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.WebhookLog) + // there is no offset in cassandra + // so we fetch till limit + offset + // and return the results from offset to limit + query := fmt.Sprintf("SELECT id, http_status, response, request, webhook_id, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.WebhookLog, pagination.Limit+pagination.Offset) + + if webhookID != "" { + totalCountQuery = fmt.Sprintf(`SELECT COUNT(*) FROM %s WHERE webhook_id='%s'`, KeySpace+"."+models.Collections.WebhookLog, webhookID) + query = fmt.Sprintf("SELECT id, http_status, response, request, webhook_id, created_at, updated_at FROM %s WHERE webhook_id = '%s' LIMIT %d", KeySpace+"."+models.Collections.WebhookLog, webhookID, pagination.Limit+pagination.Offset) + } + + err := p.db.Query(totalCountQuery).Consistency(gocql.One).Scan(&paginationClone.Total) + if err != nil { + return nil, err + } + + scanner := p.db.Query(query).Iter().Scanner() + counter := int64(0) + for scanner.Next() { + if counter >= pagination.Offset { + var webhookLog models.WebhookLog + err := scanner.Scan(&webhookLog.ID, &webhookLog.HttpStatus, &webhookLog.Response, &webhookLog.Request, &webhookLog.WebhookID, &webhookLog.CreatedAt, &webhookLog.UpdatedAt) + if err != nil { + return nil, err + } + webhookLogs = append(webhookLogs, webhookLog.AsAPIWebhookLog()) + } + counter++ + } + + return &model.WebhookLogs{ + Pagination: &paginationClone, + WebhookLogs: webhookLogs, + }, nil } diff --git a/server/db/providers/mongodb/provider.go b/server/db/providers/mongodb/provider.go index 8909406..303ec75 100644 --- a/server/db/providers/mongodb/provider.go +++ b/server/db/providers/mongodb/provider.go @@ -83,6 +83,24 @@ func NewProvider() (*provider, error) { mongodb.CreateCollection(ctx, models.Collections.Env, options.CreateCollection()) + mongodb.CreateCollection(ctx, models.Collections.Webhook, options.CreateCollection()) + webhookCollection := mongodb.Collection(models.Collections.Webhook, options.Collection()) + webhookCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{ + { + Keys: bson.M{"event_name": 1}, + Options: options.Index().SetUnique(true).SetSparse(true), + }, + }, options.CreateIndexes()) + + mongodb.CreateCollection(ctx, models.Collections.WebhookLog, options.CreateCollection()) + webhookLogCollection := mongodb.Collection(models.Collections.WebhookLog, options.Collection()) + webhookLogCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{ + { + Keys: bson.M{"webhook_id": 1}, + Options: options.Index().SetSparse(true), + }, + }, options.CreateIndexes()) + return &provider{ db: mongodb, }, nil diff --git a/server/db/providers/mongodb/webhook.go b/server/db/providers/mongodb/webhook.go index 5669a12..c568e29 100644 --- a/server/db/providers/mongodb/webhook.go +++ b/server/db/providers/mongodb/webhook.go @@ -1,17 +1,28 @@ package mongodb import ( + "time" + "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/google/uuid" ) // AddWebhook to add webhook func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { + if webhook.ID == "" { + webhook.ID = uuid.New().String() + } + + webhook.Key = webhook.ID + webhook.CreatedAt = time.Now().Unix() + webhook.UpdatedAt = time.Now().Unix() return webhook, nil } // UpdateWebhook to update webhook func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { + webhook.UpdatedAt = time.Now().Unix() return webhook, nil } diff --git a/server/db/providers/mongodb/webhook_log.go b/server/db/providers/mongodb/webhook_log.go index c497a4c..32fa7a0 100644 --- a/server/db/providers/mongodb/webhook_log.go +++ b/server/db/providers/mongodb/webhook_log.go @@ -1,16 +1,72 @@ package mongodb import ( + "time" + "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/google/uuid" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo/options" ) // AddWebhookLog to add webhook log func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { + if webhookLog.ID == "" { + webhookLog.ID = uuid.New().String() + } + + webhookLog.Key = webhookLog.ID + webhookLog.CreatedAt = time.Now().Unix() + webhookLog.UpdatedAt = time.Now().Unix() + + webhookLogCollection := p.db.Collection(models.Collections.WebhookLog, options.Collection()) + _, err := webhookLogCollection.InsertOne(nil, webhookLog) + if err != nil { + return webhookLog, err + } return webhookLog, nil } // ListWebhookLogs to list webhook logs -func (p *provider) ListWebhookLogs(req model.ListWebhookLogRequest) (*model.WebhookLogs, error) { - return nil, nil +func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { + webhookLogs := []*model.WebhookLog{} + opts := options.Find() + opts.SetLimit(pagination.Limit) + opts.SetSkip(pagination.Offset) + opts.SetSort(bson.M{"created_at": -1}) + + paginationClone := pagination + query := bson.M{} + + if webhookID != "" { + query = bson.M{"webhook_id": webhookID} + } + + webhookLogCollection := p.db.Collection(models.Collections.WebhookLog, options.Collection()) + count, err := webhookLogCollection.CountDocuments(nil, query, options.Count()) + if err != nil { + return nil, err + } + + paginationClone.Total = count + + cursor, err := webhookLogCollection.Find(nil, query, opts) + if err != nil { + return nil, err + } + + for cursor.Next(nil) { + var webhookLog models.WebhookLog + err := cursor.Decode(&webhookLog) + if err != nil { + return nil, err + } + webhookLogs = append(webhookLogs, webhookLog.AsAPIWebhookLog()) + } + + return &model.WebhookLogs{ + Pagination: &paginationClone, + WebhookLogs: webhookLogs, + }, nil } diff --git a/server/db/providers/provider_template/webhook.go b/server/db/providers/provider_template/webhook.go index 1717ca6..8b73b9f 100644 --- a/server/db/providers/provider_template/webhook.go +++ b/server/db/providers/provider_template/webhook.go @@ -1,17 +1,28 @@ package provider_template import ( + "time" + "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/google/uuid" ) // AddWebhook to add webhook func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { + if webhook.ID == "" { + webhook.ID = uuid.New().String() + } + + webhook.Key = webhook.ID + webhook.CreatedAt = time.Now().Unix() + webhook.UpdatedAt = time.Now().Unix() return webhook, nil } // UpdateWebhook to update webhook func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { + webhook.UpdatedAt = time.Now().Unix() return webhook, nil } diff --git a/server/db/providers/provider_template/webhook_log.go b/server/db/providers/provider_template/webhook_log.go index 860a8c0..5f4fbc2 100644 --- a/server/db/providers/provider_template/webhook_log.go +++ b/server/db/providers/provider_template/webhook_log.go @@ -1,16 +1,26 @@ package provider_template import ( + "time" + "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/google/uuid" ) // AddWebhookLog to add webhook log func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { + if webhookLog.ID == "" { + webhookLog.ID = uuid.New().String() + } + + webhookLog.Key = webhookLog.ID + webhookLog.CreatedAt = time.Now().Unix() + webhookLog.UpdatedAt = time.Now().Unix() return webhookLog, nil } // ListWebhookLogs to list webhook logs -func (p *provider) ListWebhookLogs(req model.ListWebhookLogRequest) (*model.WebhookLogs, error) { +func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { return nil, nil } diff --git a/server/db/providers/providers.go b/server/db/providers/providers.go index cb7caea..4ec5020 100644 --- a/server/db/providers/providers.go +++ b/server/db/providers/providers.go @@ -58,5 +58,5 @@ type Provider interface { // AddWebhookLog to add webhook log AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) // ListWebhookLogs to list webhook logs - ListWebhookLogs(req model.ListWebhookLogRequest) (*model.WebhookLogs, error) + ListWebhookLogs(pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) } diff --git a/server/db/providers/sql/provider.go b/server/db/providers/sql/provider.go index 904a756..5e3aada 100644 --- a/server/db/providers/sql/provider.go +++ b/server/db/providers/sql/provider.go @@ -60,7 +60,7 @@ func NewProvider() (*provider, error) { return nil, err } - err = sqlDB.AutoMigrate(&models.User{}, &models.VerificationRequest{}, &models.Session{}, &models.Env{}) + err = sqlDB.AutoMigrate(&models.User{}, &models.VerificationRequest{}, &models.Session{}, &models.Env{}, &models.Webhook{}, models.WebhookLog{}) if err != nil { return nil, err } diff --git a/server/db/providers/sql/webhook.go b/server/db/providers/sql/webhook.go index 58abee6..4cfb380 100644 --- a/server/db/providers/sql/webhook.go +++ b/server/db/providers/sql/webhook.go @@ -1,17 +1,28 @@ package sql import ( + "time" + "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/google/uuid" ) // AddWebhook to add webhook func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { + if webhook.ID == "" { + webhook.ID = uuid.New().String() + } + + webhook.Key = webhook.ID + webhook.CreatedAt = time.Now().Unix() + webhook.UpdatedAt = time.Now().Unix() return webhook, nil } // UpdateWebhook to update webhook func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { + webhook.UpdatedAt = time.Now().Unix() return webhook, nil } diff --git a/server/db/providers/sql/webhook_log.go b/server/db/providers/sql/webhook_log.go index 6f19e2a..3992e75 100644 --- a/server/db/providers/sql/webhook_log.go +++ b/server/db/providers/sql/webhook_log.go @@ -1,16 +1,67 @@ package sql import ( + "time" + "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/google/uuid" + "gorm.io/gorm" + "gorm.io/gorm/clause" ) // AddWebhookLog to add webhook log func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { + if webhookLog.ID == "" { + webhookLog.ID = uuid.New().String() + } + + webhookLog.Key = webhookLog.ID + webhookLog.CreatedAt = time.Now().Unix() + webhookLog.UpdatedAt = time.Now().Unix() + res := p.db.Clauses( + clause.OnConflict{ + DoNothing: true, + }).Create(&webhookLog) + if res.Error != nil { + return webhookLog, res.Error + } + return webhookLog, nil } // ListWebhookLogs to list webhook logs -func (p *provider) ListWebhookLogs(req model.ListWebhookLogRequest) (*model.WebhookLogs, error) { - return nil, nil +func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { + var webhookLogs []models.WebhookLog + var result *gorm.DB + var totalRes *gorm.DB + var total int64 + + if webhookID != "" { + result = p.db.Where("webhook_id = ?", webhookID).Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&webhookLogs) + totalRes = p.db.Where("webhook_id = ?", webhookID).Model(&models.WebhookLog{}).Count(&total) + } else { + result = p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&webhookLogs) + totalRes = p.db.Model(&models.WebhookLog{}).Count(&total) + } + + if result.Error != nil { + return nil, result.Error + } + + if totalRes.Error != nil { + return nil, totalRes.Error + } + + paginationClone := pagination + paginationClone.Total = total + + responseWebhookLogs := []*model.WebhookLog{} + for _, w := range webhookLogs { + responseWebhookLogs = append(responseWebhookLogs, w.AsAPIWebhookLog()) + } + return &model.WebhookLogs{ + WebhookLogs: responseWebhookLogs, + Pagination: &paginationClone, + }, nil } diff --git a/server/graph/generated/generated.go b/server/graph/generated/generated.go index da9aaa0..e4f972f 100644 --- a/server/graph/generated/generated.go +++ b/server/graph/generated/generated.go @@ -1576,7 +1576,6 @@ var sources = []*ast.Source{ # # https://gqlgen.com/getting-started/ scalar Int64 -scalar Int32 scalar Map scalar Any @@ -1915,7 +1914,7 @@ type Webhooks { type WebhookLog { id: ID! - http_status: Int32 + http_status: Int64 response: String request: String webhook_id: ID @@ -7513,9 +7512,9 @@ func (ec *executionContext) _WebhookLog_http_status(ctx context.Context, field g if resTmp == nil { return graphql.Null } - res := resTmp.(*string) + res := resTmp.(*int64) fc.Result = res - return ec.marshalOInt322ᚖstring(ctx, field.Selections, res) + return ec.marshalOInt642ᚖint64(ctx, field.Selections, res) } func (ec *executionContext) _WebhookLog_response(ctx context.Context, field graphql.CollectedField, obj *model.WebhookLog) (ret graphql.Marshaler) { @@ -12325,21 +12324,6 @@ func (ec *executionContext) marshalOID2ᚖstring(ctx context.Context, sel ast.Se return graphql.MarshalID(*v) } -func (ec *executionContext) unmarshalOInt322ᚖstring(ctx context.Context, v interface{}) (*string, error) { - if v == nil { - return nil, nil - } - res, err := graphql.UnmarshalString(v) - return &res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) marshalOInt322ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return graphql.MarshalString(*v) -} - func (ec *executionContext) unmarshalOInt642ᚖint64(ctx context.Context, v interface{}) (*int64, error) { if v == nil { return nil, nil diff --git a/server/graph/model/models_gen.go b/server/graph/model/models_gen.go index 803ef5e..1bfa467 100644 --- a/server/graph/model/models_gen.go +++ b/server/graph/model/models_gen.go @@ -336,7 +336,7 @@ type Webhook struct { type WebhookLog struct { ID string `json:"id"` - HTTPStatus *string `json:"http_status"` + HTTPStatus *int64 `json:"http_status"` Response *string `json:"response"` Request *string `json:"request"` WebhookID *string `json:"webhook_id"` diff --git a/server/graph/schema.graphqls b/server/graph/schema.graphqls index 032c8e5..27a8534 100644 --- a/server/graph/schema.graphqls +++ b/server/graph/schema.graphqls @@ -2,7 +2,6 @@ # # https://gqlgen.com/getting-started/ scalar Int64 -scalar Int32 scalar Map scalar Any @@ -341,7 +340,7 @@ type Webhooks { type WebhookLog { id: ID! - http_status: Int32 + http_status: Int64 response: String request: String webhook_id: ID From 0ffb3f67f1bb6fc9cfa063231105fc3705456bd9 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Fri, 8 Jul 2022 19:10:37 +0530 Subject: [PATCH 04/14] fix: index for arangodb --- server/db/providers/arangodb/provider.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/db/providers/arangodb/provider.go b/server/db/providers/arangodb/provider.go index 6207acf..ac8aa4f 100644 --- a/server/db/providers/arangodb/provider.go +++ b/server/db/providers/arangodb/provider.go @@ -131,7 +131,7 @@ func NewProvider() (*provider, error) { webhookLogCollection, _ := arangodb.Collection(nil, models.Collections.WebhookLog) webhookLogCollection.EnsureHashIndex(ctx, []string{"webhook_id"}, &arangoDriver.EnsureHashIndexOptions{ - Unique: true, + Sparse: true, }) return &provider{ From e8eb62769e595e4c41ffc5f7d7d515e90d8fba75 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Sat, 9 Jul 2022 11:21:32 +0530 Subject: [PATCH 05/14] feat: add sql database methods for webhook --- server/db/models/webhook.go | 13 +++++ server/db/models/webhook_log.go | 6 +- server/db/providers/arangodb/webhook.go | 4 +- server/db/providers/cassandradb/webhook.go | 4 +- server/db/providers/mongodb/webhook.go | 4 +- .../db/providers/provider_template/webhook.go | 4 +- server/db/providers/providers.go | 4 +- server/db/providers/sql/webhook.go | 57 +++++++++++++++++-- 8 files changed, 78 insertions(+), 18 deletions(-) diff --git a/server/db/models/webhook.go b/server/db/models/webhook.go index 17d01a7..074bb61 100644 --- a/server/db/models/webhook.go +++ b/server/db/models/webhook.go @@ -1,5 +1,7 @@ package models +import "github.com/authorizerdev/authorizer/server/graph/model" + // Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation // Webhook model for db @@ -12,3 +14,14 @@ type Webhook struct { CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"` UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"` } + +func (w *Webhook) AsAPIWebhook() *model.Webhook { + return &model.Webhook{ + ID: w.ID, + EventName: &w.EventName, + Endpoint: &w.EndPoint, + Enabled: &w.Enabled, + CreatedAt: &w.CreatedAt, + UpdatedAt: &w.UpdatedAt, + } +} diff --git a/server/db/models/webhook_log.go b/server/db/models/webhook_log.go index c5f80bd..b9fb3a8 100644 --- a/server/db/models/webhook_log.go +++ b/server/db/models/webhook_log.go @@ -17,15 +17,13 @@ type WebhookLog struct { } func (w *WebhookLog) AsAPIWebhookLog() *model.WebhookLog { - createdAt := w.CreatedAt - updatedAt := w.UpdatedAt return &model.WebhookLog{ ID: w.ID, HTTPStatus: &w.HttpStatus, Response: &w.Response, Request: &w.Request, WebhookID: &w.WebhookID, - CreatedAt: &createdAt, - UpdatedAt: &updatedAt, + CreatedAt: &w.CreatedAt, + UpdatedAt: &w.UpdatedAt, } } diff --git a/server/db/providers/arangodb/webhook.go b/server/db/providers/arangodb/webhook.go index eef4003..ca58450 100644 --- a/server/db/providers/arangodb/webhook.go +++ b/server/db/providers/arangodb/webhook.go @@ -36,8 +36,8 @@ func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { return models.Webhook{}, nil } -// GetWebhookByEvent to get webhook by event_name -func (p *provider) GetWebhookByEvent(eventName string) (models.Webhook, error) { +// GetWebhookByEventName to get webhook by event_name +func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { return models.Webhook{}, nil } diff --git a/server/db/providers/cassandradb/webhook.go b/server/db/providers/cassandradb/webhook.go index 2e9e978..fd9047a 100644 --- a/server/db/providers/cassandradb/webhook.go +++ b/server/db/providers/cassandradb/webhook.go @@ -36,8 +36,8 @@ func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { return models.Webhook{}, nil } -// GetWebhookByEvent to get webhook by event_name -func (p *provider) GetWebhookByEvent(eventName string) (models.Webhook, error) { +// GetWebhookByEventName to get webhook by event_name +func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { return models.Webhook{}, nil } diff --git a/server/db/providers/mongodb/webhook.go b/server/db/providers/mongodb/webhook.go index c568e29..781619c 100644 --- a/server/db/providers/mongodb/webhook.go +++ b/server/db/providers/mongodb/webhook.go @@ -36,8 +36,8 @@ func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { return models.Webhook{}, nil } -// GetWebhookByEvent to get webhook by event_name -func (p *provider) GetWebhookByEvent(eventName string) (models.Webhook, error) { +// GetWebhookByEventName to get webhook by event_name +func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { return models.Webhook{}, nil } diff --git a/server/db/providers/provider_template/webhook.go b/server/db/providers/provider_template/webhook.go index 8b73b9f..82577a5 100644 --- a/server/db/providers/provider_template/webhook.go +++ b/server/db/providers/provider_template/webhook.go @@ -36,8 +36,8 @@ func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { return models.Webhook{}, nil } -// GetWebhookByEvent to get webhook by event_name -func (p *provider) GetWebhookByEvent(eventName string) (models.Webhook, error) { +// GetWebhookByEventName to get webhook by event_name +func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { return models.Webhook{}, nil } diff --git a/server/db/providers/providers.go b/server/db/providers/providers.go index 4ec5020..6262f87 100644 --- a/server/db/providers/providers.go +++ b/server/db/providers/providers.go @@ -50,8 +50,8 @@ type Provider interface { ListWebhook(pagination model.Pagination) (*model.Webhooks, error) // GetWebhookByID to get webhook by id GetWebhookByID(webhookID string) (models.Webhook, error) - // GetWebhookByEvent to get webhook by event_name - GetWebhookByEvent(eventName string) (models.Webhook, error) + // GetWebhookByEventName to get webhook by event_name + GetWebhookByEventName(eventName string) (models.Webhook, error) // DeleteWebhook to delete webhook DeleteWebhook(webhookID string) error diff --git a/server/db/providers/sql/webhook.go b/server/db/providers/sql/webhook.go index 4cfb380..b006e63 100644 --- a/server/db/providers/sql/webhook.go +++ b/server/db/providers/sql/webhook.go @@ -17,31 +17,80 @@ func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.Key = webhook.ID webhook.CreatedAt = time.Now().Unix() webhook.UpdatedAt = time.Now().Unix() + res := p.db.Create(&webhook) + if res.Error != nil { + return webhook, res.Error + } return webhook, nil } // UpdateWebhook to update webhook func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.UpdatedAt = time.Now().Unix() + + result := p.db.Save(&webhook) + if result.Error != nil { + return webhook, result.Error + } + return webhook, nil } // ListWebhooks to list webhook func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { - return nil, nil + var webhooks []models.Webhook + + result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&webhooks) + if result.Error != nil { + return nil, result.Error + } + + var total int64 + totalRes := p.db.Model(&models.Webhook{}).Count(&total) + if totalRes.Error != nil { + return nil, totalRes.Error + } + + paginationClone := pagination + paginationClone.Total = total + + responseWebhooks := []*model.Webhook{} + for _, w := range webhooks { + responseWebhooks = append(responseWebhooks, w.AsAPIWebhook()) + } + return &model.Webhooks{ + Pagination: &paginationClone, + Webhooks: responseWebhooks, + }, nil } // GetWebhookByID to get webhook by id func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { - return models.Webhook{}, nil + var webhook models.Webhook + + result := p.db.Where("id = ?", webhookID).First(webhook) + if result.Error != nil { + return webhook, result.Error + } + return webhook, nil } -// GetWebhookByEvent to get webhook by event_name -func (p *provider) GetWebhookByEvent(eventName string) (models.Webhook, error) { +// GetWebhookByEventName to get webhook by event_name +func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { + var webhook models.Webhook + + result := p.db.Where("event_name = ?", eventName).First(webhook) + if result.Error != nil { + return webhook, result.Error + } return models.Webhook{}, nil } // DeleteWebhook to delete webhook func (p *provider) DeleteWebhook(webhookID string) error { + result := p.db.Delete(&models.Webhook{}, webhookID) + if result.Error != nil { + return result.Error + } return nil } From 6d586b16e4814d40b493deb09fd34f698cd9274e Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Sat, 9 Jul 2022 11:44:14 +0530 Subject: [PATCH 06/14] feat: add arangodb database methods for webhook --- server/db/providers/arangodb/webhook.go | 110 +++++++++++++++++- server/db/providers/arangodb/webhook_log.go | 2 +- server/db/providers/cassandradb/webhook.go | 2 +- server/db/providers/mongodb/webhook.go | 2 +- .../db/providers/provider_template/webhook.go | 2 +- server/db/providers/providers.go | 2 +- server/db/providers/sql/webhook.go | 4 +- 7 files changed, 113 insertions(+), 11 deletions(-) diff --git a/server/db/providers/arangodb/webhook.go b/server/db/providers/arangodb/webhook.go index ca58450..9d2bffe 100644 --- a/server/db/providers/arangodb/webhook.go +++ b/server/db/providers/arangodb/webhook.go @@ -1,8 +1,12 @@ package arangodb import ( + "context" + "fmt" "time" + "github.com/arangodb/go-driver" + arangoDriver "github.com/arangodb/go-driver" "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" "github.com/google/uuid" @@ -17,31 +21,129 @@ func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.Key = webhook.ID webhook.CreatedAt = time.Now().Unix() webhook.UpdatedAt = time.Now().Unix() + webhookCollection, _ := p.db.Collection(nil, models.Collections.Webhook) + _, err := webhookCollection.CreateDocument(nil, webhook) + if err != nil { + return webhook, err + } return webhook, nil } // UpdateWebhook to update webhook func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.UpdatedAt = time.Now().Unix() + webhookCollection, _ := p.db.Collection(nil, models.Collections.Webhook) + meta, err := webhookCollection.UpdateDocument(nil, webhook.Key, webhook) + if err != nil { + return webhook, err + } + + webhook.Key = meta.Key + webhook.ID = meta.ID.String() return webhook, nil } // ListWebhooks to list webhook func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { - return nil, nil + webhooks := []*model.Webhook{} + + query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.Webhook, pagination.Offset, pagination.Limit) + + ctx := driver.WithQueryFullCount(context.Background()) + cursor, err := p.db.Query(ctx, query, nil) + if err != nil { + return nil, err + } + defer cursor.Close() + + paginationClone := pagination + paginationClone.Total = cursor.Statistics().FullCount() + + for { + var webhook models.Webhook + meta, err := cursor.ReadDocument(nil, &webhook) + + if arangoDriver.IsNoMoreDocuments(err) { + break + } else if err != nil { + return nil, err + } + + if meta.Key != "" { + webhooks = append(webhooks, webhook.AsAPIWebhook()) + } + } + + return &model.Webhooks{ + Pagination: &paginationClone, + Webhooks: webhooks, + }, nil } // GetWebhookByID to get webhook by id func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { - return models.Webhook{}, nil + var webhook models.Webhook + query := fmt.Sprintf("FOR d in %s FILTER d._id == @webhook_id RETURN d", models.Collections.Webhook) + bindVars := map[string]interface{}{ + "webhook_id": webhookID, + } + + cursor, err := p.db.Query(nil, query, bindVars) + if err != nil { + return webhook, err + } + defer cursor.Close() + + for { + if !cursor.HasMore() { + if webhook.Key == "" { + return webhook, fmt.Errorf("webhook not found") + } + break + } + _, err := cursor.ReadDocument(nil, &webhook) + if err != nil { + return webhook, err + } + } + return webhook, nil } // GetWebhookByEventName to get webhook by event_name func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { - return models.Webhook{}, nil + var webhook models.Webhook + query := fmt.Sprintf("FOR d in %s FILTER d.event_name == @event_name RETURN d", models.Collections.Webhook) + bindVars := map[string]interface{}{ + "event_name": eventName, + } + + cursor, err := p.db.Query(nil, query, bindVars) + if err != nil { + return webhook, err + } + defer cursor.Close() + + for { + if !cursor.HasMore() { + if webhook.Key == "" { + return webhook, fmt.Errorf("webhook not found") + } + break + } + _, err := cursor.ReadDocument(nil, &webhook) + if err != nil { + return webhook, err + } + } + return webhook, nil } // DeleteWebhook to delete webhook -func (p *provider) DeleteWebhook(webhookID string) error { +func (p *provider) DeleteWebhook(webhook models.Webhook) error { + webhookCollection, _ := p.db.Collection(nil, models.Collections.Webhook) + _, err := webhookCollection.RemoveDocument(nil, webhook.Key) + if err != nil { + return err + } return nil } diff --git a/server/db/providers/arangodb/webhook_log.go b/server/db/providers/arangodb/webhook_log.go index bfad8b6..66089a2 100644 --- a/server/db/providers/arangodb/webhook_log.go +++ b/server/db/providers/arangodb/webhook_log.go @@ -39,7 +39,7 @@ func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string if webhookID != "" { query = fmt.Sprintf("FOR d in %s FILTER d.webhook_id == @webhookID SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.WebhookLog, pagination.Offset, pagination.Limit) bindVariables = map[string]interface{}{ - webhookID: webhookID, + "webhook_id": webhookID, } } ctx := driver.WithQueryFullCount(context.Background()) diff --git a/server/db/providers/cassandradb/webhook.go b/server/db/providers/cassandradb/webhook.go index fd9047a..1115127 100644 --- a/server/db/providers/cassandradb/webhook.go +++ b/server/db/providers/cassandradb/webhook.go @@ -42,6 +42,6 @@ func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, erro } // DeleteWebhook to delete webhook -func (p *provider) DeleteWebhook(webhookID string) error { +func (p *provider) DeleteWebhook(webhook models.Webhook) error { return nil } diff --git a/server/db/providers/mongodb/webhook.go b/server/db/providers/mongodb/webhook.go index 781619c..402cb75 100644 --- a/server/db/providers/mongodb/webhook.go +++ b/server/db/providers/mongodb/webhook.go @@ -42,6 +42,6 @@ func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, erro } // DeleteWebhook to delete webhook -func (p *provider) DeleteWebhook(webhookID string) error { +func (p *provider) DeleteWebhook(webhook models.Webhook) error { return nil } diff --git a/server/db/providers/provider_template/webhook.go b/server/db/providers/provider_template/webhook.go index 82577a5..c699423 100644 --- a/server/db/providers/provider_template/webhook.go +++ b/server/db/providers/provider_template/webhook.go @@ -42,6 +42,6 @@ func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, erro } // DeleteWebhook to delete webhook -func (p *provider) DeleteWebhook(webhookID string) error { +func (p *provider) DeleteWebhook(webhook models.Webhook) error { return nil } diff --git a/server/db/providers/providers.go b/server/db/providers/providers.go index 6262f87..7937051 100644 --- a/server/db/providers/providers.go +++ b/server/db/providers/providers.go @@ -53,7 +53,7 @@ type Provider interface { // GetWebhookByEventName to get webhook by event_name GetWebhookByEventName(eventName string) (models.Webhook, error) // DeleteWebhook to delete webhook - DeleteWebhook(webhookID string) error + DeleteWebhook(webhook models.Webhook) error // AddWebhookLog to add webhook log AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) diff --git a/server/db/providers/sql/webhook.go b/server/db/providers/sql/webhook.go index b006e63..9977fbf 100644 --- a/server/db/providers/sql/webhook.go +++ b/server/db/providers/sql/webhook.go @@ -87,8 +87,8 @@ func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, erro } // DeleteWebhook to delete webhook -func (p *provider) DeleteWebhook(webhookID string) error { - result := p.db.Delete(&models.Webhook{}, webhookID) +func (p *provider) DeleteWebhook(webhook models.Webhook) error { + result := p.db.Delete(&webhook) if result.Error != nil { return result.Error } From bb51775d3462ccdb511e70703103e42c8117ce3b Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Sat, 9 Jul 2022 12:16:54 +0530 Subject: [PATCH 07/14] feat: add cassandradb database methods for webhook --- server/db/providers/cassandradb/user.go | 3 - server/db/providers/cassandradb/webhook.go | 106 +++++++++++++++++- .../db/providers/cassandradb/webhook_log.go | 4 +- 3 files changed, 104 insertions(+), 9 deletions(-) diff --git a/server/db/providers/cassandradb/user.go b/server/db/providers/cassandradb/user.go index d1305da..603c710 100644 --- a/server/db/providers/cassandradb/user.go +++ b/server/db/providers/cassandradb/user.go @@ -97,9 +97,6 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) { updateFields := "" for key, value := range userMap { - if value != nil && key != "_id" { - } - if key == "_id" { continue } diff --git a/server/db/providers/cassandradb/webhook.go b/server/db/providers/cassandradb/webhook.go index 1115127..f573f22 100644 --- a/server/db/providers/cassandradb/webhook.go +++ b/server/db/providers/cassandradb/webhook.go @@ -1,10 +1,15 @@ package cassandradb import ( + "encoding/json" + "fmt" + "reflect" + "strings" "time" "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/gocql/gocql" "github.com/google/uuid" ) @@ -17,31 +22,124 @@ func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.Key = webhook.ID webhook.CreatedAt = time.Now().Unix() webhook.UpdatedAt = time.Now().Unix() + + insertQuery := fmt.Sprintf("INSERT INTO %s (id, event_name, endpoint, enabled, created_at, updated_at) VALUES ('%s', '%s', '%s', %t, %d, %d)", KeySpace+"."+models.Collections.Webhook, webhook.ID, webhook.EventName, webhook.EndPoint, webhook.Enabled, webhook.CreatedAt, webhook.UpdatedAt) + err := p.db.Query(insertQuery).Exec() + if err != nil { + return webhook, err + } + return webhook, nil } // UpdateWebhook to update webhook func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.UpdatedAt = time.Now().Unix() + + bytes, err := json.Marshal(webhook) + if err != nil { + return webhook, err + } + // use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling + decoder := json.NewDecoder(strings.NewReader(string(bytes))) + decoder.UseNumber() + webhookMap := map[string]interface{}{} + err = decoder.Decode(&webhookMap) + if err != nil { + return webhook, err + } + + updateFields := "" + for key, value := range webhookMap { + if key == "_id" { + continue + } + + if value == nil { + updateFields += fmt.Sprintf("%s = null,", key) + continue + } + + valueType := reflect.TypeOf(value) + if valueType.Name() == "string" { + updateFields += fmt.Sprintf("%s = '%s', ", key, value.(string)) + } else { + updateFields += fmt.Sprintf("%s = %v, ", key, value) + } + } + updateFields = strings.Trim(updateFields, " ") + updateFields = strings.TrimSuffix(updateFields, ",") + + query := fmt.Sprintf("UPDATE %s SET %s WHERE id = '%s'", KeySpace+"."+models.Collections.Webhook, updateFields, webhook.ID) + + err = p.db.Query(query).Exec() + if err != nil { + return webhook, err + } return webhook, nil } // ListWebhooks to list webhook func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { - return nil, nil + webhooks := []*model.Webhook{} + paginationClone := pagination + + totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.Webhook) + err := p.db.Query(totalCountQuery).Consistency(gocql.One).Scan(&paginationClone.Total) + if err != nil { + return nil, err + } + + // there is no offset in cassandra + // so we fetch till limit + offset + // and return the results from offset to limit + query := fmt.Sprintf("SELECT id, event_name, endpoint, enabled, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.Webhook, pagination.Limit+pagination.Offset) + + scanner := p.db.Query(query).Iter().Scanner() + counter := int64(0) + for scanner.Next() { + if counter >= pagination.Offset { + var webhook models.Webhook + err := scanner.Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt) + if err != nil { + return nil, err + } + webhooks = append(webhooks, webhook.AsAPIWebhook()) + } + counter++ + } + + return &model.Webhooks{ + Pagination: &paginationClone, + Webhooks: webhooks, + }, nil } // GetWebhookByID to get webhook by id func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { - return models.Webhook{}, nil + var webhook models.Webhook + query := fmt.Sprintf(`SELECT id, event_name, endpoint, enabled, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1`, KeySpace+"."+models.Collections.Webhook, webhookID) + err := p.db.Query(query).Consistency(gocql.One).Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt) + if err != nil { + return webhook, err + } + return webhook, nil } // GetWebhookByEventName to get webhook by event_name func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { - return models.Webhook{}, nil + var webhook models.Webhook + query := fmt.Sprintf(`SELECT id, event_name, endpoint, enabled, created_at, updated_at FROM %s WHERE event_name = '%s' LIMIT 1`, KeySpace+"."+models.Collections.Webhook, eventName) + err := p.db.Query(query).Consistency(gocql.One).Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt) + if err != nil { + return webhook, err + } + return webhook, nil } // DeleteWebhook to delete webhook func (p *provider) DeleteWebhook(webhook models.Webhook) error { - return nil + query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.Webhook, webhook.ID) + err := p.db.Query(query).Exec() + return err } diff --git a/server/db/providers/cassandradb/webhook_log.go b/server/db/providers/cassandradb/webhook_log.go index 73ecd8f..6955107 100644 --- a/server/db/providers/cassandradb/webhook_log.go +++ b/server/db/providers/cassandradb/webhook_log.go @@ -20,8 +20,8 @@ func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLo webhookLog.CreatedAt = time.Now().Unix() webhookLog.UpdatedAt = time.Now().Unix() - insertWebhookLogQuery := fmt.Sprintf("INSERT INTO %s (id, http_status, response, request, webhook_id, created_at, updated_at) VALUES ('%s', %d,'%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.WebhookLog, webhookLog.ID, webhookLog.HttpStatus, webhookLog.Response, webhookLog.Request, webhookLog.WebhookID, webhookLog.CreatedAt, webhookLog.UpdatedAt) - err := p.db.Query(insertWebhookLogQuery).Exec() + insertQuery := fmt.Sprintf("INSERT INTO %s (id, http_status, response, request, webhook_id, created_at, updated_at) VALUES ('%s', %d,'%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.WebhookLog, webhookLog.ID, webhookLog.HttpStatus, webhookLog.Response, webhookLog.Request, webhookLog.WebhookID, webhookLog.CreatedAt, webhookLog.UpdatedAt) + err := p.db.Query(insertQuery).Exec() if err != nil { return webhookLog, err } From 09c3eafe6b92364f5c52d58b4cfa56b263fbe342 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Sat, 9 Jul 2022 12:23:48 +0530 Subject: [PATCH 08/14] feat: add mongodb database methods for webhook --- server/db/providers/mongodb/webhook.go | 72 ++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/server/db/providers/mongodb/webhook.go b/server/db/providers/mongodb/webhook.go index 402cb75..cb7da85 100644 --- a/server/db/providers/mongodb/webhook.go +++ b/server/db/providers/mongodb/webhook.go @@ -6,6 +6,8 @@ import ( "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" "github.com/google/uuid" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo/options" ) // AddWebhook to add webhook @@ -17,31 +19,95 @@ func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.Key = webhook.ID webhook.CreatedAt = time.Now().Unix() webhook.UpdatedAt = time.Now().Unix() + + webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection()) + _, err := webhookCollection.InsertOne(nil, webhook) + if err != nil { + return webhook, err + } return webhook, nil } // UpdateWebhook to update webhook func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.UpdatedAt = time.Now().Unix() + webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection()) + _, err := webhookCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": webhook.ID}}, bson.M{"$set": webhook}, options.MergeUpdateOptions()) + if err != nil { + return webhook, err + } + return webhook, nil } // ListWebhooks to list webhook func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { - return nil, nil + var webhooks []*model.Webhook + opts := options.Find() + opts.SetLimit(pagination.Limit) + opts.SetSkip(pagination.Offset) + opts.SetSort(bson.M{"created_at": -1}) + + paginationClone := pagination + + webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection()) + count, err := webhookCollection.CountDocuments(nil, bson.M{}, options.Count()) + if err != nil { + return nil, err + } + + paginationClone.Total = count + + cursor, err := webhookCollection.Find(nil, bson.M{}, opts) + if err != nil { + return nil, err + } + defer cursor.Close(nil) + + for cursor.Next(nil) { + var webhook models.Webhook + err := cursor.Decode(&webhook) + if err != nil { + return nil, err + } + webhooks = append(webhooks, webhook.AsAPIWebhook()) + } + + return &model.Webhooks{ + Pagination: &paginationClone, + Webhooks: webhooks, + }, nil } // GetWebhookByID to get webhook by id func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { - return models.Webhook{}, nil + var webhook models.Webhook + webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection()) + err := webhookCollection.FindOne(nil, bson.M{"_id": webhookID}).Decode(&webhook) + if err != nil { + return webhook, err + } + return webhook, nil } // GetWebhookByEventName to get webhook by event_name func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { - return models.Webhook{}, nil + var webhook models.Webhook + webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection()) + err := webhookCollection.FindOne(nil, bson.M{"event_name": eventName}).Decode(&webhook) + if err != nil { + return webhook, err + } + return webhook, nil } // DeleteWebhook to delete webhook func (p *provider) DeleteWebhook(webhook models.Webhook) error { + webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection()) + _, err := webhookCollection.DeleteOne(nil, bson.M{"_id": webhook.ID}, options.Delete()) + if err != nil { + return err + } + return nil } From e91a81906751713affd0445a60652042bffac703 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Sun, 10 Jul 2022 21:49:33 +0530 Subject: [PATCH 09/14] feat: implement resolvers --- server/constants/webhook_event.go | 18 + server/db/models/webhook.go | 12 +- server/db/models/webhook_log.go | 17 +- server/db/providers/arangodb/env.go | 19 +- server/db/providers/arangodb/session.go | 11 +- server/db/providers/arangodb/user.go | 38 +- .../arangodb/verification_requests.go | 28 +- server/db/providers/arangodb/webhook.go | 62 +- server/db/providers/arangodb/webhook_log.go | 18 +- server/db/providers/cassandradb/env.go | 7 +- server/db/providers/cassandradb/session.go | 5 +- server/db/providers/cassandradb/user.go | 13 +- .../cassandradb/verification_requests.go | 11 +- server/db/providers/cassandradb/webhook.go | 47 +- .../db/providers/cassandradb/webhook_log.go | 9 +- server/db/providers/mongodb/env.go | 15 +- server/db/providers/mongodb/session.go | 9 +- server/db/providers/mongodb/user.go | 31 +- .../mongodb/verification_requests.go | 27 +- server/db/providers/mongodb/webhook.go | 45 +- server/db/providers/mongodb/webhook_log.go | 18 +- server/db/providers/provider_template/env.go | 7 +- .../db/providers/provider_template/session.go | 5 +- server/db/providers/provider_template/user.go | 13 +- .../verification_requests.go | 11 +- .../db/providers/provider_template/webhook.go | 21 +- .../provider_template/webhook_log.go | 7 +- server/db/providers/providers.go | 50 +- server/db/providers/sql/env.go | 7 +- server/db/providers/sql/session.go | 5 +- server/db/providers/sql/user.go | 13 +- .../db/providers/sql/verification_requests.go | 11 +- server/db/providers/sql/webhook.go | 31 +- server/db/providers/sql/webhook_log.go | 9 +- server/env/persist_env.go | 11 +- server/graph/generated/generated.go | 810 +++++++++++++++++- server/graph/model/models_gen.go | 43 +- server/graph/schema.graphqls | 38 +- server/graph/schema.resolvers.go | 29 +- server/handlers/authorize.go | 2 +- server/handlers/oauth_callback.go | 46 +- server/handlers/token.go | 2 +- server/handlers/userinfo.go | 2 +- server/handlers/verify_email.go | 10 +- server/resolvers/add_webhook.go | 54 ++ server/resolvers/admin_signup.go | 4 +- server/resolvers/delete_user.go | 4 +- server/resolvers/delete_webhook.go | 47 + server/resolvers/enable_access.go | 4 +- server/resolvers/forgot_password.go | 4 +- server/resolvers/invite_members.go | 6 +- server/resolvers/login.go | 4 +- server/resolvers/magic_link_login.go | 8 +- server/resolvers/profile.go | 2 +- server/resolvers/resend_verify_email.go | 6 +- server/resolvers/reset_password.go | 8 +- server/resolvers/revoke_access.go | 4 +- server/resolvers/session.go | 2 +- server/resolvers/signup.go | 8 +- server/resolvers/test_endpoint.go | 109 +++ server/resolvers/update_env.go | 4 +- server/resolvers/update_profile.go | 8 +- server/resolvers/update_user.go | 8 +- server/resolvers/update_webhook.go | 91 ++ server/resolvers/users.go | 2 +- server/resolvers/verification_requests.go | 2 +- server/resolvers/verify_email.go | 10 +- server/resolvers/webhook.go | 33 + server/resolvers/webhook_logs.go | 35 + server/resolvers/webhooks.go | 35 + server/test/enable_access_test.go | 2 +- server/test/forgot_password_test.go | 2 +- server/test/login_test.go | 2 +- server/test/logout_test.go | 2 +- server/test/magic_link_login_test.go | 2 +- server/test/profile_test.go | 2 +- server/test/reset_password_test.go | 2 +- server/test/resolvers_test.go | 6 +- server/test/revoke_access_test.go | 2 +- server/test/session_test.go | 2 +- server/test/signup_test.go | 2 +- server/test/test.go | 23 +- server/test/update_profile_test.go | 2 +- server/test/verify_email_test.go | 2 +- server/utils/refs.go | 24 + server/utils/webhook.go | 1 + server/validators/webhook.go | 12 + 87 files changed, 1807 insertions(+), 428 deletions(-) create mode 100644 server/constants/webhook_event.go create mode 100644 server/resolvers/add_webhook.go create mode 100644 server/resolvers/delete_webhook.go create mode 100644 server/resolvers/test_endpoint.go create mode 100644 server/resolvers/update_webhook.go create mode 100644 server/resolvers/webhook.go create mode 100644 server/resolvers/webhook_logs.go create mode 100644 server/resolvers/webhooks.go create mode 100644 server/utils/webhook.go create mode 100644 server/validators/webhook.go diff --git a/server/constants/webhook_event.go b/server/constants/webhook_event.go new file mode 100644 index 0000000..77b2361 --- /dev/null +++ b/server/constants/webhook_event.go @@ -0,0 +1,18 @@ +package constants + +const ( + + // UserLoginWebhookEvent name for login event + UserLoginWebhookEvent = `user.login` + // UserCreatedWebhookEvent name for user creation event + // This is triggered when user entry is created but still not verified + UserCreatedWebhookEvent = `user.created` + // UserSignUpWebhookEvent name for signup event + UserSignUpWebhookEvent = `user.signup` + // UserAccessRevokedWebhookEvent name for user access revoke event + UserAccessRevokedWebhookEvent = `user.access_revoked` + // UserAccessEnabledWebhookEvent name for user access enable event + UserAccessEnabledWebhookEvent = `user.access_enabled` + // UserDeletedWebhookEvent name for user deleted event + UserDeletedWebhookEvent = `user.deleted` +) diff --git a/server/db/models/webhook.go b/server/db/models/webhook.go index 074bb61..643d54e 100644 --- a/server/db/models/webhook.go +++ b/server/db/models/webhook.go @@ -1,6 +1,10 @@ package models -import "github.com/authorizerdev/authorizer/server/graph/model" +import ( + "encoding/json" + + "github.com/authorizerdev/authorizer/server/graph/model" +) // Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation @@ -9,17 +13,21 @@ type Webhook struct { Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"` EventName string `gorm:"unique" json:"event_name" bson:"event_name" cql:"event_name"` - EndPoint string `json:"endpoint" bson:"endpoint" cql:"endpoint"` + EndPoint string `gorm:"type:text" json:"endpoint" bson:"endpoint" cql:"endpoint"` + Headers string `gorm:"type:text" json:"headers" bson:"headers" cql:"headers"` Enabled bool `json:"enabled" bson:"enabled" cql:"enabled"` CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"` UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"` } func (w *Webhook) AsAPIWebhook() *model.Webhook { + headersMap := make(map[string]interface{}) + json.Unmarshal([]byte(w.Headers), &headersMap) return &model.Webhook{ ID: w.ID, EventName: &w.EventName, Endpoint: &w.EndPoint, + Headers: headersMap, Enabled: &w.Enabled, CreatedAt: &w.CreatedAt, UpdatedAt: &w.UpdatedAt, diff --git a/server/db/models/webhook_log.go b/server/db/models/webhook_log.go index b9fb3a8..8cce42e 100644 --- a/server/db/models/webhook_log.go +++ b/server/db/models/webhook_log.go @@ -6,14 +6,15 @@ import "github.com/authorizerdev/authorizer/server/graph/model" // WebhookLog model for db type WebhookLog struct { - Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb - ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"` - HttpStatus int64 `json:"http_status" bson:"http_status" cql:"http_status"` - Response string `json:"response" bson:"response" cql:"response"` - Request string `json:"request" bson:"request" cql:"request"` - WebhookID string `gorm:"type:char(36),index:" json:"webhook_id" bson:"webhook_id" cql:"webhook_id"` - CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"` - UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"` + Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb + ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"` + HttpStatus int64 `json:"http_status" bson:"http_status" cql:"http_status"` + Response string `gorm:"type:text" json:"response" bson:"response" cql:"response"` + Request string `gorm:"type:text" json:"request" bson:"request" cql:"request"` + WebhookID string `gorm:"type:char(36),index:" json:"webhook_id" bson:"webhook_id" cql:"webhook_id"` + Webhook Webhook `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" bson:"-" cql:"-"` + CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"` + UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"` } func (w *WebhookLog) AsAPIWebhookLog() *model.WebhookLog { diff --git a/server/db/providers/arangodb/env.go b/server/db/providers/arangodb/env.go index 6931095..2c884d4 100644 --- a/server/db/providers/arangodb/env.go +++ b/server/db/providers/arangodb/env.go @@ -1,6 +1,7 @@ package arangodb import ( + "context" "fmt" "time" @@ -11,15 +12,15 @@ import ( ) // AddEnv to save environment information in database -func (p *provider) AddEnv(env models.Env) (models.Env, error) { +func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) { if env.ID == "" { env.ID = uuid.New().String() } env.CreatedAt = time.Now().Unix() env.UpdatedAt = time.Now().Unix() - configCollection, _ := p.db.Collection(nil, models.Collections.Env) - meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(nil), env) + configCollection, _ := p.db.Collection(ctx, models.Collections.Env) + meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), env) if err != nil { return env, err } @@ -29,10 +30,10 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) { } // UpdateEnv to update environment information in database -func (p *provider) UpdateEnv(env models.Env) (models.Env, error) { +func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) { env.UpdatedAt = time.Now().Unix() - collection, _ := p.db.Collection(nil, models.Collections.Env) - meta, err := collection.UpdateDocument(nil, env.Key, env) + collection, _ := p.db.Collection(ctx, models.Collections.Env) + meta, err := collection.UpdateDocument(ctx, env.Key, env) if err != nil { return env, err } @@ -43,11 +44,11 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) { } // GetEnv to get environment information from database -func (p *provider) GetEnv() (models.Env, error) { +func (p *provider) GetEnv(ctx context.Context) (models.Env, error) { var env models.Env query := fmt.Sprintf("FOR d in %s RETURN d", models.Collections.Env) - cursor, err := p.db.Query(nil, query, nil) + cursor, err := p.db.Query(ctx, query, nil) if err != nil { return env, err } @@ -60,7 +61,7 @@ func (p *provider) GetEnv() (models.Env, error) { } break } - _, err := cursor.ReadDocument(nil, &env) + _, err := cursor.ReadDocument(ctx, &env) if err != nil { return env, err } diff --git a/server/db/providers/arangodb/session.go b/server/db/providers/arangodb/session.go index 4bda894..a9ba640 100644 --- a/server/db/providers/arangodb/session.go +++ b/server/db/providers/arangodb/session.go @@ -1,6 +1,7 @@ package arangodb import ( + "context" "fmt" "time" @@ -9,15 +10,15 @@ import ( ) // AddSession to save session information in database -func (p *provider) AddSession(session models.Session) error { +func (p *provider) AddSession(ctx context.Context, session models.Session) error { if session.ID == "" { session.ID = uuid.New().String() } session.CreatedAt = time.Now().Unix() session.UpdatedAt = time.Now().Unix() - sessionCollection, _ := p.db.Collection(nil, models.Collections.Session) - _, err := sessionCollection.CreateDocument(nil, session) + sessionCollection, _ := p.db.Collection(ctx, models.Collections.Session) + _, err := sessionCollection.CreateDocument(ctx, session) if err != nil { return err } @@ -25,12 +26,12 @@ func (p *provider) AddSession(session models.Session) error { } // DeleteSession to delete session information from database -func (p *provider) DeleteSession(userId string) error { +func (p *provider) DeleteSession(ctx context.Context, userId string) error { query := fmt.Sprintf(`FOR d IN %s FILTER d.user_id == @userId REMOVE { _key: d._key } IN %s`, models.Collections.Session, models.Collections.Session) bindVars := map[string]interface{}{ "userId": userId, } - cursor, err := p.db.Query(nil, query, bindVars) + cursor, err := p.db.Query(ctx, query, bindVars) if err != nil { return err } diff --git a/server/db/providers/arangodb/user.go b/server/db/providers/arangodb/user.go index 315a827..8e1cb98 100644 --- a/server/db/providers/arangodb/user.go +++ b/server/db/providers/arangodb/user.go @@ -15,7 +15,7 @@ import ( ) // AddUser to save user information in database -func (p *provider) AddUser(user models.User) (models.User, error) { +func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) { if user.ID == "" { user.ID = uuid.New().String() } @@ -30,8 +30,8 @@ func (p *provider) AddUser(user models.User) (models.User, error) { user.CreatedAt = time.Now().Unix() user.UpdatedAt = time.Now().Unix() - userCollection, _ := p.db.Collection(nil, models.Collections.User) - meta, err := userCollection.CreateDocument(arangoDriver.WithOverwrite(nil), user) + userCollection, _ := p.db.Collection(ctx, models.Collections.User) + meta, err := userCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), user) if err != nil { return user, err } @@ -42,10 +42,10 @@ func (p *provider) AddUser(user models.User) (models.User, error) { } // UpdateUser to update user information in database -func (p *provider) UpdateUser(user models.User) (models.User, error) { +func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) { user.UpdatedAt = time.Now().Unix() - collection, _ := p.db.Collection(nil, models.Collections.User) - meta, err := collection.UpdateDocument(nil, user.Key, user) + collection, _ := p.db.Collection(ctx, models.Collections.User) + meta, err := collection.UpdateDocument(ctx, user.Key, user) if err != nil { return user, err } @@ -56,9 +56,9 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) { } // DeleteUser to delete user information from database -func (p *provider) DeleteUser(user models.User) error { - collection, _ := p.db.Collection(nil, models.Collections.User) - _, err := collection.RemoveDocument(nil, user.Key) +func (p *provider) DeleteUser(ctx context.Context, user models.User) error { + collection, _ := p.db.Collection(ctx, models.Collections.User) + _, err := collection.RemoveDocument(ctx, user.Key) if err != nil { return err } @@ -67,13 +67,13 @@ func (p *provider) DeleteUser(user models.User) error { } // ListUsers to get list of users from database -func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) { +func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) { var users []*model.User - ctx := driver.WithQueryFullCount(context.Background()) + sctx := driver.WithQueryFullCount(ctx) query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.User, pagination.Offset, pagination.Limit) - cursor, err := p.db.Query(ctx, query, nil) + cursor, err := p.db.Query(sctx, query, nil) if err != nil { return nil, err } @@ -84,7 +84,7 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) for { var user models.User - meta, err := cursor.ReadDocument(nil, &user) + meta, err := cursor.ReadDocument(ctx, &user) if arangoDriver.IsNoMoreDocuments(err) { break @@ -104,7 +104,7 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) } // GetUserByEmail to get user information from database using email address -func (p *provider) GetUserByEmail(email string) (models.User, error) { +func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) { var user models.User query := fmt.Sprintf("FOR d in %s FILTER d.email == @email RETURN d", models.Collections.User) @@ -112,7 +112,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) { "email": email, } - cursor, err := p.db.Query(nil, query, bindVars) + cursor, err := p.db.Query(ctx, query, bindVars) if err != nil { return user, err } @@ -125,7 +125,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) { } break } - _, err := cursor.ReadDocument(nil, &user) + _, err := cursor.ReadDocument(ctx, &user) if err != nil { return user, err } @@ -135,7 +135,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) { } // GetUserByID to get user information from database using user ID -func (p *provider) GetUserByID(id string) (models.User, error) { +func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) { var user models.User query := fmt.Sprintf("FOR d in %s FILTER d._id == @id LIMIT 1 RETURN d", models.Collections.User) @@ -143,7 +143,7 @@ func (p *provider) GetUserByID(id string) (models.User, error) { "id": id, } - cursor, err := p.db.Query(nil, query, bindVars) + cursor, err := p.db.Query(ctx, query, bindVars) if err != nil { return user, err } @@ -156,7 +156,7 @@ func (p *provider) GetUserByID(id string) (models.User, error) { } break } - _, err := cursor.ReadDocument(nil, &user) + _, err := cursor.ReadDocument(ctx, &user) if err != nil { return user, err } diff --git a/server/db/providers/arangodb/verification_requests.go b/server/db/providers/arangodb/verification_requests.go index ef7ee20..a1dbfa2 100644 --- a/server/db/providers/arangodb/verification_requests.go +++ b/server/db/providers/arangodb/verification_requests.go @@ -12,15 +12,15 @@ import ( ) // AddVerification to save verification request in database -func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) { +func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) { if verificationRequest.ID == "" { verificationRequest.ID = uuid.New().String() } verificationRequest.CreatedAt = time.Now().Unix() verificationRequest.UpdatedAt = time.Now().Unix() - verificationRequestRequestCollection, _ := p.db.Collection(nil, models.Collections.VerificationRequest) - meta, err := verificationRequestRequestCollection.CreateDocument(nil, verificationRequest) + verificationRequestRequestCollection, _ := p.db.Collection(ctx, models.Collections.VerificationRequest) + meta, err := verificationRequestRequestCollection.CreateDocument(ctx, verificationRequest) if err != nil { return verificationRequest, err } @@ -31,14 +31,14 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio } // GetVerificationRequestByToken to get verification request from database using token -func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) { +func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) { var verificationRequest models.VerificationRequest query := fmt.Sprintf("FOR d in %s FILTER d.token == @token LIMIT 1 RETURN d", models.Collections.VerificationRequest) bindVars := map[string]interface{}{ "token": token, } - cursor, err := p.db.Query(nil, query, bindVars) + cursor, err := p.db.Query(ctx, query, bindVars) if err != nil { return verificationRequest, err } @@ -51,7 +51,7 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat } break } - _, err := cursor.ReadDocument(nil, &verificationRequest) + _, err := cursor.ReadDocument(ctx, &verificationRequest) if err != nil { return verificationRequest, err } @@ -61,7 +61,7 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat } // GetVerificationRequestByEmail to get verification request by email from database -func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) { +func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) { var verificationRequest models.VerificationRequest query := fmt.Sprintf("FOR d in %s FILTER d.email == @email FILTER d.identifier == @identifier LIMIT 1 RETURN d", models.Collections.VerificationRequest) @@ -70,7 +70,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string "identifier": identifier, } - cursor, err := p.db.Query(nil, query, bindVars) + cursor, err := p.db.Query(ctx, query, bindVars) if err != nil { return verificationRequest, err } @@ -83,7 +83,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string } break } - _, err := cursor.ReadDocument(nil, &verificationRequest) + _, err := cursor.ReadDocument(ctx, &verificationRequest) if err != nil { return verificationRequest, err } @@ -93,12 +93,12 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string } // ListVerificationRequests to get list of verification requests from database -func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) { +func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) { var verificationRequests []*model.VerificationRequest - ctx := driver.WithQueryFullCount(context.Background()) + sctx := driver.WithQueryFullCount(ctx) query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.VerificationRequest, pagination.Offset, pagination.Limit) - cursor, err := p.db.Query(ctx, query, nil) + cursor, err := p.db.Query(sctx, query, nil) if err != nil { return nil, err } @@ -109,7 +109,7 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model for { var verificationRequest models.VerificationRequest - meta, err := cursor.ReadDocument(nil, &verificationRequest) + meta, err := cursor.ReadDocument(ctx, &verificationRequest) if driver.IsNoMoreDocuments(err) { break @@ -130,7 +130,7 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model } // DeleteVerificationRequest to delete verification request from database -func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error { +func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error { collection, _ := p.db.Collection(nil, models.Collections.VerificationRequest) _, err := collection.RemoveDocument(nil, verificationRequest.Key) if err != nil { diff --git a/server/db/providers/arangodb/webhook.go b/server/db/providers/arangodb/webhook.go index 9d2bffe..5df2c28 100644 --- a/server/db/providers/arangodb/webhook.go +++ b/server/db/providers/arangodb/webhook.go @@ -13,7 +13,7 @@ import ( ) // AddWebhook to add webhook -func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { +func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) { if webhook.ID == "" { webhook.ID = uuid.New().String() } @@ -21,36 +21,36 @@ func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.Key = webhook.ID webhook.CreatedAt = time.Now().Unix() webhook.UpdatedAt = time.Now().Unix() - webhookCollection, _ := p.db.Collection(nil, models.Collections.Webhook) - _, err := webhookCollection.CreateDocument(nil, webhook) + webhookCollection, _ := p.db.Collection(ctx, models.Collections.Webhook) + _, err := webhookCollection.CreateDocument(ctx, webhook) if err != nil { - return webhook, err + return nil, err } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // UpdateWebhook to update webhook -func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { +func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) { webhook.UpdatedAt = time.Now().Unix() - webhookCollection, _ := p.db.Collection(nil, models.Collections.Webhook) - meta, err := webhookCollection.UpdateDocument(nil, webhook.Key, webhook) + webhookCollection, _ := p.db.Collection(ctx, models.Collections.Webhook) + meta, err := webhookCollection.UpdateDocument(ctx, webhook.Key, webhook) if err != nil { - return webhook, err + return nil, err } webhook.Key = meta.Key webhook.ID = meta.ID.String() - return webhook, nil + return webhook.AsAPIWebhook(), nil } // ListWebhooks to list webhook -func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { +func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) { webhooks := []*model.Webhook{} query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.Webhook, pagination.Offset, pagination.Limit) - ctx := driver.WithQueryFullCount(context.Background()) - cursor, err := p.db.Query(ctx, query, nil) + sctx := driver.WithQueryFullCount(ctx) + cursor, err := p.db.Query(sctx, query, nil) if err != nil { return nil, err } @@ -61,7 +61,7 @@ func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, er for { var webhook models.Webhook - meta, err := cursor.ReadDocument(nil, &webhook) + meta, err := cursor.ReadDocument(ctx, &webhook) if arangoDriver.IsNoMoreDocuments(err) { break @@ -81,67 +81,67 @@ func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, er } // GetWebhookByID to get webhook by id -func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { +func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) { var webhook models.Webhook query := fmt.Sprintf("FOR d in %s FILTER d._id == @webhook_id RETURN d", models.Collections.Webhook) bindVars := map[string]interface{}{ "webhook_id": webhookID, } - cursor, err := p.db.Query(nil, query, bindVars) + cursor, err := p.db.Query(ctx, query, bindVars) if err != nil { - return webhook, err + return nil, err } defer cursor.Close() for { if !cursor.HasMore() { if webhook.Key == "" { - return webhook, fmt.Errorf("webhook not found") + return nil, fmt.Errorf("webhook not found") } break } - _, err := cursor.ReadDocument(nil, &webhook) + _, err := cursor.ReadDocument(ctx, &webhook) if err != nil { - return webhook, err + return nil, err } } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // GetWebhookByEventName to get webhook by event_name -func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { +func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) { var webhook models.Webhook query := fmt.Sprintf("FOR d in %s FILTER d.event_name == @event_name RETURN d", models.Collections.Webhook) bindVars := map[string]interface{}{ "event_name": eventName, } - cursor, err := p.db.Query(nil, query, bindVars) + cursor, err := p.db.Query(ctx, query, bindVars) if err != nil { - return webhook, err + return nil, err } defer cursor.Close() for { if !cursor.HasMore() { if webhook.Key == "" { - return webhook, fmt.Errorf("webhook not found") + return nil, fmt.Errorf("webhook not found") } break } - _, err := cursor.ReadDocument(nil, &webhook) + _, err := cursor.ReadDocument(ctx, &webhook) if err != nil { - return webhook, err + return nil, err } } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // DeleteWebhook to delete webhook -func (p *provider) DeleteWebhook(webhook models.Webhook) error { - webhookCollection, _ := p.db.Collection(nil, models.Collections.Webhook) - _, err := webhookCollection.RemoveDocument(nil, webhook.Key) +func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error { + webhookCollection, _ := p.db.Collection(ctx, models.Collections.Webhook) + _, err := webhookCollection.RemoveDocument(ctx, webhook.ID) if err != nil { return err } diff --git a/server/db/providers/arangodb/webhook_log.go b/server/db/providers/arangodb/webhook_log.go index 66089a2..d0337e1 100644 --- a/server/db/providers/arangodb/webhook_log.go +++ b/server/db/providers/arangodb/webhook_log.go @@ -13,7 +13,7 @@ import ( ) // AddWebhookLog to add webhook log -func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { +func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) { if webhookLog.ID == "" { webhookLog.ID = uuid.New().String() } @@ -21,16 +21,16 @@ func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLo webhookLog.Key = webhookLog.ID webhookLog.CreatedAt = time.Now().Unix() webhookLog.UpdatedAt = time.Now().Unix() - webhookLogCollection, _ := p.db.Collection(nil, models.Collections.WebhookLog) - _, err := webhookLogCollection.CreateDocument(nil, webhookLog) + webhookLogCollection, _ := p.db.Collection(ctx, models.Collections.WebhookLog) + _, err := webhookLogCollection.CreateDocument(ctx, webhookLog) if err != nil { - return webhookLog, err + return nil, err } - return webhookLog, nil + return webhookLog.AsAPIWebhookLog(), nil } // ListWebhookLogs to list webhook logs -func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { +func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { webhookLogs := []*model.WebhookLog{} bindVariables := map[string]interface{}{} @@ -42,8 +42,8 @@ func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string "webhook_id": webhookID, } } - ctx := driver.WithQueryFullCount(context.Background()) - cursor, err := p.db.Query(ctx, query, bindVariables) + sctx := driver.WithQueryFullCount(ctx) + cursor, err := p.db.Query(sctx, query, bindVariables) if err != nil { return nil, err } @@ -54,7 +54,7 @@ func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string for { var webhookLog models.WebhookLog - meta, err := cursor.ReadDocument(nil, &webhookLog) + meta, err := cursor.ReadDocument(ctx, &webhookLog) if arangoDriver.IsNoMoreDocuments(err) { break diff --git a/server/db/providers/cassandradb/env.go b/server/db/providers/cassandradb/env.go index bd684b3..384b539 100644 --- a/server/db/providers/cassandradb/env.go +++ b/server/db/providers/cassandradb/env.go @@ -1,6 +1,7 @@ package cassandradb import ( + "context" "fmt" "time" @@ -10,7 +11,7 @@ import ( ) // AddEnv to save environment information in database -func (p *provider) AddEnv(env models.Env) (models.Env, error) { +func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) { if env.ID == "" { env.ID = uuid.New().String() } @@ -27,7 +28,7 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) { } // UpdateEnv to update environment information in database -func (p *provider) UpdateEnv(env models.Env) (models.Env, error) { +func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) { env.UpdatedAt = time.Now().Unix() updateEnvQuery := fmt.Sprintf("UPDATE %s SET env = '%s', updated_at = %d WHERE id = '%s'", KeySpace+"."+models.Collections.Env, env.EnvData, env.UpdatedAt, env.ID) @@ -39,7 +40,7 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) { } // GetEnv to get environment information from database -func (p *provider) GetEnv() (models.Env, error) { +func (p *provider) GetEnv(ctx context.Context) (models.Env, error) { var env models.Env query := fmt.Sprintf("SELECT id, env, hash, created_at, updated_at FROM %s LIMIT 1", KeySpace+"."+models.Collections.Env) diff --git a/server/db/providers/cassandradb/session.go b/server/db/providers/cassandradb/session.go index 28e46ed..8b3b56c 100644 --- a/server/db/providers/cassandradb/session.go +++ b/server/db/providers/cassandradb/session.go @@ -1,6 +1,7 @@ package cassandradb import ( + "context" "fmt" "time" @@ -9,7 +10,7 @@ import ( ) // AddSession to save session information in database -func (p *provider) AddSession(session models.Session) error { +func (p *provider) AddSession(ctx context.Context, session models.Session) error { if session.ID == "" { session.ID = uuid.New().String() } @@ -26,7 +27,7 @@ func (p *provider) AddSession(session models.Session) error { } // DeleteSession to delete session information from database -func (p *provider) DeleteSession(userId string) error { +func (p *provider) DeleteSession(ctx context.Context, userId string) error { deleteSessionQuery := fmt.Sprintf("DELETE FROM %s WHERE user_id = '%s'", KeySpace+"."+models.Collections.Session, userId) err := p.db.Query(deleteSessionQuery).Exec() if err != nil { diff --git a/server/db/providers/cassandradb/user.go b/server/db/providers/cassandradb/user.go index 603c710..3abef97 100644 --- a/server/db/providers/cassandradb/user.go +++ b/server/db/providers/cassandradb/user.go @@ -1,6 +1,7 @@ package cassandradb import ( + "context" "encoding/json" "fmt" "reflect" @@ -16,7 +17,7 @@ import ( ) // AddUser to save user information in database -func (p *provider) AddUser(user models.User) (models.User, error) { +func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) { if user.ID == "" { user.ID = uuid.New().String() } @@ -79,7 +80,7 @@ func (p *provider) AddUser(user models.User) (models.User, error) { } // UpdateUser to update user information in database -func (p *provider) UpdateUser(user models.User) (models.User, error) { +func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) { user.UpdatedAt = time.Now().Unix() bytes, err := json.Marshal(user) @@ -127,14 +128,14 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) { } // DeleteUser to delete user information from database -func (p *provider) DeleteUser(user models.User) error { +func (p *provider) DeleteUser(ctx context.Context, user models.User) error { query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.User, user.ID) err := p.db.Query(query).Exec() return err } // ListUsers to get list of users from database -func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) { +func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) { responseUsers := []*model.User{} paginationClone := pagination totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.User) @@ -168,7 +169,7 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) } // GetUserByEmail to get user information from database using email address -func (p *provider) GetUserByEmail(email string) (models.User, error) { +func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) { var user models.User query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s WHERE email = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, email) err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt) @@ -179,7 +180,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) { } // GetUserByID to get user information from database using user ID -func (p *provider) GetUserByID(id string) (models.User, error) { +func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) { var user models.User query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, id) err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt) diff --git a/server/db/providers/cassandradb/verification_requests.go b/server/db/providers/cassandradb/verification_requests.go index 18476ac..3786a2b 100644 --- a/server/db/providers/cassandradb/verification_requests.go +++ b/server/db/providers/cassandradb/verification_requests.go @@ -1,6 +1,7 @@ package cassandradb import ( + "context" "fmt" "time" @@ -11,7 +12,7 @@ import ( ) // AddVerification to save verification request in database -func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) { +func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) { if verificationRequest.ID == "" { verificationRequest.ID = uuid.New().String() } @@ -28,7 +29,7 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio } // GetVerificationRequestByToken to get verification request from database using token -func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) { +func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) { var verificationRequest models.VerificationRequest query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s WHERE jwt_token = '%s' LIMIT 1`, KeySpace+"."+models.Collections.VerificationRequest, token) @@ -40,7 +41,7 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat } // GetVerificationRequestByEmail to get verification request by email from database -func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) { +func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) { var verificationRequest models.VerificationRequest query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s WHERE email = '%s' AND identifier = '%s' LIMIT 1 ALLOW FILTERING`, KeySpace+"."+models.Collections.VerificationRequest, email, identifier) @@ -53,7 +54,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string } // ListVerificationRequests to get list of verification requests from database -func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) { +func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) { var verificationRequests []*model.VerificationRequest paginationClone := pagination @@ -89,7 +90,7 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model } // DeleteVerificationRequest to delete verification request from database -func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error { +func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error { query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.VerificationRequest, verificationRequest.ID) err := p.db.Query(query).Exec() if err != nil { diff --git a/server/db/providers/cassandradb/webhook.go b/server/db/providers/cassandradb/webhook.go index f573f22..9d41823 100644 --- a/server/db/providers/cassandradb/webhook.go +++ b/server/db/providers/cassandradb/webhook.go @@ -1,6 +1,7 @@ package cassandradb import ( + "context" "encoding/json" "fmt" "reflect" @@ -14,7 +15,7 @@ import ( ) // AddWebhook to add webhook -func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { +func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) { if webhook.ID == "" { webhook.ID = uuid.New().String() } @@ -23,22 +24,22 @@ func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.CreatedAt = time.Now().Unix() webhook.UpdatedAt = time.Now().Unix() - insertQuery := fmt.Sprintf("INSERT INTO %s (id, event_name, endpoint, enabled, created_at, updated_at) VALUES ('%s', '%s', '%s', %t, %d, %d)", KeySpace+"."+models.Collections.Webhook, webhook.ID, webhook.EventName, webhook.EndPoint, webhook.Enabled, webhook.CreatedAt, webhook.UpdatedAt) + insertQuery := fmt.Sprintf("INSERT INTO %s (id, event_name, endpoint, headers, enabled, created_at, updated_at) VALUES ('%s', '%s', '%s', '%s', %t, %d, %d)", KeySpace+"."+models.Collections.Webhook, webhook.ID, webhook.EventName, webhook.EndPoint, webhook.Headers, webhook.Enabled, webhook.CreatedAt, webhook.UpdatedAt) err := p.db.Query(insertQuery).Exec() if err != nil { - return webhook, err + return nil, err } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // UpdateWebhook to update webhook -func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { +func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) { webhook.UpdatedAt = time.Now().Unix() bytes, err := json.Marshal(webhook) if err != nil { - return webhook, err + return nil, err } // use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling decoder := json.NewDecoder(strings.NewReader(string(bytes))) @@ -46,7 +47,7 @@ func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) webhookMap := map[string]interface{}{} err = decoder.Decode(&webhookMap) if err != nil { - return webhook, err + return nil, err } updateFields := "" @@ -74,13 +75,13 @@ func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) err = p.db.Query(query).Exec() if err != nil { - return webhook, err + return nil, err } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // ListWebhooks to list webhook -func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { +func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) { webhooks := []*model.Webhook{} paginationClone := pagination @@ -93,14 +94,14 @@ func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, er // there is no offset in cassandra // so we fetch till limit + offset // and return the results from offset to limit - query := fmt.Sprintf("SELECT id, event_name, endpoint, enabled, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.Webhook, pagination.Limit+pagination.Offset) + query := fmt.Sprintf("SELECT id, event_name, endpoint, headers, enabled, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.Webhook, pagination.Limit+pagination.Offset) scanner := p.db.Query(query).Iter().Scanner() counter := int64(0) for scanner.Next() { if counter >= pagination.Offset { var webhook models.Webhook - err := scanner.Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt) + err := scanner.Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Headers, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt) if err != nil { return nil, err } @@ -116,29 +117,29 @@ func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, er } // GetWebhookByID to get webhook by id -func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { +func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) { var webhook models.Webhook - query := fmt.Sprintf(`SELECT id, event_name, endpoint, enabled, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1`, KeySpace+"."+models.Collections.Webhook, webhookID) - err := p.db.Query(query).Consistency(gocql.One).Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt) + query := fmt.Sprintf(`SELECT id, event_name, endpoint, headers, enabled, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1`, KeySpace+"."+models.Collections.Webhook, webhookID) + err := p.db.Query(query).Consistency(gocql.One).Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Headers, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt) if err != nil { - return webhook, err + return nil, err } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // GetWebhookByEventName to get webhook by event_name -func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { +func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) { var webhook models.Webhook - query := fmt.Sprintf(`SELECT id, event_name, endpoint, enabled, created_at, updated_at FROM %s WHERE event_name = '%s' LIMIT 1`, KeySpace+"."+models.Collections.Webhook, eventName) - err := p.db.Query(query).Consistency(gocql.One).Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt) + query := fmt.Sprintf(`SELECT id, event_name, endpoint, headers, enabled, created_at, updated_at FROM %s WHERE event_name = '%s' LIMIT 1`, KeySpace+"."+models.Collections.Webhook, eventName) + err := p.db.Query(query).Consistency(gocql.One).Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Headers, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt) if err != nil { - return webhook, err + return nil, err } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // DeleteWebhook to delete webhook -func (p *provider) DeleteWebhook(webhook models.Webhook) error { +func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error { query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.Webhook, webhook.ID) err := p.db.Query(query).Exec() return err diff --git a/server/db/providers/cassandradb/webhook_log.go b/server/db/providers/cassandradb/webhook_log.go index 6955107..ab979f7 100644 --- a/server/db/providers/cassandradb/webhook_log.go +++ b/server/db/providers/cassandradb/webhook_log.go @@ -1,6 +1,7 @@ package cassandradb import ( + "context" "fmt" "time" @@ -11,7 +12,7 @@ import ( ) // AddWebhookLog to add webhook log -func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { +func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) { if webhookLog.ID == "" { webhookLog.ID = uuid.New().String() } @@ -23,13 +24,13 @@ func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLo insertQuery := fmt.Sprintf("INSERT INTO %s (id, http_status, response, request, webhook_id, created_at, updated_at) VALUES ('%s', %d,'%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.WebhookLog, webhookLog.ID, webhookLog.HttpStatus, webhookLog.Response, webhookLog.Request, webhookLog.WebhookID, webhookLog.CreatedAt, webhookLog.UpdatedAt) err := p.db.Query(insertQuery).Exec() if err != nil { - return webhookLog, err + return nil, err } - return webhookLog, nil + return webhookLog.AsAPIWebhookLog(), nil } // ListWebhookLogs to list webhook logs -func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { +func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { webhookLogs := []*model.WebhookLog{} paginationClone := pagination totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.WebhookLog) diff --git a/server/db/providers/mongodb/env.go b/server/db/providers/mongodb/env.go index 6d17adf..a4b114c 100644 --- a/server/db/providers/mongodb/env.go +++ b/server/db/providers/mongodb/env.go @@ -1,6 +1,7 @@ package mongodb import ( + "context" "fmt" "time" @@ -11,7 +12,7 @@ import ( ) // AddEnv to save environment information in database -func (p *provider) AddEnv(env models.Env) (models.Env, error) { +func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) { if env.ID == "" { env.ID = uuid.New().String() } @@ -20,7 +21,7 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) { env.UpdatedAt = time.Now().Unix() env.Key = env.ID configCollection := p.db.Collection(models.Collections.Env, options.Collection()) - _, err := configCollection.InsertOne(nil, env) + _, err := configCollection.InsertOne(ctx, env) if err != nil { return env, err } @@ -28,10 +29,10 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) { } // UpdateEnv to update environment information in database -func (p *provider) UpdateEnv(env models.Env) (models.Env, error) { +func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) { env.UpdatedAt = time.Now().Unix() configCollection := p.db.Collection(models.Collections.Env, options.Collection()) - _, err := configCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": env.ID}}, bson.M{"$set": env}, options.MergeUpdateOptions()) + _, err := configCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": env.ID}}, bson.M{"$set": env}, options.MergeUpdateOptions()) if err != nil { return env, err } @@ -39,14 +40,14 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) { } // GetEnv to get environment information from database -func (p *provider) GetEnv() (models.Env, error) { +func (p *provider) GetEnv(ctx context.Context) (models.Env, error) { var env models.Env configCollection := p.db.Collection(models.Collections.Env, options.Collection()) - cursor, err := configCollection.Find(nil, bson.M{}, options.Find()) + cursor, err := configCollection.Find(ctx, bson.M{}, options.Find()) if err != nil { return env, err } - defer cursor.Close(nil) + defer cursor.Close(ctx) for cursor.Next(nil) { err := cursor.Decode(&env) diff --git a/server/db/providers/mongodb/session.go b/server/db/providers/mongodb/session.go index c4c04c8..58471c5 100644 --- a/server/db/providers/mongodb/session.go +++ b/server/db/providers/mongodb/session.go @@ -1,6 +1,7 @@ package mongodb import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -10,7 +11,7 @@ import ( ) // AddSession to save session information in database -func (p *provider) AddSession(session models.Session) error { +func (p *provider) AddSession(ctx context.Context, session models.Session) error { if session.ID == "" { session.ID = uuid.New().String() } @@ -19,7 +20,7 @@ func (p *provider) AddSession(session models.Session) error { session.CreatedAt = time.Now().Unix() session.UpdatedAt = time.Now().Unix() sessionCollection := p.db.Collection(models.Collections.Session, options.Collection()) - _, err := sessionCollection.InsertOne(nil, session) + _, err := sessionCollection.InsertOne(ctx, session) if err != nil { return err } @@ -27,9 +28,9 @@ func (p *provider) AddSession(session models.Session) error { } // DeleteSession to delete session information from database -func (p *provider) DeleteSession(userId string) error { +func (p *provider) DeleteSession(ctx context.Context, userId string) error { sessionCollection := p.db.Collection(models.Collections.Session, options.Collection()) - _, err := sessionCollection.DeleteMany(nil, bson.M{"user_id": userId}, options.Delete()) + _, err := sessionCollection.DeleteMany(ctx, bson.M{"user_id": userId}, options.Delete()) if err != nil { return err } diff --git a/server/db/providers/mongodb/user.go b/server/db/providers/mongodb/user.go index 465b8df..96e8c17 100644 --- a/server/db/providers/mongodb/user.go +++ b/server/db/providers/mongodb/user.go @@ -1,6 +1,7 @@ package mongodb import ( + "context" "time" "github.com/authorizerdev/authorizer/server/constants" @@ -13,7 +14,7 @@ import ( ) // AddUser to save user information in database -func (p *provider) AddUser(user models.User) (models.User, error) { +func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) { if user.ID == "" { user.ID = uuid.New().String() } @@ -29,7 +30,7 @@ func (p *provider) AddUser(user models.User) (models.User, error) { user.UpdatedAt = time.Now().Unix() user.Key = user.ID userCollection := p.db.Collection(models.Collections.User, options.Collection()) - _, err := userCollection.InsertOne(nil, user) + _, err := userCollection.InsertOne(ctx, user) if err != nil { return user, err } @@ -38,10 +39,10 @@ func (p *provider) AddUser(user models.User) (models.User, error) { } // UpdateUser to update user information in database -func (p *provider) UpdateUser(user models.User) (models.User, error) { +func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) { user.UpdatedAt = time.Now().Unix() userCollection := p.db.Collection(models.Collections.User, options.Collection()) - _, err := userCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": user.ID}}, bson.M{"$set": user}, options.MergeUpdateOptions()) + _, err := userCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": user.ID}}, bson.M{"$set": user}, options.MergeUpdateOptions()) if err != nil { return user, err } @@ -49,9 +50,9 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) { } // DeleteUser to delete user information from database -func (p *provider) DeleteUser(user models.User) error { +func (p *provider) DeleteUser(ctx context.Context, user models.User) error { userCollection := p.db.Collection(models.Collections.User, options.Collection()) - _, err := userCollection.DeleteOne(nil, bson.M{"_id": user.ID}, options.Delete()) + _, err := userCollection.DeleteOne(ctx, bson.M{"_id": user.ID}, options.Delete()) if err != nil { return err } @@ -60,7 +61,7 @@ func (p *provider) DeleteUser(user models.User) error { } // ListUsers to get list of users from database -func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) { +func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) { var users []*model.User opts := options.Find() opts.SetLimit(pagination.Limit) @@ -70,20 +71,20 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) paginationClone := pagination userCollection := p.db.Collection(models.Collections.User, options.Collection()) - count, err := userCollection.CountDocuments(nil, bson.M{}, options.Count()) + count, err := userCollection.CountDocuments(ctx, bson.M{}, options.Count()) if err != nil { return nil, err } paginationClone.Total = count - cursor, err := userCollection.Find(nil, bson.M{}, opts) + cursor, err := userCollection.Find(ctx, bson.M{}, opts) if err != nil { return nil, err } - defer cursor.Close(nil) + defer cursor.Close(ctx) - for cursor.Next(nil) { + for cursor.Next(ctx) { var user models.User err := cursor.Decode(&user) if err != nil { @@ -99,10 +100,10 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) } // GetUserByEmail to get user information from database using email address -func (p *provider) GetUserByEmail(email string) (models.User, error) { +func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) { var user models.User userCollection := p.db.Collection(models.Collections.User, options.Collection()) - err := userCollection.FindOne(nil, bson.M{"email": email}).Decode(&user) + err := userCollection.FindOne(ctx, bson.M{"email": email}).Decode(&user) if err != nil { return user, err } @@ -111,11 +112,11 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) { } // GetUserByID to get user information from database using user ID -func (p *provider) GetUserByID(id string) (models.User, error) { +func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) { var user models.User userCollection := p.db.Collection(models.Collections.User, options.Collection()) - err := userCollection.FindOne(nil, bson.M{"_id": id}).Decode(&user) + err := userCollection.FindOne(ctx, bson.M{"_id": id}).Decode(&user) if err != nil { return user, err } diff --git a/server/db/providers/mongodb/verification_requests.go b/server/db/providers/mongodb/verification_requests.go index c931982..ff6f908 100644 --- a/server/db/providers/mongodb/verification_requests.go +++ b/server/db/providers/mongodb/verification_requests.go @@ -1,6 +1,7 @@ package mongodb import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -11,7 +12,7 @@ import ( ) // AddVerification to save verification request in database -func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) { +func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) { if verificationRequest.ID == "" { verificationRequest.ID = uuid.New().String() @@ -19,7 +20,7 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio verificationRequest.UpdatedAt = time.Now().Unix() verificationRequest.Key = verificationRequest.ID verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection()) - _, err := verificationRequestCollection.InsertOne(nil, verificationRequest) + _, err := verificationRequestCollection.InsertOne(ctx, verificationRequest) if err != nil { return verificationRequest, err } @@ -29,11 +30,11 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio } // GetVerificationRequestByToken to get verification request from database using token -func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) { +func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) { var verificationRequest models.VerificationRequest verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection()) - err := verificationRequestCollection.FindOne(nil, bson.M{"token": token}).Decode(&verificationRequest) + err := verificationRequestCollection.FindOne(ctx, bson.M{"token": token}).Decode(&verificationRequest) if err != nil { return verificationRequest, err } @@ -42,11 +43,11 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat } // GetVerificationRequestByEmail to get verification request by email from database -func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) { +func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) { var verificationRequest models.VerificationRequest verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection()) - err := verificationRequestCollection.FindOne(nil, bson.M{"email": email, "identifier": identifier}).Decode(&verificationRequest) + err := verificationRequestCollection.FindOne(ctx, bson.M{"email": email, "identifier": identifier}).Decode(&verificationRequest) if err != nil { return verificationRequest, err } @@ -55,7 +56,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string } // ListVerificationRequests to get list of verification requests from database -func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) { +func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) { var verificationRequests []*model.VerificationRequest opts := options.Find() @@ -65,17 +66,17 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection()) - verificationRequestCollectionCount, err := verificationRequestCollection.CountDocuments(nil, bson.M{}) + verificationRequestCollectionCount, err := verificationRequestCollection.CountDocuments(ctx, bson.M{}) paginationClone := pagination paginationClone.Total = verificationRequestCollectionCount - cursor, err := verificationRequestCollection.Find(nil, bson.M{}, opts) + cursor, err := verificationRequestCollection.Find(ctx, bson.M{}, opts) if err != nil { return nil, err } - defer cursor.Close(nil) + defer cursor.Close(ctx) - for cursor.Next(nil) { + for cursor.Next(ctx) { var verificationRequest models.VerificationRequest err := cursor.Decode(&verificationRequest) if err != nil { @@ -91,9 +92,9 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model } // DeleteVerificationRequest to delete verification request from database -func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error { +func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error { verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection()) - _, err := verificationRequestCollection.DeleteOne(nil, bson.M{"_id": verificationRequest.ID}, options.Delete()) + _, err := verificationRequestCollection.DeleteOne(ctx, bson.M{"_id": verificationRequest.ID}, options.Delete()) if err != nil { return err } diff --git a/server/db/providers/mongodb/webhook.go b/server/db/providers/mongodb/webhook.go index cb7da85..8059eec 100644 --- a/server/db/providers/mongodb/webhook.go +++ b/server/db/providers/mongodb/webhook.go @@ -1,6 +1,7 @@ package mongodb import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -11,7 +12,7 @@ import ( ) // AddWebhook to add webhook -func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { +func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) { if webhook.ID == "" { webhook.ID = uuid.New().String() } @@ -21,27 +22,27 @@ func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.UpdatedAt = time.Now().Unix() webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection()) - _, err := webhookCollection.InsertOne(nil, webhook) + _, err := webhookCollection.InsertOne(ctx, webhook) if err != nil { - return webhook, err + return nil, err } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // UpdateWebhook to update webhook -func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { +func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) { webhook.UpdatedAt = time.Now().Unix() webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection()) - _, err := webhookCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": webhook.ID}}, bson.M{"$set": webhook}, options.MergeUpdateOptions()) + _, err := webhookCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": webhook.ID}}, bson.M{"$set": webhook}, options.MergeUpdateOptions()) if err != nil { - return webhook, err + return nil, err } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // ListWebhooks to list webhook -func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { +func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) { var webhooks []*model.Webhook opts := options.Find() opts.SetLimit(pagination.Limit) @@ -51,20 +52,20 @@ func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, er paginationClone := pagination webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection()) - count, err := webhookCollection.CountDocuments(nil, bson.M{}, options.Count()) + count, err := webhookCollection.CountDocuments(ctx, bson.M{}, options.Count()) if err != nil { return nil, err } paginationClone.Total = count - cursor, err := webhookCollection.Find(nil, bson.M{}, opts) + cursor, err := webhookCollection.Find(ctx, bson.M{}, opts) if err != nil { return nil, err } - defer cursor.Close(nil) + defer cursor.Close(ctx) - for cursor.Next(nil) { + for cursor.Next(ctx) { var webhook models.Webhook err := cursor.Decode(&webhook) if err != nil { @@ -80,29 +81,29 @@ func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, er } // GetWebhookByID to get webhook by id -func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { +func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) { var webhook models.Webhook webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection()) - err := webhookCollection.FindOne(nil, bson.M{"_id": webhookID}).Decode(&webhook) + err := webhookCollection.FindOne(ctx, bson.M{"_id": webhookID}).Decode(&webhook) if err != nil { - return webhook, err + return nil, err } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // GetWebhookByEventName to get webhook by event_name -func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { +func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) { var webhook models.Webhook webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection()) - err := webhookCollection.FindOne(nil, bson.M{"event_name": eventName}).Decode(&webhook) + err := webhookCollection.FindOne(ctx, bson.M{"event_name": eventName}).Decode(&webhook) if err != nil { - return webhook, err + return nil, err } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // DeleteWebhook to delete webhook -func (p *provider) DeleteWebhook(webhook models.Webhook) error { +func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error { webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection()) _, err := webhookCollection.DeleteOne(nil, bson.M{"_id": webhook.ID}, options.Delete()) if err != nil { diff --git a/server/db/providers/mongodb/webhook_log.go b/server/db/providers/mongodb/webhook_log.go index 32fa7a0..6e1081c 100644 --- a/server/db/providers/mongodb/webhook_log.go +++ b/server/db/providers/mongodb/webhook_log.go @@ -1,6 +1,7 @@ package mongodb import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -11,7 +12,7 @@ import ( ) // AddWebhookLog to add webhook log -func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { +func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) { if webhookLog.ID == "" { webhookLog.ID = uuid.New().String() } @@ -21,15 +22,15 @@ func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLo webhookLog.UpdatedAt = time.Now().Unix() webhookLogCollection := p.db.Collection(models.Collections.WebhookLog, options.Collection()) - _, err := webhookLogCollection.InsertOne(nil, webhookLog) + _, err := webhookLogCollection.InsertOne(ctx, webhookLog) if err != nil { - return webhookLog, err + return nil, err } - return webhookLog, nil + return webhookLog.AsAPIWebhookLog(), nil } // ListWebhookLogs to list webhook logs -func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { +func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { webhookLogs := []*model.WebhookLog{} opts := options.Find() opts.SetLimit(pagination.Limit) @@ -44,19 +45,20 @@ func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string } webhookLogCollection := p.db.Collection(models.Collections.WebhookLog, options.Collection()) - count, err := webhookLogCollection.CountDocuments(nil, query, options.Count()) + count, err := webhookLogCollection.CountDocuments(ctx, query, options.Count()) if err != nil { return nil, err } paginationClone.Total = count - cursor, err := webhookLogCollection.Find(nil, query, opts) + cursor, err := webhookLogCollection.Find(ctx, query, opts) if err != nil { return nil, err } + defer cursor.Close(ctx) - for cursor.Next(nil) { + for cursor.Next(ctx) { var webhookLog models.WebhookLog err := cursor.Decode(&webhookLog) if err != nil { diff --git a/server/db/providers/provider_template/env.go b/server/db/providers/provider_template/env.go index 0f31e8e..af232e8 100644 --- a/server/db/providers/provider_template/env.go +++ b/server/db/providers/provider_template/env.go @@ -1,6 +1,7 @@ package provider_template import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -8,7 +9,7 @@ import ( ) // AddEnv to save environment information in database -func (p *provider) AddEnv(env models.Env) (models.Env, error) { +func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) { if env.ID == "" { env.ID = uuid.New().String() } @@ -19,13 +20,13 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) { } // UpdateEnv to update environment information in database -func (p *provider) UpdateEnv(env models.Env) (models.Env, error) { +func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) { env.UpdatedAt = time.Now().Unix() return env, nil } // GetEnv to get environment information from database -func (p *provider) GetEnv() (models.Env, error) { +func (p *provider) GetEnv(ctx context.Context) (models.Env, error) { var env models.Env return env, nil diff --git a/server/db/providers/provider_template/session.go b/server/db/providers/provider_template/session.go index a914fdb..c6f45ec 100644 --- a/server/db/providers/provider_template/session.go +++ b/server/db/providers/provider_template/session.go @@ -1,6 +1,7 @@ package provider_template import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -8,7 +9,7 @@ import ( ) // AddSession to save session information in database -func (p *provider) AddSession(session models.Session) error { +func (p *provider) AddSession(ctx context.Context, session models.Session) error { if session.ID == "" { session.ID = uuid.New().String() } @@ -19,6 +20,6 @@ func (p *provider) AddSession(session models.Session) error { } // DeleteSession to delete session information from database -func (p *provider) DeleteSession(userId string) error { +func (p *provider) DeleteSession(ctx context.Context, userId string) error { return nil } diff --git a/server/db/providers/provider_template/user.go b/server/db/providers/provider_template/user.go index cb1069f..00b2db8 100644 --- a/server/db/providers/provider_template/user.go +++ b/server/db/providers/provider_template/user.go @@ -1,6 +1,7 @@ package provider_template import ( + "context" "time" "github.com/authorizerdev/authorizer/server/constants" @@ -11,7 +12,7 @@ import ( ) // AddUser to save user information in database -func (p *provider) AddUser(user models.User) (models.User, error) { +func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) { if user.ID == "" { user.ID = uuid.New().String() } @@ -31,30 +32,30 @@ func (p *provider) AddUser(user models.User) (models.User, error) { } // UpdateUser to update user information in database -func (p *provider) UpdateUser(user models.User) (models.User, error) { +func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) { user.UpdatedAt = time.Now().Unix() return user, nil } // DeleteUser to delete user information from database -func (p *provider) DeleteUser(user models.User) error { +func (p *provider) DeleteUser(ctx context.Context, user models.User) error { return nil } // ListUsers to get list of users from database -func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) { +func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) { return nil, nil } // GetUserByEmail to get user information from database using email address -func (p *provider) GetUserByEmail(email string) (models.User, error) { +func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) { var user models.User return user, nil } // GetUserByID to get user information from database using user ID -func (p *provider) GetUserByID(id string) (models.User, error) { +func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) { var user models.User return user, nil diff --git a/server/db/providers/provider_template/verification_requests.go b/server/db/providers/provider_template/verification_requests.go index c0b4b2a..577d2f6 100644 --- a/server/db/providers/provider_template/verification_requests.go +++ b/server/db/providers/provider_template/verification_requests.go @@ -1,6 +1,7 @@ package provider_template import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -9,7 +10,7 @@ import ( ) // AddVerification to save verification request in database -func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) { +func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) { if verificationRequest.ID == "" { verificationRequest.ID = uuid.New().String() } @@ -21,25 +22,25 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio } // GetVerificationRequestByToken to get verification request from database using token -func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) { +func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) { var verificationRequest models.VerificationRequest return verificationRequest, nil } // GetVerificationRequestByEmail to get verification request by email from database -func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) { +func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) { var verificationRequest models.VerificationRequest return verificationRequest, nil } // ListVerificationRequests to get list of verification requests from database -func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) { +func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) { return nil, nil } // DeleteVerificationRequest to delete verification request from database -func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error { +func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error { return nil } diff --git a/server/db/providers/provider_template/webhook.go b/server/db/providers/provider_template/webhook.go index c699423..08b85cc 100644 --- a/server/db/providers/provider_template/webhook.go +++ b/server/db/providers/provider_template/webhook.go @@ -1,6 +1,7 @@ package provider_template import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -9,7 +10,7 @@ import ( ) // AddWebhook to add webhook -func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { +func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) { if webhook.ID == "" { webhook.ID = uuid.New().String() } @@ -17,31 +18,31 @@ func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.Key = webhook.ID webhook.CreatedAt = time.Now().Unix() webhook.UpdatedAt = time.Now().Unix() - return webhook, nil + return webhook.AsAPIWebhook(), nil } // UpdateWebhook to update webhook -func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { +func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) { webhook.UpdatedAt = time.Now().Unix() - return webhook, nil + return webhook.AsAPIWebhook(), nil } // ListWebhooks to list webhook -func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { +func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) { return nil, nil } // GetWebhookByID to get webhook by id -func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { - return models.Webhook{}, nil +func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) { + return nil, nil } // GetWebhookByEventName to get webhook by event_name -func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { - return models.Webhook{}, nil +func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) { + return nil, nil } // DeleteWebhook to delete webhook -func (p *provider) DeleteWebhook(webhook models.Webhook) error { +func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error { return nil } diff --git a/server/db/providers/provider_template/webhook_log.go b/server/db/providers/provider_template/webhook_log.go index 5f4fbc2..9814bc3 100644 --- a/server/db/providers/provider_template/webhook_log.go +++ b/server/db/providers/provider_template/webhook_log.go @@ -1,6 +1,7 @@ package provider_template import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -9,7 +10,7 @@ import ( ) // AddWebhookLog to add webhook log -func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { +func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) { if webhookLog.ID == "" { webhookLog.ID = uuid.New().String() } @@ -17,10 +18,10 @@ func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLo webhookLog.Key = webhookLog.ID webhookLog.CreatedAt = time.Now().Unix() webhookLog.UpdatedAt = time.Now().Unix() - return webhookLog, nil + return webhookLog.AsAPIWebhookLog(), nil } // ListWebhookLogs to list webhook logs -func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { +func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { return nil, nil } diff --git a/server/db/providers/providers.go b/server/db/providers/providers.go index 7937051..bf6745d 100644 --- a/server/db/providers/providers.go +++ b/server/db/providers/providers.go @@ -1,62 +1,64 @@ package providers import ( + "context" + "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/graph/model" ) type Provider interface { // AddUser to save user information in database - AddUser(user models.User) (models.User, error) + AddUser(ctx context.Context, user models.User) (models.User, error) // UpdateUser to update user information in database - UpdateUser(user models.User) (models.User, error) + UpdateUser(ctx context.Context, user models.User) (models.User, error) // DeleteUser to delete user information from database - DeleteUser(user models.User) error + DeleteUser(ctx context.Context, user models.User) error // ListUsers to get list of users from database - ListUsers(pagination model.Pagination) (*model.Users, error) + ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) // GetUserByEmail to get user information from database using email address - GetUserByEmail(email string) (models.User, error) + GetUserByEmail(ctx context.Context, email string) (models.User, error) // GetUserByID to get user information from database using user ID - GetUserByID(id string) (models.User, error) + GetUserByID(ctx context.Context, id string) (models.User, error) // AddVerification to save verification request in database - AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) + AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) // GetVerificationRequestByToken to get verification request from database using token - GetVerificationRequestByToken(token string) (models.VerificationRequest, error) + GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) // GetVerificationRequestByEmail to get verification request by email from database - GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) + GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) // ListVerificationRequests to get list of verification requests from database - ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) + ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) // DeleteVerificationRequest to delete verification request from database - DeleteVerificationRequest(verificationRequest models.VerificationRequest) error + DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error // AddSession to save session information in database - AddSession(session models.Session) error + AddSession(ctx context.Context, session models.Session) error // DeleteSession to delete session information from database - DeleteSession(userId string) error + DeleteSession(ctx context.Context, userId string) error // AddEnv to save environment information in database - AddEnv(env models.Env) (models.Env, error) + AddEnv(ctx context.Context, env models.Env) (models.Env, error) // UpdateEnv to update environment information in database - UpdateEnv(env models.Env) (models.Env, error) + UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) // GetEnv to get environment information from database - GetEnv() (models.Env, error) + GetEnv(ctx context.Context) (models.Env, error) // AddWebhook to add webhook - AddWebhook(webhook models.Webhook) (models.Webhook, error) + AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) // UpdateWebhook to update webhook - UpdateWebhook(webhook models.Webhook) (models.Webhook, error) + UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) // ListWebhooks to list webhook - ListWebhook(pagination model.Pagination) (*model.Webhooks, error) + ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) // GetWebhookByID to get webhook by id - GetWebhookByID(webhookID string) (models.Webhook, error) + GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) // GetWebhookByEventName to get webhook by event_name - GetWebhookByEventName(eventName string) (models.Webhook, error) + GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) // DeleteWebhook to delete webhook - DeleteWebhook(webhook models.Webhook) error + DeleteWebhook(ctx context.Context, webhook *model.Webhook) error // AddWebhookLog to add webhook log - AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) + AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) // ListWebhookLogs to list webhook logs - ListWebhookLogs(pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) + ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) } diff --git a/server/db/providers/sql/env.go b/server/db/providers/sql/env.go index 13b45a4..1f34c38 100644 --- a/server/db/providers/sql/env.go +++ b/server/db/providers/sql/env.go @@ -1,6 +1,7 @@ package sql import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -8,7 +9,7 @@ import ( ) // AddEnv to save environment information in database -func (p *provider) AddEnv(env models.Env) (models.Env, error) { +func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) { if env.ID == "" { env.ID = uuid.New().String() } @@ -25,7 +26,7 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) { } // UpdateEnv to update environment information in database -func (p *provider) UpdateEnv(env models.Env) (models.Env, error) { +func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) { env.UpdatedAt = time.Now().Unix() result := p.db.Save(&env) @@ -36,7 +37,7 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) { } // GetEnv to get environment information from database -func (p *provider) GetEnv() (models.Env, error) { +func (p *provider) GetEnv(ctx context.Context) (models.Env, error) { var env models.Env result := p.db.First(&env) diff --git a/server/db/providers/sql/session.go b/server/db/providers/sql/session.go index 4e7e7f1..32c7e7e 100644 --- a/server/db/providers/sql/session.go +++ b/server/db/providers/sql/session.go @@ -1,6 +1,7 @@ package sql import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -9,7 +10,7 @@ import ( ) // AddSession to save session information in database -func (p *provider) AddSession(session models.Session) error { +func (p *provider) AddSession(ctx context.Context, session models.Session) error { if session.ID == "" { session.ID = uuid.New().String() } @@ -28,7 +29,7 @@ func (p *provider) AddSession(session models.Session) error { } // DeleteSession to delete session information from database -func (p *provider) DeleteSession(userId string) error { +func (p *provider) DeleteSession(ctx context.Context, userId string) error { result := p.db.Where("user_id = ?", userId).Delete(&models.Session{}) if result.Error != nil { diff --git a/server/db/providers/sql/user.go b/server/db/providers/sql/user.go index 6d4d889..07a6e91 100644 --- a/server/db/providers/sql/user.go +++ b/server/db/providers/sql/user.go @@ -1,6 +1,7 @@ package sql import ( + "context" "time" "github.com/authorizerdev/authorizer/server/constants" @@ -12,7 +13,7 @@ import ( ) // AddUser to save user information in database -func (p *provider) AddUser(user models.User) (models.User, error) { +func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) { if user.ID == "" { user.ID = uuid.New().String() } @@ -42,7 +43,7 @@ func (p *provider) AddUser(user models.User) (models.User, error) { } // UpdateUser to update user information in database -func (p *provider) UpdateUser(user models.User) (models.User, error) { +func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) { user.UpdatedAt = time.Now().Unix() result := p.db.Save(&user) @@ -55,7 +56,7 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) { } // DeleteUser to delete user information from database -func (p *provider) DeleteUser(user models.User) error { +func (p *provider) DeleteUser(ctx context.Context, user models.User) error { result := p.db.Delete(&user) if result.Error != nil { @@ -66,7 +67,7 @@ func (p *provider) DeleteUser(user models.User) error { } // ListUsers to get list of users from database -func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) { +func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) { var users []models.User result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&users) if result.Error != nil { @@ -94,7 +95,7 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) } // GetUserByEmail to get user information from database using email address -func (p *provider) GetUserByEmail(email string) (models.User, error) { +func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) { var user models.User result := p.db.Where("email = ?", email).First(&user) if result.Error != nil { @@ -105,7 +106,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) { } // GetUserByID to get user information from database using user ID -func (p *provider) GetUserByID(id string) (models.User, error) { +func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) { var user models.User result := p.db.Where("id = ?", id).First(&user) diff --git a/server/db/providers/sql/verification_requests.go b/server/db/providers/sql/verification_requests.go index 934d4cd..5b413b0 100644 --- a/server/db/providers/sql/verification_requests.go +++ b/server/db/providers/sql/verification_requests.go @@ -1,6 +1,7 @@ package sql import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -10,7 +11,7 @@ import ( ) // AddVerification to save verification request in database -func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) { +func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) { if verificationRequest.ID == "" { verificationRequest.ID = uuid.New().String() } @@ -31,7 +32,7 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio } // GetVerificationRequestByToken to get verification request from database using token -func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) { +func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) { var verificationRequest models.VerificationRequest result := p.db.Where("token = ?", token).First(&verificationRequest) @@ -43,7 +44,7 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat } // GetVerificationRequestByEmail to get verification request by email from database -func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) { +func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) { var verificationRequest models.VerificationRequest result := p.db.Where("email = ? AND identifier = ?", email, identifier).First(&verificationRequest) @@ -56,7 +57,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string } // ListVerificationRequests to get list of verification requests from database -func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) { +func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) { var verificationRequests []models.VerificationRequest result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&verificationRequests) @@ -85,7 +86,7 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model } // DeleteVerificationRequest to delete verification request from database -func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error { +func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error { result := p.db.Delete(&verificationRequest) if result.Error != nil { diff --git a/server/db/providers/sql/webhook.go b/server/db/providers/sql/webhook.go index 9977fbf..1a9a257 100644 --- a/server/db/providers/sql/webhook.go +++ b/server/db/providers/sql/webhook.go @@ -1,6 +1,7 @@ package sql import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -9,7 +10,7 @@ import ( ) // AddWebhook to add webhook -func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { +func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) { if webhook.ID == "" { webhook.ID = uuid.New().String() } @@ -19,25 +20,25 @@ func (p *provider) AddWebhook(webhook models.Webhook) (models.Webhook, error) { webhook.UpdatedAt = time.Now().Unix() res := p.db.Create(&webhook) if res.Error != nil { - return webhook, res.Error + return nil, res.Error } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // UpdateWebhook to update webhook -func (p *provider) UpdateWebhook(webhook models.Webhook) (models.Webhook, error) { +func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) { webhook.UpdatedAt = time.Now().Unix() result := p.db.Save(&webhook) if result.Error != nil { - return webhook, result.Error + return nil, result.Error } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // ListWebhooks to list webhook -func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, error) { +func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) { var webhooks []models.Webhook result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&webhooks) @@ -65,30 +66,30 @@ func (p *provider) ListWebhook(pagination model.Pagination) (*model.Webhooks, er } // GetWebhookByID to get webhook by id -func (p *provider) GetWebhookByID(webhookID string) (models.Webhook, error) { +func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) { var webhook models.Webhook result := p.db.Where("id = ?", webhookID).First(webhook) if result.Error != nil { - return webhook, result.Error + return nil, result.Error } - return webhook, nil + return webhook.AsAPIWebhook(), nil } // GetWebhookByEventName to get webhook by event_name -func (p *provider) GetWebhookByEventName(eventName string) (models.Webhook, error) { +func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) { var webhook models.Webhook result := p.db.Where("event_name = ?", eventName).First(webhook) if result.Error != nil { - return webhook, result.Error + return nil, result.Error } - return models.Webhook{}, nil + return webhook.AsAPIWebhook(), nil } // DeleteWebhook to delete webhook -func (p *provider) DeleteWebhook(webhook models.Webhook) error { - result := p.db.Delete(&webhook) +func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error { + result := p.db.Delete(&models.Webhook{}, webhook.ID) if result.Error != nil { return result.Error } diff --git a/server/db/providers/sql/webhook_log.go b/server/db/providers/sql/webhook_log.go index 3992e75..0ccbca2 100644 --- a/server/db/providers/sql/webhook_log.go +++ b/server/db/providers/sql/webhook_log.go @@ -1,6 +1,7 @@ package sql import ( + "context" "time" "github.com/authorizerdev/authorizer/server/db/models" @@ -11,7 +12,7 @@ import ( ) // AddWebhookLog to add webhook log -func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLog, error) { +func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) { if webhookLog.ID == "" { webhookLog.ID = uuid.New().String() } @@ -24,14 +25,14 @@ func (p *provider) AddWebhookLog(webhookLog models.WebhookLog) (models.WebhookLo DoNothing: true, }).Create(&webhookLog) if res.Error != nil { - return webhookLog, res.Error + return nil, res.Error } - return webhookLog, nil + return webhookLog.AsAPIWebhookLog(), nil } // ListWebhookLogs to list webhook logs -func (p *provider) ListWebhookLogs(pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { +func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) { var webhookLogs []models.WebhookLog var result *gorm.DB var totalRes *gorm.DB diff --git a/server/env/persist_env.go b/server/env/persist_env.go index 15040bb..381cfad 100644 --- a/server/env/persist_env.go +++ b/server/env/persist_env.go @@ -1,6 +1,7 @@ package env import ( + "context" "encoding/json" "os" "reflect" @@ -58,7 +59,8 @@ func fixBackwardCompatibility(data map[string]interface{}) (bool, map[string]int // GetEnvData returns the env data from database func GetEnvData() (map[string]interface{}, error) { var result map[string]interface{} - env, err := db.Provider.GetEnv() + ctx := context.Background() + env, err := db.Provider.GetEnv(ctx) // config not found in db if err != nil { log.Debug("Error while getting env data from db: ", err) @@ -108,7 +110,8 @@ func GetEnvData() (map[string]interface{}, error) { // PersistEnv persists the environment variables to the database func PersistEnv() error { - env, err := db.Provider.GetEnv() + ctx := context.Background() + env, err := db.Provider.GetEnv(ctx) // config not found in db if err != nil { // AES encryption needs 32 bit key only, so we chop off last 4 characters from 36 bit uuid @@ -137,7 +140,7 @@ func PersistEnv() error { EnvData: encryptedConfig, } - env, err = db.Provider.AddEnv(env) + env, err = db.Provider.AddEnv(ctx, env) if err != nil { log.Debug("Error while persisting env data to db: ", err) return err @@ -251,7 +254,7 @@ func PersistEnv() error { } env.EnvData = encryptedConfig - _, err = db.Provider.UpdateEnv(env) + _, err = db.Provider.UpdateEnv(ctx, env) if err != nil { log.Debug("Failed to Update Config: ", err) return err diff --git a/server/graph/generated/generated.go b/server/graph/generated/generated.go index e4f972f..1eccc26 100644 --- a/server/graph/generated/generated.go +++ b/server/graph/generated/generated.go @@ -130,10 +130,12 @@ type ComplexityRoot struct { } Mutation struct { + AddWebhook func(childComplexity int, params model.AddWebhookRequest) int AdminLogin func(childComplexity int, params model.AdminLoginInput) int AdminLogout func(childComplexity int) int AdminSignup func(childComplexity int, params model.AdminSignupInput) int DeleteUser func(childComplexity int, params model.DeleteUserInput) int + DeleteWebhook func(childComplexity int, params model.WebhookRequest) int EnableAccess func(childComplexity int, param model.UpdateAccessInput) int ForgotPassword func(childComplexity int, params model.ForgotPasswordInput) int GenerateJwtKeys func(childComplexity int, params model.GenerateJWTKeysInput) int @@ -146,9 +148,11 @@ type ComplexityRoot struct { Revoke func(childComplexity int, params model.OAuthRevokeInput) int RevokeAccess func(childComplexity int, param model.UpdateAccessInput) int Signup func(childComplexity int, params model.SignUpInput) int + TestEndpoint func(childComplexity int, params model.TestEndpointRequest) int UpdateEnv func(childComplexity int, params model.UpdateEnvInput) int UpdateProfile func(childComplexity int, params model.UpdateProfileInput) int UpdateUser func(childComplexity int, params model.UpdateUserInput) int + UpdateWebhook func(childComplexity int, params model.UpdateWebhookRequest) int VerifyEmail func(childComplexity int, params model.VerifyEmailInput) int } @@ -168,7 +172,8 @@ type ComplexityRoot struct { Users func(childComplexity int, params *model.PaginatedInput) int ValidateJwtToken func(childComplexity int, params model.ValidateJWTTokenInput) int VerificationRequests func(childComplexity int, params *model.PaginatedInput) int - WebhookLogs func(childComplexity int, params *model.ListWebhookLogRequest) int + Webhook func(childComplexity int, params model.WebhookRequest) int + WebhookLogs func(childComplexity int, params model.ListWebhookLogRequest) int Webhooks func(childComplexity int, params *model.PaginatedInput) int } @@ -176,6 +181,11 @@ type ComplexityRoot struct { Message func(childComplexity int) int } + TestEndpointResponse struct { + HTTPStatus func(childComplexity int) int + Response func(childComplexity int) int + } + User struct { Birthdate func(childComplexity int) int CreatedAt func(childComplexity int) int @@ -228,6 +238,7 @@ type ComplexityRoot struct { Enabled func(childComplexity int) int Endpoint func(childComplexity int) int EventName func(childComplexity int) int + Headers func(childComplexity int) int ID func(childComplexity int) int UpdatedAt func(childComplexity int) int } @@ -274,6 +285,10 @@ type MutationResolver interface { RevokeAccess(ctx context.Context, param model.UpdateAccessInput) (*model.Response, error) EnableAccess(ctx context.Context, param model.UpdateAccessInput) (*model.Response, error) GenerateJwtKeys(ctx context.Context, params model.GenerateJWTKeysInput) (*model.GenerateJWTKeysResponse, error) + AddWebhook(ctx context.Context, params model.AddWebhookRequest) (*model.Response, error) + UpdateWebhook(ctx context.Context, params model.UpdateWebhookRequest) (*model.Response, error) + DeleteWebhook(ctx context.Context, params model.WebhookRequest) (*model.Response, error) + TestEndpoint(ctx context.Context, params model.TestEndpointRequest) (*model.TestEndpointResponse, error) } type QueryResolver interface { Meta(ctx context.Context) (*model.Meta, error) @@ -284,8 +299,9 @@ type QueryResolver interface { VerificationRequests(ctx context.Context, params *model.PaginatedInput) (*model.VerificationRequests, error) AdminSession(ctx context.Context) (*model.Response, error) Env(ctx context.Context) (*model.Env, error) + Webhook(ctx context.Context, params model.WebhookRequest) (*model.Webhook, error) Webhooks(ctx context.Context, params *model.PaginatedInput) (*model.Webhooks, error) - WebhookLogs(ctx context.Context, params *model.ListWebhookLogRequest) (*model.WebhookLogs, error) + WebhookLogs(ctx context.Context, params model.ListWebhookLogRequest) (*model.WebhookLogs, error) } type executableSchema struct { @@ -800,6 +816,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Meta.Version(childComplexity), true + case "Mutation._add_webhook": + if e.complexity.Mutation.AddWebhook == nil { + break + } + + args, err := ec.field_Mutation__add_webhook_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.AddWebhook(childComplexity, args["params"].(model.AddWebhookRequest)), true + case "Mutation._admin_login": if e.complexity.Mutation.AdminLogin == nil { break @@ -843,6 +871,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.DeleteUser(childComplexity, args["params"].(model.DeleteUserInput)), true + case "Mutation._delete_webhook": + if e.complexity.Mutation.DeleteWebhook == nil { + break + } + + args, err := ec.field_Mutation__delete_webhook_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.DeleteWebhook(childComplexity, args["params"].(model.WebhookRequest)), true + case "Mutation._enable_access": if e.complexity.Mutation.EnableAccess == nil { break @@ -982,6 +1022,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.Signup(childComplexity, args["params"].(model.SignUpInput)), true + case "Mutation._test_endpoint": + if e.complexity.Mutation.TestEndpoint == nil { + break + } + + args, err := ec.field_Mutation__test_endpoint_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.TestEndpoint(childComplexity, args["params"].(model.TestEndpointRequest)), true + case "Mutation._update_env": if e.complexity.Mutation.UpdateEnv == nil { break @@ -1018,6 +1070,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.UpdateUser(childComplexity, args["params"].(model.UpdateUserInput)), true + case "Mutation._update_webhook": + if e.complexity.Mutation.UpdateWebhook == nil { + break + } + + args, err := ec.field_Mutation__update_webhook_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.UpdateWebhook(childComplexity, args["params"].(model.UpdateWebhookRequest)), true + case "Mutation.verify_email": if e.complexity.Mutation.VerifyEmail == nil { break @@ -1134,6 +1198,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.VerificationRequests(childComplexity, args["params"].(*model.PaginatedInput)), true + case "Query._webhook": + if e.complexity.Query.Webhook == nil { + break + } + + args, err := ec.field_Query__webhook_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Webhook(childComplexity, args["params"].(model.WebhookRequest)), true + case "Query._webhook_logs": if e.complexity.Query.WebhookLogs == nil { break @@ -1144,7 +1220,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.WebhookLogs(childComplexity, args["params"].(*model.ListWebhookLogRequest)), true + return e.complexity.Query.WebhookLogs(childComplexity, args["params"].(model.ListWebhookLogRequest)), true case "Query._webhooks": if e.complexity.Query.Webhooks == nil { @@ -1165,6 +1241,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Response.Message(childComplexity), true + case "TestEndpointResponse.http_status": + if e.complexity.TestEndpointResponse.HTTPStatus == nil { + break + } + + return e.complexity.TestEndpointResponse.HTTPStatus(childComplexity), true + + case "TestEndpointResponse.response": + if e.complexity.TestEndpointResponse.Response == nil { + break + } + + return e.complexity.TestEndpointResponse.Response(childComplexity), true + case "User.birthdate": if e.complexity.User.Birthdate == nil { break @@ -1417,6 +1507,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Webhook.EventName(childComplexity), true + case "Webhook.headers": + if e.complexity.Webhook.Headers == nil { + break + } + + return e.complexity.Webhook.Headers(childComplexity), true + case "Webhook.id": if e.complexity.Webhook.ID == nil { break @@ -1903,6 +2000,7 @@ type Webhook { event_name: String endpoint: String enabled: Boolean + headers: Map created_at: Int64 updated_at: Int64 } @@ -1922,11 +2020,41 @@ type WebhookLog { updated_at: Int64 } +type TestEndpointResponse { + http_status: Int64 + response: Map +} + input ListWebhookLogRequest { pagination: PaginatedInput! webhook_id: String } +input AddWebhookRequest { + event_name: String! + endpoint: String! + enabled: Boolean! + headers: Map +} + +input UpdateWebhookRequest { + id: ID! + event_name: String + endpoint: String + enabled: Boolean + headers: Map +} + +input WebhookRequest { + id: ID! +} + +input TestEndpointRequest { + endpoint: String! + event_name: String! + headers: Map +} + type WebhookLogs { pagination: Pagination! webhook_logs: [WebhookLog!]! @@ -1954,6 +2082,10 @@ type Mutation { _revoke_access(param: UpdateAccessInput!): Response! _enable_access(param: UpdateAccessInput!): Response! _generate_jwt_keys(params: GenerateJWTKeysInput!): GenerateJWTKeysResponse! + _add_webhook(params: AddWebhookRequest!): Response! + _update_webhook(params: UpdateWebhookRequest!): Response! + _delete_webhook(params: WebhookRequest!): Response! + _test_endpoint(params: TestEndpointRequest!): TestEndpointResponse! } type Query { @@ -1966,8 +2098,9 @@ type Query { _verification_requests(params: PaginatedInput): VerificationRequests! _admin_session: Response! _env: Env! + _webhook(params: WebhookRequest!): Webhook! _webhooks(params: PaginatedInput): Webhooks! - _webhook_logs(params: ListWebhookLogRequest): WebhookLogs! + _webhook_logs(params: ListWebhookLogRequest!): WebhookLogs! } `, BuiltIn: false}, } @@ -1977,6 +2110,21 @@ var parsedSchema = gqlparser.MustLoadSchema(sources...) // region ***************************** args.gotpl ***************************** +func (ec *executionContext) field_Mutation__add_webhook_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.AddWebhookRequest + if tmp, ok := rawArgs["params"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params")) + arg0, err = ec.unmarshalNAddWebhookRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐAddWebhookRequest(ctx, tmp) + if err != nil { + return nil, err + } + } + args["params"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation__admin_login_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -2022,6 +2170,21 @@ func (ec *executionContext) field_Mutation__delete_user_args(ctx context.Context return args, nil } +func (ec *executionContext) field_Mutation__delete_webhook_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.WebhookRequest + if tmp, ok := rawArgs["params"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params")) + arg0, err = ec.unmarshalNWebhookRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookRequest(ctx, tmp) + if err != nil { + return nil, err + } + } + args["params"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation__enable_access_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -2082,6 +2245,21 @@ func (ec *executionContext) field_Mutation__revoke_access_args(ctx context.Conte return args, nil } +func (ec *executionContext) field_Mutation__test_endpoint_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.TestEndpointRequest + if tmp, ok := rawArgs["params"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params")) + arg0, err = ec.unmarshalNTestEndpointRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐTestEndpointRequest(ctx, tmp) + if err != nil { + return nil, err + } + } + args["params"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation__update_env_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -2112,6 +2290,21 @@ func (ec *executionContext) field_Mutation__update_user_args(ctx context.Context return args, nil } +func (ec *executionContext) field_Mutation__update_webhook_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.UpdateWebhookRequest + if tmp, ok := rawArgs["params"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params")) + arg0, err = ec.unmarshalNUpdateWebhookRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐUpdateWebhookRequest(ctx, tmp) + if err != nil { + return nil, err + } + } + args["params"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_forgot_password_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -2292,13 +2485,28 @@ func (ec *executionContext) field_Query__verification_requests_args(ctx context. return args, nil } +func (ec *executionContext) field_Query__webhook_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.WebhookRequest + if tmp, ok := rawArgs["params"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params")) + arg0, err = ec.unmarshalNWebhookRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookRequest(ctx, tmp) + if err != nil { + return nil, err + } + } + args["params"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query__webhook_logs_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 *model.ListWebhookLogRequest + var arg0 model.ListWebhookLogRequest if tmp, ok := rawArgs["params"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params")) - arg0, err = ec.unmarshalOListWebhookLogRequest2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐListWebhookLogRequest(ctx, tmp) + arg0, err = ec.unmarshalNListWebhookLogRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐListWebhookLogRequest(ctx, tmp) if err != nil { return nil, err } @@ -5560,6 +5768,174 @@ func (ec *executionContext) _Mutation__generate_jwt_keys(ctx context.Context, fi return ec.marshalNGenerateJWTKeysResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐGenerateJWTKeysResponse(ctx, field.Selections, res) } +func (ec *executionContext) _Mutation__add_webhook(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation__add_webhook_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().AddWebhook(rctx, args["params"].(model.AddWebhookRequest)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Response) + fc.Result = res + return ec.marshalNResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐResponse(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation__update_webhook(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation__update_webhook_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().UpdateWebhook(rctx, args["params"].(model.UpdateWebhookRequest)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Response) + fc.Result = res + return ec.marshalNResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐResponse(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation__delete_webhook(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation__delete_webhook_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().DeleteWebhook(rctx, args["params"].(model.WebhookRequest)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Response) + fc.Result = res + return ec.marshalNResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐResponse(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation__test_endpoint(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation__test_endpoint_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().TestEndpoint(rctx, args["params"].(model.TestEndpointRequest)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.TestEndpointResponse) + fc.Result = res + return ec.marshalNTestEndpointResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐTestEndpointResponse(ctx, field.Selections, res) +} + func (ec *executionContext) _Pagination_limit(ctx context.Context, field graphql.CollectedField, obj *model.Pagination) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -6008,6 +6384,48 @@ func (ec *executionContext) _Query__env(ctx context.Context, field graphql.Colle return ec.marshalNEnv2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐEnv(ctx, field.Selections, res) } +func (ec *executionContext) _Query__webhook(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query__webhook_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Webhook(rctx, args["params"].(model.WebhookRequest)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Webhook) + fc.Result = res + return ec.marshalNWebhook2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhook(ctx, field.Selections, res) +} + func (ec *executionContext) _Query__webhooks(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -6075,7 +6493,7 @@ func (ec *executionContext) _Query__webhook_logs(ctx context.Context, field grap 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().WebhookLogs(rctx, args["params"].(*model.ListWebhookLogRequest)) + return ec.resolvers.Query().WebhookLogs(rctx, args["params"].(model.ListWebhookLogRequest)) }) if err != nil { ec.Error(ctx, err) @@ -6198,6 +6616,70 @@ func (ec *executionContext) _Response_message(ctx context.Context, field graphql return ec.marshalNString2string(ctx, field.Selections, res) } +func (ec *executionContext) _TestEndpointResponse_http_status(ctx context.Context, field graphql.CollectedField, obj *model.TestEndpointResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "TestEndpointResponse", + 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.HTTPStatus, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*int64) + fc.Result = res + return ec.marshalOInt642ᚖint64(ctx, field.Selections, res) +} + +func (ec *executionContext) _TestEndpointResponse_response(ctx context.Context, field graphql.CollectedField, obj *model.TestEndpointResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "TestEndpointResponse", + 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.Response, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(map[string]interface{}) + fc.Result = res + return ec.marshalOMap2map(ctx, field.Selections, res) +} + func (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *model.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -7386,6 +7868,38 @@ func (ec *executionContext) _Webhook_enabled(ctx context.Context, field graphql. return ec.marshalOBoolean2ᚖbool(ctx, field.Selections, res) } +func (ec *executionContext) _Webhook_headers(ctx context.Context, field graphql.CollectedField, obj *model.Webhook) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Webhook", + 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.Headers, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(map[string]interface{}) + fc.Result = res + return ec.marshalOMap2map(ctx, field.Selections, res) +} + func (ec *executionContext) _Webhook_created_at(ctx context.Context, field graphql.CollectedField, obj *model.Webhook) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -8939,6 +9453,53 @@ func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.Co // region **************************** input.gotpl ***************************** +func (ec *executionContext) unmarshalInputAddWebhookRequest(ctx context.Context, obj interface{}) (model.AddWebhookRequest, error) { + var it model.AddWebhookRequest + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "event_name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("event_name")) + it.EventName, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "endpoint": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("endpoint")) + it.Endpoint, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "enabled": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("enabled")) + it.Enabled, err = ec.unmarshalNBoolean2bool(ctx, v) + if err != nil { + return it, err + } + case "headers": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("headers")) + it.Headers, err = ec.unmarshalOMap2map(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputAdminLoginInput(ctx context.Context, obj interface{}) (model.AdminLoginInput, error) { var it model.AdminLoginInput asMap := map[string]interface{}{} @@ -9539,6 +10100,45 @@ func (ec *executionContext) unmarshalInputSignUpInput(ctx context.Context, obj i return it, nil } +func (ec *executionContext) unmarshalInputTestEndpointRequest(ctx context.Context, obj interface{}) (model.TestEndpointRequest, error) { + var it model.TestEndpointRequest + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "endpoint": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("endpoint")) + it.Endpoint, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "event_name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("event_name")) + it.EventName, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "headers": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("headers")) + it.Headers, err = ec.unmarshalOMap2map(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputUpdateAccessInput(ctx context.Context, obj interface{}) (model.UpdateAccessInput, error) { var it model.UpdateAccessInput asMap := map[string]interface{}{} @@ -10111,6 +10711,61 @@ func (ec *executionContext) unmarshalInputUpdateUserInput(ctx context.Context, o return it, nil } +func (ec *executionContext) unmarshalInputUpdateWebhookRequest(ctx context.Context, obj interface{}) (model.UpdateWebhookRequest, error) { + var it model.UpdateWebhookRequest + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalNID2string(ctx, v) + if err != nil { + return it, err + } + case "event_name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("event_name")) + it.EventName, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "endpoint": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("endpoint")) + it.Endpoint, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "enabled": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("enabled")) + it.Enabled, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "headers": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("headers")) + it.Headers, err = ec.unmarshalOMap2map(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputValidateJWTTokenInput(ctx context.Context, obj interface{}) (model.ValidateJWTTokenInput, error) { var it model.ValidateJWTTokenInput asMap := map[string]interface{}{} @@ -10173,6 +10828,29 @@ func (ec *executionContext) unmarshalInputVerifyEmailInput(ctx context.Context, return it, nil } +func (ec *executionContext) unmarshalInputWebhookRequest(ctx context.Context, obj interface{}) (model.WebhookRequest, error) { + var it model.WebhookRequest + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalNID2string(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + // endregion **************************** input.gotpl ***************************** // region ************************** interface.gotpl *************************** @@ -10620,6 +11298,26 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { invalids++ } + case "_add_webhook": + out.Values[i] = ec._Mutation__add_webhook(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "_update_webhook": + out.Values[i] = ec._Mutation__update_webhook(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "_delete_webhook": + out.Values[i] = ec._Mutation__delete_webhook(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "_test_endpoint": + out.Values[i] = ec._Mutation__test_endpoint(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -10800,6 +11498,20 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } return res }) + case "_webhook": + 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__webhook(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "_webhooks": field := field out.Concurrently(i, func() (res graphql.Marshaler) { @@ -10870,6 +11582,32 @@ func (ec *executionContext) _Response(ctx context.Context, sel ast.SelectionSet, return out } +var testEndpointResponseImplementors = []string{"TestEndpointResponse"} + +func (ec *executionContext) _TestEndpointResponse(ctx context.Context, sel ast.SelectionSet, obj *model.TestEndpointResponse) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, testEndpointResponseImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("TestEndpointResponse") + case "http_status": + out.Values[i] = ec._TestEndpointResponse_http_status(ctx, field, obj) + case "response": + out.Values[i] = ec._TestEndpointResponse_response(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var userImplementors = []string{"User"} func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *model.User) graphql.Marshaler { @@ -11099,6 +11837,8 @@ func (ec *executionContext) _Webhook(ctx context.Context, sel ast.SelectionSet, out.Values[i] = ec._Webhook_endpoint(ctx, field, obj) case "enabled": out.Values[i] = ec._Webhook_enabled(ctx, field, obj) + case "headers": + out.Values[i] = ec._Webhook_headers(ctx, field, obj) case "created_at": out.Values[i] = ec._Webhook_created_at(ctx, field, obj) case "updated_at": @@ -11467,6 +12207,11 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o // region ***************************** type.gotpl ***************************** +func (ec *executionContext) unmarshalNAddWebhookRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐAddWebhookRequest(ctx context.Context, v interface{}) (model.AddWebhookRequest, error) { + res, err := ec.unmarshalInputAddWebhookRequest(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalNAdminLoginInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐAdminLoginInput(ctx context.Context, v interface{}) (model.AdminLoginInput, error) { res, err := ec.unmarshalInputAdminLoginInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -11584,6 +12329,11 @@ func (ec *executionContext) unmarshalNInviteMemberInput2githubᚗcomᚋauthorize return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalNListWebhookLogRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐListWebhookLogRequest(ctx context.Context, v interface{}) (model.ListWebhookLogRequest, error) { + res, err := ec.unmarshalInputListWebhookLogRequest(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalNLoginInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐLoginInput(ctx context.Context, v interface{}) (model.LoginInput, error) { res, err := ec.unmarshalInputLoginInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -11708,6 +12458,25 @@ func (ec *executionContext) marshalNString2ᚕstringᚄ(ctx context.Context, sel return ret } +func (ec *executionContext) unmarshalNTestEndpointRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐTestEndpointRequest(ctx context.Context, v interface{}) (model.TestEndpointRequest, error) { + res, err := ec.unmarshalInputTestEndpointRequest(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNTestEndpointResponse2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐTestEndpointResponse(ctx context.Context, sel ast.SelectionSet, v model.TestEndpointResponse) graphql.Marshaler { + return ec._TestEndpointResponse(ctx, sel, &v) +} + +func (ec *executionContext) marshalNTestEndpointResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐTestEndpointResponse(ctx context.Context, sel ast.SelectionSet, v *model.TestEndpointResponse) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._TestEndpointResponse(ctx, sel, v) +} + func (ec *executionContext) unmarshalNUpdateAccessInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐUpdateAccessInput(ctx context.Context, v interface{}) (model.UpdateAccessInput, error) { res, err := ec.unmarshalInputUpdateAccessInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -11728,6 +12497,11 @@ func (ec *executionContext) unmarshalNUpdateUserInput2githubᚗcomᚋauthorizerd return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalNUpdateWebhookRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐUpdateWebhookRequest(ctx context.Context, v interface{}) (model.UpdateWebhookRequest, error) { + res, err := ec.unmarshalInputUpdateWebhookRequest(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalNUser2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐUser(ctx context.Context, sel ast.SelectionSet, v model.User) graphql.Marshaler { return ec._User(ctx, sel, &v) } @@ -11892,6 +12666,10 @@ func (ec *executionContext) unmarshalNVerifyEmailInput2githubᚗcomᚋauthorizer return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalNWebhook2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhook(ctx context.Context, sel ast.SelectionSet, v model.Webhook) graphql.Marshaler { + return ec._Webhook(ctx, sel, &v) +} + func (ec *executionContext) marshalNWebhook2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Webhook) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -12014,6 +12792,11 @@ func (ec *executionContext) marshalNWebhookLogs2ᚖgithubᚗcomᚋauthorizerdev return ec._WebhookLogs(ctx, sel, v) } +func (ec *executionContext) unmarshalNWebhookRequest2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhookRequest(ctx context.Context, v interface{}) (model.WebhookRequest, error) { + res, err := ec.unmarshalInputWebhookRequest(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalNWebhooks2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐWebhooks(ctx context.Context, sel ast.SelectionSet, v model.Webhooks) graphql.Marshaler { return ec._Webhooks(ctx, sel, &v) } @@ -12339,12 +13122,19 @@ func (ec *executionContext) marshalOInt642ᚖint64(ctx context.Context, sel ast. return graphql.MarshalInt64(*v) } -func (ec *executionContext) unmarshalOListWebhookLogRequest2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐListWebhookLogRequest(ctx context.Context, v interface{}) (*model.ListWebhookLogRequest, error) { +func (ec *executionContext) unmarshalOMap2map(ctx context.Context, v interface{}) (map[string]interface{}, error) { if v == nil { return nil, nil } - res, err := ec.unmarshalInputListWebhookLogRequest(ctx, v) - return &res, graphql.ErrorOnPath(ctx, err) + res, err := graphql.UnmarshalMap(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOMap2map(ctx context.Context, sel ast.SelectionSet, v map[string]interface{}) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return graphql.MarshalMap(v) } func (ec *executionContext) unmarshalOPaginatedInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginatedInput(ctx context.Context, v interface{}) (*model.PaginatedInput, error) { diff --git a/server/graph/model/models_gen.go b/server/graph/model/models_gen.go index 1bfa467..b1b9542 100644 --- a/server/graph/model/models_gen.go +++ b/server/graph/model/models_gen.go @@ -2,6 +2,13 @@ package model +type AddWebhookRequest struct { + EventName string `json:"event_name"` + Endpoint string `json:"endpoint"` + Enabled bool `json:"enabled"` + Headers map[string]interface{} `json:"headers"` +} + type AdminLoginInput struct { AdminSecret string `json:"admin_secret"` } @@ -192,6 +199,17 @@ type SignUpInput struct { RedirectURI *string `json:"redirect_uri"` } +type TestEndpointRequest struct { + Endpoint string `json:"endpoint"` + EventName string `json:"event_name"` + Headers map[string]interface{} `json:"headers"` +} + +type TestEndpointResponse struct { + HTTPStatus *int64 `json:"http_status"` + Response map[string]interface{} `json:"response"` +} + type UpdateAccessInput struct { UserID string `json:"user_id"` } @@ -268,6 +286,14 @@ type UpdateUserInput struct { Roles []*string `json:"roles"` } +type UpdateWebhookRequest struct { + ID string `json:"id"` + EventName *string `json:"event_name"` + Endpoint *string `json:"endpoint"` + Enabled *bool `json:"enabled"` + Headers map[string]interface{} `json:"headers"` +} + type User struct { ID string `json:"id"` Email string `json:"email"` @@ -326,12 +352,13 @@ type VerifyEmailInput struct { } type Webhook struct { - ID string `json:"id"` - EventName *string `json:"event_name"` - Endpoint *string `json:"endpoint"` - Enabled *bool `json:"enabled"` - CreatedAt *int64 `json:"created_at"` - UpdatedAt *int64 `json:"updated_at"` + ID string `json:"id"` + EventName *string `json:"event_name"` + Endpoint *string `json:"endpoint"` + Enabled *bool `json:"enabled"` + Headers map[string]interface{} `json:"headers"` + CreatedAt *int64 `json:"created_at"` + UpdatedAt *int64 `json:"updated_at"` } type WebhookLog struct { @@ -349,6 +376,10 @@ type WebhookLogs struct { WebhookLogs []*WebhookLog `json:"webhook_logs"` } +type WebhookRequest struct { + ID string `json:"id"` +} + type Webhooks struct { Pagination *Pagination `json:"pagination"` Webhooks []*Webhook `json:"webhooks"` diff --git a/server/graph/schema.graphqls b/server/graph/schema.graphqls index 27a8534..df8edc9 100644 --- a/server/graph/schema.graphqls +++ b/server/graph/schema.graphqls @@ -329,6 +329,7 @@ type Webhook { event_name: String endpoint: String enabled: Boolean + headers: Map created_at: Int64 updated_at: Int64 } @@ -348,11 +349,41 @@ type WebhookLog { updated_at: Int64 } +type TestEndpointResponse { + http_status: Int64 + response: Map +} + input ListWebhookLogRequest { pagination: PaginatedInput! webhook_id: String } +input AddWebhookRequest { + event_name: String! + endpoint: String! + enabled: Boolean! + headers: Map +} + +input UpdateWebhookRequest { + id: ID! + event_name: String + endpoint: String + enabled: Boolean + headers: Map +} + +input WebhookRequest { + id: ID! +} + +input TestEndpointRequest { + endpoint: String! + event_name: String! + headers: Map +} + type WebhookLogs { pagination: Pagination! webhook_logs: [WebhookLog!]! @@ -380,6 +411,10 @@ type Mutation { _revoke_access(param: UpdateAccessInput!): Response! _enable_access(param: UpdateAccessInput!): Response! _generate_jwt_keys(params: GenerateJWTKeysInput!): GenerateJWTKeysResponse! + _add_webhook(params: AddWebhookRequest!): Response! + _update_webhook(params: UpdateWebhookRequest!): Response! + _delete_webhook(params: WebhookRequest!): Response! + _test_endpoint(params: TestEndpointRequest!): TestEndpointResponse! } type Query { @@ -392,6 +427,7 @@ type Query { _verification_requests(params: PaginatedInput): VerificationRequests! _admin_session: Response! _env: Env! + _webhook(params: WebhookRequest!): Webhook! _webhooks(params: PaginatedInput): Webhooks! - _webhook_logs(params: ListWebhookLogRequest): WebhookLogs! + _webhook_logs(params: ListWebhookLogRequest!): WebhookLogs! } diff --git a/server/graph/schema.resolvers.go b/server/graph/schema.resolvers.go index 5e5cbe3..1776835 100644 --- a/server/graph/schema.resolvers.go +++ b/server/graph/schema.resolvers.go @@ -5,7 +5,6 @@ package graph import ( "context" - "fmt" "github.com/authorizerdev/authorizer/server/graph/generated" "github.com/authorizerdev/authorizer/server/graph/model" @@ -92,6 +91,22 @@ func (r *mutationResolver) GenerateJwtKeys(ctx context.Context, params model.Gen return resolvers.GenerateJWTKeysResolver(ctx, params) } +func (r *mutationResolver) AddWebhook(ctx context.Context, params model.AddWebhookRequest) (*model.Response, error) { + return resolvers.AddWebhookResolver(ctx, params) +} + +func (r *mutationResolver) UpdateWebhook(ctx context.Context, params model.UpdateWebhookRequest) (*model.Response, error) { + return resolvers.UpdateWebhookResolver(ctx, params) +} + +func (r *mutationResolver) DeleteWebhook(ctx context.Context, params model.WebhookRequest) (*model.Response, error) { + return resolvers.DeleteWebhookResolver(ctx, params) +} + +func (r *mutationResolver) TestEndpoint(ctx context.Context, params model.TestEndpointRequest) (*model.TestEndpointResponse, error) { + return resolvers.TestEndpointResolver(ctx, params) +} + func (r *queryResolver) Meta(ctx context.Context) (*model.Meta, error) { return resolvers.MetaResolver(ctx) } @@ -124,12 +139,16 @@ func (r *queryResolver) Env(ctx context.Context) (*model.Env, error) { return resolvers.EnvResolver(ctx) } -func (r *queryResolver) Webhooks(ctx context.Context, params *model.PaginatedInput) (*model.Webhooks, error) { - panic(fmt.Errorf("not implemented")) +func (r *queryResolver) Webhook(ctx context.Context, params model.WebhookRequest) (*model.Webhook, error) { + return resolvers.WebhookResolver(ctx, params) } -func (r *queryResolver) WebhookLogs(ctx context.Context, params *model.ListWebhookLogRequest) (*model.WebhookLogs, error) { - panic(fmt.Errorf("not implemented")) +func (r *queryResolver) Webhooks(ctx context.Context, params *model.PaginatedInput) (*model.Webhooks, error) { + return resolvers.WebhooksResolver(ctx, params) +} + +func (r *queryResolver) WebhookLogs(ctx context.Context, params model.ListWebhookLogRequest) (*model.WebhookLogs, error) { + return resolvers.WebhookLogsResolver(ctx, params) } // Mutation returns generated.MutationResolver implementation. diff --git a/server/handlers/authorize.go b/server/handlers/authorize.go index 372e6e1..d2a9293 100644 --- a/server/handlers/authorize.go +++ b/server/handlers/authorize.go @@ -199,7 +199,7 @@ func AuthorizeHandler() gin.HandlerFunc { return } userID := claims.Subject - user, err := db.Provider.GetUserByID(userID) + user, err := db.Provider.GetUserByID(gc, userID) if err != nil { if isQuery { gc.Redirect(http.StatusFound, loginURL) diff --git a/server/handlers/oauth_callback.go b/server/handlers/oauth_callback.go index 780f7d8..d18bf18 100644 --- a/server/handlers/oauth_callback.go +++ b/server/handlers/oauth_callback.go @@ -28,21 +28,21 @@ import ( // OAuthCallbackHandler handles the OAuth callback for various oauth providers func OAuthCallbackHandler() gin.HandlerFunc { - return func(c *gin.Context) { - provider := c.Param("oauth_provider") - state := c.Request.FormValue("state") + return func(ctx *gin.Context) { + provider := ctx.Param("oauth_provider") + state := ctx.Request.FormValue("state") sessionState, err := memorystore.Provider.GetState(state) if sessionState == "" || err != nil { log.Debug("Invalid oauth state: ", state) - c.JSON(400, gin.H{"error": "invalid oauth state"}) + ctx.JSON(400, gin.H{"error": "invalid oauth state"}) } // contains random token, redirect url, role sessionSplit := strings.Split(state, "___") if len(sessionSplit) < 3 { log.Debug("Unable to get redirect url from state: ", state) - c.JSON(400, gin.H{"error": "invalid redirect url"}) + ctx.JSON(400, gin.H{"error": "invalid redirect url"}) return } @@ -55,7 +55,7 @@ func OAuthCallbackHandler() gin.HandlerFunc { scopes := strings.Split(sessionSplit[3], ",") user := models.User{} - code := c.Request.FormValue("code") + code := ctx.Request.FormValue("code") switch provider { case constants.AuthRecipeMethodGoogle: user, err = processGoogleUserInfo(code) @@ -74,23 +74,23 @@ func OAuthCallbackHandler() gin.HandlerFunc { if err != nil { log.Debug("Failed to process user info: ", err) - c.JSON(400, gin.H{"error": err.Error()}) + ctx.JSON(400, gin.H{"error": err.Error()}) return } - existingUser, err := db.Provider.GetUserByEmail(user.Email) + existingUser, err := db.Provider.GetUserByEmail(ctx, user.Email) log := log.WithField("user", user.Email) if err != nil { isSignupDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) if err != nil { log.Debug("Failed to get signup disabled env variable: ", err) - c.JSON(400, gin.H{"error": err.Error()}) + ctx.JSON(400, gin.H{"error": err.Error()}) return } if isSignupDisabled { log.Debug("Failed to signup as disabled") - c.JSON(400, gin.H{"error": "signup is disabled for this instance"}) + ctx.JSON(400, gin.H{"error": "signup is disabled for this instance"}) return } // user not registered, register user and generate session token @@ -113,19 +113,19 @@ func OAuthCallbackHandler() gin.HandlerFunc { if hasProtectedRole { log.Debug("Signup is not allowed with protected roles:", inputRoles) - c.JSON(400, gin.H{"error": "invalid role"}) + ctx.JSON(400, gin.H{"error": "invalid role"}) return } user.Roles = strings.Join(inputRoles, ",") now := time.Now().Unix() user.EmailVerifiedAt = &now - user, _ = db.Provider.AddUser(user) + user, _ = db.Provider.AddUser(ctx, user) } else { user = existingUser if user.RevokedTimestamp != nil { log.Debug("User access revoked at: ", user.RevokedTimestamp) - c.JSON(400, gin.H{"error": "user access has been revoked"}) + ctx.JSON(400, gin.H{"error": "user access has been revoked"}) return } @@ -175,7 +175,7 @@ func OAuthCallbackHandler() gin.HandlerFunc { if hasProtectedRole { log.Debug("Invalid role. User is using protected unassigned role") - c.JSON(400, gin.H{"error": "invalid role"}) + ctx.JSON(400, gin.H{"error": "invalid role"}) return } else { user.Roles = existingUser.Roles + "," + strings.Join(unasignedRoles, ",") @@ -184,18 +184,18 @@ func OAuthCallbackHandler() gin.HandlerFunc { user.Roles = existingUser.Roles } - user, err = db.Provider.UpdateUser(user) + user, err = db.Provider.UpdateUser(ctx, user) if err != nil { log.Debug("Failed to update user: ", err) - c.JSON(500, gin.H{"error": err.Error()}) + ctx.JSON(500, gin.H{"error": err.Error()}) return } } - authToken, err := token.CreateAuthToken(c, user, inputRoles, scopes, provider) + authToken, err := token.CreateAuthToken(ctx, user, inputRoles, scopes, provider) if err != nil { log.Debug("Failed to create auth token: ", err) - c.JSON(500, gin.H{"error": err.Error()}) + ctx.JSON(500, gin.H{"error": err.Error()}) } expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix() @@ -206,7 +206,7 @@ func OAuthCallbackHandler() gin.HandlerFunc { params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + stateValue + "&id_token=" + authToken.IDToken.Token sessionKey := provider + ":" + user.ID - cookie.SetSession(c, authToken.FingerPrintHash) + cookie.SetSession(ctx, authToken.FingerPrintHash) memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash) memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token) @@ -215,10 +215,10 @@ func OAuthCallbackHandler() gin.HandlerFunc { memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token) } - go db.Provider.AddSession(models.Session{ + go db.Provider.AddSession(ctx, models.Session{ UserID: user.ID, - UserAgent: utils.GetUserAgent(c.Request), - IP: utils.GetIP(c.Request), + UserAgent: utils.GetUserAgent(ctx.Request), + IP: utils.GetIP(ctx.Request), }) if strings.Contains(redirectURL, "?") { redirectURL = redirectURL + "&" + params @@ -226,7 +226,7 @@ func OAuthCallbackHandler() gin.HandlerFunc { redirectURL = redirectURL + "?" + strings.TrimPrefix(params, "&") } - c.Redirect(http.StatusFound, redirectURL) + ctx.Redirect(http.StatusFound, redirectURL) } } diff --git a/server/handlers/token.go b/server/handlers/token.go index e808dbb..090eb6a 100644 --- a/server/handlers/token.go +++ b/server/handlers/token.go @@ -190,7 +190,7 @@ func TokenHandler() gin.HandlerFunc { return } - user, err := db.Provider.GetUserByID(userID) + user, err := db.Provider.GetUserByID(gc, userID) if err != nil { log.Debug("Error getting user: ", err) gc.JSON(http.StatusUnauthorized, gin.H{ diff --git a/server/handlers/userinfo.go b/server/handlers/userinfo.go index 3bc0164..a603fe0 100644 --- a/server/handlers/userinfo.go +++ b/server/handlers/userinfo.go @@ -31,7 +31,7 @@ func UserInfoHandler() gin.HandlerFunc { } userID := claims["sub"].(string) - user, err := db.Provider.GetUserByID(userID) + user, err := db.Provider.GetUserByID(gc, userID) if err != nil { log.Debug("Error getting user: ", err) gc.JSON(http.StatusUnauthorized, gin.H{ diff --git a/server/handlers/verify_email.go b/server/handlers/verify_email.go index 4e9d7d7..6d900bd 100644 --- a/server/handlers/verify_email.go +++ b/server/handlers/verify_email.go @@ -33,7 +33,7 @@ func VerifyEmailHandler() gin.HandlerFunc { return } - verificationRequest, err := db.Provider.GetVerificationRequestByToken(tokenInQuery) + verificationRequest, err := db.Provider.GetVerificationRequestByToken(c, tokenInQuery) if err != nil { log.Debug("Error getting verification request: ", err) errorRes["error_description"] = err.Error() @@ -58,7 +58,7 @@ func VerifyEmailHandler() gin.HandlerFunc { return } - user, err := db.Provider.GetUserByEmail(verificationRequest.Email) + user, err := db.Provider.GetUserByEmail(c, verificationRequest.Email) if err != nil { log.Debug("Error getting user: ", err) errorRes["error_description"] = err.Error() @@ -70,10 +70,10 @@ func VerifyEmailHandler() gin.HandlerFunc { if user.EmailVerifiedAt == nil { now := time.Now().Unix() user.EmailVerifiedAt = &now - db.Provider.UpdateUser(user) + db.Provider.UpdateUser(c, user) } // delete from verification table - db.Provider.DeleteVerificationRequest(verificationRequest) + db.Provider.DeleteVerificationRequest(c, verificationRequest) state := strings.TrimSpace(c.Query("state")) redirectURL := strings.TrimSpace(c.Query("redirect_uri")) @@ -131,7 +131,7 @@ func VerifyEmailHandler() gin.HandlerFunc { redirectURL = redirectURL + "?" + strings.TrimPrefix(params, "&") } - go db.Provider.AddSession(models.Session{ + go db.Provider.AddSession(c, models.Session{ UserID: user.ID, UserAgent: utils.GetUserAgent(c.Request), IP: utils.GetIP(c.Request), diff --git a/server/resolvers/add_webhook.go b/server/resolvers/add_webhook.go new file mode 100644 index 0000000..fd80578 --- /dev/null +++ b/server/resolvers/add_webhook.go @@ -0,0 +1,54 @@ +package resolvers + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/token" + "github.com/authorizerdev/authorizer/server/utils" + "github.com/authorizerdev/authorizer/server/validators" + log "github.com/sirupsen/logrus" +) + +// AddWebhookResolver resolver for add webhook mutation +func AddWebhookResolver(ctx context.Context, params model.AddWebhookRequest) (*model.Response, error) { + gc, err := utils.GinContextFromContext(ctx) + if err != nil { + log.Debug("Failed to get GinContext: ", err) + return nil, err + } + + if !token.IsSuperAdmin(gc) { + log.Debug("Not logged in as super admin") + return nil, fmt.Errorf("unauthorized") + } + + if !validators.IsValidWebhookEventName(params.EventName) { + log.Debug("Invalid Event Name: ", params.EventName) + return nil, fmt.Errorf("invalid event name %s", params.EventName) + } + + headerBytes, err := json.Marshal(params.Headers) + if err != nil { + return nil, err + } + + _, err = db.Provider.AddWebhook(ctx, models.Webhook{ + EventName: params.EventName, + EndPoint: params.Endpoint, + Enabled: params.Enabled, + Headers: string(headerBytes), + }) + if err != nil { + log.Debug("Failed to add webhook: ", err) + return nil, err + } + + return &model.Response{ + Message: `Webhook added successfully`, + }, nil +} diff --git a/server/resolvers/admin_signup.go b/server/resolvers/admin_signup.go index a8d0c3f..c1dd5c1 100644 --- a/server/resolvers/admin_signup.go +++ b/server/resolvers/admin_signup.go @@ -58,7 +58,7 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m return res, err } - env, err := db.Provider.GetEnv() + env, err := db.Provider.GetEnv(ctx) if err != nil { log.Debug("Failed to get env: ", err) return res, err @@ -71,7 +71,7 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m } env.EnvData = envData - if _, err := db.Provider.UpdateEnv(env); err != nil { + if _, err := db.Provider.UpdateEnv(ctx, env); err != nil { log.Debug("Failed to update env: ", err) return res, err } diff --git a/server/resolvers/delete_user.go b/server/resolvers/delete_user.go index 5166769..862e6ac 100644 --- a/server/resolvers/delete_user.go +++ b/server/resolvers/delete_user.go @@ -32,7 +32,7 @@ func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*mod "email": params.Email, }) - user, err := db.Provider.GetUserByEmail(params.Email) + user, err := db.Provider.GetUserByEmail(ctx, params.Email) if err != nil { log.Debug("Failed to get user from DB: ", err) return res, err @@ -40,7 +40,7 @@ func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*mod go memorystore.Provider.DeleteAllUserSessions(user.ID) - err = db.Provider.DeleteUser(user) + err = db.Provider.DeleteUser(ctx, user) if err != nil { log.Debug("Failed to delete user: ", err) return res, err diff --git a/server/resolvers/delete_webhook.go b/server/resolvers/delete_webhook.go new file mode 100644 index 0000000..4241840 --- /dev/null +++ b/server/resolvers/delete_webhook.go @@ -0,0 +1,47 @@ +package resolvers + +import ( + "context" + "fmt" + + "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/token" + "github.com/authorizerdev/authorizer/server/utils" + log "github.com/sirupsen/logrus" +) + +// DeleteWebhookResolver resolver to delete webhook and its relevant logs +func DeleteWebhookResolver(ctx context.Context, params model.WebhookRequest) (*model.Response, error) { + gc, err := utils.GinContextFromContext(ctx) + if err != nil { + log.Debug("Failed to get GinContext: ", err) + return nil, err + } + + if !token.IsSuperAdmin(gc) { + log.Debug("Not logged in as super admin") + return nil, fmt.Errorf("unauthorized") + } + + if params.ID == "" { + log.Debug("webhookID is required") + return nil, fmt.Errorf("webhook ID required") + } + + log := log.WithField("webhook_id", params.ID) + + webhook, err := db.Provider.GetWebhookByID(ctx, params.ID) + if err != nil { + log.Debug("failed to get webhook: ", err) + return nil, err + } + + err = db.Provider.DeleteWebhook(ctx, webhook) + if err != nil { + log.Debug("failed to delete webhook: ", err) + return nil, err + } + + panic(fmt.Errorf("not implemented")) +} diff --git a/server/resolvers/enable_access.go b/server/resolvers/enable_access.go index 0d9f148..3b92c07 100644 --- a/server/resolvers/enable_access.go +++ b/server/resolvers/enable_access.go @@ -31,7 +31,7 @@ func EnableAccessResolver(ctx context.Context, params model.UpdateAccessInput) ( "user_id": params.UserID, }) - user, err := db.Provider.GetUserByID(params.UserID) + user, err := db.Provider.GetUserByID(ctx, params.UserID) if err != nil { log.Debug("Failed to get user from DB: ", err) return res, err @@ -39,7 +39,7 @@ func EnableAccessResolver(ctx context.Context, params model.UpdateAccessInput) ( user.RevokedTimestamp = nil - user, err = db.Provider.UpdateUser(user) + user, err = db.Provider.UpdateUser(ctx, user) if err != nil { log.Debug("Failed to update user: ", err) return res, err diff --git a/server/resolvers/forgot_password.go b/server/resolvers/forgot_password.go index 4bcf107..a8672f3 100644 --- a/server/resolvers/forgot_password.go +++ b/server/resolvers/forgot_password.go @@ -49,7 +49,7 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu log := log.WithFields(log.Fields{ "email": params.Email, }) - _, err = db.Provider.GetUserByEmail(params.Email) + _, err = db.Provider.GetUserByEmail(ctx, params.Email) if err != nil { log.Debug("User not found: ", err) return res, fmt.Errorf(`user with this email not found`) @@ -71,7 +71,7 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu log.Debug("Failed to create verification token", err) return res, err } - _, err = db.Provider.AddVerificationRequest(models.VerificationRequest{ + _, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{ Token: verificationToken, Identifier: constants.VerificationTypeForgotPassword, ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), diff --git a/server/resolvers/invite_members.go b/server/resolvers/invite_members.go index 7b77ca4..2316456 100644 --- a/server/resolvers/invite_members.go +++ b/server/resolvers/invite_members.go @@ -70,7 +70,7 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput) // for each emails check if emails exists in db newEmails := []string{} for _, email := range emails { - _, err := db.Provider.GetUserByEmail(email) + _, err := db.Provider.GetUserByEmail(ctx, email) if err != nil { log.Debugf("User with %s email not found, so inviting user", email) newEmails = append(newEmails, email) @@ -140,13 +140,13 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput) } - user, err = db.Provider.AddUser(user) + user, err = db.Provider.AddUser(ctx, user) if err != nil { log.Debugf("Error adding user: %s, err: %v", email, err) return nil, err } - _, err = db.Provider.AddVerificationRequest(verificationRequest) + _, err = db.Provider.AddVerificationRequest(ctx, verificationRequest) if err != nil { log.Debugf("Error adding verification request: %s, err: %v", email, err) return nil, err diff --git a/server/resolvers/login.go b/server/resolvers/login.go index 4cffee1..a74755b 100644 --- a/server/resolvers/login.go +++ b/server/resolvers/login.go @@ -45,7 +45,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes "email": params.Email, }) params.Email = strings.ToLower(params.Email) - user, err := db.Provider.GetUserByEmail(params.Email) + user, err := db.Provider.GetUserByEmail(ctx, params.Email) if err != nil { log.Debug("Failed to get user by email: ", err) return res, fmt.Errorf(`user with this email not found`) @@ -126,7 +126,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token) } - go db.Provider.AddSession(models.Session{ + go db.Provider.AddSession(ctx, models.Session{ UserID: user.ID, UserAgent: utils.GetUserAgent(gc.Request), IP: utils.GetIP(gc.Request), diff --git a/server/resolvers/magic_link_login.go b/server/resolvers/magic_link_login.go index caae37a..f7f8949 100644 --- a/server/resolvers/magic_link_login.go +++ b/server/resolvers/magic_link_login.go @@ -59,7 +59,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu } // find user with email - existingUser, err := db.Provider.GetUserByEmail(params.Email) + existingUser, err := db.Provider.GetUserByEmail(ctx, params.Email) if err != nil { isSignupDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) if err != nil { @@ -99,7 +99,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu } user.Roles = strings.Join(inputRoles, ",") - user, _ = db.Provider.AddUser(user) + user, _ = db.Provider.AddUser(ctx, user) } else { user = existingUser // There multiple scenarios with roles here in magic link login @@ -163,7 +163,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu } user.SignupMethods = signupMethod - user, _ = db.Provider.UpdateUser(user) + user, _ = db.Provider.UpdateUser(ctx, user) if err != nil { log.Debug("Failed to update user: ", err) } @@ -205,7 +205,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu if err != nil { log.Debug("Failed to create verification token: ", err) } - _, err = db.Provider.AddVerificationRequest(models.VerificationRequest{ + _, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{ Token: verificationToken, Identifier: verificationType, ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), diff --git a/server/resolvers/profile.go b/server/resolvers/profile.go index b76d3a6..78af46a 100644 --- a/server/resolvers/profile.go +++ b/server/resolvers/profile.go @@ -38,7 +38,7 @@ func ProfileResolver(ctx context.Context) (*model.User, error) { log := log.WithFields(log.Fields{ "user_id": userID, }) - user, err := db.Provider.GetUserByID(userID) + user, err := db.Provider.GetUserByID(ctx, userID) if err != nil { log.Debug("Failed to get user: ", err) return res, err diff --git a/server/resolvers/resend_verify_email.go b/server/resolvers/resend_verify_email.go index 79abb4b..bd72bdd 100644 --- a/server/resolvers/resend_verify_email.go +++ b/server/resolvers/resend_verify_email.go @@ -39,14 +39,14 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma return res, fmt.Errorf("invalid identifier") } - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(params.Email, params.Identifier) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, params.Email, params.Identifier) if err != nil { log.Debug("Failed to get verification request: ", err) return res, fmt.Errorf(`verification request not found`) } // delete current verification and create new one - err = db.Provider.DeleteVerificationRequest(verificationRequest) + err = db.Provider.DeleteVerificationRequest(ctx, verificationRequest) if err != nil { log.Debug("Failed to delete verification request: ", err) } @@ -62,7 +62,7 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma if err != nil { log.Debug("Failed to create verification token: ", err) } - _, err = db.Provider.AddVerificationRequest(models.VerificationRequest{ + _, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{ Token: verificationToken, Identifier: params.Identifier, ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), diff --git a/server/resolvers/reset_password.go b/server/resolvers/reset_password.go index e747830..abdfc79 100644 --- a/server/resolvers/reset_password.go +++ b/server/resolvers/reset_password.go @@ -39,7 +39,7 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput) return res, fmt.Errorf(`basic authentication is disabled for this instance`) } - verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token) + verificationRequest, err := db.Provider.GetVerificationRequestByToken(ctx, params.Token) if err != nil { log.Debug("Failed to get verification request: ", err) return res, fmt.Errorf(`invalid token`) @@ -72,7 +72,7 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput) log := log.WithFields(log.Fields{ "email": email, }) - user, err := db.Provider.GetUserByEmail(email) + user, err := db.Provider.GetUserByEmail(ctx, email) if err != nil { log.Debug("Failed to get user: ", err) return res, err @@ -94,13 +94,13 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput) } // delete from verification table - err = db.Provider.DeleteVerificationRequest(verificationRequest) + err = db.Provider.DeleteVerificationRequest(ctx, verificationRequest) if err != nil { log.Debug("Failed to delete verification request: ", err) return res, err } - _, err = db.Provider.UpdateUser(user) + _, err = db.Provider.UpdateUser(ctx, user) if err != nil { log.Debug("Failed to update user: ", err) return res, err diff --git a/server/resolvers/revoke_access.go b/server/resolvers/revoke_access.go index 34ecaad..e856951 100644 --- a/server/resolvers/revoke_access.go +++ b/server/resolvers/revoke_access.go @@ -32,7 +32,7 @@ func RevokeAccessResolver(ctx context.Context, params model.UpdateAccessInput) ( log := log.WithFields(log.Fields{ "user_id": params.UserID, }) - user, err := db.Provider.GetUserByID(params.UserID) + user, err := db.Provider.GetUserByID(ctx, params.UserID) if err != nil { log.Debug("Failed to get user by ID: ", err) return res, err @@ -41,7 +41,7 @@ func RevokeAccessResolver(ctx context.Context, params model.UpdateAccessInput) ( now := time.Now().Unix() user.RevokedTimestamp = &now - user, err = db.Provider.UpdateUser(user) + user, err = db.Provider.UpdateUser(ctx, user) if err != nil { log.Debug("Failed to update user: ", err) return res, err diff --git a/server/resolvers/session.go b/server/resolvers/session.go index 903f8cb..dfa4e3d 100644 --- a/server/resolvers/session.go +++ b/server/resolvers/session.go @@ -46,7 +46,7 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod "user_id": userID, }) - user, err := db.Provider.GetUserByID(userID) + user, err := db.Provider.GetUserByID(ctx, userID) if err != nil { return res, err } diff --git a/server/resolvers/signup.go b/server/resolvers/signup.go index 4f7051e..11653fb 100644 --- a/server/resolvers/signup.go +++ b/server/resolvers/signup.go @@ -74,7 +74,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR "email": params.Email, }) // find user with email - existingUser, err := db.Provider.GetUserByEmail(params.Email) + existingUser, err := db.Provider.GetUserByEmail(ctx, params.Email) if err != nil { log.Debug("Failed to get user by email: ", err) } @@ -167,7 +167,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR now := time.Now().Unix() user.EmailVerifiedAt = &now } - user, err = db.Provider.AddUser(user) + user, err = db.Provider.AddUser(ctx, user) if err != nil { log.Debug("Failed to add user: ", err) return res, err @@ -193,7 +193,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR log.Debug("Failed to create verification token: ", err) return res, err } - _, err = db.Provider.AddVerificationRequest(models.VerificationRequest{ + _, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{ Token: verificationToken, Identifier: verificationType, ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), @@ -225,7 +225,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR return res, err } - go db.Provider.AddSession(models.Session{ + go db.Provider.AddSession(ctx, models.Session{ UserID: user.ID, UserAgent: utils.GetUserAgent(gc.Request), IP: utils.GetIP(gc.Request), diff --git a/server/resolvers/test_endpoint.go b/server/resolvers/test_endpoint.go new file mode 100644 index 0000000..0d0486a --- /dev/null +++ b/server/resolvers/test_endpoint.go @@ -0,0 +1,109 @@ +package resolvers + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "time" + + "github.com/authorizerdev/authorizer/server/constants" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/token" + "github.com/authorizerdev/authorizer/server/utils" + "github.com/authorizerdev/authorizer/server/validators" + "github.com/google/uuid" + log "github.com/sirupsen/logrus" +) + +// TestEndpointResolver resolver to test webhook endpoints +func TestEndpointResolver(ctx context.Context, params model.TestEndpointRequest) (*model.TestEndpointResponse, error) { + gc, err := utils.GinContextFromContext(ctx) + if err != nil { + log.Debug("Failed to get GinContext: ", err) + return nil, err + } + + if !token.IsSuperAdmin(gc) { + log.Debug("Not logged in as super admin") + return nil, fmt.Errorf("unauthorized") + } + + if !validators.IsValidWebhookEventName(params.EventName) { + log.Debug("Invalid event name: ", params.EventName) + return nil, fmt.Errorf("invalid event_name %s", params.EventName) + } + + user := model.User{ + ID: uuid.NewString(), + Email: "test_endpoint@foo.com", + EmailVerified: true, + SignupMethods: constants.AuthRecipeMethodMagicLinkLogin, + GivenName: utils.NewStringRef("Foo"), + FamilyName: utils.NewStringRef("Bar"), + } + + userBytes, err := json.Marshal(user) + if err != nil { + log.Debug("error marshalling user obj: ", err) + return nil, err + } + userMap := map[string]interface{}{} + err = json.Unmarshal(userBytes, &userMap) + if err != nil { + log.Debug("error un-marshalling user obj: ", err) + return nil, err + } + + reqBody := map[string]interface{}{ + "event_name": constants.UserLoginWebhookEvent, + "user": userMap, + } + + if params.EventName == constants.UserLoginWebhookEvent { + reqBody["login_method"] = constants.AuthRecipeMethodMagicLinkLogin + } + + requestBody, err := json.Marshal(reqBody) + if err != nil { + log.Debug("error marshalling requestBody obj: ", err) + return nil, err + } + + req, err := http.NewRequest("POST", params.Endpoint, bytes.NewBuffer(requestBody)) + if err != nil { + log.Debug("error creating post request: ", err) + return nil, err + } + req.Header.Set("Content-Type", "application/json") + for key, val := range params.Headers { + req.Header.Set(key, val.(string)) + } + client := &http.Client{Timeout: time.Second * 30} + resp, err := client.Do(req) + if err != nil { + log.Debug("error making request: ", err) + return nil, err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Debug("error reading response: ", err) + return nil, err + } + + response := map[string]interface{}{} + if err := json.Unmarshal(body, &response); err != nil { + log.Debug("error un-marshalling response: ", err) + return nil, err + } + + statusCode := int64(resp.StatusCode) + return &model.TestEndpointResponse{ + HTTPStatus: &statusCode, + Response: response, + }, nil +} diff --git a/server/resolvers/update_env.go b/server/resolvers/update_env.go index 41fe5fa..508d47e 100644 --- a/server/resolvers/update_env.go +++ b/server/resolvers/update_env.go @@ -287,7 +287,7 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model } // Fetch the current db store and update it - env, err := db.Provider.GetEnv() + env, err := db.Provider.GetEnv(ctx) if err != nil { log.Debug("Failed to get env: ", err) return res, err @@ -314,7 +314,7 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model } env.EnvData = encryptedConfig - _, err = db.Provider.UpdateEnv(env) + _, err = db.Provider.UpdateEnv(ctx, env) if err != nil { log.Debug("Failed to update env: ", err) return res, err diff --git a/server/resolvers/update_profile.go b/server/resolvers/update_profile.go index fdc3203..bd78fd3 100644 --- a/server/resolvers/update_profile.go +++ b/server/resolvers/update_profile.go @@ -55,7 +55,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput) "user_id": userID, }) - user, err := db.Provider.GetUserByID(userID) + user, err := db.Provider.GetUserByID(ctx, userID) if err != nil { log.Debug("Failed to get user by id: ", err) return res, err @@ -135,7 +135,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput) return res, fmt.Errorf("invalid new email address") } // check if user with new email exists - _, err := db.Provider.GetUserByEmail(newEmail) + _, err := db.Provider.GetUserByEmail(ctx, newEmail) // err = nil means user exists if err == nil { log.Debug("Failed to get user by email: ", newEmail) @@ -168,7 +168,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput) log.Debug("Failed to create verification token: ", err) return res, err } - _, err = db.Provider.AddVerificationRequest(models.VerificationRequest{ + _, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{ Token: verificationToken, Identifier: verificationType, ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), @@ -186,7 +186,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput) } } - _, err = db.Provider.UpdateUser(user) + _, err = db.Provider.UpdateUser(ctx, user) if err != nil { log.Debug("Failed to update user: ", err) return res, err diff --git a/server/resolvers/update_user.go b/server/resolvers/update_user.go index d4585b9..d2aa7b0 100644 --- a/server/resolvers/update_user.go +++ b/server/resolvers/update_user.go @@ -50,7 +50,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod return res, fmt.Errorf("please enter atleast one param to update") } - user, err := db.Provider.GetUserByID(params.ID) + user, err := db.Provider.GetUserByID(ctx, params.ID) if err != nil { log.Debug("Failed to get user by id: ", err) return res, fmt.Errorf(`User not found`) @@ -105,7 +105,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod } newEmail := strings.ToLower(*params.Email) // check if user with new email exists - _, err = db.Provider.GetUserByEmail(newEmail) + _, err = db.Provider.GetUserByEmail(ctx, newEmail) // err = nil means user exists if err == nil { log.Debug("User with email already exists: ", newEmail) @@ -130,7 +130,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod if err != nil { log.Debug("Failed to create verification token: ", err) } - _, err = db.Provider.AddVerificationRequest(models.VerificationRequest{ + _, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{ Token: verificationToken, Identifier: verificationType, ExpiresAt: time.Now().Add(time.Minute * 30).Unix(), @@ -189,7 +189,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod user.Roles = rolesToSave } - user, err = db.Provider.UpdateUser(user) + user, err = db.Provider.UpdateUser(ctx, user) if err != nil { log.Debug("Failed to update user: ", err) return res, err diff --git a/server/resolvers/update_webhook.go b/server/resolvers/update_webhook.go new file mode 100644 index 0000000..5a7801c --- /dev/null +++ b/server/resolvers/update_webhook.go @@ -0,0 +1,91 @@ +package resolvers + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/token" + "github.com/authorizerdev/authorizer/server/utils" + "github.com/authorizerdev/authorizer/server/validators" + log "github.com/sirupsen/logrus" +) + +// UpdateWebhookResolver resolver for update webhook mutation +func UpdateWebhookResolver(ctx context.Context, params model.UpdateWebhookRequest) (*model.Response, error) { + gc, err := utils.GinContextFromContext(ctx) + if err != nil { + log.Debug("Failed to get GinContext: ", err) + return nil, err + } + + if !token.IsSuperAdmin(gc) { + log.Debug("Not logged in as super admin") + return nil, fmt.Errorf("unauthorized") + } + + webhook, err := db.Provider.GetWebhookByID(ctx, params.ID) + if err != nil { + log.Debug("failed to get webhook: ", err) + return nil, err + } + + headersString := "" + if webhook.Headers != nil { + headerBytes, err := json.Marshal(webhook.Headers) + if err != nil { + log.Debug("failed to marshall source headers: ", err) + } + headersString = string(headerBytes) + } + + webhookDetails := models.Webhook{ + ID: webhook.ID, + Key: webhook.ID, + EventName: utils.StringValue(webhook.EventName), + EndPoint: utils.StringValue(webhook.Endpoint), + Enabled: utils.BoolValue(webhook.Enabled), + Headers: headersString, + } + if webhookDetails.EventName != utils.StringValue(params.EventName) { + if isValid := validators.IsValidWebhookEventName(utils.StringValue(params.EventName)); !isValid { + log.Debug("invalid event name: ", utils.StringValue(params.EventName)) + return nil, fmt.Errorf("invalid event name %s", utils.StringValue(params.EventName)) + } + webhookDetails.EventName = utils.StringValue(params.EventName) + } + + if webhookDetails.EndPoint != utils.StringValue(params.Endpoint) { + webhookDetails.EventName = utils.StringValue(params.EventName) + } + + if webhookDetails.Enabled != utils.BoolValue(params.Enabled) { + webhookDetails.Enabled = utils.BoolValue(params.Enabled) + } + + if params.Headers != nil { + for key, val := range params.Headers { + webhook.Headers[key] = val + } + + headerBytes, err := json.Marshal(webhook.Headers) + if err != nil { + log.Debug("failed to marshall headers: ", err) + return nil, err + } + + webhookDetails.Headers = string(headerBytes) + } + + _, err = db.Provider.UpdateWebhook(ctx, webhookDetails) + if err != nil { + return nil, err + } + + return &model.Response{ + Message: `Webhook updated successfully.`, + }, nil +} diff --git a/server/resolvers/users.go b/server/resolvers/users.go index 5f24b2b..1ee6aad 100644 --- a/server/resolvers/users.go +++ b/server/resolvers/users.go @@ -28,7 +28,7 @@ func UsersResolver(ctx context.Context, params *model.PaginatedInput) (*model.Us pagination := utils.GetPagination(params) - res, err := db.Provider.ListUsers(pagination) + res, err := db.Provider.ListUsers(ctx, pagination) if err != nil { log.Debug("Failed to get users: ", err) return nil, err diff --git a/server/resolvers/verification_requests.go b/server/resolvers/verification_requests.go index fe2f5f0..4a629de 100644 --- a/server/resolvers/verification_requests.go +++ b/server/resolvers/verification_requests.go @@ -28,7 +28,7 @@ func VerificationRequestsResolver(ctx context.Context, params *model.PaginatedIn pagination := utils.GetPagination(params) - res, err := db.Provider.ListVerificationRequests(pagination) + res, err := db.Provider.ListVerificationRequests(ctx, pagination) if err != nil { log.Debug("Failed to get verification requests: ", err) return nil, err diff --git a/server/resolvers/verify_email.go b/server/resolvers/verify_email.go index a10d83d..6898932 100644 --- a/server/resolvers/verify_email.go +++ b/server/resolvers/verify_email.go @@ -29,7 +29,7 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m return res, err } - verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token) + verificationRequest, err := db.Provider.GetVerificationRequestByToken(ctx, params.Token) if err != nil { log.Debug("Failed to get verification request by token: ", err) return res, fmt.Errorf(`invalid token: %s`, err.Error()) @@ -52,7 +52,7 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m log := log.WithFields(log.Fields{ "email": email, }) - user, err := db.Provider.GetUserByEmail(email) + user, err := db.Provider.GetUserByEmail(ctx, email) if err != nil { log.Debug("Failed to get user by email: ", err) return res, err @@ -61,13 +61,13 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m // update email_verified_at in users table now := time.Now().Unix() user.EmailVerifiedAt = &now - user, err = db.Provider.UpdateUser(user) + user, err = db.Provider.UpdateUser(ctx, user) if err != nil { log.Debug("Failed to update user: ", err) return res, err } // delete from verification table - err = db.Provider.DeleteVerificationRequest(verificationRequest) + err = db.Provider.DeleteVerificationRequest(gc, verificationRequest) if err != nil { log.Debug("Failed to delete verification request: ", err) return res, err @@ -86,7 +86,7 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m return res, err } - go db.Provider.AddSession(models.Session{ + go db.Provider.AddSession(ctx, models.Session{ UserID: user.ID, UserAgent: utils.GetUserAgent(gc.Request), IP: utils.GetIP(gc.Request), diff --git a/server/resolvers/webhook.go b/server/resolvers/webhook.go new file mode 100644 index 0000000..d547e79 --- /dev/null +++ b/server/resolvers/webhook.go @@ -0,0 +1,33 @@ +package resolvers + +import ( + "context" + "fmt" + + "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/token" + "github.com/authorizerdev/authorizer/server/utils" + log "github.com/sirupsen/logrus" +) + +// WebhookResolver resolver for getting webhook by identifier +func WebhookResolver(ctx context.Context, params model.WebhookRequest) (*model.Webhook, error) { + gc, err := utils.GinContextFromContext(ctx) + if err != nil { + log.Debug("Failed to get GinContext: ", err) + return nil, err + } + + if !token.IsSuperAdmin(gc) { + log.Debug("Not logged in as super admin") + return nil, fmt.Errorf("unauthorized") + } + + webhook, err := db.Provider.GetWebhookByID(ctx, params.ID) + if err != nil { + log.Debug("error getting webhook: ", err) + return nil, err + } + return webhook, nil +} diff --git a/server/resolvers/webhook_logs.go b/server/resolvers/webhook_logs.go new file mode 100644 index 0000000..ed3080d --- /dev/null +++ b/server/resolvers/webhook_logs.go @@ -0,0 +1,35 @@ +package resolvers + +import ( + "context" + "fmt" + + "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/token" + "github.com/authorizerdev/authorizer/server/utils" + log "github.com/sirupsen/logrus" +) + +// WebhookLogsResolver resolver for getting the list of webhook_logs based on pagination & webhook identifier +func WebhookLogsResolver(ctx context.Context, params model.ListWebhookLogRequest) (*model.WebhookLogs, error) { + gc, err := utils.GinContextFromContext(ctx) + if err != nil { + log.Debug("Failed to get GinContext: ", err) + return nil, err + } + + if !token.IsSuperAdmin(gc) { + log.Debug("Not logged in as super admin") + return nil, fmt.Errorf("unauthorized") + } + + pagination := utils.GetPagination(params.Pagination) + + webhookLogs, err := db.Provider.ListWebhookLogs(ctx, pagination, utils.StringValue(params.WebhookID)) + if err != nil { + log.Debug("failed to get webhook logs: ", err) + return nil, err + } + return webhookLogs, nil +} diff --git a/server/resolvers/webhooks.go b/server/resolvers/webhooks.go new file mode 100644 index 0000000..df6dd30 --- /dev/null +++ b/server/resolvers/webhooks.go @@ -0,0 +1,35 @@ +package resolvers + +import ( + "context" + "fmt" + + "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/token" + "github.com/authorizerdev/authorizer/server/utils" + log "github.com/sirupsen/logrus" +) + +// WebhooksResolver resolver for getting the list of webhooks based on pagination +func WebhooksResolver(ctx context.Context, params *model.PaginatedInput) (*model.Webhooks, error) { + gc, err := utils.GinContextFromContext(ctx) + if err != nil { + log.Debug("Failed to get GinContext: ", err) + return nil, err + } + + if !token.IsSuperAdmin(gc) { + log.Debug("Not logged in as super admin") + return nil, fmt.Errorf("unauthorized") + } + + pagination := utils.GetPagination(params) + + webhooks, err := db.Provider.ListWebhook(ctx, pagination) + if err != nil { + log.Debug("failed to get webhook logs: ", err) + return nil, err + } + return webhooks, nil +} diff --git a/server/test/enable_access_test.go b/server/test/enable_access_test.go index cc57be3..be49efc 100644 --- a/server/test/enable_access_test.go +++ b/server/test/enable_access_test.go @@ -22,7 +22,7 @@ func enableAccessTest(t *testing.T, s TestSetup) { Email: email, }) assert.NoError(t, err) - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeMagicLinkLogin) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeMagicLinkLogin) verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{ Token: verificationRequest.Token, }) diff --git a/server/test/forgot_password_test.go b/server/test/forgot_password_test.go index 1479cc9..cd09a0a 100644 --- a/server/test/forgot_password_test.go +++ b/server/test/forgot_password_test.go @@ -26,7 +26,7 @@ func forgotPasswordTest(t *testing.T, s TestSetup) { }) assert.Nil(t, err, "no errors for forgot password") - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeForgotPassword) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeForgotPassword) assert.Nil(t, err) assert.Equal(t, verificationRequest.Identifier, constants.VerificationTypeForgotPassword) diff --git a/server/test/login_test.go b/server/test/login_test.go index b2243e9..3a85d0f 100644 --- a/server/test/login_test.go +++ b/server/test/login_test.go @@ -29,7 +29,7 @@ func loginTests(t *testing.T, s TestSetup) { assert.NotNil(t, err, "should fail because email is not verified") assert.Nil(t, res) - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup) n, err := utils.EncryptNonce(verificationRequest.Nonce) assert.NoError(t, err) assert.NotEmpty(t, n) diff --git a/server/test/logout_test.go b/server/test/logout_test.go index 2b7a897..3e1c6ff 100644 --- a/server/test/logout_test.go +++ b/server/test/logout_test.go @@ -24,7 +24,7 @@ func logoutTests(t *testing.T, s TestSetup) { Email: email, }) - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeMagicLinkLogin) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeMagicLinkLogin) verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{ Token: verificationRequest.Token, }) diff --git a/server/test/magic_link_login_test.go b/server/test/magic_link_login_test.go index cb6df35..b2cff2c 100644 --- a/server/test/magic_link_login_test.go +++ b/server/test/magic_link_login_test.go @@ -29,7 +29,7 @@ func magicLinkLoginTests(t *testing.T, s TestSetup) { }) assert.Nil(t, err, "signup should be successful") - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeMagicLinkLogin) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeMagicLinkLogin) verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{ Token: verificationRequest.Token, }) diff --git a/server/test/profile_test.go b/server/test/profile_test.go index 8f5592c..edb52a0 100644 --- a/server/test/profile_test.go +++ b/server/test/profile_test.go @@ -26,7 +26,7 @@ func profileTests(t *testing.T, s TestSetup) { _, err := resolvers.ProfileResolver(ctx) assert.NotNil(t, err, "unauthorized") - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup) verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{ Token: verificationRequest.Token, }) diff --git a/server/test/reset_password_test.go b/server/test/reset_password_test.go index 75ad76b..f33e774 100644 --- a/server/test/reset_password_test.go +++ b/server/test/reset_password_test.go @@ -26,7 +26,7 @@ func resetPasswordTest(t *testing.T, s TestSetup) { }) assert.Nil(t, err, "no errors for forgot password") - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeForgotPassword) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeForgotPassword) assert.Nil(t, err, "should get forgot password request") _, err = resolvers.ResetPasswordResolver(ctx, model.ResetPasswordInput{ diff --git a/server/test/resolvers_test.go b/server/test/resolvers_test.go index 55e7f73..a51a1c5 100644 --- a/server/test/resolvers_test.go +++ b/server/test/resolvers_test.go @@ -1,6 +1,7 @@ package test import ( + "context" "testing" "github.com/authorizerdev/authorizer/server/constants" @@ -20,6 +21,7 @@ func TestResolvers(t *testing.T) { for dbType, dbURL := range databases { s := testSetup() defer s.Server.Close() + ctx := context.Background() memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDatabaseURL, dbURL) memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDatabaseType, dbType) @@ -29,10 +31,10 @@ func TestResolvers(t *testing.T) { } // clean the persisted config for test to use fresh config - envData, err := db.Provider.GetEnv() + envData, err := db.Provider.GetEnv(ctx) if err == nil { envData.EnvData = "" - db.Provider.UpdateEnv(envData) + db.Provider.UpdateEnv(ctx, envData) } env.PersistEnv() diff --git a/server/test/revoke_access_test.go b/server/test/revoke_access_test.go index 3018c07..4223a0d 100644 --- a/server/test/revoke_access_test.go +++ b/server/test/revoke_access_test.go @@ -22,7 +22,7 @@ func revokeAccessTest(t *testing.T, s TestSetup) { Email: email, }) assert.NoError(t, err) - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeMagicLinkLogin) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeMagicLinkLogin) verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{ Token: verificationRequest.Token, }) diff --git a/server/test/session_test.go b/server/test/session_test.go index 4d2e8df..86b848a 100644 --- a/server/test/session_test.go +++ b/server/test/session_test.go @@ -29,7 +29,7 @@ func sessionTests(t *testing.T, s TestSetup) { _, err := resolvers.SessionResolver(ctx, &model.SessionQueryInput{}) assert.NotNil(t, err, "unauthorized") - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup) verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{ Token: verificationRequest.Token, }) diff --git a/server/test/signup_test.go b/server/test/signup_test.go index 1e34429..a66906c 100644 --- a/server/test/signup_test.go +++ b/server/test/signup_test.go @@ -57,7 +57,7 @@ func signupTests(t *testing.T, s TestSetup) { assert.NotNil(t, err, "should throw duplicate email error") - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup) assert.Nil(t, err) assert.Equal(t, email, verificationRequest.Email) cleanData(email) diff --git a/server/test/test.go b/server/test/test.go index 0160ca0..a152490 100644 --- a/server/test/test.go +++ b/server/test/test.go @@ -33,30 +33,31 @@ type TestSetup struct { } func cleanData(email string) { - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup) + ctx := context.Background() + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup) if err == nil { - err = db.Provider.DeleteVerificationRequest(verificationRequest) + err = db.Provider.DeleteVerificationRequest(ctx, verificationRequest) } - verificationRequest, err = db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeForgotPassword) + verificationRequest, err = db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeForgotPassword) if err == nil { - err = db.Provider.DeleteVerificationRequest(verificationRequest) + err = db.Provider.DeleteVerificationRequest(ctx, verificationRequest) } - verificationRequest, err = db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeUpdateEmail) + verificationRequest, err = db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeUpdateEmail) if err == nil { - err = db.Provider.DeleteVerificationRequest(verificationRequest) + err = db.Provider.DeleteVerificationRequest(ctx, verificationRequest) } - verificationRequest, err = db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeMagicLinkLogin) + verificationRequest, err = db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeMagicLinkLogin) if err == nil { - err = db.Provider.DeleteVerificationRequest(verificationRequest) + err = db.Provider.DeleteVerificationRequest(ctx, verificationRequest) } - dbUser, err := db.Provider.GetUserByEmail(email) + dbUser, err := db.Provider.GetUserByEmail(ctx, email) if err == nil { - db.Provider.DeleteUser(dbUser) - db.Provider.DeleteSession(dbUser.ID) + db.Provider.DeleteUser(ctx, dbUser) + db.Provider.DeleteSession(ctx, dbUser.ID) } } diff --git a/server/test/update_profile_test.go b/server/test/update_profile_test.go index 68dae47..d8e4f0f 100644 --- a/server/test/update_profile_test.go +++ b/server/test/update_profile_test.go @@ -29,7 +29,7 @@ func updateProfileTests(t *testing.T, s TestSetup) { }) assert.NotNil(t, err, "unauthorized") - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup) verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{ Token: verificationRequest.Token, }) diff --git a/server/test/verify_email_test.go b/server/test/verify_email_test.go index 9cb4583..146dd27 100644 --- a/server/test/verify_email_test.go +++ b/server/test/verify_email_test.go @@ -24,7 +24,7 @@ func verifyEmailTest(t *testing.T, s TestSetup) { user := *res.User assert.Equal(t, email, user.Email) assert.Nil(t, res.AccessToken, "access token should be nil") - verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup) + verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup) assert.Nil(t, err) assert.Equal(t, email, verificationRequest.Email) diff --git a/server/utils/refs.go b/server/utils/refs.go index 3dd87cd..80cd598 100644 --- a/server/utils/refs.go +++ b/server/utils/refs.go @@ -4,3 +4,27 @@ package utils func NewStringRef(v string) *string { return &v } + +// StringValue returns the value of the given string ref +func StringValue(r *string, defaultValue ...string) string { + if r != nil { + return *r + } + if len(defaultValue) > 0 { + return defaultValue[0] + } + return "" +} + +// NewBoolRef returns a reference to a bool with given value +func NewBoolRef(v bool) *bool { + return &v +} + +// BoolValue returns the value of the given bool ref +func BoolValue(r *bool) bool { + if r != nil { + return false + } + return *r +} diff --git a/server/utils/webhook.go b/server/utils/webhook.go new file mode 100644 index 0000000..d4b585b --- /dev/null +++ b/server/utils/webhook.go @@ -0,0 +1 @@ +package utils diff --git a/server/validators/webhook.go b/server/validators/webhook.go new file mode 100644 index 0000000..1309cad --- /dev/null +++ b/server/validators/webhook.go @@ -0,0 +1,12 @@ +package validators + +import "github.com/authorizerdev/authorizer/server/constants" + +// IsValidWebhookEventName to validate webhook event name +func IsValidWebhookEventName(eventName string) bool { + if eventName != constants.UserCreatedWebhookEvent && eventName != constants.UserLoginWebhookEvent && eventName != constants.UserSignUpWebhookEvent && eventName != constants.UserDeletedWebhookEvent && eventName != constants.UserAccessEnabledWebhookEvent && eventName != constants.UserAccessRevokedWebhookEvent { + return false + } + + return true +} From bbb064b93967a083c1d27d6d1c7bafe568cf8dc0 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Mon, 11 Jul 2022 10:42:42 +0530 Subject: [PATCH 10/14] feat: add register event --- server/handlers/oauth_callback.go | 19 ++++-- server/handlers/verify_email.go | 20 ++++-- server/resolvers/login.go | 13 ++-- server/resolvers/magic_link_login.go | 1 + server/resolvers/signup.go | 20 +++--- server/resolvers/update_webhook.go | 2 + server/resolvers/verify_email.go | 35 +++++++---- server/test/add_webhook_test.go | 1 + server/test/delete_webhook_test.go | 1 + server/test/test_endpoint_test.go | 1 + server/test/update_webhook_test.go | 1 + server/test/webhook_logs_test.go | 1 + server/test/webhooks_test.go | 1 + server/utils/webhook.go | 91 ++++++++++++++++++++++++++++ 14 files changed, 173 insertions(+), 34 deletions(-) create mode 100644 server/test/add_webhook_test.go create mode 100644 server/test/delete_webhook_test.go create mode 100644 server/test/test_endpoint_test.go create mode 100644 server/test/update_webhook_test.go create mode 100644 server/test/webhook_logs_test.go create mode 100644 server/test/webhooks_test.go diff --git a/server/handlers/oauth_callback.go b/server/handlers/oauth_callback.go index d18bf18..fe588c3 100644 --- a/server/handlers/oauth_callback.go +++ b/server/handlers/oauth_callback.go @@ -80,6 +80,7 @@ func OAuthCallbackHandler() gin.HandlerFunc { existingUser, err := db.Provider.GetUserByEmail(ctx, user.Email) log := log.WithField("user", user.Email) + isSignUp := false if err != nil { isSignupDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) @@ -121,6 +122,7 @@ func OAuthCallbackHandler() gin.HandlerFunc { now := time.Now().Unix() user.EmailVerifiedAt = &now user, _ = db.Provider.AddUser(ctx, user) + isSignUp = true } else { user = existingUser if user.RevokedTimestamp != nil { @@ -215,11 +217,18 @@ func OAuthCallbackHandler() gin.HandlerFunc { memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token) } - go db.Provider.AddSession(ctx, models.Session{ - UserID: user.ID, - UserAgent: utils.GetUserAgent(ctx.Request), - IP: utils.GetIP(ctx.Request), - }) + go func() { + if isSignUp { + utils.RegisterEvent(ctx, constants.EnvKeyDisableSignUp, provider, user) + } else { + utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, provider, user) + } + db.Provider.AddSession(ctx, models.Session{ + UserID: user.ID, + UserAgent: utils.GetUserAgent(ctx.Request), + IP: utils.GetIP(ctx.Request), + }) + }() if strings.Contains(redirectURL, "?") { redirectURL = redirectURL + "&" + params } else { diff --git a/server/handlers/verify_email.go b/server/handlers/verify_email.go index 6d900bd..10d4fad 100644 --- a/server/handlers/verify_email.go +++ b/server/handlers/verify_email.go @@ -66,10 +66,12 @@ func VerifyEmailHandler() gin.HandlerFunc { return } + isSignUp := false // update email_verified_at in users table if user.EmailVerifiedAt == nil { now := time.Now().Unix() user.EmailVerifiedAt = &now + isSignUp = true db.Provider.UpdateUser(c, user) } // delete from verification table @@ -131,11 +133,19 @@ func VerifyEmailHandler() gin.HandlerFunc { redirectURL = redirectURL + "?" + strings.TrimPrefix(params, "&") } - go db.Provider.AddSession(c, models.Session{ - UserID: user.ID, - UserAgent: utils.GetUserAgent(c.Request), - IP: utils.GetIP(c.Request), - }) + go func() { + if isSignUp { + utils.RegisterEvent(c, constants.UserSignUpWebhookEvent, loginMethod, user) + } else { + utils.RegisterEvent(c, constants.UserLoginWebhookEvent, loginMethod, user) + } + + db.Provider.AddSession(c, models.Session{ + UserID: user.ID, + UserAgent: utils.GetUserAgent(c.Request), + IP: utils.GetIP(c.Request), + }) + }() c.Redirect(http.StatusTemporaryRedirect, redirectURL) } diff --git a/server/resolvers/login.go b/server/resolvers/login.go index a74755b..e55f984 100644 --- a/server/resolvers/login.go +++ b/server/resolvers/login.go @@ -126,11 +126,14 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token) } - go db.Provider.AddSession(ctx, models.Session{ - UserID: user.ID, - UserAgent: utils.GetUserAgent(gc.Request), - IP: utils.GetIP(gc.Request), - }) + go func() { + utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodBasicAuth, user) + db.Provider.AddSession(ctx, models.Session{ + UserID: user.ID, + UserAgent: utils.GetUserAgent(gc.Request), + IP: utils.GetIP(gc.Request), + }) + }() return res, nil } diff --git a/server/resolvers/magic_link_login.go b/server/resolvers/magic_link_login.go index f7f8949..456d5c0 100644 --- a/server/resolvers/magic_link_login.go +++ b/server/resolvers/magic_link_login.go @@ -100,6 +100,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu user.Roles = strings.Join(inputRoles, ",") user, _ = db.Provider.AddUser(ctx, user) + go utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodMagicLinkLogin, user) } else { user = existingUser // There multiple scenarios with roles here in magic link login diff --git a/server/resolvers/signup.go b/server/resolvers/signup.go index 11653fb..dbd3652 100644 --- a/server/resolvers/signup.go +++ b/server/resolvers/signup.go @@ -207,7 +207,10 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR } // exec it as go routin so that we can reduce the api latency - go email.SendVerificationMail(params.Email, verificationToken, hostname) + go func() { + email.SendVerificationMail(params.Email, verificationToken, hostname) + utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodBasicAuth, user) + }() res = &model.AuthResponse{ Message: `Verification email has been sent. Please check your inbox`, @@ -225,12 +228,6 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR return res, err } - go db.Provider.AddSession(ctx, models.Session{ - UserID: user.ID, - UserAgent: utils.GetUserAgent(gc.Request), - IP: utils.GetIP(gc.Request), - }) - expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix() if expiresIn <= 0 { expiresIn = 1 @@ -252,6 +249,15 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR res.RefreshToken = &authToken.RefreshToken.Token memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token) } + + go func() { + utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, constants.AuthRecipeMethodBasicAuth, user) + db.Provider.AddSession(ctx, models.Session{ + UserID: user.ID, + UserAgent: utils.GetUserAgent(gc.Request), + IP: utils.GetIP(gc.Request), + }) + }() } return res, nil diff --git a/server/resolvers/update_webhook.go b/server/resolvers/update_webhook.go index 5a7801c..4ce49d6 100644 --- a/server/resolvers/update_webhook.go +++ b/server/resolvers/update_webhook.go @@ -49,7 +49,9 @@ func UpdateWebhookResolver(ctx context.Context, params model.UpdateWebhookReques EndPoint: utils.StringValue(webhook.Endpoint), Enabled: utils.BoolValue(webhook.Enabled), Headers: headersString, + CreatedAt: *webhook.CreatedAt, } + if webhookDetails.EventName != utils.StringValue(params.EventName) { if isValid := validators.IsValidWebhookEventName(utils.StringValue(params.EventName)); !isValid { log.Debug("invalid event name: ", utils.StringValue(params.EventName)) diff --git a/server/resolvers/verify_email.go b/server/resolvers/verify_email.go index 6898932..624d08a 100644 --- a/server/resolvers/verify_email.go +++ b/server/resolvers/verify_email.go @@ -58,13 +58,17 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m return res, err } - // update email_verified_at in users table - now := time.Now().Unix() - user.EmailVerifiedAt = &now - user, err = db.Provider.UpdateUser(ctx, user) - if err != nil { - log.Debug("Failed to update user: ", err) - return res, err + isSignUp := false + if user.EmailVerifiedAt == nil { + isSignUp = true + // update email_verified_at in users table + now := time.Now().Unix() + user.EmailVerifiedAt = &now + user, err = db.Provider.UpdateUser(ctx, user) + if err != nil { + log.Debug("Failed to update user: ", err) + return res, err + } } // delete from verification table err = db.Provider.DeleteVerificationRequest(gc, verificationRequest) @@ -86,12 +90,19 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m return res, err } - go db.Provider.AddSession(ctx, models.Session{ - UserID: user.ID, - UserAgent: utils.GetUserAgent(gc.Request), - IP: utils.GetIP(gc.Request), - }) + go func() { + if isSignUp { + utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, loginMethod, user) + } else { + utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, loginMethod, user) + } + db.Provider.AddSession(ctx, models.Session{ + UserID: user.ID, + UserAgent: utils.GetUserAgent(gc.Request), + IP: utils.GetIP(gc.Request), + }) + }() expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix() if expiresIn <= 0 { expiresIn = 1 diff --git a/server/test/add_webhook_test.go b/server/test/add_webhook_test.go new file mode 100644 index 0000000..56e5404 --- /dev/null +++ b/server/test/add_webhook_test.go @@ -0,0 +1 @@ +package test diff --git a/server/test/delete_webhook_test.go b/server/test/delete_webhook_test.go new file mode 100644 index 0000000..56e5404 --- /dev/null +++ b/server/test/delete_webhook_test.go @@ -0,0 +1 @@ +package test diff --git a/server/test/test_endpoint_test.go b/server/test/test_endpoint_test.go new file mode 100644 index 0000000..56e5404 --- /dev/null +++ b/server/test/test_endpoint_test.go @@ -0,0 +1 @@ +package test diff --git a/server/test/update_webhook_test.go b/server/test/update_webhook_test.go new file mode 100644 index 0000000..56e5404 --- /dev/null +++ b/server/test/update_webhook_test.go @@ -0,0 +1 @@ +package test diff --git a/server/test/webhook_logs_test.go b/server/test/webhook_logs_test.go new file mode 100644 index 0000000..56e5404 --- /dev/null +++ b/server/test/webhook_logs_test.go @@ -0,0 +1 @@ +package test diff --git a/server/test/webhooks_test.go b/server/test/webhooks_test.go new file mode 100644 index 0000000..56e5404 --- /dev/null +++ b/server/test/webhooks_test.go @@ -0,0 +1 @@ +package test diff --git a/server/utils/webhook.go b/server/utils/webhook.go index d4b585b..cfd0b2c 100644 --- a/server/utils/webhook.go +++ b/server/utils/webhook.go @@ -1 +1,92 @@ package utils + +import ( + "bytes" + "context" + "encoding/json" + "io/ioutil" + "net/http" + "time" + + "github.com/authorizerdev/authorizer/server/constants" + "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/db/models" + log "github.com/sirupsen/logrus" +) + +func RegisterEvent(ctx context.Context, eventName string, authRecipe string, user models.User) error { + webhook, err := db.Provider.GetWebhookByEventName(ctx, eventName) + if err != nil { + return err + } + + userBytes, err := json.Marshal(user) + if err != nil { + log.Debug("error marshalling user obj: ", err) + return err + } + userMap := map[string]interface{}{} + err = json.Unmarshal(userBytes, &userMap) + if err != nil { + log.Debug("error un-marshalling user obj: ", err) + return err + } + + reqBody := map[string]interface{}{ + "event_name": eventName, + "user": userMap, + } + + if eventName == constants.UserLoginWebhookEvent || eventName == constants.UserSignUpWebhookEvent { + reqBody["auth_recipe"] = authRecipe + } + + requestBody, err := json.Marshal(reqBody) + if err != nil { + log.Debug("error marshalling requestBody obj: ", err) + return err + } + + requestBytesBuffer := bytes.NewBuffer(requestBody) + req, err := http.NewRequest("POST", StringValue(webhook.Endpoint), requestBytesBuffer) + if err != nil { + log.Debug("error creating webhook post request: ", err) + return err + } + req.Header.Set("Content-Type", "application/json") + + if webhook.Headers != nil { + for key, val := range webhook.Headers { + req.Header.Set(key, val.(string)) + } + } + + client := &http.Client{Timeout: time.Second * 30} + resp, err := client.Do(req) + if err != nil { + log.Debug("error making request: ", err) + return err + } + defer resp.Body.Close() + + responseBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Debug("error reading response: ", err) + return err + } + + statusCode := int64(resp.StatusCode) + _, err = db.Provider.AddWebhookLog(ctx, models.WebhookLog{ + HttpStatus: statusCode, + Request: string(requestBytesBuffer.Bytes()), + Response: string(responseBytes), + WebhookID: webhook.ID, + }) + + if err != nil { + log.Debug("failed to add webhook log: ", err) + return err + } + + return nil +} From 6347b6075317ac169662342b125db270cdf4a719 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Mon, 11 Jul 2022 11:10:30 +0530 Subject: [PATCH 11/14] fix: rename revoke refresh token handler for better reading --- server/handlers/{revoke.go => revoke_refresh_token.go} | 4 ++-- server/routes/routes.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename server/handlers/{revoke.go => revoke_refresh_token.go} (94%) diff --git a/server/handlers/revoke.go b/server/handlers/revoke_refresh_token.go similarity index 94% rename from server/handlers/revoke.go rename to server/handlers/revoke_refresh_token.go index faeb663..632df2d 100644 --- a/server/handlers/revoke.go +++ b/server/handlers/revoke_refresh_token.go @@ -12,8 +12,8 @@ import ( "github.com/authorizerdev/authorizer/server/token" ) -// Revoke handler to revoke refresh token -func RevokeHandler() gin.HandlerFunc { +// RevokeRefreshTokenHandler handler to revoke refresh token +func RevokeRefreshTokenHandler() gin.HandlerFunc { return func(gc *gin.Context) { var reqBody map[string]string if err := gc.BindJSON(&reqBody); err != nil { diff --git a/server/routes/routes.go b/server/routes/routes.go index 80bbcb1..fd8bf23 100644 --- a/server/routes/routes.go +++ b/server/routes/routes.go @@ -32,7 +32,7 @@ func InitRouter(log *logrus.Logger) *gin.Engine { router.GET("/userinfo", handlers.UserInfoHandler()) router.GET("/logout", handlers.LogoutHandler()) router.POST("/oauth/token", handlers.TokenHandler()) - router.POST("/oauth/revoke", handlers.RevokeHandler()) + router.POST("/oauth/revoke", handlers.RevokeRefreshTokenHandler()) router.LoadHTMLGlob("templates/*") // login page app related routes. From 6a8309a23144b8f5b9bf4be6286a7e086c5a9c60 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Mon, 11 Jul 2022 11:12:30 +0530 Subject: [PATCH 12/14] feat: register event for revoke/enable access + delete user --- server/resolvers/delete_user.go | 3 +++ server/resolvers/enable_access.go | 3 +++ server/resolvers/revoke_access.go | 6 +++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/server/resolvers/delete_user.go b/server/resolvers/delete_user.go index 862e6ac..be444de 100644 --- a/server/resolvers/delete_user.go +++ b/server/resolvers/delete_user.go @@ -6,6 +6,7 @@ import ( log "github.com/sirupsen/logrus" + "github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/memorystore" @@ -50,5 +51,7 @@ func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*mod Message: `user deleted successfully`, } + go utils.RegisterEvent(ctx, constants.UserDeletedWebhookEvent, "", user) + return res, nil } diff --git a/server/resolvers/enable_access.go b/server/resolvers/enable_access.go index 3b92c07..8e245b8 100644 --- a/server/resolvers/enable_access.go +++ b/server/resolvers/enable_access.go @@ -6,6 +6,7 @@ import ( log "github.com/sirupsen/logrus" + "github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/token" @@ -49,5 +50,7 @@ func EnableAccessResolver(ctx context.Context, params model.UpdateAccessInput) ( Message: `user access enabled successfully`, } + go utils.RegisterEvent(ctx, constants.UserAccessEnabledWebhookEvent, "", user) + return res, nil } diff --git a/server/resolvers/revoke_access.go b/server/resolvers/revoke_access.go index e856951..1262397 100644 --- a/server/resolvers/revoke_access.go +++ b/server/resolvers/revoke_access.go @@ -7,6 +7,7 @@ import ( log "github.com/sirupsen/logrus" + "github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/memorystore" @@ -47,7 +48,10 @@ func RevokeAccessResolver(ctx context.Context, params model.UpdateAccessInput) ( return res, err } - go memorystore.Provider.DeleteAllUserSessions(user.ID) + go func() { + memorystore.Provider.DeleteAllUserSessions(user.ID) + utils.RegisterEvent(ctx, constants.UserAccessRevokedWebhookEvent, "", user) + }() res = &model.Response{ Message: `user access revoked successfully`, From 334041d0e470cbacbf0a4c99658bb830781222d8 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Mon, 11 Jul 2022 11:13:32 +0530 Subject: [PATCH 13/14] fix: delete user event flow --- server/resolvers/delete_user.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/resolvers/delete_user.go b/server/resolvers/delete_user.go index be444de..96dd456 100644 --- a/server/resolvers/delete_user.go +++ b/server/resolvers/delete_user.go @@ -39,8 +39,6 @@ func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*mod return res, err } - go memorystore.Provider.DeleteAllUserSessions(user.ID) - err = db.Provider.DeleteUser(ctx, user) if err != nil { log.Debug("Failed to delete user: ", err) @@ -51,7 +49,10 @@ func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*mod Message: `user deleted successfully`, } - go utils.RegisterEvent(ctx, constants.UserDeletedWebhookEvent, "", user) + go func() { + memorystore.Provider.DeleteAllUserSessions(user.ID) + utils.RegisterEvent(ctx, constants.UserDeletedWebhookEvent, "", user) + }() return res, nil } From 018a13ab3ccf9d1e943b37f3e302c2b40ac4ea5f Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Mon, 11 Jul 2022 19:40:54 +0530 Subject: [PATCH 14/14] feat: add tests for webhook resolvers --- server/db/providers/arangodb/webhook.go | 12 ++++ server/db/providers/cassandradb/webhook.go | 6 ++ server/db/providers/mongodb/webhook.go | 6 ++ .../db/providers/provider_template/webhook.go | 1 + server/db/providers/sql/webhook.go | 13 +++- server/graph/generated/generated.go | 14 ++--- server/graph/model/models_gen.go | 4 +- server/graph/schema.graphqls | 2 +- server/handlers/oauth_callback.go | 2 +- server/resolvers/delete_webhook.go | 4 +- server/resolvers/test_endpoint.go | 2 +- server/resolvers/update_webhook.go | 6 +- server/resolvers/webhook_logs.go | 4 +- server/test/add_webhook_test.go | 38 ++++++++++++ server/test/delete_webhook_test.go | 49 +++++++++++++++ server/test/resolvers_test.go | 18 ++++-- server/test/test.go | 12 ++-- server/test/test_endpoint_test.go | 36 +++++++++++ server/test/update_webhook_test.go | 59 +++++++++++++++++++ server/test/webhook_logs_test.go | 44 ++++++++++++++ server/test/webhook_test.go | 42 +++++++++++++ server/test/webhooks_test.go | 28 +++++++++ server/utils/refs.go | 2 +- server/utils/webhook.go | 8 ++- 24 files changed, 381 insertions(+), 31 deletions(-) create mode 100644 server/test/webhook_test.go diff --git a/server/db/providers/arangodb/webhook.go b/server/db/providers/arangodb/webhook.go index 5df2c28..1a33d76 100644 --- a/server/db/providers/arangodb/webhook.go +++ b/server/db/providers/arangodb/webhook.go @@ -145,5 +145,17 @@ func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) er if err != nil { return err } + + query := fmt.Sprintf("FOR d in %s FILTER d.event_id == @event_id REMOVE { _key: d._key }", models.Collections.WebhookLog) + bindVars := map[string]interface{}{ + "event_id": webhook.ID, + } + + cursor, err := p.db.Query(ctx, query, bindVars) + if err != nil { + return err + } + defer cursor.Close() + return nil } diff --git a/server/db/providers/cassandradb/webhook.go b/server/db/providers/cassandradb/webhook.go index 9d41823..7f7a123 100644 --- a/server/db/providers/cassandradb/webhook.go +++ b/server/db/providers/cassandradb/webhook.go @@ -142,5 +142,11 @@ func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error { query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.Webhook, webhook.ID) err := p.db.Query(query).Exec() + if err != nil { + return err + } + + query = fmt.Sprintf("DELETE FROM %s WHERE webhook_id = '%s'", KeySpace+"."+models.Collections.WebhookLog, webhook.ID) + err = p.db.Query(query).Exec() return err } diff --git a/server/db/providers/mongodb/webhook.go b/server/db/providers/mongodb/webhook.go index 8059eec..b0c2c32 100644 --- a/server/db/providers/mongodb/webhook.go +++ b/server/db/providers/mongodb/webhook.go @@ -110,5 +110,11 @@ func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) er return err } + webhookLogCollection := p.db.Collection(models.Collections.WebhookLog, options.Collection()) + _, err = webhookLogCollection.DeleteOne(nil, bson.M{"webhook_id": webhook.ID}, options.Delete()) + if err != nil { + return err + } + return nil } diff --git a/server/db/providers/provider_template/webhook.go b/server/db/providers/provider_template/webhook.go index 08b85cc..eda82ee 100644 --- a/server/db/providers/provider_template/webhook.go +++ b/server/db/providers/provider_template/webhook.go @@ -44,5 +44,6 @@ func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) // DeleteWebhook to delete webhook func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error { + // Also delete webhook logs for given webhook id return nil } diff --git a/server/db/providers/sql/webhook.go b/server/db/providers/sql/webhook.go index 1a9a257..93f21a4 100644 --- a/server/db/providers/sql/webhook.go +++ b/server/db/providers/sql/webhook.go @@ -69,7 +69,7 @@ func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) { var webhook models.Webhook - result := p.db.Where("id = ?", webhookID).First(webhook) + result := p.db.Where("id = ?", webhookID).First(&webhook) if result.Error != nil { return nil, result.Error } @@ -80,7 +80,7 @@ func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) { var webhook models.Webhook - result := p.db.Where("event_name = ?", eventName).First(webhook) + result := p.db.Where("event_name = ?", eventName).First(&webhook) if result.Error != nil { return nil, result.Error } @@ -89,7 +89,14 @@ func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) // DeleteWebhook to delete webhook func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error { - result := p.db.Delete(&models.Webhook{}, webhook.ID) + result := p.db.Delete(&models.Webhook{ + ID: webhook.ID, + }) + if result.Error != nil { + return result.Error + } + + result = p.db.Where("webhook_id = ?", webhook.ID).Delete(&models.WebhookLog{}) if result.Error != nil { return result.Error } diff --git a/server/graph/generated/generated.go b/server/graph/generated/generated.go index 1eccc26..ebb680f 100644 --- a/server/graph/generated/generated.go +++ b/server/graph/generated/generated.go @@ -2026,7 +2026,7 @@ type TestEndpointResponse { } input ListWebhookLogRequest { - pagination: PaginatedInput! + pagination: PaginationInput! webhook_id: String } @@ -9675,7 +9675,7 @@ func (ec *executionContext) unmarshalInputListWebhookLogRequest(ctx context.Cont var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("pagination")) - it.Pagination, err = ec.unmarshalNPaginatedInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginatedInput(ctx, v) + it.Pagination, err = ec.unmarshalNPaginationInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginationInput(ctx, v) if err != nil { return it, err } @@ -12363,11 +12363,6 @@ func (ec *executionContext) unmarshalNOAuthRevokeInput2githubᚗcomᚋauthorizer return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalNPaginatedInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginatedInput(ctx context.Context, v interface{}) (*model.PaginatedInput, error) { - res, err := ec.unmarshalInputPaginatedInput(ctx, v) - return &res, graphql.ErrorOnPath(ctx, err) -} - func (ec *executionContext) marshalNPagination2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPagination(ctx context.Context, sel ast.SelectionSet, v *model.Pagination) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -12378,6 +12373,11 @@ func (ec *executionContext) marshalNPagination2ᚖgithubᚗcomᚋauthorizerdev return ec._Pagination(ctx, sel, v) } +func (ec *executionContext) unmarshalNPaginationInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginationInput(ctx context.Context, v interface{}) (*model.PaginationInput, error) { + res, err := ec.unmarshalInputPaginationInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalNResendVerifyEmailInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐResendVerifyEmailInput(ctx context.Context, v interface{}) (model.ResendVerifyEmailInput, error) { res, err := ec.unmarshalInputResendVerifyEmailInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/server/graph/model/models_gen.go b/server/graph/model/models_gen.go index b1b9542..7e2c0ed 100644 --- a/server/graph/model/models_gen.go +++ b/server/graph/model/models_gen.go @@ -108,8 +108,8 @@ type InviteMemberInput struct { } type ListWebhookLogRequest struct { - Pagination *PaginatedInput `json:"pagination"` - WebhookID *string `json:"webhook_id"` + Pagination *PaginationInput `json:"pagination"` + WebhookID *string `json:"webhook_id"` } type LoginInput struct { diff --git a/server/graph/schema.graphqls b/server/graph/schema.graphqls index df8edc9..1a6395f 100644 --- a/server/graph/schema.graphqls +++ b/server/graph/schema.graphqls @@ -355,7 +355,7 @@ type TestEndpointResponse { } input ListWebhookLogRequest { - pagination: PaginatedInput! + pagination: PaginationInput! webhook_id: String } diff --git a/server/handlers/oauth_callback.go b/server/handlers/oauth_callback.go index fe588c3..a19fa46 100644 --- a/server/handlers/oauth_callback.go +++ b/server/handlers/oauth_callback.go @@ -219,7 +219,7 @@ func OAuthCallbackHandler() gin.HandlerFunc { go func() { if isSignUp { - utils.RegisterEvent(ctx, constants.EnvKeyDisableSignUp, provider, user) + utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, provider, user) } else { utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, provider, user) } diff --git a/server/resolvers/delete_webhook.go b/server/resolvers/delete_webhook.go index 4241840..917d502 100644 --- a/server/resolvers/delete_webhook.go +++ b/server/resolvers/delete_webhook.go @@ -43,5 +43,7 @@ func DeleteWebhookResolver(ctx context.Context, params model.WebhookRequest) (*m return nil, err } - panic(fmt.Errorf("not implemented")) + return &model.Response{ + Message: "Webhook deleted successfully", + }, nil } diff --git a/server/resolvers/test_endpoint.go b/server/resolvers/test_endpoint.go index 0d0486a..6699966 100644 --- a/server/resolvers/test_endpoint.go +++ b/server/resolvers/test_endpoint.go @@ -63,7 +63,7 @@ func TestEndpointResolver(ctx context.Context, params model.TestEndpointRequest) } if params.EventName == constants.UserLoginWebhookEvent { - reqBody["login_method"] = constants.AuthRecipeMethodMagicLinkLogin + reqBody["auth_recipe"] = constants.AuthRecipeMethodMagicLinkLogin } requestBody, err := json.Marshal(reqBody) diff --git a/server/resolvers/update_webhook.go b/server/resolvers/update_webhook.go index 4ce49d6..6df1ef8 100644 --- a/server/resolvers/update_webhook.go +++ b/server/resolvers/update_webhook.go @@ -52,7 +52,7 @@ func UpdateWebhookResolver(ctx context.Context, params model.UpdateWebhookReques CreatedAt: *webhook.CreatedAt, } - if webhookDetails.EventName != utils.StringValue(params.EventName) { + if params.EventName != nil && webhookDetails.EventName != utils.StringValue(params.EventName) { if isValid := validators.IsValidWebhookEventName(utils.StringValue(params.EventName)); !isValid { log.Debug("invalid event name: ", utils.StringValue(params.EventName)) return nil, fmt.Errorf("invalid event name %s", utils.StringValue(params.EventName)) @@ -60,11 +60,11 @@ func UpdateWebhookResolver(ctx context.Context, params model.UpdateWebhookReques webhookDetails.EventName = utils.StringValue(params.EventName) } - if webhookDetails.EndPoint != utils.StringValue(params.Endpoint) { + if params.Endpoint != nil && webhookDetails.EndPoint != utils.StringValue(params.Endpoint) { webhookDetails.EventName = utils.StringValue(params.EventName) } - if webhookDetails.Enabled != utils.BoolValue(params.Enabled) { + if params.Enabled != nil && webhookDetails.Enabled != utils.BoolValue(params.Enabled) { webhookDetails.Enabled = utils.BoolValue(params.Enabled) } diff --git a/server/resolvers/webhook_logs.go b/server/resolvers/webhook_logs.go index ed3080d..beb2145 100644 --- a/server/resolvers/webhook_logs.go +++ b/server/resolvers/webhook_logs.go @@ -24,7 +24,9 @@ func WebhookLogsResolver(ctx context.Context, params model.ListWebhookLogRequest return nil, fmt.Errorf("unauthorized") } - pagination := utils.GetPagination(params.Pagination) + pagination := utils.GetPagination(&model.PaginatedInput{ + Pagination: params.Pagination, + }) webhookLogs, err := db.Provider.ListWebhookLogs(ctx, pagination, utils.StringValue(params.WebhookID)) if err != nil { diff --git a/server/test/add_webhook_test.go b/server/test/add_webhook_test.go index 56e5404..7b99a54 100644 --- a/server/test/add_webhook_test.go +++ b/server/test/add_webhook_test.go @@ -1 +1,39 @@ package test + +import ( + "fmt" + "testing" + + "github.com/authorizerdev/authorizer/server/constants" + "github.com/authorizerdev/authorizer/server/crypto" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/memorystore" + "github.com/authorizerdev/authorizer/server/resolvers" + "github.com/stretchr/testify/assert" +) + +func addWebhookTest(t *testing.T, s TestSetup) { + t.Helper() + t.Run("should add webhook", func(t *testing.T) { + req, ctx := createContext(s) + adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) + assert.NoError(t, err) + h, err := crypto.EncryptPassword(adminSecret) + assert.NoError(t, err) + req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h)) + + for _, eventType := range s.TestInfo.TestEventTypes { + webhook, err := resolvers.AddWebhookResolver(ctx, model.AddWebhookRequest{ + EventName: eventType, + Endpoint: s.TestInfo.WebhookEndpoint, + Enabled: true, + Headers: map[string]interface{}{ + "x-test": "foo", + }, + }) + assert.NoError(t, err) + assert.NotNil(t, webhook) + assert.NotEmpty(t, webhook.Message) + } + }) +} diff --git a/server/test/delete_webhook_test.go b/server/test/delete_webhook_test.go index 56e5404..471a5f5 100644 --- a/server/test/delete_webhook_test.go +++ b/server/test/delete_webhook_test.go @@ -1 +1,50 @@ package test + +import ( + "fmt" + "testing" + + "github.com/authorizerdev/authorizer/server/constants" + "github.com/authorizerdev/authorizer/server/crypto" + "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/memorystore" + "github.com/authorizerdev/authorizer/server/resolvers" + "github.com/stretchr/testify/assert" +) + +func deleteWebhookTest(t *testing.T, s TestSetup) { + t.Helper() + t.Run("should delete webhook", func(t *testing.T) { + req, ctx := createContext(s) + adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) + assert.NoError(t, err) + h, err := crypto.EncryptPassword(adminSecret) + assert.NoError(t, err) + req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h)) + + // get all webhooks + webhooks, err := db.Provider.ListWebhook(ctx, model.Pagination{}) + assert.NoError(t, err) + + for _, w := range webhooks.Webhooks { + res, err := resolvers.DeleteWebhookResolver(ctx, model.WebhookRequest{ + ID: w.ID, + }) + + assert.NoError(t, err) + assert.NotNil(t, res) + assert.NotEmpty(t, res.Message) + } + + webhooks, err = db.Provider.ListWebhook(ctx, model.Pagination{}) + assert.NoError(t, err) + assert.Len(t, webhooks.Webhooks, 0) + + webhookLogs, err := db.Provider.ListWebhookLogs(ctx, model.Pagination{ + Limit: 10, + }, "") + assert.NoError(t, err) + assert.Len(t, webhookLogs.WebhookLogs, 0) + }) +} diff --git a/server/test/resolvers_test.go b/server/test/resolvers_test.go index a51a1c5..29ff0c4 100644 --- a/server/test/resolvers_test.go +++ b/server/test/resolvers_test.go @@ -3,6 +3,7 @@ package test import ( "context" "testing" + "time" "github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/db" @@ -13,8 +14,8 @@ import ( func TestResolvers(t *testing.T) { databases := map[string]string{ constants.DbTypeSqlite: "../../data.db", - // constants.DbTypeArangodb: "http://localhost:8529", - // constants.DbTypeMongodb: "mongodb://localhost:27017", + // constants.DbTypeArangodb: "http://localhost:8529", + // constants.DbTypeMongodb: "mongodb://localhost:27017", // constants.DbTypeCassandraDB: "127.0.0.1:9042", } @@ -41,9 +42,14 @@ func TestResolvers(t *testing.T) { memorystore.Provider.UpdateEnvVariable(constants.EnvKeyEnv, "test") memorystore.Provider.UpdateEnvVariable(constants.EnvKeyIsProd, false) t.Run("should pass tests for "+dbType, func(t *testing.T) { - // admin tests + // admin resolvers tests adminSignupTests(t, s) + addWebhookTest(t, s) // add webhooks for all the system events + testEndpointTest(t, s) verificationRequestsTest(t, s) + updateWebhookTest(t, s) + webhookTest(t, s) + webhooksTest(t, s) usersTest(t, s) deleteUserTest(t, s) updateUserTest(t, s) @@ -56,7 +62,7 @@ func TestResolvers(t *testing.T) { enableAccessTest(t, s) generateJWTkeyTest(t, s) - // user tests + // user resolvers tests loginTests(t, s) signupTests(t, s) forgotPasswordTest(t, s) @@ -71,6 +77,10 @@ func TestResolvers(t *testing.T) { metaTests(t, s) inviteUserTest(t, s) validateJwtTokenTest(t, s) + + time.Sleep(5 * time.Second) // add sleep for webhooklogs to get generated as they are async + webhookLogsTest(t, s) // get logs after above resolver tests are done + deleteWebhookTest(t, s) // delete webhooks (admin resolver) }) } } diff --git a/server/test/test.go b/server/test/test.go index a152490..fa35c5f 100644 --- a/server/test/test.go +++ b/server/test/test.go @@ -21,8 +21,10 @@ import ( // common user data to share across tests type TestData struct { - Email string - Password string + Email string + Password string + WebhookEndpoint string + TestEventTypes []string } type TestSetup struct { @@ -75,8 +77,10 @@ func createContext(s TestSetup) (*http.Request, context.Context) { func testSetup() TestSetup { testData := TestData{ - Email: fmt.Sprintf("%d_authorizer_tester@yopmail.com", time.Now().Unix()), - Password: "Test@123", + Email: fmt.Sprintf("%d_authorizer_tester@yopmail.com", time.Now().Unix()), + Password: "Test@123", + WebhookEndpoint: "https://62cbc6738042b16aa7c22df2.mockapi.io/api/v1/webhook", + TestEventTypes: []string{constants.UserAccessEnabledWebhookEvent, constants.UserAccessRevokedWebhookEvent, constants.UserCreatedWebhookEvent, constants.UserDeletedWebhookEvent, constants.UserLoginWebhookEvent, constants.UserSignUpWebhookEvent}, } err := os.Setenv(constants.EnvKeyEnvPath, "../../.env.test") diff --git a/server/test/test_endpoint_test.go b/server/test/test_endpoint_test.go index 56e5404..6613c58 100644 --- a/server/test/test_endpoint_test.go +++ b/server/test/test_endpoint_test.go @@ -1 +1,37 @@ package test + +import ( + "fmt" + "testing" + + "github.com/authorizerdev/authorizer/server/constants" + "github.com/authorizerdev/authorizer/server/crypto" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/memorystore" + "github.com/authorizerdev/authorizer/server/resolvers" + "github.com/stretchr/testify/assert" +) + +func testEndpointTest(t *testing.T, s TestSetup) { + t.Helper() + t.Run("should test endpoint", func(t *testing.T) { + req, ctx := createContext(s) + adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) + assert.NoError(t, err) + h, err := crypto.EncryptPassword(adminSecret) + assert.NoError(t, err) + req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h)) + + res, err := resolvers.TestEndpointResolver(ctx, model.TestEndpointRequest{ + Endpoint: s.TestInfo.WebhookEndpoint, + EventName: constants.UserLoginWebhookEvent, + Headers: map[string]interface{}{ + "x-test": "test", + }, + }) + assert.NoError(t, err) + assert.NotNil(t, res) + assert.GreaterOrEqual(t, int64(201), *res.HTTPStatus) + assert.NotEmpty(t, res.Response) + }) +} diff --git a/server/test/update_webhook_test.go b/server/test/update_webhook_test.go index 56e5404..3318f9b 100644 --- a/server/test/update_webhook_test.go +++ b/server/test/update_webhook_test.go @@ -1 +1,60 @@ package test + +import ( + "fmt" + "testing" + + "github.com/authorizerdev/authorizer/server/constants" + "github.com/authorizerdev/authorizer/server/crypto" + "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/memorystore" + "github.com/authorizerdev/authorizer/server/resolvers" + "github.com/authorizerdev/authorizer/server/utils" + "github.com/stretchr/testify/assert" +) + +func updateWebhookTest(t *testing.T, s TestSetup) { + t.Helper() + t.Run("should update webhook", func(t *testing.T) { + req, ctx := createContext(s) + adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) + assert.NoError(t, err) + h, err := crypto.EncryptPassword(adminSecret) + assert.NoError(t, err) + req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h)) + // get webhook + webhook, err := db.Provider.GetWebhookByEventName(ctx, constants.UserDeletedWebhookEvent) + assert.NoError(t, err) + assert.NotNil(t, webhook) + webhook.Headers["x-new-test"] = "new-test" + + res, err := resolvers.UpdateWebhookResolver(ctx, model.UpdateWebhookRequest{ + ID: webhook.ID, + Headers: webhook.Headers, + Enabled: utils.NewBoolRef(false), + }) + + assert.NoError(t, err) + assert.NotEmpty(t, res) + assert.NotEmpty(t, res.Message) + + updatedWebhook, err := db.Provider.GetWebhookByEventName(ctx, constants.UserDeletedWebhookEvent) + assert.NoError(t, err) + assert.NotNil(t, updatedWebhook) + assert.Equal(t, webhook.ID, updatedWebhook.ID) + assert.Equal(t, utils.StringValue(webhook.EventName), utils.StringValue(updatedWebhook.EventName)) + assert.Equal(t, utils.StringValue(webhook.Endpoint), utils.StringValue(updatedWebhook.Endpoint)) + assert.Len(t, updatedWebhook.Headers, 2) + assert.False(t, utils.BoolValue(updatedWebhook.Enabled)) + + res, err = resolvers.UpdateWebhookResolver(ctx, model.UpdateWebhookRequest{ + ID: webhook.ID, + Headers: webhook.Headers, + Enabled: utils.NewBoolRef(true), + }) + assert.NoError(t, err) + assert.NotEmpty(t, res) + assert.NotEmpty(t, res.Message) + }) +} diff --git a/server/test/webhook_logs_test.go b/server/test/webhook_logs_test.go index 56e5404..543c0c5 100644 --- a/server/test/webhook_logs_test.go +++ b/server/test/webhook_logs_test.go @@ -1 +1,45 @@ package test + +import ( + "fmt" + "testing" + + "github.com/authorizerdev/authorizer/server/constants" + "github.com/authorizerdev/authorizer/server/crypto" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/memorystore" + "github.com/authorizerdev/authorizer/server/resolvers" + "github.com/authorizerdev/authorizer/server/utils" + "github.com/stretchr/testify/assert" +) + +func webhookLogsTest(t *testing.T, s TestSetup) { + t.Helper() + t.Run("should get webhook logs", func(t *testing.T) { + req, ctx := createContext(s) + adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) + assert.NoError(t, err) + h, err := crypto.EncryptPassword(adminSecret) + assert.NoError(t, err) + req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h)) + + webhooks, err := resolvers.WebhooksResolver(ctx, nil) + assert.NoError(t, err) + assert.NotEmpty(t, webhooks) + + webhookLogs, err := resolvers.WebhookLogsResolver(ctx, model.ListWebhookLogRequest{}) + assert.NoError(t, err) + assert.Greater(t, len(webhookLogs.WebhookLogs), 1) + + for _, w := range webhooks.Webhooks { + webhookLogs, err := resolvers.WebhookLogsResolver(ctx, model.ListWebhookLogRequest{ + WebhookID: &w.ID, + }) + assert.NoError(t, err) + assert.GreaterOrEqual(t, len(webhookLogs.WebhookLogs), 1) + for _, wl := range webhookLogs.WebhookLogs { + assert.Equal(t, utils.StringValue(wl.WebhookID), w.ID) + } + } + }) +} diff --git a/server/test/webhook_test.go b/server/test/webhook_test.go new file mode 100644 index 0000000..ad840e3 --- /dev/null +++ b/server/test/webhook_test.go @@ -0,0 +1,42 @@ +package test + +import ( + "fmt" + "testing" + + "github.com/authorizerdev/authorizer/server/constants" + "github.com/authorizerdev/authorizer/server/crypto" + "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/memorystore" + "github.com/authorizerdev/authorizer/server/resolvers" + "github.com/authorizerdev/authorizer/server/utils" + "github.com/stretchr/testify/assert" +) + +func webhookTest(t *testing.T, s TestSetup) { + t.Helper() + t.Run("should get webhook", func(t *testing.T) { + req, ctx := createContext(s) + adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) + assert.NoError(t, err) + h, err := crypto.EncryptPassword(adminSecret) + assert.NoError(t, err) + req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h)) + + // get webhook by event name + webhook, err := db.Provider.GetWebhookByEventName(ctx, constants.UserCreatedWebhookEvent) + assert.NoError(t, err) + assert.NotNil(t, webhook) + + res, err := resolvers.WebhookResolver(ctx, model.WebhookRequest{ + ID: webhook.ID, + }) + assert.NoError(t, err) + assert.Equal(t, res.ID, webhook.ID) + assert.Equal(t, utils.StringValue(res.Endpoint), utils.StringValue(webhook.Endpoint)) + assert.Equal(t, utils.StringValue(res.EventName), utils.StringValue(webhook.EventName)) + assert.Equal(t, utils.BoolValue(res.Enabled), utils.BoolValue(webhook.Enabled)) + assert.Len(t, res.Headers, len(webhook.Headers)) + }) +} diff --git a/server/test/webhooks_test.go b/server/test/webhooks_test.go index 56e5404..7b64bd7 100644 --- a/server/test/webhooks_test.go +++ b/server/test/webhooks_test.go @@ -1 +1,29 @@ package test + +import ( + "fmt" + "testing" + + "github.com/authorizerdev/authorizer/server/constants" + "github.com/authorizerdev/authorizer/server/crypto" + "github.com/authorizerdev/authorizer/server/memorystore" + "github.com/authorizerdev/authorizer/server/resolvers" + "github.com/stretchr/testify/assert" +) + +func webhooksTest(t *testing.T, s TestSetup) { + t.Helper() + t.Run("should get webhooks", func(t *testing.T) { + req, ctx := createContext(s) + adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret) + assert.NoError(t, err) + h, err := crypto.EncryptPassword(adminSecret) + assert.NoError(t, err) + req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h)) + + webhooks, err := resolvers.WebhooksResolver(ctx, nil) + assert.NoError(t, err) + assert.NotEmpty(t, webhooks) + assert.Len(t, webhooks.Webhooks, len(s.TestInfo.TestEventTypes)) + }) +} diff --git a/server/utils/refs.go b/server/utils/refs.go index 80cd598..f51cc19 100644 --- a/server/utils/refs.go +++ b/server/utils/refs.go @@ -23,7 +23,7 @@ func NewBoolRef(v bool) *bool { // BoolValue returns the value of the given bool ref func BoolValue(r *bool) bool { - if r != nil { + if r == nil { return false } return *r diff --git a/server/utils/webhook.go b/server/utils/webhook.go index cfd0b2c..b6a75d2 100644 --- a/server/utils/webhook.go +++ b/server/utils/webhook.go @@ -20,7 +20,11 @@ func RegisterEvent(ctx context.Context, eventName string, authRecipe string, use return err } - userBytes, err := json.Marshal(user) + if !BoolValue(webhook.Enabled) { + return nil + } + + userBytes, err := json.Marshal(user.AsAPIUser()) if err != nil { log.Debug("error marshalling user obj: ", err) return err @@ -78,7 +82,7 @@ func RegisterEvent(ctx context.Context, eventName string, authRecipe string, use statusCode := int64(resp.StatusCode) _, err = db.Provider.AddWebhookLog(ctx, models.WebhookLog{ HttpStatus: statusCode, - Request: string(requestBytesBuffer.Bytes()), + Request: string(requestBody), Response: string(responseBytes), WebhookID: webhook.ID, })