Some worker typescript conversions.
This commit is contained in:
parent
29dd98a7fc
commit
cdc25d7032
|
@ -1,97 +1,97 @@
|
|||
const { Config } = require("@budibase/backend-core/constants")
|
||||
import { constants } from "@budibase/backend-core"
|
||||
|
||||
exports.LOGO_URL =
|
||||
export const LOGO_URL =
|
||||
"https://d33wubrfki0l68.cloudfront.net/aac32159d7207b5085e74a7ef67afbb7027786c5/2b1fd/img/logo/bb-emblem.svg"
|
||||
|
||||
exports.UserStatus = {
|
||||
ACTIVE: "active",
|
||||
INACTIVE: "inactive",
|
||||
export enum UserStatus {
|
||||
ACTIVE = "active",
|
||||
INACTIVE = "inactive",
|
||||
}
|
||||
|
||||
exports.Config = Config
|
||||
export const Config = constants.Config
|
||||
|
||||
exports.ConfigUploads = {
|
||||
LOGO: "logo",
|
||||
OIDC_LOGO: "oidc_logo",
|
||||
export enum ConfigUpload {
|
||||
LOGO = "logo",
|
||||
OIDC_LOGO = "oidc_logo",
|
||||
}
|
||||
|
||||
const TemplateTypes = {
|
||||
EMAIL: "email",
|
||||
export enum TemplateType {
|
||||
EMAIL = "email",
|
||||
}
|
||||
|
||||
const EmailTemplatePurpose = {
|
||||
BASE: "base",
|
||||
PASSWORD_RECOVERY: "password_recovery",
|
||||
INVITATION: "invitation",
|
||||
WELCOME: "welcome",
|
||||
CUSTOM: "custom",
|
||||
export enum EmailTemplatePurpose {
|
||||
BASE = "base",
|
||||
PASSWORD_RECOVERY = "password_recovery",
|
||||
INVITATION = "invitation",
|
||||
WELCOME = "welcome",
|
||||
CUSTOM = "custom",
|
||||
}
|
||||
|
||||
const InternalTemplateBindings = {
|
||||
PLATFORM_URL: "platformUrl",
|
||||
COMPANY: "company",
|
||||
LOGO_URL: "logoUrl",
|
||||
EMAIL: "email",
|
||||
USER: "user",
|
||||
REQUEST: "request",
|
||||
DOCS_URL: "docsUrl",
|
||||
LOGIN_URL: "loginUrl",
|
||||
CURRENT_YEAR: "currentYear",
|
||||
CURRENT_DATE: "currentDate",
|
||||
BODY: "body",
|
||||
STYLES: "styles",
|
||||
RESET_URL: "resetUrl",
|
||||
RESET_CODE: "resetCode",
|
||||
INVITE_URL: "inviteUrl",
|
||||
INVITE_CODE: "inviteUrl",
|
||||
CONTENTS: "contents",
|
||||
export enum InternalTemplateBinding {
|
||||
PLATFORM_URL = "platformUrl",
|
||||
COMPANY = "company",
|
||||
LOGO_URL = "logoUrl",
|
||||
EMAIL = "email",
|
||||
USER = "user",
|
||||
REQUEST = "request",
|
||||
DOCS_URL = "docsUrl",
|
||||
LOGIN_URL = "loginUrl",
|
||||
CURRENT_YEAR = "currentYear",
|
||||
CURRENT_DATE = "currentDate",
|
||||
BODY = "body",
|
||||
STYLES = "styles",
|
||||
RESET_URL = "resetUrl",
|
||||
RESET_CODE = "resetCode",
|
||||
INVITE_URL = "inviteUrl",
|
||||
INVITE_CODE = "inviteUrl",
|
||||
CONTENTS = "contents",
|
||||
}
|
||||
|
||||
const TemplateBindings = {
|
||||
export const TemplateBindings = {
|
||||
PLATFORM_URL: {
|
||||
name: InternalTemplateBindings.PLATFORM_URL,
|
||||
name: InternalTemplateBinding.PLATFORM_URL,
|
||||
description: "The URL used to access the budibase platform",
|
||||
},
|
||||
COMPANY: {
|
||||
name: InternalTemplateBindings.COMPANY,
|
||||
name: InternalTemplateBinding.COMPANY,
|
||||
description: "The name of your organization",
|
||||
},
|
||||
LOGO_URL: {
|
||||
name: InternalTemplateBindings.LOGO_URL,
|
||||
name: InternalTemplateBinding.LOGO_URL,
|
||||
description: "The URL of your organizations logo.",
|
||||
},
|
||||
EMAIL: {
|
||||
name: InternalTemplateBindings.EMAIL,
|
||||
name: InternalTemplateBinding.EMAIL,
|
||||
description: "The recipients email address.",
|
||||
},
|
||||
USER: {
|
||||
name: InternalTemplateBindings.USER,
|
||||
name: InternalTemplateBinding.USER,
|
||||
description: "The recipients user object.",
|
||||
},
|
||||
REQUEST: {
|
||||
name: InternalTemplateBindings.REQUEST,
|
||||
name: InternalTemplateBinding.REQUEST,
|
||||
description: "Additional request metadata.",
|
||||
},
|
||||
DOCS_URL: {
|
||||
name: InternalTemplateBindings.DOCS_URL,
|
||||
name: InternalTemplateBinding.DOCS_URL,
|
||||
description: "Organization documentation URL.",
|
||||
},
|
||||
LOGIN_URL: {
|
||||
name: InternalTemplateBindings.LOGIN_URL,
|
||||
name: InternalTemplateBinding.LOGIN_URL,
|
||||
description: "The URL used to log into the organization budibase instance.",
|
||||
},
|
||||
CURRENT_YEAR: {
|
||||
name: InternalTemplateBindings.CURRENT_YEAR,
|
||||
name: InternalTemplateBinding.CURRENT_YEAR,
|
||||
description: "The current year.",
|
||||
},
|
||||
CURRENT_DATE: {
|
||||
name: InternalTemplateBindings.CURRENT_DATE,
|
||||
name: InternalTemplateBinding.CURRENT_DATE,
|
||||
description: "The current date.",
|
||||
},
|
||||
}
|
||||
|
||||
const TemplateMetadata = {
|
||||
[TemplateTypes.EMAIL]: [
|
||||
export const TemplateMetadata = {
|
||||
[TemplateType.EMAIL]: [
|
||||
{
|
||||
name: "Base format",
|
||||
description:
|
||||
|
@ -100,11 +100,11 @@ const TemplateMetadata = {
|
|||
purpose: EmailTemplatePurpose.BASE,
|
||||
bindings: [
|
||||
{
|
||||
name: InternalTemplateBindings.BODY,
|
||||
name: InternalTemplateBinding.BODY,
|
||||
description: "The main body of another email template.",
|
||||
},
|
||||
{
|
||||
name: InternalTemplateBindings.STYLES,
|
||||
name: InternalTemplateBinding.STYLES,
|
||||
description: "The contents of the Styling email template.",
|
||||
},
|
||||
],
|
||||
|
@ -117,12 +117,12 @@ const TemplateMetadata = {
|
|||
purpose: EmailTemplatePurpose.PASSWORD_RECOVERY,
|
||||
bindings: [
|
||||
{
|
||||
name: InternalTemplateBindings.RESET_URL,
|
||||
name: InternalTemplateBinding.RESET_URL,
|
||||
description:
|
||||
"The URL the recipient must click to reset their password.",
|
||||
},
|
||||
{
|
||||
name: InternalTemplateBindings.RESET_CODE,
|
||||
name: InternalTemplateBinding.RESET_CODE,
|
||||
description:
|
||||
"The temporary password reset code used in the recipients password reset URL.",
|
||||
},
|
||||
|
@ -144,12 +144,12 @@ const TemplateMetadata = {
|
|||
purpose: EmailTemplatePurpose.INVITATION,
|
||||
bindings: [
|
||||
{
|
||||
name: InternalTemplateBindings.INVITE_URL,
|
||||
name: InternalTemplateBinding.INVITE_URL,
|
||||
description:
|
||||
"The URL the recipient must click to accept the invitation and activate their account.",
|
||||
},
|
||||
{
|
||||
name: InternalTemplateBindings.INVITE_CODE,
|
||||
name: InternalTemplateBinding.INVITE_CODE,
|
||||
description:
|
||||
"The temporary invite code used in the recipients invitation URL.",
|
||||
},
|
||||
|
@ -163,7 +163,7 @@ const TemplateMetadata = {
|
|||
purpose: EmailTemplatePurpose.CUSTOM,
|
||||
bindings: [
|
||||
{
|
||||
name: InternalTemplateBindings.CONTENTS,
|
||||
name: InternalTemplateBinding.CONTENTS,
|
||||
description: "Custom content body.",
|
||||
},
|
||||
],
|
||||
|
@ -172,12 +172,5 @@ const TemplateMetadata = {
|
|||
}
|
||||
|
||||
// all purpose combined
|
||||
exports.TemplatePurpose = {
|
||||
...EmailTemplatePurpose,
|
||||
}
|
||||
exports.TemplateTypes = TemplateTypes
|
||||
exports.EmailTemplatePurpose = EmailTemplatePurpose
|
||||
exports.TemplateMetadata = TemplateMetadata
|
||||
exports.TemplateBindings = TemplateBindings
|
||||
exports.InternalTemplateBindings = InternalTemplateBindings
|
||||
exports.GLOBAL_OWNER = "global"
|
||||
export { EmailTemplatePurpose as TemplatePurpose }
|
||||
export const GLOBAL_OWNER = "global"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const { readStaticFile } = require("../../utilities/fileSystem")
|
||||
const {
|
||||
EmailTemplatePurpose,
|
||||
TemplateTypes,
|
||||
TemplateType,
|
||||
TemplatePurpose,
|
||||
GLOBAL_OWNER,
|
||||
} = require("../index")
|
||||
|
@ -26,7 +26,7 @@ exports.EmailTemplates = {
|
|||
exports.addBaseTemplates = (templates, type = null) => {
|
||||
let purposeList
|
||||
switch (type) {
|
||||
case TemplateTypes.EMAIL:
|
||||
case TemplateType.EMAIL:
|
||||
purposeList = Object.values(EmailTemplatePurpose)
|
||||
break
|
||||
default:
|
||||
|
|
|
@ -1,15 +1,33 @@
|
|||
import env from "../environment"
|
||||
import { EmailTemplatePurpose, TemplateType, Config } from "../constants"
|
||||
import { getTemplateByPurpose } from "../constants/templates"
|
||||
import { getSettingsTemplateContext } from "./templates"
|
||||
import { processString } from "@budibase/string-templates"
|
||||
import { getResetPasswordCode, getInviteCode } from "./redis"
|
||||
import { User } from "@budibase/types"
|
||||
import { tenancy, db as dbCore, PouchLike } from "@budibase/backend-core"
|
||||
const nodemailer = require("nodemailer")
|
||||
const env = require("../environment")
|
||||
const { getScopedConfig } = require("@budibase/backend-core/db")
|
||||
const { EmailTemplatePurpose, TemplateTypes, Config } = require("../constants")
|
||||
const { getTemplateByPurpose } = require("../constants/templates")
|
||||
const { getSettingsTemplateContext } = require("./templates")
|
||||
const { processString } = require("@budibase/string-templates")
|
||||
const { getResetPasswordCode, getInviteCode } = require("../utilities/redis")
|
||||
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
||||
|
||||
type SendEmailOpts = {
|
||||
// workspaceId If finer grain controls being used then this will lookup config for workspace.
|
||||
workspaceId?: string
|
||||
// user If sending to an existing user the object can be provided, this is used in the context.
|
||||
user: User
|
||||
// from If sending from an address that is not what is configured in the SMTP config.
|
||||
from?: string
|
||||
// contents If sending a custom email then can supply contents which will be added to it.
|
||||
contents?: string
|
||||
// subject A custom subject can be specified if the config one is not desired.
|
||||
subject?: string
|
||||
// info Pass in a structure of information to be stored alongside the invitation.
|
||||
info?: any
|
||||
cc?: boolean
|
||||
bcc?: boolean
|
||||
automation?: boolean
|
||||
}
|
||||
|
||||
const TEST_MODE = false
|
||||
const TYPE = TemplateTypes.EMAIL
|
||||
const TYPE = TemplateType.EMAIL
|
||||
|
||||
const FULL_EMAIL_PURPOSES = [
|
||||
EmailTemplatePurpose.INVITATION,
|
||||
|
@ -18,8 +36,8 @@ const FULL_EMAIL_PURPOSES = [
|
|||
EmailTemplatePurpose.CUSTOM,
|
||||
]
|
||||
|
||||
function createSMTPTransport(config) {
|
||||
let options
|
||||
function createSMTPTransport(config: any) {
|
||||
let options: any
|
||||
let secure = config.secure
|
||||
// default it if not specified
|
||||
if (secure == null) {
|
||||
|
@ -52,10 +70,15 @@ function createSMTPTransport(config) {
|
|||
return nodemailer.createTransport(options)
|
||||
}
|
||||
|
||||
async function getLinkCode(purpose, email, user, info = null) {
|
||||
async function getLinkCode(
|
||||
purpose: EmailTemplatePurpose,
|
||||
email: string,
|
||||
user: User,
|
||||
info: any = null
|
||||
) {
|
||||
switch (purpose) {
|
||||
case EmailTemplatePurpose.PASSWORD_RECOVERY:
|
||||
return getResetPasswordCode(user._id, info)
|
||||
return getResetPasswordCode(user._id!, info)
|
||||
case EmailTemplatePurpose.INVITATION:
|
||||
return getInviteCode(email, info)
|
||||
default:
|
||||
|
@ -72,7 +95,12 @@ async function getLinkCode(purpose, email, user, info = null) {
|
|||
* @param {string|null} contents if using a custom template can supply contents for context.
|
||||
* @return {Promise<string>} returns the built email HTML if all provided parameters were valid.
|
||||
*/
|
||||
async function buildEmail(purpose, email, context, { user, contents } = {}) {
|
||||
async function buildEmail(
|
||||
purpose: EmailTemplatePurpose,
|
||||
email: string,
|
||||
context: any,
|
||||
{ user, contents }: any = {}
|
||||
) {
|
||||
// this isn't a full email
|
||||
if (FULL_EMAIL_PURPOSES.indexOf(purpose) === -1) {
|
||||
throw `Unable to build an email of type ${purpose}`
|
||||
|
@ -113,15 +141,19 @@ async function buildEmail(purpose, email, context, { user, contents } = {}) {
|
|||
* @param {boolean|null} automation Whether or not the configuration is being fetched for an email automation.
|
||||
* @return {Promise<object|null>} returns the SMTP configuration if it exists
|
||||
*/
|
||||
async function getSmtpConfiguration(db, workspaceId = null, automation) {
|
||||
const params = {
|
||||
async function getSmtpConfiguration(
|
||||
db: PouchLike,
|
||||
workspaceId?: string,
|
||||
automation?: boolean
|
||||
) {
|
||||
const params: any = {
|
||||
type: Config.SMTP,
|
||||
}
|
||||
if (workspaceId) {
|
||||
params.workspace = workspaceId
|
||||
}
|
||||
|
||||
const customConfig = await getScopedConfig(db, params)
|
||||
const customConfig = await dbCore.getScopedConfig(db, params)
|
||||
|
||||
if (customConfig) {
|
||||
return customConfig
|
||||
|
@ -146,12 +178,12 @@ async function getSmtpConfiguration(db, workspaceId = null, automation) {
|
|||
* Checks if a SMTP config exists based on passed in parameters.
|
||||
* @return {Promise<boolean>} returns true if there is a configuration that can be used.
|
||||
*/
|
||||
exports.isEmailConfigured = async (workspaceId = null) => {
|
||||
export async function isEmailConfigured(workspaceId?: string) {
|
||||
// when "testing" or smtp fallback is enabled simply return true
|
||||
if (TEST_MODE || env.SMTP_FALLBACK_ENABLED) {
|
||||
return true
|
||||
}
|
||||
const db = getGlobalDB()
|
||||
const db = tenancy.getGlobalDB()
|
||||
const config = await getSmtpConfiguration(db, workspaceId)
|
||||
return config != null
|
||||
}
|
||||
|
@ -161,48 +193,49 @@ exports.isEmailConfigured = async (workspaceId = null) => {
|
|||
* send an email using it.
|
||||
* @param {string} email The email address to send to.
|
||||
* @param {string} purpose The purpose of the email being sent (e.g. reset password).
|
||||
* @param {string|undefined} workspaceId If finer grain controls being used then this will lookup config for workspace.
|
||||
* @param {object|undefined} user If sending to an existing user the object can be provided, this is used in the context.
|
||||
* @param {string|undefined} from If sending from an address that is not what is configured in the SMTP config.
|
||||
* @param {string|undefined} contents If sending a custom email then can supply contents which will be added to it.
|
||||
* @param {string|undefined} subject A custom subject can be specified if the config one is not desired.
|
||||
* @param {object|undefined} info Pass in a structure of information to be stored alongside the invitation.
|
||||
* @param {boolean|undefined} disableFallback Prevent email being sent from SMTP fallback to avoid spam.
|
||||
* @param {object} opts The options for sending the email.
|
||||
* @return {Promise<object>} returns details about the attempt to send email, e.g. if it is successful; based on
|
||||
* nodemailer response.
|
||||
*/
|
||||
exports.sendEmail = async (
|
||||
email,
|
||||
purpose,
|
||||
{ workspaceId, user, from, contents, subject, info, cc, bcc, automation } = {}
|
||||
) => {
|
||||
const db = getGlobalDB()
|
||||
let config = (await getSmtpConfiguration(db, workspaceId, automation)) || {}
|
||||
export async function sendEmail(
|
||||
email: string,
|
||||
purpose: EmailTemplatePurpose,
|
||||
opts: SendEmailOpts
|
||||
) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
let config =
|
||||
(await getSmtpConfiguration(db, opts?.workspaceId, opts?.automation)) || {}
|
||||
if (Object.keys(config).length === 0 && !TEST_MODE) {
|
||||
throw "Unable to find SMTP configuration."
|
||||
}
|
||||
const transport = createSMTPTransport(config)
|
||||
// if there is a link code needed this will retrieve it
|
||||
const code = await getLinkCode(purpose, email, user, info)
|
||||
const context = await getSettingsTemplateContext(purpose, code)
|
||||
const code = await getLinkCode(purpose, email, opts.user, opts?.info)
|
||||
let context
|
||||
if (code) {
|
||||
context = await getSettingsTemplateContext(purpose, code)
|
||||
}
|
||||
|
||||
let message = {
|
||||
from: from || config.from,
|
||||
let message: any = {
|
||||
from: opts?.from || config.from,
|
||||
html: await buildEmail(purpose, email, context, {
|
||||
user,
|
||||
contents,
|
||||
user: opts?.user,
|
||||
contents: opts?.contents,
|
||||
}),
|
||||
}
|
||||
|
||||
message = {
|
||||
...message,
|
||||
to: email,
|
||||
cc: cc,
|
||||
bcc: bcc,
|
||||
cc: opts?.cc,
|
||||
bcc: opts?.bcc,
|
||||
}
|
||||
|
||||
if (subject || config.subject) {
|
||||
message.subject = await processString(subject || config.subject, context)
|
||||
if (opts?.subject || config.subject) {
|
||||
message.subject = await processString(
|
||||
opts?.subject || config.subject,
|
||||
context
|
||||
)
|
||||
}
|
||||
const response = await transport.sendMail(message)
|
||||
if (TEST_MODE) {
|
||||
|
@ -216,7 +249,7 @@ exports.sendEmail = async (
|
|||
* @param {object} config an SMTP configuration - this is based on the nodemailer API.
|
||||
* @return {Promise<boolean>} returns true if the configuration is valid.
|
||||
*/
|
||||
exports.verifyConfig = async config => {
|
||||
export async function verifyConfig(config: any) {
|
||||
const transport = createSMTPTransport(config)
|
||||
await transport.verify()
|
||||
}
|
||||
|
|
|
@ -1,36 +1,35 @@
|
|||
const { Client, utils } = require("@budibase/backend-core/redis")
|
||||
const { newid } = require("@budibase/backend-core/utils")
|
||||
import { redis, utils } from "@budibase/backend-core"
|
||||
|
||||
function getExpirySecondsForDB(db) {
|
||||
function getExpirySecondsForDB(db: string) {
|
||||
switch (db) {
|
||||
case utils.Databases.PW_RESETS:
|
||||
case redis.utils.Databases.PW_RESETS:
|
||||
// a hour
|
||||
return 3600
|
||||
case utils.Databases.INVITATIONS:
|
||||
case redis.utils.Databases.INVITATIONS:
|
||||
// a day
|
||||
return 86400
|
||||
}
|
||||
}
|
||||
|
||||
let pwResetClient, invitationClient
|
||||
let pwResetClient: any, invitationClient: any
|
||||
|
||||
function getClient(db) {
|
||||
function getClient(db: string) {
|
||||
switch (db) {
|
||||
case utils.Databases.PW_RESETS:
|
||||
case redis.utils.Databases.PW_RESETS:
|
||||
return pwResetClient
|
||||
case utils.Databases.INVITATIONS:
|
||||
case redis.utils.Databases.INVITATIONS:
|
||||
return invitationClient
|
||||
}
|
||||
}
|
||||
|
||||
async function writeACode(db, value) {
|
||||
async function writeACode(db: string, value: any) {
|
||||
const client = await getClient(db)
|
||||
const code = newid()
|
||||
const code = utils.newid()
|
||||
await client.store(code, value, getExpirySecondsForDB(db))
|
||||
return code
|
||||
}
|
||||
|
||||
async function getACode(db, code, deleteCode = true) {
|
||||
async function getACode(db: string, code: string, deleteCode = true) {
|
||||
const client = await getClient(db)
|
||||
const value = await client.get(code)
|
||||
if (!value) {
|
||||
|
@ -42,9 +41,9 @@ async function getACode(db, code, deleteCode = true) {
|
|||
return value
|
||||
}
|
||||
|
||||
exports.init = async () => {
|
||||
pwResetClient = new Client(utils.Databases.PW_RESETS)
|
||||
invitationClient = new Client(utils.Databases.INVITATIONS)
|
||||
export async function init() {
|
||||
pwResetClient = new redis.Client(redis.utils.Databases.PW_RESETS)
|
||||
invitationClient = new redis.Client(redis.utils.Databases.INVITATIONS)
|
||||
await pwResetClient.init()
|
||||
await invitationClient.init()
|
||||
}
|
||||
|
@ -52,7 +51,7 @@ exports.init = async () => {
|
|||
/**
|
||||
* make sure redis connection is closed.
|
||||
*/
|
||||
exports.shutdown = async () => {
|
||||
export async function shutdown() {
|
||||
if (pwResetClient) await pwResetClient.finish()
|
||||
if (invitationClient) await invitationClient.finish()
|
||||
console.log("Redis shutdown")
|
||||
|
@ -65,8 +64,8 @@ exports.shutdown = async () => {
|
|||
* @param {object} info Info about the user/the reset process.
|
||||
* @return {Promise<string>} returns the code that was stored to redis.
|
||||
*/
|
||||
exports.getResetPasswordCode = async (userId, info) => {
|
||||
return writeACode(utils.Databases.PW_RESETS, { userId, info })
|
||||
export async function getResetPasswordCode(userId: string, info: any) {
|
||||
return writeACode(redis.utils.Databases.PW_RESETS, { userId, info })
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,9 +74,12 @@ exports.getResetPasswordCode = async (userId, info) => {
|
|||
* @param {boolean} deleteCode If the code is used/finished with this will delete it - defaults to true.
|
||||
* @return {Promise<string>} returns the user ID if it is found
|
||||
*/
|
||||
exports.checkResetPasswordCode = async (resetCode, deleteCode = true) => {
|
||||
export async function checkResetPasswordCode(
|
||||
resetCode: string,
|
||||
deleteCode = true
|
||||
) {
|
||||
try {
|
||||
return getACode(utils.Databases.PW_RESETS, resetCode, deleteCode)
|
||||
return getACode(redis.utils.Databases.PW_RESETS, resetCode, deleteCode)
|
||||
} catch (err) {
|
||||
throw "Provided information is not valid, cannot reset password - please try again."
|
||||
}
|
||||
|
@ -89,8 +91,8 @@ exports.checkResetPasswordCode = async (resetCode, deleteCode = true) => {
|
|||
* @param {object|null} info Information to be carried along with the invitation.
|
||||
* @return {Promise<string>} returns the code that was stored to redis.
|
||||
*/
|
||||
exports.getInviteCode = async (email, info) => {
|
||||
return writeACode(utils.Databases.INVITATIONS, { email, info })
|
||||
export async function getInviteCode(email: string, info: any) {
|
||||
return writeACode(redis.utils.Databases.INVITATIONS, { email, info })
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,9 +101,12 @@ exports.getInviteCode = async (email, info) => {
|
|||
* @param {boolean} deleteCode whether or not the code should be deleted after retrieval - defaults to true.
|
||||
* @return {Promise<object>} If the code is valid then an email address will be returned.
|
||||
*/
|
||||
exports.checkInviteCode = async (inviteCode, deleteCode = true) => {
|
||||
export async function checkInviteCode(
|
||||
inviteCode: string,
|
||||
deleteCode: boolean = true
|
||||
) {
|
||||
try {
|
||||
return getACode(utils.Databases.INVITATIONS, inviteCode, deleteCode)
|
||||
return getACode(redis.utils.Databases.INVITATIONS, inviteCode, deleteCode)
|
||||
} catch (err) {
|
||||
throw "Invitation is not valid or has expired, please request a new one."
|
||||
}
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
const { getScopedConfig } = require("@budibase/backend-core/db")
|
||||
const {
|
||||
import { db as dbCore, tenancy } from "@budibase/backend-core"
|
||||
import {
|
||||
Config,
|
||||
InternalTemplateBindings,
|
||||
InternalTemplateBinding,
|
||||
LOGO_URL,
|
||||
EmailTemplatePurpose,
|
||||
} = require("../constants")
|
||||
const { checkSlashesInUrl } = require("./index")
|
||||
const {
|
||||
getGlobalDB,
|
||||
addTenantToUrl,
|
||||
} = require("@budibase/backend-core/tenancy")
|
||||
} from "../constants"
|
||||
import { checkSlashesInUrl } from "./index"
|
||||
const BASE_COMPANY = "Budibase"
|
||||
|
||||
exports.getSettingsTemplateContext = async (purpose, code = null) => {
|
||||
const db = getGlobalDB()
|
||||
export async function getSettingsTemplateContext(
|
||||
purpose: EmailTemplatePurpose,
|
||||
code?: string
|
||||
) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
// TODO: use more granular settings in the future if required
|
||||
let settings = (await getScopedConfig(db, { type: Config.SETTINGS })) || {}
|
||||
let settings =
|
||||
(await dbCore.getScopedConfig(db, { type: Config.SETTINGS })) || {}
|
||||
const URL = settings.platformUrl
|
||||
const context = {
|
||||
[InternalTemplateBindings.LOGO_URL]:
|
||||
const context: any = {
|
||||
[InternalTemplateBinding.LOGO_URL]:
|
||||
checkSlashesInUrl(`${URL}/${settings.logoUrl}`) || LOGO_URL,
|
||||
[InternalTemplateBindings.PLATFORM_URL]: URL,
|
||||
[InternalTemplateBindings.COMPANY]: settings.company || BASE_COMPANY,
|
||||
[InternalTemplateBindings.DOCS_URL]:
|
||||
[InternalTemplateBinding.PLATFORM_URL]: URL,
|
||||
[InternalTemplateBinding.COMPANY]: settings.company || BASE_COMPANY,
|
||||
[InternalTemplateBinding.DOCS_URL]:
|
||||
settings.docsUrl || "https://docs.budibase.com/",
|
||||
[InternalTemplateBindings.LOGIN_URL]: checkSlashesInUrl(
|
||||
addTenantToUrl(`${URL}/login`)
|
||||
[InternalTemplateBinding.LOGIN_URL]: checkSlashesInUrl(
|
||||
tenancy.addTenantToUrl(`${URL}/login`)
|
||||
),
|
||||
[InternalTemplateBindings.CURRENT_DATE]: new Date().toISOString(),
|
||||
[InternalTemplateBindings.CURRENT_YEAR]: new Date().getFullYear(),
|
||||
[InternalTemplateBinding.CURRENT_DATE]: new Date().toISOString(),
|
||||
[InternalTemplateBinding.CURRENT_YEAR]: new Date().getFullYear(),
|
||||
}
|
||||
// attach purpose specific context
|
||||
switch (purpose) {
|
||||
case EmailTemplatePurpose.PASSWORD_RECOVERY:
|
||||
context[InternalTemplateBindings.RESET_CODE] = code
|
||||
context[InternalTemplateBindings.RESET_URL] = checkSlashesInUrl(
|
||||
addTenantToUrl(`${URL}/builder/auth/reset?code=${code}`)
|
||||
context[InternalTemplateBinding.RESET_CODE] = code
|
||||
context[InternalTemplateBinding.RESET_URL] = checkSlashesInUrl(
|
||||
tenancy.addTenantToUrl(`${URL}/builder/auth/reset?code=${code}`)
|
||||
)
|
||||
break
|
||||
case EmailTemplatePurpose.INVITATION:
|
||||
context[InternalTemplateBindings.INVITE_CODE] = code
|
||||
context[InternalTemplateBindings.INVITE_URL] = checkSlashesInUrl(
|
||||
addTenantToUrl(`${URL}/builder/invite?code=${code}`)
|
||||
context[InternalTemplateBinding.INVITE_CODE] = code
|
||||
context[InternalTemplateBinding.INVITE_URL] = checkSlashesInUrl(
|
||||
tenancy.addTenantToUrl(`${URL}/builder/invite?code=${code}`)
|
||||
)
|
||||
break
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue