From 789462aa5ff917bebac8d9f0ab4d357209c8f3f8 Mon Sep 17 00:00:00 2001 From: Rishabh Garg Date: Wed, 12 Feb 2020 16:42:49 +0530 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Added=20labels=20to=20member=20sign?= =?UTF-8?q?up=20flow=20(#124)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no issue refs https://github.com/TryGhost/Ghost/pull/11538 --- ghost/magic-link/index.js | 19 ++++++++++++++++++- ghost/members-api/index.js | 22 ++++++++++++++-------- ghost/members-api/lib/users.js | 16 ++++++++++++++-- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/ghost/magic-link/index.js b/ghost/magic-link/index.js index 68321f8fd1..350b8501d6 100644 --- a/ghost/magic-link/index.js +++ b/ghost/magic-link/index.js @@ -83,12 +83,14 @@ function MagicLink(options) { * * @param {object} options * @param {string} options.email - The email to send magic link to + * @param {string} options.payload - The payload for token * @param {object} options.subject - The subject to associate with the magic link (user id, or email) * @param {string=} [options.type='signin'] - The type to be passed to the url and content generator functions * @returns {Promise<{token: JSONWebToken, info: SentMessageInfo}>} */ MagicLink.prototype.sendMagicLink = async function sendMagicLink(options) { - const token = jwt.sign({}, this.secret, { + const payload = options.payload || {}; + const token = jwt.sign(payload, this.secret, { algorithm: 'HS256', subject: options.subject, expiresIn: '10m' @@ -141,3 +143,18 @@ MagicLink.prototype.getUserFromToken = function getUserFromToken(token) { }); return claims.sub; }; + +/** + * getPayloadFromToken + * + * @param {JSONWebToken} token - The token to decode + * @returns {object} payload - The payload object associated with the magic link + */ +MagicLink.prototype.getPayloadFromToken = function getPayloadFromToken(token) { + /** @type {object} */ + const claims = jwt.verify(token, this.secret, { + algorithms: ['HS256'], + maxAge: '10m' + }); + return claims || {}; +}; diff --git a/ghost/members-api/index.js b/ghost/members-api/index.js index 375a3ae393..86054b6bb1 100644 --- a/ghost/members-api/index.js +++ b/ghost/members-api/index.js @@ -72,16 +72,16 @@ module.exports = function MembersApi({ getSubject }); - async function sendEmailWithMagicLink(email, requestedType, options = {forceEmailType: false}){ + async function sendEmailWithMagicLink({email, requestedType, payload, options = {forceEmailType: false}}){ if (options.forceEmailType) { - return magicLinkService.sendMagicLink({email, subject: email, type: requestedType}); + return magicLinkService.sendMagicLink({email, payload, subject: email, type: requestedType}); } const member = await users.get({email}); if (member) { - return magicLinkService.sendMagicLink({email, subject: email, type: 'signin'}); + return magicLinkService.sendMagicLink({email, payload, subject: email, type: 'signin'}); } else { const type = requestedType === 'subscribe' ? 'subscribe' : 'signup'; - return magicLinkService.sendMagicLink({email, subject: email, type}); + return magicLinkService.sendMagicLink({email, payload, subject: email, type}); } } @@ -96,14 +96,16 @@ module.exports = function MembersApi({ async function getMemberDataFromMagicLinkToken(token){ const email = await magicLinkService.getUserFromToken(token); + const {labels = []} = await magicLinkService.getPayloadFromToken(token); if (!email) { return null; } + const member = await getMemberIdentityData(email); if (member) { return member; } - await users.create({email}); + await users.create({email, labels}); return getMemberIdentityData(email); } async function getMemberIdentityData(email){ @@ -131,14 +133,18 @@ module.exports = function MembersApi({ return res.end('Bad Request.'); } const emailType = req.body.emailType; + const payload = {}; + if (req.body.labels) { + payload.labels = req.body.labels; + } try { if (!allowSelfSignup) { const member = await users.get({email}); if (member) { - await sendEmailWithMagicLink(email, emailType); + await sendEmailWithMagicLink({email, requestedType: emailType}); } } else { - await sendEmailWithMagicLink(email, emailType); + await sendEmailWithMagicLink({email, requestedType: emailType, payload}); } res.writeHead(201); return res.end('Created.'); @@ -238,7 +244,7 @@ module.exports = function MembersApi({ } const emailType = 'signup'; - await sendEmailWithMagicLink(customer.email, emailType, {forceEmailType: true}); + await sendEmailWithMagicLink({email: customer.email, requestedType: emailType, options: {forceEmailType: true}}); } res.writeHead(200); diff --git a/ghost/members-api/lib/users.js b/ghost/members-api/lib/users.js index 70c9255582..e8dd97ace5 100644 --- a/ghost/members-api/lib/users.js +++ b/ghost/members-api/lib/users.js @@ -1,13 +1,15 @@ +const _ = require('lodash'); const debug = require('ghost-ignition').debug('users'); const common = require('./common'); let Member; -async function createMember({email, name, note}) { +async function createMember({email, name, note, labels}) { const model = await Member.add({ email, name, - note + note, + labels }); const member = model.toJSON(); return member; @@ -153,6 +155,16 @@ module.exports = function ({ async function create(data) { debug(`create email:${data.email}`); + + /** Member.add model method expects label object array*/ + if (data.labels) { + data.labels.forEach((label, index) => { + if (_.isString(label)) { + data.labels[index] = {name: label}; + } + }); + } + const member = await createMember(data); return member; }