diff --git a/dashboard/src/constants.ts b/dashboard/src/constants.ts
index 79b6c26..b2e7152 100644
--- a/dashboard/src/constants.ts
+++ b/dashboard/src/constants.ts
@@ -206,27 +206,27 @@ export enum webhookVerifiedStatus {
}
export const emailTemplateVariables = {
- 'user.id': '{user.id}}',
- 'user.email': '{user.email}}',
- 'user.given_name': '{user.given_name}}',
- 'user.family_name': '{user.family_name}}',
- 'user.signup_methods': '{user.signup_methods}}',
- 'user.email_verified': '{user.email_verified}}',
- 'user.picture': '{user.picture}}',
- 'user.roles': '{user.roles}}',
- 'user.middle_name': '{user.middle_name}}',
- 'user.nickname': '{user.nickname}}',
- 'user.preferred_username': '{user.preferred_username}}',
- 'user.gender': '{user.gender}}',
- 'user.birthdate': '{user.birthdate}}',
- 'user.phone_number': '{user.phone_number}}',
- 'user.phone_number_verified': '{user.phone_number_verified}}',
- 'user.created_at': '{user.created_at}}',
- 'user.updated_at': '{user.updated_at}}',
- 'organization.name': '{organization.name}}',
- 'organization.logo': '{organization.logo}}',
- verification_url: '{verification_url}}',
- otp: '{otp}}',
+ 'user.id': '{.user.id}}',
+ 'user.email': '{.user.email}}',
+ 'user.given_name': '{.user.given_name}}',
+ 'user.family_name': '{.user.family_name}}',
+ 'user.signup_methods': '{.user.signup_methods}}',
+ 'user.email_verified': '{.user.email_verified}}',
+ 'user.picture': '{.user.picture}}',
+ 'user.roles': '{.user.roles}}',
+ 'user.middle_name': '{.user.middle_name}}',
+ 'user.nickname': '{.user.nickname}}',
+ 'user.preferred_username': '{.user.preferred_username}}',
+ 'user.gender': '{.user.gender}}',
+ 'user.birthdate': '{.user.birthdate}}',
+ 'user.phone_number': '{.user.phone_number}}',
+ 'user.phone_number_verified': '{.user.phone_number_verified}}',
+ 'user.created_at': '{.user.created_at}}',
+ 'user.updated_at': '{.user.updated_at}}',
+ 'organization.name': '{.organization.name}}',
+ 'organization.logo': '{.organization.logo}}',
+ verification_url: '{.verification_url}}',
+ otp: '{.otp}}',
};
export const webhookPayloadExample: string = `{
diff --git a/server/constants/verification_types.go b/server/constants/verification_types.go
index de64dbb..0a83df8 100644
--- a/server/constants/verification_types.go
+++ b/server/constants/verification_types.go
@@ -9,4 +9,8 @@ const (
VerificationTypeUpdateEmail = "update_email"
// VerificationTypeForgotPassword is the forgot_password verification type
VerificationTypeForgotPassword = "forgot_password"
+ // VerificationTypeInviteMember is the invite_member verification type
+ VerificationTypeInviteMember = "invite_member"
+ // VerificationTypeOTP is the otp verification type
+ VerificationTypeOTP = "otp"
)
diff --git a/server/db/models/user.go b/server/db/models/user.go
index bc5bc04..f8a054d 100644
--- a/server/db/models/user.go
+++ b/server/db/models/user.go
@@ -1,6 +1,7 @@
package models
import (
+ "encoding/json"
"strings"
"github.com/authorizerdev/authorizer/server/graph/model"
@@ -64,3 +65,10 @@ func (user *User) AsAPIUser() *model.User {
UpdatedAt: refs.NewInt64Ref(user.UpdatedAt),
}
}
+
+func (user *User) ToMap() map[string]interface{} {
+ res := map[string]interface{}{}
+ data, _ := json.Marshal(user) // Convert to a json string
+ json.Unmarshal(data, &res) // Convert to a map
+ return res
+}
diff --git a/server/email/email.go b/server/email/email.go
index 99b2c03..730ae56 100644
--- a/server/email/email.go
+++ b/server/email/email.go
@@ -2,8 +2,8 @@ package email
import (
"bytes"
+ "context"
"crypto/tls"
- "encoding/json"
"strconv"
"text/template"
@@ -11,27 +11,75 @@ import (
gomail "gopkg.in/mail.v2"
"github.com/authorizerdev/authorizer/server/constants"
+ "github.com/authorizerdev/authorizer/server/db"
+ "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore"
)
-// addEmailTemplate is used to add html template in email body
-func addEmailTemplate(a string, b map[string]interface{}, templateName string) string {
- tmpl, err := template.New(templateName).Parse(a)
- if err != nil {
- output, _ := json.Marshal(b)
- return string(output)
+func getDefaultTemplate(event string) *model.EmailTemplate {
+ switch event {
+ case constants.VerificationTypeBasicAuthSignup, constants.VerificationTypeMagicLinkLogin:
+ return &model.EmailTemplate{
+ Subject: emailVerificationSubject,
+ Template: emailVerificationTemplate,
+ }
+ case constants.VerificationTypeForgotPassword:
+ return &model.EmailTemplate{
+ Subject: forgotPasswordSubject,
+ Template: forgotPasswordTemplate,
+ }
+ case constants.VerificationTypeInviteMember:
+ return &model.EmailTemplate{
+ Subject: inviteEmailSubject,
+ Template: inviteEmailTemplate,
+ }
+ case constants.VerificationTypeOTP:
+ return &model.EmailTemplate{
+ Subject: otpEmailSubject,
+ Template: otpEmailTemplate,
+ }
+ default:
+ return nil
}
- buf := &bytes.Buffer{}
- err = tmpl.Execute(buf, b)
- if err != nil {
- panic(err)
- }
- s := buf.String()
- return s
}
-// SendMail function to send mail
-func SendMail(to []string, Subject, bodyMessage string) error {
+func getEmailTemplate(event string, data map[string]interface{}) (*model.EmailTemplate, error) {
+ ctx := context.Background()
+ tmp, err := db.Provider.GetEmailTemplateByEventName(ctx, event)
+ if err != nil || tmp == nil {
+ tmp = getDefaultTemplate(event)
+ }
+
+ templ, err := template.New(event + "_template.tmpl").Parse(tmp.Template)
+ if err != nil {
+ return nil, err
+ }
+ buf := &bytes.Buffer{}
+ err = templ.Execute(buf, data)
+ if err != nil {
+ return nil, err
+ }
+ templateString := buf.String()
+
+ subject, err := template.New(event + "_subject.tmpl").Parse(tmp.Subject)
+ if err != nil {
+ return nil, err
+ }
+ buf = &bytes.Buffer{}
+ err = subject.Execute(buf, data)
+ if err != nil {
+ return nil, err
+ }
+ subjectString := buf.String()
+
+ return &model.EmailTemplate{
+ Template: templateString,
+ Subject: subjectString,
+ }, nil
+}
+
+// SendEmail function to send mail
+func SendEmail(to []string, event string, data map[string]interface{}) error {
// dont trigger email sending in case of test
envKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyEnv)
if err != nil {
@@ -40,6 +88,13 @@ func SendMail(to []string, Subject, bodyMessage string) error {
if envKey == constants.TestEnv {
return nil
}
+
+ tmp, err := getEmailTemplate(event, data)
+ if err != nil {
+ log.Errorf("Failed to get event template: ", err)
+ return err
+ }
+
m := gomail.NewMessage()
senderEmail, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeySenderEmail)
if err != nil {
@@ -79,8 +134,8 @@ func SendMail(to []string, Subject, bodyMessage string) error {
m.SetHeader("From", senderEmail)
m.SetHeader("To", to...)
- m.SetHeader("Subject", Subject)
- m.SetBody("text/html", bodyMessage)
+ m.SetHeader("Subject", tmp.Subject)
+ m.SetBody("text/html", tmp.Template)
port, _ := strconv.Atoi(smtpPort)
d := gomail.NewDialer(smtpHost, port, smtpUsername, smtpPassword)
if !isProd {
diff --git a/server/email/verification_email.go b/server/email/email_verification.go
similarity index 85%
rename from server/email/verification_email.go
rename to server/email/email_verification.go
index dded5ef..51a99bc 100644
--- a/server/email/verification_email.go
+++ b/server/email/email_verification.go
@@ -1,19 +1,8 @@
package email
-import (
- log "github.com/sirupsen/logrus"
-
- "github.com/authorizerdev/authorizer/server/constants"
- "github.com/authorizerdev/authorizer/server/memorystore"
-)
-
-// SendVerificationMail to send verification email
-func SendVerificationMail(toEmail, token, hostname string) error {
- // The receiver needs to be in slice as the receive supports multiple receiver
- Receiver := []string{toEmail}
-
- Subject := "Please verify your email"
- message := `
+const (
+ emailVerificationSubject = "Please verify your email"
+ emailVerificationTemplate = `
@@ -98,23 +87,4 @@ func SendVerificationMail(toEmail, token, hostname string) error {
`
- data := make(map[string]interface{}, 3)
- var err error
- data["org_logo"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
- if err != nil {
- return err
- }
- data["org_name"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
- if err != nil {
- return err
- }
- data["verification_url"] = hostname + "/verify_email?token=" + token
- message = addEmailTemplate(message, data, "verify_email.tmpl")
- // bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
-
- err = SendMail(Receiver, Subject, message)
- if err != nil {
- log.Warn("error sending email: ", err)
- }
- return err
-}
+)
diff --git a/server/email/forgot_password_email.go b/server/email/forgot_password_email.go
index aabd6a9..678f83c 100644
--- a/server/email/forgot_password_email.go
+++ b/server/email/forgot_password_email.go
@@ -1,28 +1,8 @@
package email
-import (
- "github.com/authorizerdev/authorizer/server/constants"
- "github.com/authorizerdev/authorizer/server/memorystore"
-)
-
-// SendForgotPasswordMail to send forgot password email
-func SendForgotPasswordMail(toEmail, token, hostname string) error {
- resetPasswordUrl, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyResetPasswordURL)
- if err != nil {
- return err
- }
- if resetPasswordUrl == "" {
- if err := memorystore.Provider.UpdateEnvVariable(constants.EnvKeyResetPasswordURL, hostname+"/app/reset-password"); err != nil {
- return err
- }
- }
-
- // The receiver needs to be in slice as the receive supports multiple receiver
- Receiver := []string{toEmail}
-
- Subject := "Reset Password"
-
- message := `
+const (
+ forgotPasswordSubject = "Reset Password"
+ forgotPasswordTemplate = `
@@ -73,13 +53,13 @@ func SendForgotPasswordMail(toEmail, token, hostname string) error {
-  |
+  |
Hey there 👋
- We have received a request to reset password for email: {{.org_name}}. If this is correct, please reset the password clicking the button below.
+ We have received a request to reset password for email: {{.organization.name}}. If this is correct, please reset the password clicking the button below.
Reset Password
|
@@ -106,18 +86,4 @@ func SendForgotPasswordMail(toEmail, token, hostname string) error {
`
-
- data := make(map[string]interface{}, 3)
- data["org_logo"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
- if err != nil {
- return err
- }
- data["org_name"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
- if err != nil {
- return err
- }
- data["verification_url"] = resetPasswordUrl + "?token=" + token
- message = addEmailTemplate(message, data, "reset_password_email.tmpl")
-
- return SendMail(Receiver, Subject, message)
-}
+)
diff --git a/server/email/invite_email.go b/server/email/invite_email.go
index 4faaf3f..bec33a6 100644
--- a/server/email/invite_email.go
+++ b/server/email/invite_email.go
@@ -1,19 +1,8 @@
package email
-import (
- log "github.com/sirupsen/logrus"
-
- "github.com/authorizerdev/authorizer/server/constants"
- "github.com/authorizerdev/authorizer/server/memorystore"
-)
-
-// InviteEmail to send invite email
-func InviteEmail(toEmail, token, verificationURL, redirectURI string) error {
- // The receiver needs to be in slice as the receive supports multiple receiver
- Receiver := []string{toEmail}
-
- Subject := "Please accept the invitation"
- message := `
+const (
+ inviteEmailSubject = "Please accept the invitation"
+ inviteEmailTemplate = `
@@ -64,13 +53,13 @@ func InviteEmail(toEmail, token, verificationURL, redirectURI string) error {
-  |
+  |
Hi there 👋
- Join us! You are invited to sign-up for {{.org_name}}. Please accept the invitation by clicking the button below.
+ Join us! You are invited to sign-up for {{.organization.name}}. Please accept the invitation by clicking the button below.
Get Started
|
@@ -98,23 +87,4 @@ func InviteEmail(toEmail, token, verificationURL, redirectURI string) error {
`
- data := make(map[string]interface{}, 3)
- var err error
- data["org_logo"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
- if err != nil {
- return err
- }
- data["org_name"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
- if err != nil {
- return err
- }
- data["verification_url"] = verificationURL + "?token=" + token + "&redirect_uri=" + redirectURI
- message = addEmailTemplate(message, data, "invite_email.tmpl")
- // bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
-
- err = SendMail(Receiver, Subject, message)
- if err != nil {
- log.Warn("error sending email: ", err)
- }
- return err
-}
+)
diff --git a/server/email/otp.go b/server/email/otp.go
index 181a1e0..d3bf7c0 100644
--- a/server/email/otp.go
+++ b/server/email/otp.go
@@ -1,19 +1,8 @@
package email
-import (
- log "github.com/sirupsen/logrus"
-
- "github.com/authorizerdev/authorizer/server/constants"
- "github.com/authorizerdev/authorizer/server/memorystore"
-)
-
-// SendOtpMail to send otp email
-func SendOtpMail(toEmail, otp string) error {
- // The receiver needs to be in slice as the receive supports multiple receiver
- Receiver := []string{toEmail}
-
- Subject := "OTP for your multi factor authentication"
- message := `
+const (
+ otpEmailSubject = "OTP for your multi factor authentication"
+ otpEmailTemplate = `
@@ -64,13 +53,13 @@ func SendOtpMail(toEmail, otp string) error {
-  |
+  |
Hey there 👋
- {{.otp}} is your one time password (OTP) for accessing {{.org_name}}. Please keep your OTP confidential and it will expire in 1 minute.
+ {{.otp}} is your one time password (OTP) for accessing {{.organization.name}}. Please keep your OTP confidential and it will expire in 1 minute.
|
@@ -96,23 +85,4 @@ func SendOtpMail(toEmail, otp string) error {
`
- data := make(map[string]interface{}, 3)
- var err error
- data["org_logo"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
- if err != nil {
- return err
- }
- data["org_name"], err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
- if err != nil {
- return err
- }
- data["otp"] = otp
- message = addEmailTemplate(message, data, "otp.tmpl")
- // bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
-
- err = SendMail(Receiver, Subject, message)
- if err != nil {
- log.Warn("error sending email: ", err)
- }
- return err
-}
+)
diff --git a/server/email/utils.go b/server/email/utils.go
new file mode 100644
index 0000000..8774a6e
--- /dev/null
+++ b/server/email/utils.go
@@ -0,0 +1 @@
+package email
diff --git a/server/resolvers/forgot_password.go b/server/resolvers/forgot_password.go
index a8672f3..77ff265 100644
--- a/server/resolvers/forgot_password.go
+++ b/server/resolvers/forgot_password.go
@@ -49,7 +49,7 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
log := log.WithFields(log.Fields{
"email": params.Email,
})
- _, err = db.Provider.GetUserByEmail(ctx, params.Email)
+ user, err := db.Provider.GetUserByEmail(ctx, params.Email)
if err != nil {
log.Debug("User not found: ", err)
return res, fmt.Errorf(`user with this email not found`)
@@ -84,8 +84,12 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
return res, err
}
- // exec it as go routin so that we can reduce the api latency
- go email.SendForgotPasswordMail(params.Email, verificationToken, hostname)
+ // exec it as go routine so that we can reduce the api latency
+ go email.SendEmail([]string{params.Email}, constants.VerificationTypeForgotPassword, map[string]interface{}{
+ "user": user.ToMap(),
+ "organization": utils.GetOrganization(),
+ "verification_url": utils.GetForgotPasswordURL(verificationToken, hostname),
+ })
res = &model.Response{
Message: `Please check your inbox! We have sent a password reset link.`,
diff --git a/server/resolvers/invite_members.go b/server/resolvers/invite_members.go
index e05406e..c642740 100644
--- a/server/resolvers/invite_members.go
+++ b/server/resolvers/invite_members.go
@@ -115,7 +115,7 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
return nil, err
}
- verificationToken, err := token.CreateVerificationToken(email, constants.VerificationTypeForgotPassword, hostname, nonceHash, redirectURL)
+ verificationToken, err := token.CreateVerificationToken(email, constants.VerificationTypeInviteMember, hostname, nonceHash, redirectURL)
if err != nil {
log.Debug("Failed to create verification token: ", err)
}
@@ -135,7 +135,7 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
} else {
// use basic authentication if that option is on
user.SignupMethods = constants.AuthRecipeMethodBasicAuth
- verificationRequest.Identifier = constants.VerificationTypeForgotPassword
+ verificationRequest.Identifier = constants.VerificationTypeInviteMember
isMFAEnforced, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyEnforceMultiFactorAuthentication)
if err != nil {
@@ -162,7 +162,12 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
return nil, err
}
- go emailservice.InviteEmail(email, verificationToken, verifyEmailURL, redirectURL)
+ // exec it as go routine so that we can reduce the api latency
+ go emailservice.SendEmail([]string{user.Email}, constants.VerificationTypeInviteMember, map[string]interface{}{
+ "user": user.ToMap(),
+ "organization": utils.GetOrganization(),
+ "verification_url": utils.GetInviteVerificationURL(verifyEmailURL, verificationToken, hostname),
+ })
}
return &model.Response{
diff --git a/server/resolvers/login.go b/server/resolvers/login.go
index 8587330..ed29e8c 100644
--- a/server/resolvers/login.go
+++ b/server/resolvers/login.go
@@ -123,7 +123,12 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
}
go func() {
- err := email.SendOtpMail(user.Email, otpData.Otp)
+ // exec it as go routine so that we can reduce the api latency
+ go email.SendEmail([]string{params.Email}, constants.VerificationTypeOTP, map[string]interface{}{
+ "user": user.ToMap(),
+ "organization": utils.GetOrganization(),
+ "otp": otpData.Otp,
+ })
if err != nil {
log.Debug("Failed to send otp email: ", err)
}
diff --git a/server/resolvers/magic_link_login.go b/server/resolvers/magic_link_login.go
index 456d5c0..611c47f 100644
--- a/server/resolvers/magic_link_login.go
+++ b/server/resolvers/magic_link_login.go
@@ -219,8 +219,12 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
return res, err
}
- // exec it as go routing so that we can reduce the api latency
- go email.SendVerificationMail(params.Email, verificationToken, hostname)
+ // exec it as go routine so that we can reduce the api latency
+ go email.SendEmail([]string{params.Email}, constants.VerificationTypeMagicLinkLogin, map[string]interface{}{
+ "user": user.ToMap(),
+ "organization": utils.GetOrganization(),
+ "verification_url": utils.GetEmailVerificationURL(verificationToken, hostname),
+ })
}
res = &model.Response{
diff --git a/server/resolvers/resend_otp.go b/server/resolvers/resend_otp.go
index 4ae53c0..65d9cf1 100644
--- a/server/resolvers/resend_otp.go
+++ b/server/resolvers/resend_otp.go
@@ -84,7 +84,12 @@ func ResendOTPResolver(ctx context.Context, params model.ResendOTPRequest) (*mod
}
go func() {
- err := email.SendOtpMail(params.Email, otp)
+ // exec it as go routine so that we can reduce the api latency
+ go email.SendEmail([]string{params.Email}, constants.VerificationTypeOTP, map[string]interface{}{
+ "user": user.ToMap(),
+ "organization": utils.GetOrganization(),
+ "otp": otp,
+ })
if err != nil {
log.Debug("Error sending otp email: ", otp)
}
diff --git a/server/resolvers/resend_verify_email.go b/server/resolvers/resend_verify_email.go
index bd72bdd..c58a034 100644
--- a/server/resolvers/resend_verify_email.go
+++ b/server/resolvers/resend_verify_email.go
@@ -39,6 +39,11 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
return res, fmt.Errorf("invalid identifier")
}
+ user, err := db.Provider.GetUserByEmail(ctx, params.Email)
+ if err != nil {
+ return res, fmt.Errorf("invalid user")
+ }
+
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, params.Email, params.Identifier)
if err != nil {
log.Debug("Failed to get verification request: ", err)
@@ -74,8 +79,12 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
log.Debug("Failed to add verification request: ", err)
}
- // exec it as go routin so that we can reduce the api latency
- go email.SendVerificationMail(params.Email, verificationToken, hostname)
+ // exec it as go routine so that we can reduce the api latency
+ go email.SendEmail([]string{params.Email}, params.Identifier, map[string]interface{}{
+ "user": user.ToMap(),
+ "organization": utils.GetOrganization(),
+ "verification_url": utils.GetEmailVerificationURL(verificationToken, hostname),
+ })
res = &model.Response{
Message: `Verification email has been sent. Please check your inbox`,
diff --git a/server/resolvers/signup.go b/server/resolvers/signup.go
index b7a548c..d5cd071 100644
--- a/server/resolvers/signup.go
+++ b/server/resolvers/signup.go
@@ -221,9 +221,14 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
return res, err
}
- // exec it as go routin so that we can reduce the api latency
+ // exec it as go routine so that we can reduce the api latency
go func() {
- email.SendVerificationMail(params.Email, verificationToken, hostname)
+ // exec it as go routine so that we can reduce the api latency
+ email.SendEmail([]string{params.Email}, constants.VerificationTypeBasicAuthSignup, map[string]interface{}{
+ "user": user.ToMap(),
+ "organization": utils.GetOrganization(),
+ "verification_url": utils.GetEmailVerificationURL(verificationToken, hostname),
+ })
utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
}()
diff --git a/server/resolvers/update_profile.go b/server/resolvers/update_profile.go
index 87762d9..9888aa5 100644
--- a/server/resolvers/update_profile.go
+++ b/server/resolvers/update_profile.go
@@ -244,8 +244,12 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
return res, err
}
- // exec it as go routin so that we can reduce the api latency
- go email.SendVerificationMail(newEmail, verificationToken, hostname)
+ // exec it as go routine so that we can reduce the api latency
+ go email.SendEmail([]string{user.Email}, constants.VerificationTypeBasicAuthSignup, map[string]interface{}{
+ "user": user.ToMap(),
+ "organization": utils.GetOrganization(),
+ "verification_url": utils.GetEmailVerificationURL(verificationToken, hostname),
+ })
}
}
diff --git a/server/resolvers/update_user.go b/server/resolvers/update_user.go
index d20e4a9..e2f6618 100644
--- a/server/resolvers/update_user.go
+++ b/server/resolvers/update_user.go
@@ -156,8 +156,12 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
return res, err
}
- // exec it as go routin so that we can reduce the api latency
- go email.SendVerificationMail(newEmail, verificationToken, hostname)
+ // exec it as go routine so that we can reduce the api latency
+ go email.SendEmail([]string{user.Email}, constants.VerificationTypeBasicAuthSignup, map[string]interface{}{
+ "user": user.ToMap(),
+ "organization": utils.GetOrganization(),
+ "verification_url": utils.GetEmailVerificationURL(verificationToken, hostname),
+ })
}
diff --git a/server/utils/common.go b/server/utils/common.go
index 86156be..2040885 100644
--- a/server/utils/common.go
+++ b/server/utils/common.go
@@ -2,6 +2,9 @@ package utils
import (
"reflect"
+
+ "github.com/authorizerdev/authorizer/server/constants"
+ "github.com/authorizerdev/authorizer/server/memorystore"
)
// StringSliceContains checks if a string slice contains a particular string
@@ -58,3 +61,46 @@ func ConvertInterfaceToStringSlice(slice interface{}) []string {
}
return resSlice
}
+
+// GetOrganization to get organization object
+func GetOrganization() map[string]interface{} {
+ orgLogo, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationLogo)
+ if err != nil {
+ return nil
+ }
+ orgName, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyOrganizationName)
+ if err != nil {
+ return nil
+ }
+ organization := map[string]interface{}{
+ "name": orgName,
+ "logo": orgLogo,
+ }
+
+ return organization
+}
+
+// GetForgotPasswordURL to get url for given token and hostname
+func GetForgotPasswordURL(token, hostname string) string {
+ resetPasswordUrl, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyResetPasswordURL)
+ if err != nil {
+ return ""
+ }
+ if resetPasswordUrl == "" {
+ if err := memorystore.Provider.UpdateEnvVariable(constants.EnvKeyResetPasswordURL, hostname+"/app/reset-password"); err != nil {
+ return ""
+ }
+ }
+ verificationURL := resetPasswordUrl + "?token=" + token
+ return verificationURL
+}
+
+// GetInviteVerificationURL to get url for invite email verification
+func GetInviteVerificationURL(verificationURL, token, redirectURI string) string {
+ return verificationURL + "?token=" + token + "&redirect_uri=" + redirectURI
+}
+
+// GetEmailVerificationURL to get url for invite email verification
+func GetEmailVerificationURL(token, hostname string) string {
+ return hostname + "/verify_email?token=" + token
+}
diff --git a/server/validators/email_template.go b/server/validators/email_template.go
index 1dd0766..fb5aa25 100644
--- a/server/validators/email_template.go
+++ b/server/validators/email_template.go
@@ -4,7 +4,7 @@ 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 {
+ if eventName != constants.VerificationTypeBasicAuthSignup && eventName != constants.VerificationTypeForgotPassword && eventName != constants.VerificationTypeMagicLinkLogin && eventName != constants.VerificationTypeUpdateEmail && eventName != constants.VerificationTypeOTP {
return false
}