mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-30 06:12:03 +03:00
177411045a
* Installed @tryghost/members-api@0.2.0 refs #10886 This will allow us to mount one router rather than having a static and api router. * Added members v2 api directory refs #10886 This brings the members api more inline with how the rest of the apis work within Ghost. * Mounted the members api app to the api route closes #10886 This successfully mounts the api and the static pages to the /api/v2/members/ URL. * Installed @tryghost/members-auth-pages@1.0.0 refs #10886 This updates the auth pages to work correctly with the new mount point. * Changed membersUrl in members.js to use members api refs #10886 This keeps the membersUrl lined up with the path for the static members pages. * Removed old members static mount point refs #10886 These are no longer used, nor desired. * Remove superfluous code from members service refs #10886 This remove the gateway getter which is no longer used, and the fallback for members not enabled - which is handled within the members app. * Updated ssoOrigin to use admin url refs #10886 This ensures that sites running on a separate admin domain have the correct ssoOrigin, which is used to ensure only the designated auth pages are used to hit the authentication endpoints. Since the auth pages are now hosted under the `/ghost` url, they will be on the admin origin and not the site origin
232 lines
6.5 KiB
JavaScript
232 lines
6.5 KiB
JavaScript
const url = require('url');
|
|
const settingsCache = require('../settings/cache');
|
|
const urlUtils = require('../../lib/url-utils');
|
|
const MembersApi = require('@tryghost/members-api');
|
|
const MembersSSR = require('@tryghost/members-ssr');
|
|
const common = require('../../lib/common');
|
|
const models = require('../../models');
|
|
const mail = require('../mail');
|
|
const blogIcon = require('../../lib/image/blog-icon');
|
|
const doBlock = fn => fn();
|
|
|
|
function createMember({name, email, password}) {
|
|
return models.Member.add({
|
|
name,
|
|
email,
|
|
password
|
|
}).then((member) => {
|
|
return member.toJSON();
|
|
});
|
|
}
|
|
|
|
function updateMember(member, newData) {
|
|
return models.Member.findOne(member, {
|
|
require: true
|
|
}).then(({id}) => {
|
|
return models.Member.edit(newData, {id});
|
|
}).then((member) => {
|
|
return member.toJSON();
|
|
});
|
|
}
|
|
|
|
function getMember(data, options = {}) {
|
|
return models.Member.findOne(data, Object.assign({require: true}, options)).then((model) => {
|
|
if (!model) {
|
|
return null;
|
|
}
|
|
return model.toJSON(options);
|
|
});
|
|
}
|
|
|
|
function deleteMember(options) {
|
|
options = options || {};
|
|
return models.Member.destroy(options).catch(models.Member.NotFoundError, () => {
|
|
throw new common.errors.NotFoundError({
|
|
message: common.i18n.t('errors.api.resource.resourceNotFound', {
|
|
resource: 'Member'
|
|
})
|
|
});
|
|
});
|
|
}
|
|
|
|
function listMembers(options) {
|
|
return models.Member.findPage(options).then((models) => {
|
|
return {
|
|
members: models.data.map(model => model.toJSON(options)),
|
|
meta: models.meta
|
|
};
|
|
});
|
|
}
|
|
|
|
function validateMember({email, password}) {
|
|
return models.Member.findOne({email}, {
|
|
require: true
|
|
}).then((member) => {
|
|
return member.comparePassword(password).then((res) => {
|
|
if (!res) {
|
|
throw new Error('Password is incorrect');
|
|
}
|
|
return member;
|
|
});
|
|
}).then((member) => {
|
|
return member.toJSON();
|
|
});
|
|
}
|
|
|
|
function getSubscriptionSettings() {
|
|
let membersSettings = settingsCache.get('members_subscription_settings');
|
|
if (!membersSettings) {
|
|
membersSettings = {
|
|
isPaid: false,
|
|
paymentProcessors: [{
|
|
adapter: 'stripe',
|
|
config: {
|
|
secret_token: '',
|
|
public_token: '',
|
|
product: {
|
|
name: 'Ghost Subscription'
|
|
},
|
|
plans: [
|
|
{
|
|
name: 'Monthly',
|
|
currency: 'usd',
|
|
interval: 'month',
|
|
amount: ''
|
|
},
|
|
{
|
|
name: 'Yearly',
|
|
currency: 'usd',
|
|
interval: 'year',
|
|
amount: ''
|
|
}
|
|
]
|
|
}
|
|
}]
|
|
};
|
|
}
|
|
if (!membersSettings.isPaid) {
|
|
membersSettings.paymentProcessors = [];
|
|
}
|
|
return membersSettings;
|
|
}
|
|
|
|
const siteUrl = urlUtils.getSiteUrl();
|
|
const siteOrigin = doBlock(() => {
|
|
const {protocol, host} = url.parse(siteUrl);
|
|
return `${protocol}//${host}`;
|
|
});
|
|
|
|
const adminOrigin = doBlock(() => {
|
|
const {protocol, host} = url.parse(urlUtils.urlFor('admin', true));
|
|
return `${protocol}//${host}`;
|
|
});
|
|
|
|
const getApiUrl = ({version, type}) => {
|
|
const {href} = new url.URL(
|
|
urlUtils.getApiPath({version, type}),
|
|
urlUtils.urlFor('admin', true)
|
|
);
|
|
return href;
|
|
};
|
|
|
|
const contentApiUrl = getApiUrl({version: 'v2', type: 'content'});
|
|
const membersApiUrl = getApiUrl({version: 'v2', type: 'members'});
|
|
|
|
const accessControl = {
|
|
[siteOrigin]: {
|
|
[contentApiUrl]: {
|
|
tokenLength: '20m'
|
|
},
|
|
[membersApiUrl]: {
|
|
tokenLength: '180d'
|
|
}
|
|
},
|
|
'*': {
|
|
tokenLength: '20m'
|
|
}
|
|
};
|
|
|
|
const sendEmail = (function createSendEmail(mailer) {
|
|
return function sendEmail(member, {token}) {
|
|
if (!(mailer instanceof mail.GhostMailer)) {
|
|
mailer = new mail.GhostMailer();
|
|
}
|
|
const message = {
|
|
to: member.email,
|
|
subject: 'Reset password',
|
|
html: `
|
|
Hi ${member.name},
|
|
|
|
To reset your password, click the following link and follow the instructions:
|
|
|
|
${siteUrl}#reset-password?token=${token}
|
|
|
|
If you didn't request a password change, just ignore this email.
|
|
`
|
|
};
|
|
|
|
/* eslint-disable */
|
|
// @TODO remove this
|
|
console.log(message.html);
|
|
/* eslint-enable */
|
|
return mailer.send(message).catch((err) => {
|
|
return Promise.reject(err);
|
|
});
|
|
};
|
|
})();
|
|
|
|
const getSiteConfig = () => {
|
|
return {
|
|
title: settingsCache.get('title') ? settingsCache.get('title').replace(/"/g, '\\"') : 'Publication',
|
|
icon: blogIcon.getIconUrl()
|
|
};
|
|
};
|
|
|
|
const membersApiInstance = MembersApi({
|
|
authConfig: {
|
|
issuer: membersApiUrl,
|
|
ssoOrigin: adminOrigin,
|
|
publicKey: settingsCache.get('members_public_key'),
|
|
privateKey: settingsCache.get('members_private_key'),
|
|
sessionSecret: settingsCache.get('members_session_secret'),
|
|
accessControl
|
|
},
|
|
paymentConfig: {
|
|
processors: getSubscriptionSettings().paymentProcessors
|
|
},
|
|
siteConfig: getSiteConfig(),
|
|
createMember,
|
|
getMember,
|
|
deleteMember,
|
|
listMembers,
|
|
validateMember,
|
|
updateMember,
|
|
sendEmail
|
|
});
|
|
|
|
const updateSettingFromModel = function updateSettingFromModel(settingModel) {
|
|
if (!['members_subscription_settings', 'title', 'icon'].includes(settingModel.get('key'))) {
|
|
return;
|
|
}
|
|
|
|
membersApiInstance.reconfigureSettings({
|
|
paymentConfig: {
|
|
processors: getSubscriptionSettings().paymentProcessors
|
|
},
|
|
siteConfig: getSiteConfig()
|
|
});
|
|
};
|
|
|
|
// Bind to events to automatically keep subscription info up-to-date from settings
|
|
common.events.on('settings.edited', updateSettingFromModel);
|
|
|
|
module.exports = membersApiInstance;
|
|
module.exports.ssr = MembersSSR({
|
|
cookieSecure: urlUtils.isSSL(siteUrl),
|
|
cookieKeys: [settingsCache.get('theme_session_secret')],
|
|
membersApi: membersApiInstance
|
|
});
|
|
module.exports.isPaymentConfigured = function () {
|
|
return getSubscriptionSettings().paymentProcessors.length !== 0;
|
|
};
|