Merge branch 'main' of https://github.com/authorizerdev/authorizer into feat/webhooks
This commit is contained in:
commit
79c94fcaf0
11
Makefile
11
Makefile
|
@ -10,7 +10,16 @@ build-dashboard:
|
||||||
clean:
|
clean:
|
||||||
rm -rf build
|
rm -rf build
|
||||||
test:
|
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:
|
generate:
|
||||||
cd server && go get github.com/99designs/gqlgen/cmd@v0.14.0 && go run github.com/99designs/gqlgen generate
|
cd server && go get github.com/99designs/gqlgen/cmd@v0.14.0 && go run github.com/99designs/gqlgen generate
|
||||||
|
|
|
@ -8,6 +8,9 @@ const (
|
||||||
FacebookUserInfoURL = "https://graph.facebook.com/me?fields=id,first_name,last_name,name,email,picture&access_token="
|
FacebookUserInfoURL = "https://graph.facebook.com/me?fields=id,first_name,last_name,name,email,picture&access_token="
|
||||||
// Ref: https://docs.github.com/en/developers/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#3-your-github-app-accesses-the-api-with-the-users-access-token
|
// Ref: https://docs.github.com/en/developers/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#3-your-github-app-accesses-the-api-with-the-users-access-token
|
||||||
GithubUserInfoURL = "https://api.github.com/user"
|
GithubUserInfoURL = "https://api.github.com/user"
|
||||||
|
// Get github user emails when user info email is empty Ref: https://stackoverflow.com/a/35387123
|
||||||
|
GithubUserEmails = "https://api/github.com/user/emails"
|
||||||
|
|
||||||
// Ref: https://docs.microsoft.com/en-us/linkedin/shared/integrations/people/profile-api
|
// Ref: https://docs.microsoft.com/en-us/linkedin/shared/integrations/people/profile-api
|
||||||
LinkedInUserInfoURL = "https://api.linkedin.com/v2/me?projection=(id,localizedFirstName,localizedLastName,emailAddress,profilePicture(displayImage~:playableStreams))"
|
LinkedInUserInfoURL = "https://api.linkedin.com/v2/me?projection=(id,localizedFirstName,localizedLastName,emailAddress,profilePicture(displayImage~:playableStreams))"
|
||||||
LinkedInEmailURL = "https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))"
|
LinkedInEmailURL = "https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))"
|
||||||
|
|
33
server/db/models/email_templates.go
Normal file
33
server/db/models/email_templates.go
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/authorizerdev/authorizer/server/refs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EmailTemplate model for database
|
||||||
|
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:"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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsAPIEmailTemplate to return email template as graphql response object
|
||||||
|
func (e *EmailTemplate) AsAPIEmailTemplate() *model.EmailTemplate {
|
||||||
|
id := e.ID
|
||||||
|
if strings.Contains(id, Collections.EmailTemplate+"/") {
|
||||||
|
id = strings.TrimPrefix(id, Collections.EmailTemplate+"/")
|
||||||
|
}
|
||||||
|
return &model.EmailTemplate{
|
||||||
|
ID: id,
|
||||||
|
EventName: e.EventName,
|
||||||
|
Template: e.Template,
|
||||||
|
CreatedAt: refs.NewInt64Ref(e.CreatedAt),
|
||||||
|
UpdatedAt: refs.NewInt64Ref(e.UpdatedAt),
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ type CollectionList struct {
|
||||||
Env string
|
Env string
|
||||||
Webhook string
|
Webhook string
|
||||||
WebhookLog string
|
WebhookLog string
|
||||||
|
EmailTemplate string
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -21,5 +22,6 @@ var (
|
||||||
Env: Prefix + "env",
|
Env: Prefix + "env",
|
||||||
Webhook: Prefix + "webhook",
|
Webhook: Prefix + "webhook",
|
||||||
WebhookLog: Prefix + "webhook_log",
|
WebhookLog: Prefix + "webhook_log",
|
||||||
|
EmailTemplate: Prefix + "email_template",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -22,6 +22,7 @@ type Webhook struct {
|
||||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AsAPIWebhook to return webhook as graphql response object
|
||||||
func (w *Webhook) AsAPIWebhook() *model.Webhook {
|
func (w *Webhook) AsAPIWebhook() *model.Webhook {
|
||||||
headersMap := make(map[string]interface{})
|
headersMap := make(map[string]interface{})
|
||||||
json.Unmarshal([]byte(w.Headers), &headersMap)
|
json.Unmarshal([]byte(w.Headers), &headersMap)
|
||||||
|
|
|
@ -21,6 +21,7 @@ type WebhookLog struct {
|
||||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AsAPIWebhookLog to return webhook log as graphql response object
|
||||||
func (w *WebhookLog) AsAPIWebhookLog() *model.WebhookLog {
|
func (w *WebhookLog) AsAPIWebhookLog() *model.WebhookLog {
|
||||||
id := w.ID
|
id := w.ID
|
||||||
if strings.Contains(id, Collections.WebhookLog+"/") {
|
if strings.Contains(id, Collections.WebhookLog+"/") {
|
||||||
|
|
151
server/db/providers/arangodb/email_template.go
Normal file
151
server/db/providers/arangodb/email_template.go
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEmailTemplate to add EmailTemplate
|
||||||
|
func (p *provider) AddEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
if emailTemplate.ID == "" {
|
||||||
|
emailTemplate.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate.Key = emailTemplate.ID
|
||||||
|
emailTemplate.CreatedAt = time.Now().Unix()
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
emailTemplateCollection, _ := p.db.Collection(ctx, models.Collections.EmailTemplate)
|
||||||
|
_, err := emailTemplateCollection.CreateDocument(ctx, emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEmailTemplate to update EmailTemplate
|
||||||
|
func (p *provider) UpdateEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
emailTemplateCollection, _ := p.db.Collection(ctx, models.Collections.EmailTemplate)
|
||||||
|
meta, err := emailTemplateCollection.UpdateDocument(ctx, emailTemplate.Key, emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate.Key = meta.Key
|
||||||
|
emailTemplate.ID = meta.ID.String()
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmailTemplates to list EmailTemplate
|
||||||
|
func (p *provider) ListEmailTemplate(ctx context.Context, pagination model.Pagination) (*model.EmailTemplates, error) {
|
||||||
|
emailTemplates := []*model.EmailTemplate{}
|
||||||
|
|
||||||
|
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.EmailTemplate, pagination.Offset, pagination.Limit)
|
||||||
|
|
||||||
|
sctx := driver.WithQueryFullCount(ctx)
|
||||||
|
cursor, err := p.db.Query(sctx, query, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
|
||||||
|
paginationClone := pagination
|
||||||
|
paginationClone.Total = cursor.Statistics().FullCount()
|
||||||
|
|
||||||
|
for {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
meta, err := cursor.ReadDocument(ctx, &emailTemplate)
|
||||||
|
|
||||||
|
if arangoDriver.IsNoMoreDocuments(err) {
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.Key != "" {
|
||||||
|
emailTemplates = append(emailTemplates, emailTemplate.AsAPIEmailTemplate())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.EmailTemplates{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
EmailTemplates: emailTemplates,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByID to get EmailTemplate by id
|
||||||
|
func (p *provider) GetEmailTemplateByID(ctx context.Context, emailTemplateID string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
query := fmt.Sprintf("FOR d in %s FILTER d._key == @email_template_id RETURN d", models.Collections.EmailTemplate)
|
||||||
|
bindVars := map[string]interface{}{
|
||||||
|
"email_template_id": emailTemplateID,
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
if !cursor.HasMore() {
|
||||||
|
if emailTemplate.Key == "" {
|
||||||
|
return nil, fmt.Errorf("email template not found")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, err := cursor.ReadDocument(ctx, &emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByEventName to get EmailTemplate by event_name
|
||||||
|
func (p *provider) GetEmailTemplateByEventName(ctx context.Context, eventName string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
query := fmt.Sprintf("FOR d in %s FILTER d.event_name == @event_name RETURN d", models.Collections.EmailTemplate)
|
||||||
|
bindVars := map[string]interface{}{
|
||||||
|
"event_name": eventName,
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
if !cursor.HasMore() {
|
||||||
|
if emailTemplate.Key == "" {
|
||||||
|
return nil, fmt.Errorf("email template not found")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, err := cursor.ReadDocument(ctx, &emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailTemplate to delete EmailTemplate
|
||||||
|
func (p *provider) DeleteEmailTemplate(ctx context.Context, emailTemplate *model.EmailTemplate) error {
|
||||||
|
eventTemplateCollection, _ := p.db.Collection(ctx, models.Collections.EmailTemplate)
|
||||||
|
_, err := eventTemplateCollection.RemoveDocument(ctx, emailTemplate.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -134,6 +134,20 @@ func NewProvider() (*provider, error) {
|
||||||
Sparse: true,
|
Sparse: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
emailTemplateCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.EmailTemplate)
|
||||||
|
if !emailTemplateCollectionExists {
|
||||||
|
_, err = arangodb.CreateCollection(ctx, models.Collections.EmailTemplate, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplateCollection, _ := arangodb.Collection(nil, models.Collections.EmailTemplate)
|
||||||
|
emailTemplateCollection.EnsureHashIndex(ctx, []string{"event_name"}, &arangoDriver.EnsureHashIndexOptions{
|
||||||
|
Unique: true,
|
||||||
|
Sparse: true,
|
||||||
|
})
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
db: arangodb,
|
db: arangodb,
|
||||||
}, err
|
}, err
|
||||||
|
|
159
server/db/providers/cassandradb/email_template.go
Normal file
159
server/db/providers/cassandradb/email_template.go
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
package cassandradb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEmailTemplate to add EmailTemplate
|
||||||
|
func (p *provider) AddEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
if emailTemplate.ID == "" {
|
||||||
|
emailTemplate.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate.Key = emailTemplate.ID
|
||||||
|
emailTemplate.CreatedAt = time.Now().Unix()
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
existingEmailTemplate, _ := p.GetEmailTemplateByEventName(ctx, emailTemplate.EventName)
|
||||||
|
if existingEmailTemplate != nil {
|
||||||
|
return nil, fmt.Errorf("Email template with %s event_name already exists", emailTemplate.EventName)
|
||||||
|
}
|
||||||
|
|
||||||
|
insertQuery := fmt.Sprintf("INSERT INTO %s (id, event_name, template, created_at, updated_at) VALUES ('%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.EmailTemplate, emailTemplate.ID, emailTemplate.EventName, emailTemplate.Template, emailTemplate.CreatedAt, emailTemplate.UpdatedAt)
|
||||||
|
err := p.db.Query(insertQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEmailTemplate to update EmailTemplate
|
||||||
|
func (p *provider) UpdateEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling
|
||||||
|
decoder := json.NewDecoder(strings.NewReader(string(bytes)))
|
||||||
|
decoder.UseNumber()
|
||||||
|
emailTemplateMap := map[string]interface{}{}
|
||||||
|
err = decoder.Decode(&emailTemplateMap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFields := ""
|
||||||
|
for key, value := range emailTemplateMap {
|
||||||
|
if key == "_id" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if key == "_key" {
|
||||||
|
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.EmailTemplate, updateFields, emailTemplate.ID)
|
||||||
|
err = p.db.Query(query).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmailTemplates to list EmailTemplate
|
||||||
|
func (p *provider) ListEmailTemplate(ctx context.Context, pagination model.Pagination) (*model.EmailTemplates, error) {
|
||||||
|
emailTemplates := []*model.EmailTemplate{}
|
||||||
|
paginationClone := pagination
|
||||||
|
|
||||||
|
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.EmailTemplate)
|
||||||
|
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, template, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.EmailTemplate, pagination.Limit+pagination.Offset)
|
||||||
|
|
||||||
|
scanner := p.db.Query(query).Iter().Scanner()
|
||||||
|
counter := int64(0)
|
||||||
|
for scanner.Next() {
|
||||||
|
if counter >= pagination.Offset {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
err := scanner.Scan(&emailTemplate.ID, &emailTemplate.EventName, &emailTemplate.Template, &emailTemplate.CreatedAt, &emailTemplate.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
emailTemplates = append(emailTemplates, emailTemplate.AsAPIEmailTemplate())
|
||||||
|
}
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.EmailTemplates{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
EmailTemplates: emailTemplates,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByID to get EmailTemplate by id
|
||||||
|
func (p *provider) GetEmailTemplateByID(ctx context.Context, emailTemplateID string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
query := fmt.Sprintf(`SELECT id, event_name, template, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1`, KeySpace+"."+models.Collections.EmailTemplate, emailTemplateID)
|
||||||
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&emailTemplate.ID, &emailTemplate.EventName, &emailTemplate.Template, &emailTemplate.CreatedAt, &emailTemplate.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByEventName to get EmailTemplate by event_name
|
||||||
|
func (p *provider) GetEmailTemplateByEventName(ctx context.Context, eventName string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
query := fmt.Sprintf(`SELECT id, event_name, template, created_at, updated_at FROM %s WHERE event_name = '%s' LIMIT 1 ALLOW FILTERING`, KeySpace+"."+models.Collections.EmailTemplate, eventName)
|
||||||
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&emailTemplate.ID, &emailTemplate.EventName, &emailTemplate.Template, &emailTemplate.CreatedAt, &emailTemplate.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailTemplate to delete EmailTemplate
|
||||||
|
func (p *provider) DeleteEmailTemplate(ctx context.Context, emailTemplate *model.EmailTemplate) error {
|
||||||
|
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.EmailTemplate, emailTemplate.ID)
|
||||||
|
err := p.db.Query(query).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -204,6 +204,17 @@ func NewProvider() (*provider, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emailTemplateCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, event_name text, template text, updated_at bigint, created_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.EmailTemplate)
|
||||||
|
err = session.Query(emailTemplateCollectionQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
emailTemplateIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_email_template_event_name ON %s.%s (event_name)", KeySpace, models.Collections.EmailTemplate)
|
||||||
|
err = session.Query(emailTemplateIndexQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
db: session,
|
db: session,
|
||||||
}, err
|
}, err
|
||||||
|
|
115
server/db/providers/mongodb/email_template.go
Normal file
115
server/db/providers/mongodb/email_template.go
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
package mongodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEmailTemplate to add EmailTemplate
|
||||||
|
func (p *provider) AddEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
if emailTemplate.ID == "" {
|
||||||
|
emailTemplate.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate.Key = emailTemplate.ID
|
||||||
|
emailTemplate.CreatedAt = time.Now().Unix()
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
emailTemplateCollection := p.db.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
_, err := emailTemplateCollection.InsertOne(ctx, emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEmailTemplate to update EmailTemplate
|
||||||
|
func (p *provider) UpdateEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
emailTemplateCollection := p.db.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
_, err := emailTemplateCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": emailTemplate.ID}}, bson.M{"$set": emailTemplate}, options.MergeUpdateOptions())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmailTemplates to list EmailTemplate
|
||||||
|
func (p *provider) ListEmailTemplate(ctx context.Context, pagination model.Pagination) (*model.EmailTemplates, error) {
|
||||||
|
var emailTemplates []*model.EmailTemplate
|
||||||
|
opts := options.Find()
|
||||||
|
opts.SetLimit(pagination.Limit)
|
||||||
|
opts.SetSkip(pagination.Offset)
|
||||||
|
opts.SetSort(bson.M{"created_at": -1})
|
||||||
|
|
||||||
|
paginationClone := pagination
|
||||||
|
|
||||||
|
emailTemplateCollection := p.db.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
count, err := emailTemplateCollection.CountDocuments(ctx, bson.M{}, options.Count())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
paginationClone.Total = count
|
||||||
|
|
||||||
|
cursor, err := emailTemplateCollection.Find(ctx, bson.M{}, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close(ctx)
|
||||||
|
|
||||||
|
for cursor.Next(ctx) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
err := cursor.Decode(&emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
emailTemplates = append(emailTemplates, emailTemplate.AsAPIEmailTemplate())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.EmailTemplates{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
EmailTemplates: emailTemplates,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByID to get EmailTemplate by id
|
||||||
|
func (p *provider) GetEmailTemplateByID(ctx context.Context, emailTemplateID string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
emailTemplateCollection := p.db.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
err := emailTemplateCollection.FindOne(ctx, bson.M{"_id": emailTemplateID}).Decode(&emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByEventName to get EmailTemplate by event_name
|
||||||
|
func (p *provider) GetEmailTemplateByEventName(ctx context.Context, eventName string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
emailTemplateCollection := p.db.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
err := emailTemplateCollection.FindOne(ctx, bson.M{"event_name": eventName}).Decode(&emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailTemplate to delete EmailTemplate
|
||||||
|
func (p *provider) DeleteEmailTemplate(ctx context.Context, emailTemplate *model.EmailTemplate) error {
|
||||||
|
emailTemplateCollection := p.db.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
_, err := emailTemplateCollection.DeleteOne(nil, bson.M{"_id": emailTemplate.ID}, options.Delete())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -101,6 +101,15 @@ func NewProvider() (*provider, error) {
|
||||||
},
|
},
|
||||||
}, options.CreateIndexes())
|
}, options.CreateIndexes())
|
||||||
|
|
||||||
|
mongodb.CreateCollection(ctx, models.Collections.EmailTemplate, options.CreateCollection())
|
||||||
|
emailTemplateCollection := mongodb.Collection(models.Collections.EmailTemplate, options.Collection())
|
||||||
|
emailTemplateCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
|
{
|
||||||
|
Keys: bson.M{"event_name": 1},
|
||||||
|
Options: options.Index().SetUnique(true).SetSparse(true),
|
||||||
|
},
|
||||||
|
}, options.CreateIndexes())
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
db: mongodb,
|
db: mongodb,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
48
server/db/providers/provider_template/email_template.go
Normal file
48
server/db/providers/provider_template/email_template.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package provider_template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEmailTemplate to add EmailTemplate
|
||||||
|
func (p *provider) AddEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
if emailTemplate.ID == "" {
|
||||||
|
emailTemplate.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate.Key = emailTemplate.ID
|
||||||
|
emailTemplate.CreatedAt = time.Now().Unix()
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEmailTemplate to update EmailTemplate
|
||||||
|
func (p *provider) UpdateEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmailTemplates to list EmailTemplate
|
||||||
|
func (p *provider) ListEmailTemplate(ctx context.Context, pagination model.Pagination) (*model.EmailTemplates, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByID to get EmailTemplate by id
|
||||||
|
func (p *provider) GetEmailTemplateByID(ctx context.Context, emailTemplateID string) (*model.EmailTemplate, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByEventName to get EmailTemplate by event_name
|
||||||
|
func (p *provider) GetEmailTemplateByEventName(ctx context.Context, eventName string) (*model.EmailTemplate, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailTemplate to delete EmailTemplate
|
||||||
|
func (p *provider) DeleteEmailTemplate(ctx context.Context, emailTemplate *model.EmailTemplate) error {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -59,4 +59,17 @@ type Provider interface {
|
||||||
AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error)
|
AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error)
|
||||||
// ListWebhookLogs to list webhook logs
|
// ListWebhookLogs to list webhook logs
|
||||||
ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error)
|
ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error)
|
||||||
|
|
||||||
|
// AddEmailTemplate to add EmailTemplate
|
||||||
|
AddEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error)
|
||||||
|
// UpdateEmailTemplate to update EmailTemplate
|
||||||
|
UpdateEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error)
|
||||||
|
// ListEmailTemplates to list EmailTemplate
|
||||||
|
ListEmailTemplate(ctx context.Context, pagination model.Pagination) (*model.EmailTemplates, error)
|
||||||
|
// GetEmailTemplateByID to get EmailTemplate by id
|
||||||
|
GetEmailTemplateByID(ctx context.Context, emailTemplateID string) (*model.EmailTemplate, error)
|
||||||
|
// GetEmailTemplateByEventName to get EmailTemplate by event_name
|
||||||
|
GetEmailTemplateByEventName(ctx context.Context, eventName string) (*model.EmailTemplate, error)
|
||||||
|
// DeleteEmailTemplate to delete EmailTemplate
|
||||||
|
DeleteEmailTemplate(ctx context.Context, emailTemplate *model.EmailTemplate) error
|
||||||
}
|
}
|
||||||
|
|
100
server/db/providers/sql/email_template.go
Normal file
100
server/db/providers/sql/email_template.go
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
package sql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEmailTemplate to add EmailTemplate
|
||||||
|
func (p *provider) AddEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
if emailTemplate.ID == "" {
|
||||||
|
emailTemplate.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate.Key = emailTemplate.ID
|
||||||
|
emailTemplate.CreatedAt = time.Now().Unix()
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
res := p.db.Create(&emailTemplate)
|
||||||
|
if res.Error != nil {
|
||||||
|
return nil, res.Error
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEmailTemplate to update EmailTemplate
|
||||||
|
func (p *provider) UpdateEmailTemplate(ctx context.Context, emailTemplate models.EmailTemplate) (*model.EmailTemplate, error) {
|
||||||
|
emailTemplate.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
res := p.db.Save(&emailTemplate)
|
||||||
|
if res.Error != nil {
|
||||||
|
return nil, res.Error
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmailTemplates to list EmailTemplate
|
||||||
|
func (p *provider) ListEmailTemplate(ctx context.Context, pagination model.Pagination) (*model.EmailTemplates, error) {
|
||||||
|
var emailTemplates []models.EmailTemplate
|
||||||
|
|
||||||
|
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&emailTemplates)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
var total int64
|
||||||
|
totalRes := p.db.Model(&models.EmailTemplate{}).Count(&total)
|
||||||
|
if totalRes.Error != nil {
|
||||||
|
return nil, totalRes.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
paginationClone := pagination
|
||||||
|
paginationClone.Total = total
|
||||||
|
|
||||||
|
responseEmailTemplates := []*model.EmailTemplate{}
|
||||||
|
for _, w := range emailTemplates {
|
||||||
|
responseEmailTemplates = append(responseEmailTemplates, w.AsAPIEmailTemplate())
|
||||||
|
}
|
||||||
|
return &model.EmailTemplates{
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
EmailTemplates: responseEmailTemplates,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByID to get EmailTemplate by id
|
||||||
|
func (p *provider) GetEmailTemplateByID(ctx context.Context, emailTemplateID string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
|
||||||
|
result := p.db.Where("id = ?", emailTemplateID).First(&emailTemplate)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEmailTemplateByEventName to get EmailTemplate by event_name
|
||||||
|
func (p *provider) GetEmailTemplateByEventName(ctx context.Context, eventName string) (*model.EmailTemplate, error) {
|
||||||
|
var emailTemplate models.EmailTemplate
|
||||||
|
|
||||||
|
result := p.db.Where("event_name = ?", eventName).First(&emailTemplate)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
|
}
|
||||||
|
return emailTemplate.AsAPIEmailTemplate(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailTemplate to delete EmailTemplate
|
||||||
|
func (p *provider) DeleteEmailTemplate(ctx context.Context, emailTemplate *model.EmailTemplate) error {
|
||||||
|
result := p.db.Delete(&models.EmailTemplate{
|
||||||
|
ID: emailTemplate.ID,
|
||||||
|
})
|
||||||
|
if result.Error != nil {
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -60,7 +60,7 @@ func NewProvider() (*provider, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sqlDB.AutoMigrate(&models.User{}, &models.VerificationRequest{}, &models.Session{}, &models.Env{}, &models.Webhook{}, models.WebhookLog{})
|
err = sqlDB.AutoMigrate(&models.User{}, &models.VerificationRequest{}, &models.Session{}, &models.Env{}, &models.Webhook{}, models.WebhookLog{}, models.EmailTemplate{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
package model
|
package model
|
||||||
|
|
||||||
|
type AddEmailTemplateRequest struct {
|
||||||
|
EventName string `json:"event_name"`
|
||||||
|
Template string `json:"template"`
|
||||||
|
}
|
||||||
|
|
||||||
type AddWebhookRequest struct {
|
type AddWebhookRequest struct {
|
||||||
EventName string `json:"event_name"`
|
EventName string `json:"event_name"`
|
||||||
Endpoint string `json:"endpoint"`
|
Endpoint string `json:"endpoint"`
|
||||||
|
@ -26,10 +31,27 @@ type AuthResponse struct {
|
||||||
User *User `json:"user"`
|
User *User `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeleteEmailTemplateRequest struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
type DeleteUserInput struct {
|
type DeleteUserInput struct {
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EmailTemplate struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
EventName string `json:"event_name"`
|
||||||
|
Template string `json:"template"`
|
||||||
|
CreatedAt *int64 `json:"created_at"`
|
||||||
|
UpdatedAt *int64 `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EmailTemplates struct {
|
||||||
|
Pagination *Pagination `json:"pagination"`
|
||||||
|
EmailTemplates []*EmailTemplate `json:"EmailTemplates"`
|
||||||
|
}
|
||||||
|
|
||||||
type Env struct {
|
type Env struct {
|
||||||
AccessTokenExpiryTime *string `json:"ACCESS_TOKEN_EXPIRY_TIME"`
|
AccessTokenExpiryTime *string `json:"ACCESS_TOKEN_EXPIRY_TIME"`
|
||||||
AdminSecret *string `json:"ADMIN_SECRET"`
|
AdminSecret *string `json:"ADMIN_SECRET"`
|
||||||
|
@ -214,6 +236,12 @@ type UpdateAccessInput struct {
|
||||||
UserID string `json:"user_id"`
|
UserID string `json:"user_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateEmailTemplateRequest struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
EventName *string `json:"event_name"`
|
||||||
|
Template *string `json:"template"`
|
||||||
|
}
|
||||||
|
|
||||||
type UpdateEnvInput struct {
|
type UpdateEnvInput struct {
|
||||||
AccessTokenExpiryTime *string `json:"ACCESS_TOKEN_EXPIRY_TIME"`
|
AccessTokenExpiryTime *string `json:"ACCESS_TOKEN_EXPIRY_TIME"`
|
||||||
AdminSecret *string `json:"ADMIN_SECRET"`
|
AdminSecret *string `json:"ADMIN_SECRET"`
|
||||||
|
|
|
@ -150,6 +150,54 @@ type GenerateJWTKeysResponse {
|
||||||
private_key: String
|
private_key: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Webhook {
|
||||||
|
id: ID!
|
||||||
|
event_name: String
|
||||||
|
endpoint: String
|
||||||
|
enabled: Boolean
|
||||||
|
headers: Map
|
||||||
|
created_at: Int64
|
||||||
|
updated_at: Int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Webhooks {
|
||||||
|
pagination: Pagination!
|
||||||
|
webhooks: [Webhook!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebhookLog {
|
||||||
|
id: ID!
|
||||||
|
http_status: Int64
|
||||||
|
response: String
|
||||||
|
request: String
|
||||||
|
webhook_id: ID
|
||||||
|
created_at: Int64
|
||||||
|
updated_at: Int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestEndpointResponse {
|
||||||
|
http_status: Int64
|
||||||
|
response: Map
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebhookLogs {
|
||||||
|
pagination: Pagination!
|
||||||
|
webhook_logs: [WebhookLog!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type EmailTemplate {
|
||||||
|
id: ID!
|
||||||
|
event_name: String!
|
||||||
|
template: String!
|
||||||
|
created_at: Int64
|
||||||
|
updated_at: Int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type EmailTemplates {
|
||||||
|
pagination: Pagination!
|
||||||
|
EmailTemplates: [EmailTemplate!]!
|
||||||
|
}
|
||||||
|
|
||||||
input UpdateEnvInput {
|
input UpdateEnvInput {
|
||||||
ACCESS_TOKEN_EXPIRY_TIME: String
|
ACCESS_TOKEN_EXPIRY_TIME: String
|
||||||
ADMIN_SECRET: String
|
ADMIN_SECRET: String
|
||||||
|
@ -324,36 +372,6 @@ input GenerateJWTKeysInput {
|
||||||
type: String!
|
type: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Webhook {
|
|
||||||
id: ID!
|
|
||||||
event_name: String
|
|
||||||
endpoint: String
|
|
||||||
enabled: Boolean
|
|
||||||
headers: Map
|
|
||||||
created_at: Int64
|
|
||||||
updated_at: Int64
|
|
||||||
}
|
|
||||||
|
|
||||||
type Webhooks {
|
|
||||||
pagination: Pagination!
|
|
||||||
webhooks: [Webhook!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type WebhookLog {
|
|
||||||
id: ID!
|
|
||||||
http_status: Int64
|
|
||||||
response: String
|
|
||||||
request: String
|
|
||||||
webhook_id: ID
|
|
||||||
created_at: Int64
|
|
||||||
updated_at: Int64
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestEndpointResponse {
|
|
||||||
http_status: Int64
|
|
||||||
response: Map
|
|
||||||
}
|
|
||||||
|
|
||||||
input ListWebhookLogRequest {
|
input ListWebhookLogRequest {
|
||||||
pagination: PaginationInput
|
pagination: PaginationInput
|
||||||
webhook_id: String
|
webhook_id: String
|
||||||
|
@ -384,9 +402,19 @@ input TestEndpointRequest {
|
||||||
headers: Map
|
headers: Map
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebhookLogs {
|
input AddEmailTemplateRequest {
|
||||||
pagination: Pagination!
|
event_name: String!
|
||||||
webhook_logs: [WebhookLog!]!
|
template: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
input UpdateEmailTemplateRequest {
|
||||||
|
id: ID!
|
||||||
|
event_name: String
|
||||||
|
template: String
|
||||||
|
}
|
||||||
|
|
||||||
|
input DeleteEmailTemplateRequest {
|
||||||
|
id: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
|
@ -415,6 +443,9 @@ type Mutation {
|
||||||
_update_webhook(params: UpdateWebhookRequest!): Response!
|
_update_webhook(params: UpdateWebhookRequest!): Response!
|
||||||
_delete_webhook(params: WebhookRequest!): Response!
|
_delete_webhook(params: WebhookRequest!): Response!
|
||||||
_test_endpoint(params: TestEndpointRequest!): TestEndpointResponse!
|
_test_endpoint(params: TestEndpointRequest!): TestEndpointResponse!
|
||||||
|
_add_email_template(params: AddEmailTemplateRequest!): Response!
|
||||||
|
_update_email_template(params: UpdateEmailTemplateRequest!): Response!
|
||||||
|
_delete_email_template(params: DeleteEmailTemplateRequest!): Response!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
|
@ -430,4 +461,5 @@ type Query {
|
||||||
_webhook(params: WebhookRequest!): Webhook!
|
_webhook(params: WebhookRequest!): Webhook!
|
||||||
_webhooks(params: PaginatedInput): Webhooks!
|
_webhooks(params: PaginatedInput): Webhooks!
|
||||||
_webhook_logs(params: ListWebhookLogRequest): WebhookLogs!
|
_webhook_logs(params: ListWebhookLogRequest): WebhookLogs!
|
||||||
|
_email_templates(params: PaginatedInput): EmailTemplates!
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,18 @@ func (r *mutationResolver) TestEndpoint(ctx context.Context, params model.TestEn
|
||||||
return resolvers.TestEndpointResolver(ctx, params)
|
return resolvers.TestEndpointResolver(ctx, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) AddEmailTemplate(ctx context.Context, params model.AddEmailTemplateRequest) (*model.Response, error) {
|
||||||
|
return resolvers.AddEmailTemplateResolver(ctx, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) UpdateEmailTemplate(ctx context.Context, params model.UpdateEmailTemplateRequest) (*model.Response, error) {
|
||||||
|
return resolvers.UpdateEmailTemplateResolver(ctx, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) DeleteEmailTemplate(ctx context.Context, params model.DeleteEmailTemplateRequest) (*model.Response, error) {
|
||||||
|
return resolvers.DeleteEmailTemplateResolver(ctx, params)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Meta(ctx context.Context) (*model.Meta, error) {
|
func (r *queryResolver) Meta(ctx context.Context) (*model.Meta, error) {
|
||||||
return resolvers.MetaResolver(ctx)
|
return resolvers.MetaResolver(ctx)
|
||||||
}
|
}
|
||||||
|
@ -151,11 +163,17 @@ func (r *queryResolver) WebhookLogs(ctx context.Context, params *model.ListWebho
|
||||||
return resolvers.WebhookLogsResolver(ctx, params)
|
return resolvers.WebhookLogsResolver(ctx, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *queryResolver) EmailTemplates(ctx context.Context, params *model.PaginatedInput) (*model.EmailTemplates, error) {
|
||||||
|
return resolvers.EmailTemplatesResolver(ctx, params)
|
||||||
|
}
|
||||||
|
|
||||||
// Mutation returns generated.MutationResolver implementation.
|
// Mutation returns generated.MutationResolver implementation.
|
||||||
func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} }
|
func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} }
|
||||||
|
|
||||||
// Query returns generated.QueryResolver implementation.
|
// Query returns generated.QueryResolver implementation.
|
||||||
func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} }
|
func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} }
|
||||||
|
|
||||||
type mutationResolver struct{ *Resolver }
|
type (
|
||||||
type queryResolver struct{ *Resolver }
|
mutationResolver struct{ *Resolver }
|
||||||
|
queryResolver struct{ *Resolver }
|
||||||
|
)
|
||||||
|
|
|
@ -320,12 +320,60 @@ func processGithubUserInfo(code string) (models.User, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
picture := userRawData["avatar_url"]
|
picture := userRawData["avatar_url"]
|
||||||
|
email := userRawData["email"]
|
||||||
|
|
||||||
|
if email == "" {
|
||||||
|
type GithubUserEmails struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
Primary bool `json:"primary"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch using /users/email endpoint
|
||||||
|
req, err := http.NewRequest("GET", constants.GithubUserEmails, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to create github emails request: ", err)
|
||||||
|
return user, fmt.Errorf("error creating github user info request: %s", err.Error())
|
||||||
|
}
|
||||||
|
req.Header = http.Header{
|
||||||
|
"Authorization": []string{fmt.Sprintf("token %s", oauth2Token.AccessToken)},
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to request github user email: ", err)
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer response.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(response.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to read github user email response body: ", err)
|
||||||
|
return user, fmt.Errorf("failed to read github response body: %s", err.Error())
|
||||||
|
}
|
||||||
|
if response.StatusCode >= 400 {
|
||||||
|
log.Debug("Failed to request github user email: ", string(body))
|
||||||
|
return user, fmt.Errorf("failed to request github user info: %s", string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
emailData := []GithubUserEmails{}
|
||||||
|
err = json.Unmarshal(body, &emailData)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to parse github user email: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, userEmail := range emailData {
|
||||||
|
email = userEmail.Email
|
||||||
|
if userEmail.Primary {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
user = models.User{
|
user = models.User{
|
||||||
GivenName: &firstName,
|
GivenName: &firstName,
|
||||||
FamilyName: &lastName,
|
FamilyName: &lastName,
|
||||||
Picture: &picture,
|
Picture: &picture,
|
||||||
Email: userRawData["email"],
|
Email: email,
|
||||||
}
|
}
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
|
|
53
server/resolvers/add_email_template.go
Normal file
53
server/resolvers/add_email_template.go
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
package resolvers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO add template validator
|
||||||
|
|
||||||
|
// AddEmailTemplateResolver resolver for add email template mutation
|
||||||
|
func AddEmailTemplateResolver(ctx context.Context, params model.AddEmailTemplateRequest) (*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.IsValidEmailTemplateEventName(params.EventName) {
|
||||||
|
log.Debug("Invalid Event Name: ", params.EventName)
|
||||||
|
return nil, fmt.Errorf("invalid event name %s", params.EventName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.TrimSpace(params.Template) == "" {
|
||||||
|
return nil, fmt.Errorf("empty template not allowed")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = db.Provider.AddEmailTemplate(ctx, models.EmailTemplate{
|
||||||
|
EventName: params.EventName,
|
||||||
|
Template: params.Template,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to add email template: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.Response{
|
||||||
|
Message: `Email template added successfully`,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"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)
|
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)
|
headerBytes, err := json.Marshal(params.Headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
49
server/resolvers/delete_email_template.go
Normal file
49
server/resolvers/delete_email_template.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeleteEmailTemplateResolver resolver to delete email template and its relevant logs
|
||||||
|
func DeleteEmailTemplateResolver(ctx context.Context, params model.DeleteEmailTemplateRequest) (*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("email template is required")
|
||||||
|
return nil, fmt.Errorf("email template ID required")
|
||||||
|
}
|
||||||
|
|
||||||
|
log := log.WithField("email_template_id", params.ID)
|
||||||
|
|
||||||
|
emailTemplate, err := db.Provider.GetEmailTemplateByID(ctx, params.ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("failed to get email template: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.Provider.DeleteEmailTemplate(ctx, emailTemplate)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("failed to delete email template: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.Response{
|
||||||
|
Message: "Email templated deleted successfully",
|
||||||
|
}, nil
|
||||||
|
}
|
35
server/resolvers/email_templates.go
Normal file
35
server/resolvers/email_templates.go
Normal file
|
@ -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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EmailTemplatesResolver resolver for getting the list of email templates based on pagination
|
||||||
|
func EmailTemplatesResolver(ctx context.Context, params *model.PaginatedInput) (*model.EmailTemplates, 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)
|
||||||
|
|
||||||
|
emailTemplates, err := db.Provider.ListEmailTemplate(ctx, pagination)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("failed to get email templates: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return emailTemplates, nil
|
||||||
|
}
|
70
server/resolvers/update_email_template.go
Normal file
70
server/resolvers/update_email_template.go
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package resolvers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"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/refs"
|
||||||
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
|
"github.com/authorizerdev/authorizer/server/validators"
|
||||||
|
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)
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplate, err := db.Provider.GetEmailTemplateByID(ctx, params.ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("failed to get email template: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
emailTemplateDetails := models.EmailTemplate{
|
||||||
|
ID: emailTemplate.ID,
|
||||||
|
Key: emailTemplate.ID,
|
||||||
|
EventName: emailTemplate.EventName,
|
||||||
|
CreatedAt: refs.Int64Value(emailTemplate.CreatedAt),
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.EventName != nil && emailTemplateDetails.EventName != refs.StringValue(params.EventName) {
|
||||||
|
if isValid := validators.IsValidEmailTemplateEventName(refs.StringValue(params.EventName)); !isValid {
|
||||||
|
log.Debug("invalid event name: ", refs.StringValue(params.EventName))
|
||||||
|
return nil, fmt.Errorf("invalid event name %s", refs.StringValue(params.EventName))
|
||||||
|
}
|
||||||
|
emailTemplateDetails.EventName = refs.StringValue(params.EventName)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = db.Provider.UpdateEmailTemplate(ctx, emailTemplateDetails)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.Response{
|
||||||
|
Message: `Email template updated successfully.`,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
@ -50,7 +51,7 @@ func UpdateWebhookResolver(ctx context.Context, params model.UpdateWebhookReques
|
||||||
EndPoint: refs.StringValue(webhook.Endpoint),
|
EndPoint: refs.StringValue(webhook.Endpoint),
|
||||||
Enabled: refs.BoolValue(webhook.Enabled),
|
Enabled: refs.BoolValue(webhook.Enabled),
|
||||||
Headers: headersString,
|
Headers: headersString,
|
||||||
CreatedAt: *webhook.CreatedAt,
|
CreatedAt: refs.Int64Value(webhook.CreatedAt),
|
||||||
}
|
}
|
||||||
|
|
||||||
if params.EventName != nil && webhookDetails.EventName != refs.StringValue(params.EventName) {
|
if params.EventName != nil && webhookDetails.EventName != refs.StringValue(params.EventName) {
|
||||||
|
@ -62,7 +63,11 @@ func UpdateWebhookResolver(ctx context.Context, params model.UpdateWebhookReques
|
||||||
}
|
}
|
||||||
|
|
||||||
if params.Endpoint != nil && webhookDetails.EndPoint != refs.StringValue(params.Endpoint) {
|
if params.Endpoint != nil && webhookDetails.EndPoint != refs.StringValue(params.Endpoint) {
|
||||||
webhookDetails.EventName = refs.StringValue(params.EventName)
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
if params.Enabled != nil && webhookDetails.Enabled != refs.BoolValue(params.Enabled) {
|
if params.Enabled != nil && webhookDetails.Enabled != refs.BoolValue(params.Enabled) {
|
||||||
|
|
|
@ -28,7 +28,7 @@ func WebhooksResolver(ctx context.Context, params *model.PaginatedInput) (*model
|
||||||
|
|
||||||
webhooks, err := db.Provider.ListWebhook(ctx, pagination)
|
webhooks, err := db.Provider.ListWebhook(ctx, pagination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("failed to get webhook logs: ", err)
|
log.Debug("failed to get webhooks: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return webhooks, nil
|
return webhooks, nil
|
||||||
|
|
58
server/test/add_email_template_test.go
Normal file
58
server/test/add_email_template_test.go
Normal file
|
@ -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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ func addWebhookTest(t *testing.T, s TestSetup) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h))
|
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{
|
webhook, err := resolvers.AddWebhookResolver(ctx, model.AddWebhookRequest{
|
||||||
EventName: eventType,
|
EventName: eventType,
|
||||||
Endpoint: s.TestInfo.WebhookEndpoint,
|
Endpoint: s.TestInfo.WebhookEndpoint,
|
||||||
|
|
52
server/test/delete_email_template_test.go
Normal file
52
server/test/delete_email_template_test.go
Normal file
|
@ -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)
|
||||||
|
})
|
||||||
|
}
|
29
server/test/email_templates_test.go
Normal file
29
server/test/email_templates_test.go
Normal file
|
@ -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))
|
||||||
|
})
|
||||||
|
}
|
|
@ -3,20 +3,39 @@ package test
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/env"
|
"github.com/authorizerdev/authorizer/server/env"
|
||||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||||
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestResolvers(t *testing.T) {
|
func TestResolvers(t *testing.T) {
|
||||||
databases := map[string]string{
|
databases := map[string]string{
|
||||||
constants.DbTypeSqlite: "../../test.db",
|
constants.DbTypeSqlite: "../../test.db",
|
||||||
// constants.DbTypeArangodb: "http://localhost:8529",
|
constants.DbTypeArangodb: "http://localhost:8529",
|
||||||
// constants.DbTypeMongodb: "mongodb://localhost:27017",
|
constants.DbTypeMongodb: "mongodb://localhost:27017",
|
||||||
// constants.DbTypeScyllaDB: "127.0.0.1:9042",
|
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"
|
testDb := "authorizer_test"
|
||||||
|
@ -75,6 +94,10 @@ func TestResolvers(t *testing.T) {
|
||||||
revokeAccessTest(t, s)
|
revokeAccessTest(t, s)
|
||||||
enableAccessTest(t, s)
|
enableAccessTest(t, s)
|
||||||
generateJWTkeyTest(t, s)
|
generateJWTkeyTest(t, s)
|
||||||
|
addEmailTemplateTest(t, s)
|
||||||
|
updateEmailTemplateTest(t, s)
|
||||||
|
emailTemplatesTest(t, s)
|
||||||
|
deleteEmailTemplateTest(t, s)
|
||||||
|
|
||||||
// user resolvers tests
|
// user resolvers tests
|
||||||
loginTests(t, s)
|
loginTests(t, s)
|
||||||
|
|
|
@ -24,7 +24,8 @@ type TestData struct {
|
||||||
Email string
|
Email string
|
||||||
Password string
|
Password string
|
||||||
WebhookEndpoint string
|
WebhookEndpoint string
|
||||||
TestEventTypes []string
|
TestWebhookEventTypes []string
|
||||||
|
TestEmailTemplateEventTypes []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestSetup struct {
|
type TestSetup struct {
|
||||||
|
@ -79,7 +80,8 @@ func testSetup() TestSetup {
|
||||||
Email: fmt.Sprintf("%d_authorizer_tester@yopmail.com", time.Now().Unix()),
|
Email: fmt.Sprintf("%d_authorizer_tester@yopmail.com", time.Now().Unix()),
|
||||||
Password: "Test@123",
|
Password: "Test@123",
|
||||||
WebhookEndpoint: "https://62cbc6738042b16aa7c22df2.mockapi.io/api/v1/webhook",
|
WebhookEndpoint: "https://62cbc6738042b16aa7c22df2.mockapi.io/api/v1/webhook",
|
||||||
TestEventTypes: []string{constants.UserAccessEnabledWebhookEvent, constants.UserAccessRevokedWebhookEvent, constants.UserCreatedWebhookEvent, constants.UserDeletedWebhookEvent, constants.UserLoginWebhookEvent, constants.UserSignUpWebhookEvent},
|
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")
|
err := os.Setenv(constants.EnvKeyEnvPath, "../../.env.test")
|
||||||
|
|
46
server/test/update_email_template_test.go
Normal file
46
server/test/update_email_template_test.go
Normal file
|
@ -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")
|
||||||
|
})
|
||||||
|
}
|
|
@ -36,6 +36,7 @@ func updateWebhookTest(t *testing.T, s TestSetup) {
|
||||||
ID: webhook.ID,
|
ID: webhook.ID,
|
||||||
Headers: webhook.Headers,
|
Headers: webhook.Headers,
|
||||||
Enabled: refs.NewBoolRef(false),
|
Enabled: refs.NewBoolRef(false),
|
||||||
|
Endpoint: refs.NewStringRef("https://sometest.com"),
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -47,17 +48,18 @@ func updateWebhookTest(t *testing.T, s TestSetup) {
|
||||||
assert.NotNil(t, updatedWebhook)
|
assert.NotNil(t, updatedWebhook)
|
||||||
assert.Equal(t, webhook.ID, updatedWebhook.ID)
|
assert.Equal(t, webhook.ID, updatedWebhook.ID)
|
||||||
assert.Equal(t, refs.StringValue(webhook.EventName), refs.StringValue(updatedWebhook.EventName))
|
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.Len(t, updatedWebhook.Headers, 1)
|
||||||
assert.False(t, refs.BoolValue(updatedWebhook.Enabled))
|
assert.False(t, refs.BoolValue(updatedWebhook.Enabled))
|
||||||
for key, val := range updatedWebhook.Headers {
|
for key, val := range updatedWebhook.Headers {
|
||||||
assert.Equal(t, val, webhook.Headers[key])
|
assert.Equal(t, val, webhook.Headers[key])
|
||||||
}
|
}
|
||||||
|
assert.Equal(t, refs.StringValue(updatedWebhook.Endpoint), "https://sometest.com")
|
||||||
|
|
||||||
res, err = resolvers.UpdateWebhookResolver(ctx, model.UpdateWebhookRequest{
|
res, err = resolvers.UpdateWebhookResolver(ctx, model.UpdateWebhookRequest{
|
||||||
ID: webhook.ID,
|
ID: webhook.ID,
|
||||||
Headers: webhook.Headers,
|
Headers: webhook.Headers,
|
||||||
Enabled: refs.NewBoolRef(true),
|
Enabled: refs.NewBoolRef(true),
|
||||||
|
Endpoint: refs.NewStringRef(s.TestInfo.WebhookEndpoint),
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotEmpty(t, res)
|
assert.NotEmpty(t, res)
|
||||||
|
|
|
@ -24,6 +24,6 @@ func webhooksTest(t *testing.T, s TestSetup) {
|
||||||
webhooks, err := resolvers.WebhooksResolver(ctx, nil)
|
webhooks, err := resolvers.WebhooksResolver(ctx, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotEmpty(t, webhooks)
|
assert.NotEmpty(t, webhooks)
|
||||||
assert.Len(t, webhooks.Webhooks, len(s.TestInfo.TestEventTypes))
|
assert.Len(t, webhooks.Webhooks, len(s.TestInfo.TestWebhookEventTypes))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
12
server/validators/email_template.go
Normal file
12
server/validators/email_template.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package validators
|
||||||
|
|
||||||
|
import "github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
|
||||||
|
// IsValidEmailTemplateEventName function to validate email template events
|
||||||
|
func IsValidEmailTemplateEventName(eventName string) bool {
|
||||||
|
if eventName != constants.VerificationTypeBasicAuthSignup && eventName != constants.VerificationTypeForgotPassword && eventName != constants.VerificationTypeMagicLinkLogin && eventName != constants.VerificationTypeUpdateEmail {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user