diff --git a/server/constants/oauth_info_urls.go b/server/constants/oauth_info_urls.go index 900a2bf..1dcec3a 100644 --- a/server/constants/oauth_info_urls.go +++ b/server/constants/oauth_info_urls.go @@ -8,7 +8,7 @@ const ( 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 GithubUserInfoURL = "https://api.github.com/user" - // Get github user emails Ref: https://stackoverflow.com/a/35387123 + // 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 diff --git a/server/graph/schema.resolvers.go b/server/graph/schema.resolvers.go index 299edca..a0fea39 100644 --- a/server/graph/schema.resolvers.go +++ b/server/graph/schema.resolvers.go @@ -5,7 +5,6 @@ package graph import ( "context" - "fmt" "github.com/authorizerdev/authorizer/server/graph/generated" "github.com/authorizerdev/authorizer/server/graph/model" @@ -109,15 +108,15 @@ func (r *mutationResolver) TestEndpoint(ctx context.Context, params model.TestEn } func (r *mutationResolver) AddEmailTemplate(ctx context.Context, params model.AddEmailTemplateRequest) (*model.Response, error) { - panic(fmt.Errorf("not implemented")) + return resolvers.AddEmailTemplateResolver(ctx, params) } func (r *mutationResolver) UpdateEmailTemplate(ctx context.Context, params model.UpdateEmailTemplateRequest) (*model.Response, error) { - panic(fmt.Errorf("not implemented")) + return resolvers.UpdateEmailTemplateResolver(ctx, params) } func (r *mutationResolver) DeleteEmailTemplate(ctx context.Context, params model.DeleteEmailTemplateRequest) (*model.Response, error) { - panic(fmt.Errorf("not implemented")) + return resolvers.DeleteEmailTemplateResolver(ctx, params) } func (r *queryResolver) Meta(ctx context.Context) (*model.Meta, error) { @@ -165,7 +164,7 @@ func (r *queryResolver) WebhookLogs(ctx context.Context, params *model.ListWebho } func (r *queryResolver) EmailTemplates(ctx context.Context, params *model.PaginatedInput) (*model.EmailTemplates, error) { - panic(fmt.Errorf("not implemented")) + return resolvers.EmailTemplatesResolver(ctx, params) } // Mutation returns generated.MutationResolver implementation. @@ -174,5 +173,7 @@ func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResol // Query returns generated.QueryResolver implementation. func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } -type mutationResolver struct{ *Resolver } -type queryResolver struct{ *Resolver } +type ( + mutationResolver struct{ *Resolver } + queryResolver struct{ *Resolver } +) diff --git a/server/resolvers/add_email_template.go b/server/resolvers/add_email_template.go index 91fea07..1cba02f 100644 --- a/server/resolvers/add_email_template.go +++ b/server/resolvers/add_email_template.go @@ -1 +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 +} diff --git a/server/resolvers/delete_email_template.go b/server/resolvers/delete_email_template.go index 91fea07..92a6172 100644 --- a/server/resolvers/delete_email_template.go +++ b/server/resolvers/delete_email_template.go @@ -1 +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 +} diff --git a/server/resolvers/email_templates.go b/server/resolvers/email_templates.go index 91fea07..7230400 100644 --- a/server/resolvers/email_templates.go +++ b/server/resolvers/email_templates.go @@ -1 +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 +} diff --git a/server/resolvers/update_email_template.go b/server/resolvers/update_email_template.go index 91fea07..6cc912d 100644 --- a/server/resolvers/update_email_template.go +++ b/server/resolvers/update_email_template.go @@ -1 +1,63 @@ package resolvers + +import ( + "context" + "fmt" + + "github.com/authorizerdev/authorizer/server/db" + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" + "github.com/authorizerdev/authorizer/server/refs" + "github.com/authorizerdev/authorizer/server/token" + "github.com/authorizerdev/authorizer/server/utils" + "github.com/authorizerdev/authorizer/server/validators" + log "github.com/sirupsen/logrus" +) + +// 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) { + 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 +} diff --git a/server/resolvers/update_webhook.go b/server/resolvers/update_webhook.go index d9ea6b7..934bfdd 100644 --- a/server/resolvers/update_webhook.go +++ b/server/resolvers/update_webhook.go @@ -50,7 +50,7 @@ func UpdateWebhookResolver(ctx context.Context, params model.UpdateWebhookReques EndPoint: refs.StringValue(webhook.Endpoint), Enabled: refs.BoolValue(webhook.Enabled), Headers: headersString, - CreatedAt: *webhook.CreatedAt, + CreatedAt: refs.Int64Value(webhook.CreatedAt), } if params.EventName != nil && webhookDetails.EventName != refs.StringValue(params.EventName) { @@ -62,7 +62,7 @@ func UpdateWebhookResolver(ctx context.Context, params model.UpdateWebhookReques } if params.Endpoint != nil && webhookDetails.EndPoint != refs.StringValue(params.Endpoint) { - webhookDetails.EventName = refs.StringValue(params.EventName) + webhookDetails.EndPoint = refs.StringValue(params.Endpoint) } if params.Enabled != nil && webhookDetails.Enabled != refs.BoolValue(params.Enabled) { diff --git a/server/resolvers/webhooks.go b/server/resolvers/webhooks.go index df6dd30..5a6ccbb 100644 --- a/server/resolvers/webhooks.go +++ b/server/resolvers/webhooks.go @@ -28,7 +28,7 @@ func WebhooksResolver(ctx context.Context, params *model.PaginatedInput) (*model webhooks, err := db.Provider.ListWebhook(ctx, pagination) if err != nil { - log.Debug("failed to get webhook logs: ", err) + log.Debug("failed to get webhooks: ", err) return nil, err } return webhooks, nil diff --git a/server/validators/email_template.go b/server/validators/email_template.go new file mode 100644 index 0000000..1dd0766 --- /dev/null +++ b/server/validators/email_template.go @@ -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 +}