2018-12-17 14:53:45 +03:00
|
|
|
const url = require('url');
|
2018-12-11 10:57:01 +03:00
|
|
|
const settingsCache = require('../settings/cache');
|
|
|
|
const config = require('../../config');
|
|
|
|
const MembersApi = require('../../lib/members');
|
2019-02-26 06:09:16 +03:00
|
|
|
const common = require('../../lib/common');
|
2018-12-11 10:57:01 +03:00
|
|
|
const models = require('../../models');
|
|
|
|
const mail = require('../mail');
|
2019-02-26 06:09:16 +03:00
|
|
|
const blogIcon = require('../../lib/image/blog-icon');
|
2018-12-11 10:57:01 +03:00
|
|
|
|
|
|
|
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();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-01-30 14:36:09 +03:00
|
|
|
function getMember(data, options) {
|
|
|
|
options = options || {};
|
|
|
|
return models.Member.findOne(data, options).then((model) => {
|
|
|
|
if (!model) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return model.toJSON(options);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-04-13 08:08:56 +03:00
|
|
|
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'
|
|
|
|
})
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-01-30 14:36:09 +03:00
|
|
|
function listMembers(options) {
|
|
|
|
return models.Member.findPage(options).then((models) => {
|
|
|
|
return {
|
|
|
|
members: models.data.map(model => model.toJSON(options)),
|
|
|
|
meta: models.meta
|
|
|
|
};
|
2018-12-11 10:57:01 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-02-26 06:09:16 +03:00
|
|
|
function parseMembersSettings() {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-12-11 10:57:01 +03:00
|
|
|
const publicKey = settingsCache.get('members_public_key');
|
|
|
|
const privateKey = settingsCache.get('members_private_key');
|
|
|
|
const sessionSecret = settingsCache.get('members_session_secret');
|
|
|
|
const passwordResetUrl = config.get('url');
|
2018-12-17 14:53:45 +03:00
|
|
|
const {protocol, host} = url.parse(config.get('url'));
|
|
|
|
const siteOrigin = `${protocol}//${host}`;
|
2018-12-11 15:45:03 +03:00
|
|
|
const issuer = siteOrigin;
|
|
|
|
const ssoOrigin = siteOrigin;
|
2018-12-11 10:57:01 +03:00
|
|
|
let mailer;
|
|
|
|
|
2019-02-07 12:41:39 +03:00
|
|
|
const membersConfig = config.get('members');
|
2019-02-26 06:09:16 +03:00
|
|
|
const membersSettings = parseMembersSettings();
|
2019-02-07 12:41:39 +03:00
|
|
|
|
2019-02-23 06:47:42 +03:00
|
|
|
function validateAudience({audience, origin}) {
|
|
|
|
if (audience === origin) {
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
if (audience === siteOrigin) {
|
|
|
|
if (membersConfig.contentApiAccess.includes(origin)) {
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Promise.reject();
|
|
|
|
}
|
|
|
|
|
2018-12-11 10:57:01 +03:00
|
|
|
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:
|
|
|
|
|
|
|
|
${passwordResetUrl}#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);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-02-26 06:09:16 +03:00
|
|
|
const defaultBlogTitle = settingsCache.get('title') ? settingsCache.get('title').replace(/"/g, '\\"') : 'Publication';
|
|
|
|
const blogIconUrl = blogIcon.getIconUrl();
|
2018-12-11 10:57:01 +03:00
|
|
|
const api = MembersApi({
|
2019-02-07 12:41:39 +03:00
|
|
|
authConfig: {
|
2018-12-11 10:57:01 +03:00
|
|
|
issuer,
|
|
|
|
publicKey,
|
|
|
|
privateKey,
|
|
|
|
sessionSecret,
|
|
|
|
ssoOrigin
|
|
|
|
},
|
2019-02-07 12:41:39 +03:00
|
|
|
paymentConfig: {
|
2019-02-26 06:09:16 +03:00
|
|
|
processors: membersSettings.paymentProcessors
|
|
|
|
},
|
|
|
|
siteConfig: {
|
|
|
|
title: defaultBlogTitle,
|
|
|
|
icon: blogIconUrl
|
2019-02-07 12:41:39 +03:00
|
|
|
},
|
2018-12-11 10:57:01 +03:00
|
|
|
validateAudience,
|
|
|
|
createMember,
|
|
|
|
getMember,
|
2019-04-13 08:08:56 +03:00
|
|
|
deleteMember,
|
2019-01-30 14:36:09 +03:00
|
|
|
listMembers,
|
2018-12-11 10:57:01 +03:00
|
|
|
validateMember,
|
|
|
|
updateMember,
|
|
|
|
sendEmail
|
|
|
|
});
|
|
|
|
|
2019-02-26 06:09:16 +03:00
|
|
|
const updateSettingFromModel = function updateSettingFromModel(settingModel) {
|
|
|
|
if (settingModel.get('key') === 'members_subscription_settings'
|
|
|
|
|| settingModel.get('key') === 'title'
|
|
|
|
|| settingModel.get('key') === 'icon') {
|
|
|
|
let membersSettings = parseMembersSettings();
|
|
|
|
const defaultBlogTitle = settingsCache.get('title') ? settingsCache.get('title').replace(/"/g, '\\"') : 'Publication';
|
|
|
|
const blogIconUrl = blogIcon.getIconUrl();
|
|
|
|
api.reconfigureSettings({
|
|
|
|
paymentConfig: {
|
|
|
|
processors: membersSettings.paymentProcessors
|
|
|
|
},
|
|
|
|
siteConfig: {
|
|
|
|
title: defaultBlogTitle,
|
|
|
|
icon: blogIconUrl
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Bind to events to automatically keep subscription info up-to-date from settings
|
|
|
|
common.events.on('settings.edited', updateSettingFromModel);
|
|
|
|
|
2018-12-11 10:57:01 +03:00
|
|
|
module.exports = api;
|
|
|
|
module.exports.publicKey = publicKey;
|
2019-02-26 06:09:16 +03:00
|
|
|
module.exports.isPaymentConfigured = function () {
|
|
|
|
let membersSettings = parseMembersSettings();
|
|
|
|
return !!membersSettings.paymentProcessors.length;
|
|
|
|
};
|