diff --git a/core/server/api/canary/members.js b/core/server/api/canary/members.js index a7105202a7..5bf94bcbd4 100644 --- a/core/server/api/canary/members.js +++ b/core/server/api/canary/members.js @@ -6,6 +6,28 @@ const membersService = require('../../services/members'); const common = require('../../lib/common'); const fsLib = require('../../lib/fs'); +const listMembers = async function (options) { + const res = (await models.Member.findPage(options)); + const members = res.data.map(model => model.toJSON(options)); + + // NOTE: this logic is here until relations between Members/MemberStripeCustomer/StripeCustomerSubscription + // are in place + const membersWithSubscriptions = await Promise.all(members.map(async function (member) { + const subscriptions = await membersService.api.members.getStripeSubscriptions(member); + + return Object.assign(member, { + stripe: { + subscriptions + } + }); + })); + + return { + members: membersWithSubscriptions, + meta: res.meta + }; +}; + const members = { docName: 'members', browse: { @@ -19,8 +41,8 @@ const members = { ], permissions: true, validation: {}, - query(frame) { - return membersService.api.members.list(frame.options); + async query(frame) { + return listMembers(frame.options); } }, @@ -33,12 +55,24 @@ const members = { validation: {}, permissions: true, async query(frame) { - const member = await membersService.api.members.get(frame.data, frame.options); + let member = await models.Member.findOne(frame.data, frame.options); + if (!member) { throw new common.errors.NotFoundError({ message: common.i18n.t('errors.api.members.memberNotFound') }); } + + // NOTE: this logic is here until relations between Members/MemberStripeCustomer/StripeCustomerSubscription + // are in place + const subscriptions = await membersService.api.members.getStripeSubscriptions(member); + member = member.toJSON(frame.options); + Object.assign(member, { + stripe: { + subscriptions + } + }); + return member; } }, @@ -63,10 +97,12 @@ const members = { permissions: true, async query(frame) { try { - const member = await membersService.api.members.create(frame.data.members[0], { - sendEmail: frame.options.send_email, - emailType: frame.options.email_type - }); + const member = await models.Member.add(frame.data.members[0], frame.options); + + if (frame.options.send_email) { + await membersService.api.sendEmailWithMagicLink(member.get('email'), frame.options.email_type); + } + return member; } catch (error) { if (error.code && error.message.toLowerCase().indexOf('unique') !== -1) { @@ -93,7 +129,8 @@ const members = { }, permissions: true, async query(frame) { - const member = await membersService.api.members.update(frame.data.members[0], frame.options); + const member = await models.Member.edit(frame.data.members[0], frame.options); + return member; } }, @@ -114,7 +151,21 @@ const members = { permissions: true, async query(frame) { frame.options.require = true; - await membersService.api.members.destroy(frame.options) + + let member = await models.Member.findOne(frame.data, frame.options); + + if (!member) { + throw new common.errors.NotFoundError({ + message: common.i18n.t('errors.api.resource.resourceNotFound', { + resource: 'Member' + }) + }); + } + + // NOTE: move to a model layer once Members/MemberStripeCustomer relations are in place + await membersService.api.members.destroyStripeSubscriptions(member); + + await models.Member.destroy(frame.options) .catch(models.Member.NotFoundError, () => { throw new common.errors.NotFoundError({ message: common.i18n.t('errors.api.resource.resourceNotFound', { @@ -147,8 +198,8 @@ const members = { method: 'browse' }, validation: {}, - query(frame) { - return membersService.api.members.list(frame.options); + async query(frame) { + return listMembers(frame.options); } }, diff --git a/core/server/api/canary/utils/validators/input/schemas/members-edit.json b/core/server/api/canary/utils/validators/input/schemas/members-edit.json index a1a9adf791..6bf5dc2d76 100644 --- a/core/server/api/canary/utils/validators/input/schemas/members-edit.json +++ b/core/server/api/canary/utils/validators/input/schemas/members-edit.json @@ -13,7 +13,40 @@ "maxItems": 1, "items": { "type": "object", - "allOf": [{"$ref": "members#/definitions/member"}] + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "maxLength": 191, + "pattern": "^([^,]|$)" + }, + "note": { + "type": "string", + "minLength": 0, + "maxLength": 2000 + }, + "subscribed": { + "type": "boolean" + }, + "id": { + "strip": true + }, + "email": { + "strip": true + }, + "created_at": { + "strip": true + }, + "created_by": { + "strip": true + }, + "updated_at": { + "strip": true + }, + "updated_by": { + "strip": true + } + } } } }, diff --git a/package.json b/package.json index 3882dd5757..ef5147a9e7 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "dependencies": { "@nexes/nql": "0.3.0", "@tryghost/helpers": "1.1.20", - "@tryghost/members-api": "0.11.0", + "@tryghost/members-api": "0.11.1", "@tryghost/members-ssr": "0.7.3", "@tryghost/social-urls": "0.1.5", "@tryghost/string": "^0.1.3", diff --git a/yarn.lock b/yarn.lock index e5fda0e475..31041a7e13 100644 --- a/yarn.lock +++ b/yarn.lock @@ -237,10 +237,10 @@ jsonwebtoken "^8.5.1" lodash "^4.17.15" -"@tryghost/members-api@0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@tryghost/members-api/-/members-api-0.11.0.tgz#94a6ca7b11bf5132b7c8102dc92501965bf2e766" - integrity sha512-WV+8y1TzYnvoZGnw9kXH8hMuJhgebHbOskeJiy8X8yn45UD/hlMMuF+y015W1lrMYblEhBS5E4eGfAX+laKqOw== +"@tryghost/members-api@0.11.1": + version "0.11.1" + resolved "https://registry.yarnpkg.com/@tryghost/members-api/-/members-api-0.11.1.tgz#c878ea23b46eeede101715d2ecc72df8f31f307a" + integrity sha512-SeT66Ddkfq2PQIt9XGn+/qcgc2tRMShgFIuGcE01Df/b27WfkELQu8IP+CK/1giuXg/cooEdpoWmbLQ5qm/+3w== dependencies: "@tryghost/magic-link" "^0.3.3" bluebird "^3.5.4"