Ghost/core/server/services/members/settings.js
Hannah Wolfe bd597db829
Moved settings/cache to shared/settings-cache
- This is part of the quest to separate the frontend and server & get rid of all the places where there are cross-requires
- At the moment the settings cache is one big shared cache used by the frontend and server liberally
- This change doesn't really solve the fundamental problems, as we still depend on events, and requires from inside frontend
- However it allows us to control the misuse slightly better by getting rid of restricted requires and turning on that eslint ruleset
2021-06-30 15:49:10 +01:00

117 lines
3.9 KiB
JavaScript

const MagicLink = require('@tryghost/magic-link');
const {URL} = require('url');
const path = require('path');
const urlUtils = require('../../../shared/url-utils');
const settingsCache = require('../../../shared/settings-cache');
const logging = require('@tryghost/logging');
const mail = require('../mail');
const updateEmailTemplate = require('./emails/updateEmail');
const SingleUseTokenProvider = require('./SingleUseTokenProvider');
const models = require('../../models');
const MAGIC_LINK_TOKEN_VALIDITY = 24 * 60 * 60 * 1000;
const ghostMailer = new mail.GhostMailer();
function createSettingsInstance(config) {
const {transporter, getSubject, getText, getHTML, getSigninURL} = {
transporter: {
sendMail(message) {
if (process.env.NODE_ENV !== 'production') {
logging.warn(message.text);
}
let msg = Object.assign({
from: config.getAuthEmailFromAddress(),
subject: 'Update email address',
forceTextContent: true
}, message);
return ghostMailer.send(msg);
}
},
getSubject() {
return `Confirm your email address`;
},
getText(url, type, email) {
return `
Hey there,
Please confirm your email address with this link:
${url}
For your security, the link will expire in 24 hours time.
---
Sent to ${email}
If you did not make this request, you can simply delete this message. This email address will not be used.
`;
},
getHTML(url, type, email) {
const siteTitle = settingsCache.get('title');
return updateEmailTemplate({url, email, siteTitle});
},
getSigninURL(token, type) {
const signinURL = new URL(getApiUrl({version: 'v4', type: 'admin'}));
signinURL.pathname = path.join(signinURL.pathname, '/settings/members/email/');
signinURL.searchParams.set('token', token);
signinURL.searchParams.set('action', type);
return signinURL.href;
}
};
const getApiUrl = ({version, type}) => {
return urlUtils.urlFor('api', {version: version, versionType: type}, true);
};
const magicLinkService = new MagicLink({
transporter,
tokenProvider: new SingleUseTokenProvider(models.SingleUseToken, MAGIC_LINK_TOKEN_VALIDITY),
getSigninURL,
getText,
getHTML,
getSubject
});
const sendEmailAddressUpdateMagicLink = ({email, type = 'fromAddressUpdate'}) => {
const [,toDomain] = email.split('@');
let fromEmail = `noreply@${toDomain}`;
if (fromEmail === email) {
fromEmail = `no-reply@${toDomain}`;
}
magicLinkService.transporter = {
sendMail(message) {
if (process.env.NODE_ENV !== 'production') {
logging.warn(message.text);
}
let msg = Object.assign({
from: fromEmail,
subject: 'Update email address',
forceTextContent: true
}, message);
return ghostMailer.send(msg);
}
};
return magicLinkService.sendMagicLink({email, tokenData: {email}, subject: email, type});
};
const getEmailFromToken = async ({token}) => {
const data = await magicLinkService.getDataFromToken(token);
return data.email;
};
const getAdminRedirectLink = ({type}) => {
const adminUrl = urlUtils.urlFor('admin', true);
return urlUtils.urlJoin(adminUrl, `#/settings/members-email/?${type}=success`);
};
return {
sendEmailAddressUpdateMagicLink,
getEmailFromToken,
getAdminRedirectLink
};
}
module.exports = createSettingsInstance;