From a48b809a89e8b6a01f74991b33cdc6eb6f5461a5 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Sun, 17 Jul 2022 13:37:34 +0530 Subject: [PATCH] feat: add tests for email template resolvers --- Makefile | 11 +++- server/db/models/email_templates.go | 2 +- .../providers/cassandradb/email_template.go | 1 + server/resolvers/add_webhook.go | 6 ++ server/resolvers/update_email_template.go | 7 +++ server/resolvers/update_webhook.go | 5 ++ server/test/add_email_template_test.go | 58 +++++++++++++++++++ server/test/add_webhook_test.go | 2 +- server/test/delete_email_template_test.go | 52 +++++++++++++++++ server/test/email_templates_test.go | 29 ++++++++++ server/test/resolvers_test.go | 31 ++++++++-- server/test/test.go | 18 +++--- server/test/update_email_template_test.go | 46 +++++++++++++++ server/test/update_webhook_test.go | 16 ++--- server/test/webhooks_test.go | 2 +- 15 files changed, 263 insertions(+), 23 deletions(-) create mode 100644 server/test/add_email_template_test.go create mode 100644 server/test/delete_email_template_test.go create mode 100644 server/test/email_templates_test.go create mode 100644 server/test/update_email_template_test.go diff --git a/Makefile b/Makefile index c883a9c..b5539f7 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,16 @@ build-dashboard: clean: rm -rf build test: - rm -rf server/test/test.db && rm -rf test.db && cd server && go clean --testcache && go test -p 1 -v ./test + rm -rf server/test/test.db && rm -rf test.db && cd server && go clean --testcache && TEST_DBS="sqlite" go test -p 1 -v ./test +test-all-db: + rm -rf server/test/test.db && rm -rf test.db + docker run -d --name authorizer_scylla_db -p 9042:9042 scylladb/scylla + docker run -d --name authorizer_mongodb_db -p 27017:27017 mongo:4.4.15 + docker run -d --name authorizer_arangodb -p 8529:8529 -e ARANGO_NO_AUTH=1 arangodb/arangodb:3.8.4 + cd server && go clean --testcache && TEST_DBS="sqlite,mongodb,arangodb,scylladb" go test -p 1 -v ./test + docker rm -vf authorizer_mongodb_db + docker rm -vf authorizer_scylla_db + docker rm -vf authorizer_arangodb generate: cd server && go get github.com/99designs/gqlgen/cmd@v0.14.0 && go run github.com/99designs/gqlgen generate \ No newline at end of file diff --git a/server/db/models/email_templates.go b/server/db/models/email_templates.go index 2573de0..23ac7fa 100644 --- a/server/db/models/email_templates.go +++ b/server/db/models/email_templates.go @@ -12,7 +12,7 @@ type EmailTemplate 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"` - Template string `gorm:"type:text" json:"endpoint" bson:"endpoint" cql:"endpoint"` + Template string `gorm:"type:text" json:"template" bson:"template" cql:"template"` 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/providers/cassandradb/email_template.go b/server/db/providers/cassandradb/email_template.go index 4fa9109..87d65ea 100644 --- a/server/db/providers/cassandradb/email_template.go +++ b/server/db/providers/cassandradb/email_template.go @@ -81,6 +81,7 @@ func (p *provider) UpdateEmailTemplate(ctx context.Context, emailTemplate models updateFields = strings.TrimSuffix(updateFields, ",") query := fmt.Sprintf("UPDATE %s SET %s WHERE id = '%s'", KeySpace+"."+models.Collections.EmailTemplate, updateFields, emailTemplate.ID) + fmt.Println("=> query:", query) err = p.db.Query(query).Exec() if err != nil { return nil, err diff --git a/server/resolvers/add_webhook.go b/server/resolvers/add_webhook.go index fd80578..d8c768a 100644 --- a/server/resolvers/add_webhook.go +++ b/server/resolvers/add_webhook.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db/models" @@ -32,6 +33,11 @@ func AddWebhookResolver(ctx context.Context, params model.AddWebhookRequest) (*m return nil, fmt.Errorf("invalid event name %s", params.EventName) } + if strings.TrimSpace(params.Endpoint) == "" { + log.Debug("empty endpoint not allowed") + return nil, fmt.Errorf("empty endpoint not allowed") + } + headerBytes, err := json.Marshal(params.Headers) if err != nil { return nil, err diff --git a/server/resolvers/update_email_template.go b/server/resolvers/update_email_template.go index 6cc912d..95362c0 100644 --- a/server/resolvers/update_email_template.go +++ b/server/resolvers/update_email_template.go @@ -3,6 +3,7 @@ package resolvers import ( "context" "fmt" + "strings" "github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db/models" @@ -14,6 +15,8 @@ import ( log "github.com/sirupsen/logrus" ) +// TODO add template validator + // UpdateEmailTemplateResolver resolver for update email template mutation func UpdateEmailTemplateResolver(ctx context.Context, params model.UpdateEmailTemplateRequest) (*model.Response, error) { gc, err := utils.GinContextFromContext(ctx) @@ -49,6 +52,10 @@ func UpdateEmailTemplateResolver(ctx context.Context, params model.UpdateEmailTe } if params.Template != nil && emailTemplateDetails.Template != refs.StringValue(params.Template) { + if strings.TrimSpace(refs.StringValue(params.Template)) == "" { + log.Debug("empty template not allowed") + return nil, fmt.Errorf("empty template not allowed") + } emailTemplateDetails.Template = refs.StringValue(params.Template) } diff --git a/server/resolvers/update_webhook.go b/server/resolvers/update_webhook.go index 934bfdd..f1d1009 100644 --- a/server/resolvers/update_webhook.go +++ b/server/resolvers/update_webhook.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db/models" @@ -62,6 +63,10 @@ func UpdateWebhookResolver(ctx context.Context, params model.UpdateWebhookReques } if params.Endpoint != nil && webhookDetails.EndPoint != refs.StringValue(params.Endpoint) { + if strings.TrimSpace(refs.StringValue(params.Endpoint)) == "" { + log.Debug("empty endpoint not allowed") + return nil, fmt.Errorf("empty endpoint not allowed") + } webhookDetails.EndPoint = refs.StringValue(params.Endpoint) } diff --git a/server/test/add_email_template_test.go b/server/test/add_email_template_test.go new file mode 100644 index 0000000..743ed12 --- /dev/null +++ b/server/test/add_email_template_test.go @@ -0,0 +1,58 @@ +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 addEmailTemplateTest(t *testing.T, s TestSetup) { + t.Helper() + t.Run("should add email templates", 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)) + + t.Run("should not add email template for invalid event type", func(t *testing.T) { + emailTemplate, err := resolvers.AddEmailTemplateResolver(ctx, model.AddEmailTemplateRequest{ + EventName: "test", + }) + assert.Error(t, err) + assert.Nil(t, emailTemplate) + }) + + t.Run("should not add email template for empty template", func(t *testing.T) { + emailTemplate, err := resolvers.AddEmailTemplateResolver(ctx, model.AddEmailTemplateRequest{ + EventName: s.TestInfo.TestEmailTemplateEventTypes[0], + Template: " ", + }) + assert.Error(t, err) + assert.Nil(t, emailTemplate) + }) + for _, eventType := range s.TestInfo.TestEmailTemplateEventTypes { + t.Run("should add email template for "+eventType, func(t *testing.T) { + emailTemplate, err := resolvers.AddEmailTemplateResolver(ctx, model.AddEmailTemplateRequest{ + EventName: eventType, + Template: `Test email`, + }) + assert.NoError(t, err) + assert.NotNil(t, emailTemplate) + assert.NotEmpty(t, emailTemplate.Message) + + et, err := db.Provider.GetEmailTemplateByEventName(ctx, eventType) + assert.NoError(t, err) + assert.Equal(t, et.EventName, eventType) + }) + } + }) +} diff --git a/server/test/add_webhook_test.go b/server/test/add_webhook_test.go index 7b99a54..3068740 100644 --- a/server/test/add_webhook_test.go +++ b/server/test/add_webhook_test.go @@ -22,7 +22,7 @@ func addWebhookTest(t *testing.T, s TestSetup) { assert.NoError(t, err) req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h)) - for _, eventType := range s.TestInfo.TestEventTypes { + for _, eventType := range s.TestInfo.TestWebhookEventTypes { webhook, err := resolvers.AddWebhookResolver(ctx, model.AddWebhookRequest{ EventName: eventType, Endpoint: s.TestInfo.WebhookEndpoint, diff --git a/server/test/delete_email_template_test.go b/server/test/delete_email_template_test.go new file mode 100644 index 0000000..ef79db9 --- /dev/null +++ b/server/test/delete_email_template_test.go @@ -0,0 +1,52 @@ +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 deleteEmailTemplateTest(t *testing.T, s TestSetup) { + t.Helper() + t.Run("should delete email templates", 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 email templates + emailTemplates, err := db.Provider.ListEmailTemplate(ctx, model.Pagination{ + Limit: 10, + Page: 1, + Offset: 0, + }) + assert.NoError(t, err) + + for _, e := range emailTemplates.EmailTemplates { + res, err := resolvers.DeleteEmailTemplateResolver(ctx, model.DeleteEmailTemplateRequest{ + ID: e.ID, + }) + + assert.NoError(t, err) + assert.NotNil(t, res) + assert.NotEmpty(t, res.Message) + } + + emailTemplates, err = db.Provider.ListEmailTemplate(ctx, model.Pagination{ + Limit: 10, + Page: 1, + Offset: 0, + }) + assert.NoError(t, err) + assert.Len(t, emailTemplates.EmailTemplates, 0) + }) +} diff --git a/server/test/email_templates_test.go b/server/test/email_templates_test.go new file mode 100644 index 0000000..b5c9083 --- /dev/null +++ b/server/test/email_templates_test.go @@ -0,0 +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 emailTemplatesTest(t *testing.T, s TestSetup) { + t.Helper() + t.Run("should get email templates", 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)) + + emailTemplates, err := resolvers.EmailTemplatesResolver(ctx, nil) + assert.NoError(t, err) + assert.NotEmpty(t, emailTemplates) + assert.Len(t, emailTemplates.EmailTemplates, len(s.TestInfo.TestEmailTemplateEventTypes)) + }) +} diff --git a/server/test/resolvers_test.go b/server/test/resolvers_test.go index 44feaff..1a49632 100644 --- a/server/test/resolvers_test.go +++ b/server/test/resolvers_test.go @@ -3,20 +3,39 @@ package test import ( "context" "os" + "strings" "testing" + "time" "github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/env" "github.com/authorizerdev/authorizer/server/memorystore" + "github.com/authorizerdev/authorizer/server/utils" ) func TestResolvers(t *testing.T) { databases := map[string]string{ - constants.DbTypeSqlite: "../../test.db", - // constants.DbTypeArangodb: "http://localhost:8529", - // constants.DbTypeMongodb: "mongodb://localhost:27017", - // constants.DbTypeScyllaDB: "127.0.0.1:9042", + constants.DbTypeSqlite: "../../test.db", + constants.DbTypeArangodb: "http://localhost:8529", + constants.DbTypeMongodb: "mongodb://localhost:27017", + constants.DbTypeScyllaDB: "127.0.0.1:9042", + } + + testDBs := strings.Split(os.Getenv("TEST_DBS"), ",") + t.Log("Running tests for following dbs: ", testDBs) + for dbType := range databases { + if !utils.StringSliceContains(testDBs, dbType) { + delete(databases, dbType) + } + } + + if utils.StringSliceContains(testDBs, constants.DbTypeSqlite) && len(testDBs) == 1 { + // do nothing + } else { + t.Log("waiting for docker containers to spun up") + // wait for docker containers to spun up + time.Sleep(30 * time.Second) } testDb := "authorizer_test" @@ -75,6 +94,10 @@ func TestResolvers(t *testing.T) { revokeAccessTest(t, s) enableAccessTest(t, s) generateJWTkeyTest(t, s) + addEmailTemplateTest(t, s) + updateEmailTemplateTest(t, s) + emailTemplatesTest(t, s) + deleteEmailTemplateTest(t, s) // user resolvers tests loginTests(t, s) diff --git a/server/test/test.go b/server/test/test.go index af27fb4..b2288ff 100644 --- a/server/test/test.go +++ b/server/test/test.go @@ -21,10 +21,11 @@ import ( // common user data to share across tests type TestData struct { - Email string - Password string - WebhookEndpoint string - TestEventTypes []string + Email string + Password string + WebhookEndpoint string + TestWebhookEventTypes []string + TestEmailTemplateEventTypes []string } type TestSetup struct { @@ -76,10 +77,11 @@ 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", - WebhookEndpoint: "https://62cbc6738042b16aa7c22df2.mockapi.io/api/v1/webhook", - TestEventTypes: []string{constants.UserAccessEnabledWebhookEvent, constants.UserAccessRevokedWebhookEvent, constants.UserCreatedWebhookEvent, constants.UserDeletedWebhookEvent, constants.UserLoginWebhookEvent, constants.UserSignUpWebhookEvent}, + Email: fmt.Sprintf("%d_authorizer_tester@yopmail.com", time.Now().Unix()), + Password: "Test@123", + WebhookEndpoint: "https://62cbc6738042b16aa7c22df2.mockapi.io/api/v1/webhook", + TestWebhookEventTypes: []string{constants.UserAccessEnabledWebhookEvent, constants.UserAccessRevokedWebhookEvent, constants.UserCreatedWebhookEvent, constants.UserDeletedWebhookEvent, constants.UserLoginWebhookEvent, constants.UserSignUpWebhookEvent}, + TestEmailTemplateEventTypes: []string{constants.VerificationTypeBasicAuthSignup, constants.VerificationTypeForgotPassword, constants.VerificationTypeMagicLinkLogin, constants.VerificationTypeUpdateEmail}, } err := os.Setenv(constants.EnvKeyEnvPath, "../../.env.test") diff --git a/server/test/update_email_template_test.go b/server/test/update_email_template_test.go new file mode 100644 index 0000000..1f23ff4 --- /dev/null +++ b/server/test/update_email_template_test.go @@ -0,0 +1,46 @@ +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/refs" + "github.com/authorizerdev/authorizer/server/resolvers" + "github.com/stretchr/testify/assert" +) + +func updateEmailTemplateTest(t *testing.T, s TestSetup) { + t.Helper() + t.Run("should update email template", 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 email template + emailTemplate, err := db.Provider.GetEmailTemplateByEventName(ctx, constants.VerificationTypeBasicAuthSignup) + assert.NoError(t, err) + assert.NotNil(t, emailTemplate) + + res, err := resolvers.UpdateEmailTemplateResolver(ctx, model.UpdateEmailTemplateRequest{ + ID: emailTemplate.ID, + Template: refs.NewStringRef("Updated test template"), + }) + + assert.NoError(t, err) + assert.NotEmpty(t, res) + assert.NotEmpty(t, res.Message) + + updatedEmailTemplate, err := db.Provider.GetEmailTemplateByEventName(ctx, constants.VerificationTypeBasicAuthSignup) + assert.NoError(t, err) + assert.NotNil(t, updatedEmailTemplate) + assert.Equal(t, emailTemplate.ID, updatedEmailTemplate.ID) + assert.Equal(t, updatedEmailTemplate.Template, "Updated test template") + }) +} diff --git a/server/test/update_webhook_test.go b/server/test/update_webhook_test.go index cb96b72..07f658c 100644 --- a/server/test/update_webhook_test.go +++ b/server/test/update_webhook_test.go @@ -33,9 +33,10 @@ func updateWebhookTest(t *testing.T, s TestSetup) { } res, err := resolvers.UpdateWebhookResolver(ctx, model.UpdateWebhookRequest{ - ID: webhook.ID, - Headers: webhook.Headers, - Enabled: refs.NewBoolRef(false), + ID: webhook.ID, + Headers: webhook.Headers, + Enabled: refs.NewBoolRef(false), + Endpoint: refs.NewStringRef("https://sometest.com"), }) assert.NoError(t, err) @@ -47,17 +48,18 @@ func updateWebhookTest(t *testing.T, s TestSetup) { assert.NotNil(t, updatedWebhook) assert.Equal(t, webhook.ID, updatedWebhook.ID) assert.Equal(t, refs.StringValue(webhook.EventName), refs.StringValue(updatedWebhook.EventName)) - assert.Equal(t, refs.StringValue(webhook.Endpoint), refs.StringValue(updatedWebhook.Endpoint)) assert.Len(t, updatedWebhook.Headers, 1) assert.False(t, refs.BoolValue(updatedWebhook.Enabled)) for key, val := range updatedWebhook.Headers { assert.Equal(t, val, webhook.Headers[key]) } + assert.Equal(t, refs.StringValue(updatedWebhook.Endpoint), "https://sometest.com") res, err = resolvers.UpdateWebhookResolver(ctx, model.UpdateWebhookRequest{ - ID: webhook.ID, - Headers: webhook.Headers, - Enabled: refs.NewBoolRef(true), + ID: webhook.ID, + Headers: webhook.Headers, + Enabled: refs.NewBoolRef(true), + Endpoint: refs.NewStringRef(s.TestInfo.WebhookEndpoint), }) assert.NoError(t, err) assert.NotEmpty(t, res) diff --git a/server/test/webhooks_test.go b/server/test/webhooks_test.go index 7b64bd7..b4ec561 100644 --- a/server/test/webhooks_test.go +++ b/server/test/webhooks_test.go @@ -24,6 +24,6 @@ func webhooksTest(t *testing.T, s TestSetup) { webhooks, err := resolvers.WebhooksResolver(ctx, nil) assert.NoError(t, err) assert.NotEmpty(t, webhooks) - assert.Len(t, webhooks.Webhooks, len(s.TestInfo.TestEventTypes)) + assert.Len(t, webhooks.Webhooks, len(s.TestInfo.TestWebhookEventTypes)) }) }