Merge pull request #209 from authorizerdev/feat/send-email-based-on-template
feat: send email based on template
This commit is contained in:
commit
5c6e643efb
21
dashboard/package-lock.json
generated
21
dashboard/package-lock.json
generated
|
@ -2798,7 +2798,8 @@
|
|||
"@chakra-ui/css-reset": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/css-reset/-/css-reset-1.1.1.tgz",
|
||||
"integrity": "sha512-+KNNHL4OWqeKia5SL858K3Qbd8WxMij9mWIilBzLD4j2KFrl/+aWFw8syMKth3NmgIibrjsljo+PU3fy2o50dg=="
|
||||
"integrity": "sha512-+KNNHL4OWqeKia5SL858K3Qbd8WxMij9mWIilBzLD4j2KFrl/+aWFw8syMKth3NmgIibrjsljo+PU3fy2o50dg==",
|
||||
"requires": {}
|
||||
},
|
||||
"@chakra-ui/descendant": {
|
||||
"version": "2.1.1",
|
||||
|
@ -3402,7 +3403,8 @@
|
|||
"@graphql-typed-document-node/core": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz",
|
||||
"integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg=="
|
||||
"integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==",
|
||||
"requires": {}
|
||||
},
|
||||
"@popperjs/core": {
|
||||
"version": "2.11.0",
|
||||
|
@ -3739,7 +3741,8 @@
|
|||
"draft-js-utils": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/draft-js-utils/-/draft-js-utils-1.4.1.tgz",
|
||||
"integrity": "sha512-xE81Y+z/muC5D5z9qWmKfxEW1XyXfsBzSbSBk2JRsoD0yzMGGHQm/0MtuqHl/EUDkaBJJLjJ2EACycoDMY/OOg=="
|
||||
"integrity": "sha512-xE81Y+z/muC5D5z9qWmKfxEW1XyXfsBzSbSBk2JRsoD0yzMGGHQm/0MtuqHl/EUDkaBJJLjJ2EACycoDMY/OOg==",
|
||||
"requires": {}
|
||||
},
|
||||
"draftjs-to-html": {
|
||||
"version": "0.9.1",
|
||||
|
@ -3749,7 +3752,8 @@
|
|||
"draftjs-utils": {
|
||||
"version": "0.10.2",
|
||||
"resolved": "https://registry.npmjs.org/draftjs-utils/-/draftjs-utils-0.10.2.tgz",
|
||||
"integrity": "sha512-EstHqr3R3JVcilJrBaO/A+01GvwwKmC7e4TCjC7S94ZeMh4IVmf60OuQXtHHpwItK8C2JCi3iljgN5KHkJboUg=="
|
||||
"integrity": "sha512-EstHqr3R3JVcilJrBaO/A+01GvwwKmC7e4TCjC7S94ZeMh4IVmf60OuQXtHHpwItK8C2JCi3iljgN5KHkJboUg==",
|
||||
"requires": {}
|
||||
},
|
||||
"error-ex": {
|
||||
"version": "1.3.2",
|
||||
|
@ -4043,7 +4047,8 @@
|
|||
"html-to-draftjs": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/html-to-draftjs/-/html-to-draftjs-1.5.0.tgz",
|
||||
"integrity": "sha512-kggLXBNciKDwKf+KYsuE+V5gw4dZ7nHyGMX9m0wy7urzWjKGWyNFetmArRLvRV0VrxKN70WylFsJvMTJx02OBQ=="
|
||||
"integrity": "sha512-kggLXBNciKDwKf+KYsuE+V5gw4dZ7nHyGMX9m0wy7urzWjKGWyNFetmArRLvRV0VrxKN70WylFsJvMTJx02OBQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"immutable": {
|
||||
"version": "3.7.6",
|
||||
|
@ -4272,7 +4277,8 @@
|
|||
"react-icons": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.3.1.tgz",
|
||||
"integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ=="
|
||||
"integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
|
@ -4483,7 +4489,8 @@
|
|||
"use-callback-ref": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz",
|
||||
"integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg=="
|
||||
"integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==",
|
||||
"requires": {}
|
||||
},
|
||||
"use-sidecar": {
|
||||
"version": "1.0.5",
|
||||
|
|
|
@ -62,8 +62,7 @@ interface validatorDataType {
|
|||
}
|
||||
|
||||
const initTemplateData: emailTemplateDataType = {
|
||||
[EmailTemplateInputDataFields.EVENT_NAME]:
|
||||
emailTemplateEventNames.BASIC_AUTH_SIGNUP,
|
||||
[EmailTemplateInputDataFields.EVENT_NAME]: emailTemplateEventNames.Signup,
|
||||
[EmailTemplateInputDataFields.SUBJECT]: '',
|
||||
};
|
||||
|
||||
|
@ -206,10 +205,10 @@ const UpdateEmailTemplate = ({
|
|||
).reduce((acc, varData): any => {
|
||||
if (
|
||||
(templateData[EmailTemplateInputDataFields.EVENT_NAME] !==
|
||||
emailTemplateEventNames.VERIFY_OTP &&
|
||||
emailTemplateEventNames['Verify Otp'] &&
|
||||
varData[1] === emailTemplateVariables.otp) ||
|
||||
(templateData[EmailTemplateInputDataFields.EVENT_NAME] ===
|
||||
emailTemplateEventNames.VERIFY_OTP &&
|
||||
emailTemplateEventNames['Verify Otp'] &&
|
||||
varData[1] === emailTemplateVariables.verification_url)
|
||||
) {
|
||||
return acc;
|
||||
|
|
|
@ -94,7 +94,7 @@ interface validatorDataType {
|
|||
}
|
||||
|
||||
const initWebhookData: webhookDataType = {
|
||||
[WebhookInputDataFields.EVENT_NAME]: webhookEventNames.USER_LOGIN,
|
||||
[WebhookInputDataFields.EVENT_NAME]: webhookEventNames['User login'],
|
||||
[WebhookInputDataFields.ENDPOINT]: '',
|
||||
[WebhookInputDataFields.ENABLED]: true,
|
||||
[WebhookInputDataFields.HEADERS]: [{ ...initHeadersData }],
|
||||
|
|
|
@ -183,20 +183,21 @@ export enum UpdateModalViews {
|
|||
export const pageLimits: number[] = [5, 10, 15];
|
||||
|
||||
export const webhookEventNames = {
|
||||
USER_SIGNUP: 'user.signup',
|
||||
USER_CREATED: 'user.created',
|
||||
USER_LOGIN: 'user.login',
|
||||
USER_DELETED: 'user.deleted',
|
||||
USER_ACCESS_ENABLED: 'user.access_enabled',
|
||||
USER_ACCESS_REVOKED: 'user.access_revoked',
|
||||
'User signup': 'user.signup',
|
||||
'User created': 'user.created',
|
||||
'User login': 'user.login',
|
||||
'User deleted': 'user.deleted',
|
||||
'User access enabled': 'user.access_enabled',
|
||||
'User access revoked': 'user.access_revoked',
|
||||
};
|
||||
|
||||
export const emailTemplateEventNames = {
|
||||
BASIC_AUTH_SIGNUP: 'basic_auth_signup',
|
||||
MAGIC_LINK_LOGIN: 'magic_link_login',
|
||||
UPDATE_EMAIL: 'update_email',
|
||||
FORGOT_PASSWORD: 'forgot_password',
|
||||
VERIFY_OTP: 'verify_otp',
|
||||
Signup: 'basic_auth_signup',
|
||||
'Magic Link Login': 'magic_link_login',
|
||||
'Update Email': 'update_email',
|
||||
'Forgot Password': 'forgot_password',
|
||||
'Verify Otp': 'verify_otp',
|
||||
'Invite member': 'invite_member',
|
||||
};
|
||||
|
||||
export enum webhookVerifiedStatus {
|
||||
|
@ -206,27 +207,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 = `{
|
||||
|
|
|
@ -126,7 +126,7 @@ export const WebhooksDataQuery = `
|
|||
export const EmailTemplatesQuery = `
|
||||
query getEmailTemplates($params: PaginatedInput!) {
|
||||
_email_templates(params: $params) {
|
||||
EmailTemplates {
|
||||
email_templates {
|
||||
id
|
||||
event_name
|
||||
subject
|
||||
|
|
|
@ -40,7 +40,7 @@ import {
|
|||
UpdateModalViews,
|
||||
EmailTemplateInputDataFields,
|
||||
} from '../constants';
|
||||
import { EmailTemplatesQuery, WebhooksDataQuery } from '../graphql/queries';
|
||||
import { EmailTemplatesQuery } from '../graphql/queries';
|
||||
import dayjs from 'dayjs';
|
||||
import DeleteEmailTemplateModal from '../components/DeleteEmailTemplateModal';
|
||||
|
||||
|
@ -94,7 +94,7 @@ const EmailTemplates = () => {
|
|||
})
|
||||
.toPromise();
|
||||
if (res.data?._email_templates) {
|
||||
const { pagination, EmailTemplates: emailTemplates } =
|
||||
const { pagination, email_templates: emailTemplates } =
|
||||
res.data?._email_templates;
|
||||
const maxPages = getMaxPages(pagination);
|
||||
if (emailTemplates?.length) {
|
||||
|
|
|
@ -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
|
|
@ -441,7 +441,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||
|
||||
return e.complexity.EmailTemplate.UpdatedAt(childComplexity), true
|
||||
|
||||
case "EmailTemplates.EmailTemplates":
|
||||
case "EmailTemplates.email_templates":
|
||||
if e.complexity.EmailTemplates.EmailTemplates == nil {
|
||||
break
|
||||
}
|
||||
|
@ -2066,7 +2066,7 @@ type EmailTemplate {
|
|||
|
||||
type EmailTemplates {
|
||||
pagination: Pagination!
|
||||
EmailTemplates: [EmailTemplate!]!
|
||||
email_templates: [EmailTemplate!]!
|
||||
}
|
||||
|
||||
input UpdateEnvInput {
|
||||
|
@ -3404,7 +3404,7 @@ func (ec *executionContext) _EmailTemplates_pagination(ctx context.Context, fiel
|
|||
return ec.marshalNPagination2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPagination(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _EmailTemplates_EmailTemplates(ctx context.Context, field graphql.CollectedField, obj *model.EmailTemplates) (ret graphql.Marshaler) {
|
||||
func (ec *executionContext) _EmailTemplates_email_templates(ctx context.Context, field graphql.CollectedField, obj *model.EmailTemplates) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
|
@ -12198,8 +12198,8 @@ func (ec *executionContext) _EmailTemplates(ctx context.Context, sel ast.Selecti
|
|||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "EmailTemplates":
|
||||
out.Values[i] = ec._EmailTemplates_EmailTemplates(ctx, field, obj)
|
||||
case "email_templates":
|
||||
out.Values[i] = ec._EmailTemplates_email_templates(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ type EmailTemplate struct {
|
|||
|
||||
type EmailTemplates struct {
|
||||
Pagination *Pagination `json:"pagination"`
|
||||
EmailTemplates []*EmailTemplate `json:"EmailTemplates"`
|
||||
EmailTemplates []*EmailTemplate `json:"email_templates"`
|
||||
}
|
||||
|
||||
type Env struct {
|
||||
|
|
|
@ -201,7 +201,7 @@ type EmailTemplate {
|
|||
|
||||
type EmailTemplates {
|
||||
pagination: Pagination!
|
||||
EmailTemplates: [EmailTemplate!]!
|
||||
email_templates: [EmailTemplate!]!
|
||||
}
|
||||
|
||||
input UpdateEnvInput {
|
||||
|
|
|
@ -14,8 +14,6 @@ import (
|
|||
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)
|
||||
|
|
|
@ -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, redirectURL),
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
}()
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ import (
|
|||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// TODO add template validator
|
||||
|
||||
// UpdateEmailTemplateResolver resolver for update email template mutation
|
||||
func UpdateEmailTemplateResolver(ctx context.Context, params model.UpdateEmailTemplateRequest) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
|
|
|
@ -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 && eventName != constants.VerificationTypeInviteMember {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user