feat: send email based on template
This commit is contained in:
parent
0714b4360b
commit
81fce1a471
|
@ -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 = `{
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 = `
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
<head>
|
||||
|
@ -98,23 +87,4 @@ func SendVerificationMail(toEmail, token, hostname string) error {
|
|||
</body>
|
||||
</html>
|
||||
`
|
||||
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
|
||||
}
|
||||
)
|
|
@ -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 = `
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
<head>
|
||||
|
@ -73,13 +53,13 @@ func SendForgotPasswordMail(toEmail, token, hostname string) error {
|
|||
<table width="100%%" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank" clicktracking="off"><img src="{{.org_logo}}" alt="icon" style="display: block;" title="icon" width="30"></a></td>
|
||||
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank" clicktracking="off"><img src="{{.organization.logo}}" alt="icon" style="display: block;" title="icon" width="30"></a></td>
|
||||
</tr>
|
||||
|
||||
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
|
||||
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
|
||||
<p>Hey there 👋</p>
|
||||
<p>We have received a request to reset password for email: <b>{{.org_name}}</b>. If this is correct, please reset the password clicking the button below.</p> <br/>
|
||||
<p>We have received a request to reset password for email: <b>{{.organization.name}}</b>. If this is correct, please reset the password clicking the button below.</p> <br/>
|
||||
<a clicktracking="off" href="{{.verification_url}}" class="es-button" target="_blank" style="text-decoration: none;padding:10px 15px;background-color: rgba(59,130,246,1);color: #fff;font-size: 1em;border-radius:5px;">Reset Password</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -106,18 +86,4 @@ func SendForgotPasswordMail(toEmail, token, hostname string) error {
|
|||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
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)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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 = `
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
<head>
|
||||
|
@ -64,13 +53,13 @@ func InviteEmail(toEmail, token, verificationURL, redirectURI string) error {
|
|||
<table width="100%%" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank" clicktracking="off"><img src="{{.org_logo}}" alt="icon" style="display: block;" title="icon" width="30"></a></td>
|
||||
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank" clicktracking="off"><img src="{{.organization.logo}}" alt="icon" style="display: block;" title="icon" width="30"></a></td>
|
||||
</tr>
|
||||
|
||||
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
|
||||
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
|
||||
<p>Hi there 👋</p>
|
||||
<p>Join us! You are invited to sign-up for <b>{{.org_name}}</b>. Please accept the invitation by clicking the button below.</p> <br/>
|
||||
<p>Join us! You are invited to sign-up for <b>{{.organization.name}}</b>. Please accept the invitation by clicking the button below.</p> <br/>
|
||||
<a
|
||||
clicktracking="off" href="{{.verification_url}}" class="es-button" target="_blank" style="text-decoration: none;padding:10px 15px;background-color: rgba(59,130,246,1);color: #fff;font-size: 1em;border-radius:5px;">Get Started</a>
|
||||
</td>
|
||||
|
@ -98,23 +87,4 @@ func InviteEmail(toEmail, token, verificationURL, redirectURI string) error {
|
|||
</body>
|
||||
</html>
|
||||
`
|
||||
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
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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 = `
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
<head>
|
||||
|
@ -64,13 +53,13 @@ func SendOtpMail(toEmail, otp string) error {
|
|||
<table width="100%%" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank" clicktracking="off"><img src="{{.org_logo}}" alt="icon" style="display: block;" title="icon" width="30"></a></td>
|
||||
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank" clicktracking="off"><img src="{{.organization.logo}}" alt="icon" style="display: block;" title="icon" width="30"></a></td>
|
||||
</tr>
|
||||
|
||||
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
|
||||
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
|
||||
<p>Hey there 👋</p>
|
||||
<b>{{.otp}}</b> is your one time password (OTP) for accessing {{.org_name}}. Please keep your OTP confidential and it will expire in 1 minute.
|
||||
<b>{{.otp}}</b> is your one time password (OTP) for accessing {{.organization.name}}. Please keep your OTP confidential and it will expire in 1 minute.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -96,23 +85,4 @@ func SendOtpMail(toEmail, otp string) error {
|
|||
</body>
|
||||
</html>
|
||||
`
|
||||
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
|
||||
}
|
||||
)
|
||||
|
|
1
server/email/utils.go
Normal file
1
server/email/utils.go
Normal file
|
@ -0,0 +1 @@
|
|||
package email
|
|
@ -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.`,
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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`,
|
||||
|
|
|
@ -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)
|
||||
}()
|
||||
|
||||
|
|
|
@ -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),
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user