feat: mock-email and some fixes for email auth

This commit is contained in:
Rafael Taranto 2023-11-28 19:01:35 +00:00
parent ab304093f3
commit c173f241eb
10 changed files with 97 additions and 26 deletions

View file

@ -3,7 +3,7 @@ const ph = require('./plugin-helper')
function sendMessage (settings, rec) { function sendMessage (settings, rec) {
return Promise.resolve() return Promise.resolve()
.then(() => { .then(() => {
const pluginCode = 'mailgun' const pluginCode = settings.config.notifications_thirdParty_email
const plugin = ph.load(ph.EMAIL, pluginCode) const plugin = ph.load(ph.EMAIL, pluginCode)
const account = settings.accounts[pluginCode] const account = settings.accounts[pluginCode]
@ -11,4 +11,15 @@ function sendMessage (settings, rec) {
}) })
} }
module.exports = {sendMessage} function sendCustomerMessage (settings, rec) {
return Promise.resolve()
.then(() => {
const pluginCode = settings.config.notifications_thirdParty_email
const plugin = ph.load(ph.EMAIL, pluginCode)
const account = settings.accounts[pluginCode]
return plugin.sendMessage(account, rec)
})
}
module.exports = {sendMessage, sendCustomerMessage}

View file

@ -53,6 +53,7 @@ const ALL_ACCOUNTS = [
{ code: 'telnyx', display: 'Telnyx', class: SMS }, { code: 'telnyx', display: 'Telnyx', class: SMS },
{ code: 'vonage', display: 'Vonage', class: SMS }, { code: 'vonage', display: 'Vonage', class: SMS },
{ code: 'mailgun', display: 'Mailgun', class: EMAIL }, { code: 'mailgun', display: 'Mailgun', class: EMAIL },
{ code: 'mock-email', display: 'Mock Email', class: EMAIL, dev: true },
{ code: 'none', display: 'None', class: ZERO_CONF, cryptos: ALL_CRYPTOS }, { code: 'none', display: 'None', class: ZERO_CONF, cryptos: ALL_CRYPTOS },
{ code: 'blockcypher', display: 'Blockcypher', class: ZERO_CONF, cryptos: [BTC] }, { code: 'blockcypher', display: 'Blockcypher', class: ZERO_CONF, cryptos: [BTC] },
{ code: 'mock-zero-conf', display: 'Mock 0-conf', class: ZERO_CONF, cryptos: ALL_CRYPTOS, dev: true }, { code: 'mock-zero-conf', display: 'Mock 0-conf', class: ZERO_CONF, cryptos: ALL_CRYPTOS, dev: true },

View file

@ -763,7 +763,7 @@ function plugins (settings, deviceId) {
function getPhoneCode (phone) { function getPhoneCode (phone) {
const notifications = configManager.getNotifications(settings.config) const notifications = configManager.getNotifications(settings.config)
const code = notifications.thirdParty_sms === 'mock-sms' const code = settings.config.notifications_thirdParty_sms === 'mock-sms'
? '123' ? '123'
: randomCode() : randomCode()
@ -780,13 +780,11 @@ function plugins (settings, deviceId) {
} }
function getEmailCode (toEmail) { function getEmailCode (toEmail) {
const notifications = configManager.getNotifications(settings.config) const code = settings.config.notifications_thirdParty_email === 'mock-email'
const code = notifications.thirdParty_email === 'mock-email'
? '123' ? '123'
: randomCode() : randomCode()
const req = { const rec = {
email: { email: {
toEmail, toEmail,
subject: 'Your cryptomat code', subject: 'Your cryptomat code',
@ -794,10 +792,8 @@ function plugins (settings, deviceId) {
} }
} }
console.log(code) return email.sendCustomerMessage(settings, rec)
return Promise.resolve(code) .then(() => code)
// return sms.sendMessage(settings, rec)
// .then(() => code)
} }
function sweepHdRow (row) { function sweepHdRow (row) {

View file

@ -16,7 +16,22 @@ function sendMessage ({apiKey, domain, fromEmail, toEmail}, rec) {
return mailgun.messages().send(emailData) return mailgun.messages().send(emailData)
} }
function sendCustomerMessage ({apiKey, domain, fromEmail}, rec) {
const mailgun = Mailgun({apiKey, domain})
const to = req.email.toEmail
const emailData = {
from: fromEmail,
to,
subject: rec.email.subject,
text: rec.email.body
}
return mailgun.messages().send(emailData)
}
module.exports = { module.exports = {
NAME, NAME,
sendMessage sendMessage,
sendCustomerMessage
} }

View file

@ -0,0 +1,15 @@
const NAME = 'mock-email'
function sendMessage (settings, rec) {
console.log('sending email', rec)
}
function sendCustomerMessage(settings, rec) {
console.log('sending email', rec)
}
module.exports = {
NAME,
sendMessage,
sendCustomerMessage
}

View file

@ -31,7 +31,8 @@ const ThirdPartyProvider = () => {
} }
const ThirdPartySchema = Yup.object().shape({ const ThirdPartySchema = Yup.object().shape({
sms: Yup.string('The sms must be a string').required('The sms is required') sms: Yup.string('SMS must be a string').required('SMS is required'),
email: Yup.string('Email must be a string').required('Email is required')
}) })
const elements = [ const elements = [
@ -46,14 +47,30 @@ const ThirdPartyProvider = () => {
valueProp: 'code', valueProp: 'code',
labelProp: 'display' labelProp: 'display'
} }
},
{
name: 'email',
size: 'sm',
view: getDisplayName('email'),
width: 175,
input: Autocomplete,
inputProps: {
options: filterOptions('email'),
valueProp: 'code',
labelProp: 'display'
}
} }
] ]
const values = {
sms: data.sms ?? 'twilio',
email: data.email ?? 'mailgun'
}
return ( return (
<EditableTable <EditableTable
name="thirdParty" name="thirdParty"
initialValues={{ sms: data.sms ?? 'twilio' }} initialValues={values}
data={R.of({ sms: data.sms ?? 'twilio' })} data={R.of(values)}
error={error?.message} error={error?.message}
enableEdit enableEdit
editWidth={174} editWidth={174}

View file

@ -28,7 +28,8 @@ const TriggerView = ({
config, config,
toggleWizard, toggleWizard,
addNewTriger, addNewTriger,
customInfoRequests customInfoRequests,
emailAuth
}) => { }) => {
const currency = R.path(['fiatCurrency'])( const currency = R.path(['fiatCurrency'])(
fromNamespace(namespaces.LOCALE)(config) fromNamespace(namespaces.LOCALE)(config)
@ -77,6 +78,7 @@ const TriggerView = ({
save={add} save={add}
onClose={() => toggleWizard(true)} onClose={() => toggleWizard(true)}
customInfoRequests={customInfoRequests} customInfoRequests={customInfoRequests}
emailAuth={emailAuth}
/> />
)} )}
{R.isEmpty(triggers) && ( {R.isEmpty(triggers) && (

View file

@ -58,7 +58,7 @@ const GET_CUSTOM_REQUESTS = gql`
const Triggers = () => { const Triggers = () => {
const classes = useStyles() const classes = useStyles()
const [wizardType, setWizard] = useState(false) const [wizardType, setWizard] = useState(false)
const { data, loading: configLoading } = useQuery(GET_CONFIG) const { data, loading: configLoading, refetch } = useQuery(GET_CONFIG)
const { data: customInfoReqData, loading: customInfoLoading } = useQuery( const { data: customInfoReqData, loading: customInfoLoading } = useQuery(
GET_CUSTOM_REQUESTS GET_CUSTOM_REQUESTS
) )
@ -72,6 +72,8 @@ const Triggers = () => {
const enabledCustomInfoRequests = R.filter(R.propEq('enabled', true))( const enabledCustomInfoRequests = R.filter(R.propEq('enabled', true))(
customInfoRequests customInfoRequests
) )
const emailAuth =
data?.config?.triggersConfig_customerAuthentication === 'EMAIL'
const triggers = fromServer(data?.config?.triggers ?? []) const triggers = fromServer(data?.config?.triggers ?? [])
const complianceConfig = const complianceConfig =
@ -141,6 +143,7 @@ const Triggers = () => {
inverseIcon: ReverseSettingsIcon, inverseIcon: ReverseSettingsIcon,
forceDisable: !(subMenu === 'advancedSettings'), forceDisable: !(subMenu === 'advancedSettings'),
toggle: show => { toggle: show => {
refetch()
setSubMenu(show ? 'advancedSettings' : false) setSubMenu(show ? 'advancedSettings' : false)
} }
}, },
@ -150,6 +153,7 @@ const Triggers = () => {
inverseIcon: ReverseCustomInfoIcon, inverseIcon: ReverseCustomInfoIcon,
forceDisable: !(subMenu === 'customInfoRequests'), forceDisable: !(subMenu === 'customInfoRequests'),
toggle: show => { toggle: show => {
refetch()
setSubMenu(show ? 'customInfoRequests' : false) setSubMenu(show ? 'customInfoRequests' : false)
} }
} }
@ -216,6 +220,7 @@ const Triggers = () => {
toggleWizard={toggleWizard('newTrigger')} toggleWizard={toggleWizard('newTrigger')}
addNewTriger={addNewTriger} addNewTriger={addNewTriger}
customInfoRequests={enabledCustomInfoRequests} customInfoRequests={enabledCustomInfoRequests}
emailAuth={emailAuth}
/> />
)} )}
{!loading && subMenu === 'advancedSettings' && ( {!loading && subMenu === 'advancedSettings' && (

View file

@ -48,14 +48,14 @@ const styles = {
const useStyles = makeStyles(styles) const useStyles = makeStyles(styles)
const getStep = (step, currency, customInfoRequests) => { const getStep = (step, currency, customInfoRequests, emailAuth) => {
switch (step) { switch (step) {
// case 1: // case 1:
// return txDirection // return txDirection
case 1: case 1:
return type(currency) return type(currency)
case 2: case 2:
return requirements(customInfoRequests) return requirements(customInfoRequests, emailAuth)
default: default:
return Fragment return Fragment
} }
@ -204,7 +204,14 @@ const GetValues = ({ setValues }) => {
return null return null
} }
const Wizard = ({ onClose, save, error, currency, customInfoRequests }) => { const Wizard = ({
onClose,
save,
error,
currency,
customInfoRequests,
emailAuth
}) => {
const classes = useStyles() const classes = useStyles()
const [liveValues, setLiveValues] = useState({}) const [liveValues, setLiveValues] = useState({})
@ -213,7 +220,7 @@ const Wizard = ({ onClose, save, error, currency, customInfoRequests }) => {
}) })
const isLastStep = step === LAST_STEP const isLastStep = step === LAST_STEP
const stepOptions = getStep(step, currency, customInfoRequests) const stepOptions = getStep(step, currency, customInfoRequests, emailAuth)
const onContinue = async it => { const onContinue = async it => {
const newConfig = R.merge(config, stepOptions.schema.cast(it)) const newConfig = R.merge(config, stepOptions.schema.cast(it))

View file

@ -545,7 +545,7 @@ const hasCustomRequirementError = (errors, touched, values) =>
(!values.requirement?.customInfoRequestId || (!values.requirement?.customInfoRequestId ||
!R.isNil(values.requirement?.customInfoRequestId)) !R.isNil(values.requirement?.customInfoRequestId))
const Requirement = ({ customInfoRequests }) => { const Requirement = ({ customInfoRequests, emailAuth }) => {
const classes = useStyles() const classes = useStyles()
const { const {
touched, touched,
@ -568,9 +568,11 @@ const Requirement = ({ customInfoRequests }) => {
display: 'Custom information requirement', display: 'Custom information requirement',
code: 'custom' code: 'custom'
} }
const itemToRemove = emailAuth ? 'sms' : 'email'
const reqOptions = requirementOptions.filter(it => it.code !== itemToRemove)
const options = enableCustomRequirement const options = enableCustomRequirement
? [...requirementOptions, customInfoOption] ? [...reqOptions, customInfoOption]
: [...requirementOptions] : [...reqOptions]
const titleClass = { const titleClass = {
[classes.error]: [classes.error]:
(!!errors.requirement && !isSuspend && !isCustom) || (!!errors.requirement && !isSuspend && !isCustom) ||
@ -622,11 +624,11 @@ const Requirement = ({ customInfoRequests }) => {
) )
} }
const requirements = customInfoRequests => ({ const requirements = (customInfoRequests, emailAuth) => ({
schema: requirementSchema, schema: requirementSchema,
options: requirementOptions, options: requirementOptions,
Component: Requirement, Component: Requirement,
props: { customInfoRequests }, props: { customInfoRequests, emailAuth },
hasRequirementError: hasRequirementError, hasRequirementError: hasRequirementError,
hasCustomRequirementError: hasCustomRequirementError, hasCustomRequirementError: hasCustomRequirementError,
initialValues: { initialValues: {