@bitblit/ratchet-warden-server
Version:
Typescript library to simplify using simplewebauthn and secondary auth methods over GraphQL
104 lines • 5.44 kB
JavaScript
import { Logger } from '@bitblit/ratchet-common/logger/logger';
import { ErrorRatchet } from '@bitblit/ratchet-common/lang/error-ratchet';
import { StringRatchet } from '@bitblit/ratchet-common/lang/string-ratchet';
import { Base64Ratchet } from '@bitblit/ratchet-common/lang/base64-ratchet';
import { WardenContactType } from '@bitblit/ratchet-warden-common/common/model/warden-contact-type';
import { WardenCustomerMessageType } from '@bitblit/ratchet-warden-common/common/model/warden-customer-message-type';
export class WardenMailerAndExpiringCodeRatchetSingleUseCodeProvider {
mailer;
expiringCodeRatchet;
mailerOptions;
static defaultOptions() {
const rval = {
emailBaseLayoutName: undefined,
expiringTokenHtmlTemplateName: 'expiring-token-request-email',
expiringTokenTxtTemplateName: undefined,
magicLinkHtmlTemplateName: 'magic-token-request-email',
magicLinkTxtTemplateName: undefined,
};
return rval;
}
constructor(mailer, expiringCodeRatchet, mailerOptions = WardenMailerAndExpiringCodeRatchetSingleUseCodeProvider.defaultOptions()) {
this.mailer = mailer;
this.expiringCodeRatchet = expiringCodeRatchet;
this.mailerOptions = mailerOptions;
}
handlesContactType(type) {
return type === WardenContactType.EmailAddress;
}
async createAndSendNewCode(contact, relyingPartyName, origin) {
let rval = null;
const token = await this.expiringCodeRatchet.createNewCode({
context: contact.value,
length: 6,
alphabet: '0123456789',
timeToLiveSeconds: 300,
tags: ['Login'],
});
const msg = await this.formatMessage(contact, WardenCustomerMessageType.ExpiringCode, {
requestor: contact.value,
requestorB64: Base64Ratchet.encodeStringToBase64String(contact.value),
code: token.code,
relyingPartyName: relyingPartyName,
origin: origin
});
rval = await this.sendMessage(msg);
return rval;
}
async checkCode(contactValue, code) {
const rval = await this.expiringCodeRatchet.checkCode(code, contactValue);
return rval;
}
async createCodeAndSendMagicLink(loginContact, relyingPartyName, landingUrl, metaIn, ttlSeconds, destinationContact, customTemplate) {
let rval = null;
const token = await this.expiringCodeRatchet.createNewCode({
context: loginContact.value,
length: 36,
alphabet: StringRatchet.UPPER_CASE_LATIN,
timeToLiveSeconds: ttlSeconds,
tags: ['MagicLink'],
});
const meta = Object.assign({}, metaIn || {}, { contact: loginContact });
const encodedMeta = Base64Ratchet.safeObjectToBase64JSON(meta || {});
const landingUrlFilled = StringRatchet.simpleTemplateFill(landingUrl, { CODE: token.code, META: encodedMeta }, true, '{', '}');
const context = Object.assign({}, meta || {}, {
landingUrl: landingUrlFilled,
code: token.code,
relyingPartyName: relyingPartyName,
});
const msgType = customTemplate ? WardenCustomerMessageType.Custom : WardenCustomerMessageType.MagicLink;
const msg = await this.formatMessage(loginContact, msgType, context, destinationContact, customTemplate);
rval = await this.sendMessage(msg);
return rval;
}
async formatMessage(contact, messageType, context, destinationContact, customTemplate) {
const rts = {
destinationAddresses: [destinationContact?.value || contact.value],
subject: customTemplate?.subjectLine || this.mailerOptions.magicLinkSubjectLine || 'Login token for ' + contact.value,
};
Logger.info('Formatting Message for magic link, rts: %j, messageType: %s, context: %j', rts, messageType, context);
if (messageType === WardenCustomerMessageType.ExpiringCode) {
await this.mailer.fillEmailBody(rts, context, this.mailerOptions.expiringTokenHtmlTemplateName, this.mailerOptions.expiringTokenTxtTemplateName, this.mailerOptions.emailBaseLayoutName);
}
else if (messageType === WardenCustomerMessageType.MagicLink) {
await this.mailer.fillEmailBody(rts, context, this.mailerOptions.magicLinkHtmlTemplateName, this.mailerOptions.magicLinkTxtTemplateName, this.mailerOptions.emailBaseLayoutName);
}
else if (messageType === WardenCustomerMessageType.Custom) {
if (!customTemplate) {
throw ErrorRatchet.fErr('Cannot send custom message if customTemplate not set');
}
Logger.info('Sending custom template : %j', customTemplate);
await this.mailer.fillEmailBody(rts, context, customTemplate.htmlVersion, customTemplate.textVersion, customTemplate.baseLayout === 'DEFAULT' ? this.mailerOptions.emailBaseLayoutName : customTemplate.baseLayout);
}
else {
throw ErrorRatchet.fErr('No such message type : %s', messageType);
}
return rts;
}
async sendMessage(message) {
const rval = await this.mailer.sendEmail(message);
Logger.debug('SendRawEmailResponse was : %j', rval);
return !!rval;
}
}
//# sourceMappingURL=warden-mailer-and-expiring-code-ratchet-single-use-code-provider.js.map