diff --git a/core/server/api/canary/members.js b/core/server/api/canary/members.js index c6a37383b8..19e8794f1b 100644 --- a/core/server/api/canary/members.js +++ b/core/server/api/canary/members.js @@ -214,17 +214,21 @@ module.exports = { let member; frame.options.withRelated = ['stripeSubscriptions', 'stripeSubscriptions.customer']; try { + if (!membersService.config.isStripeConnected() + && (frame.data.members[0].stripe_customer_id || frame.data.members[0].comped)) { + const property = frame.data.members[0].comped ? 'comped' : 'stripe_customer_id'; + + throw new errors.ValidationError({ + message: i18n.t('errors.api.members.stripeNotConnected.message'), + context: i18n.t('errors.api.members.stripeNotConnected.context'), + help: i18n.t('errors.api.members.stripeNotConnected.help'), + property + }); + } + member = await membersService.api.members.create(frame.data.members[0], frame.options); if (frame.data.members[0].stripe_customer_id) { - if (!membersService.config.isStripeConnected()) { - throw new errors.ValidationError({ - message: i18n.t('errors.api.members.stripeNotConnected.message'), - context: i18n.t('errors.api.members.stripeNotConnected.context'), - help: i18n.t('errors.api.members.stripeNotConnected.help') - }); - } - await membersService.api.members.linkStripeCustomer(frame.data.members[0].stripe_customer_id, member); } @@ -250,7 +254,7 @@ module.exports = { // NOTE: failed to link Stripe customer/plan/subscription or have thrown custom Stripe connection error. // It's a bit ugly doing regex matching to detect errors, but it's the easiest way that works without // introducing additional logic/data format into current error handling - const isStripeLinkingError = error.message && (error.message.match(/customer|plan|subscription/g) || error.context === i18n.t('errors.api.members.stripeNotConnected.context')); + const isStripeLinkingError = error.message && (error.message.match(/customer|plan|subscription/g)); if (member && isStripeLinkingError) { if (error.message.indexOf('customer') && error.code === 'resource_missing') { error.message = `Member not imported. ${error.message}`; diff --git a/core/server/translations/en.json b/core/server/translations/en.json index b0128e8f37..e4a4de995c 100644 --- a/core/server/translations/en.json +++ b/core/server/translations/en.json @@ -399,8 +399,8 @@ "members": { "memberNotFound": "Member not found.", "stripeNotConnected": { - "message": "Missing Stripe connection", - "context": "Attempting to import members with Stripe data when there is no Stripe account connected", + "message": "Missing Stripe connection.", + "context": "Attempting to import members with Stripe data when there is no Stripe account connected.", "help": "You need to connect to Stripe to import Stripe customers. " }, "stripeCustomerNotFound": { diff --git a/package.json b/package.json index 1e8fe48de2..ad813367a1 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "@nexes/nql": "0.4.0", "@sentry/node": "5.26.0", "@tryghost/adapter-manager": "0.1.11", - "@tryghost/admin-api-schema": "1.0.1", + "@tryghost/admin-api-schema": "1.1.0", "@tryghost/bootstrap-socket": "0.2.2", "@tryghost/constants": "0.1.1", "@tryghost/errors": "0.2.4", diff --git a/test/regression/api/canary/admin/members_spec.js b/test/regression/api/canary/admin/members_spec.js index e7a1d593d7..d20ff56ba2 100644 --- a/test/regression/api/canary/admin/members_spec.js +++ b/test/regression/api/canary/admin/members_spec.js @@ -105,6 +105,30 @@ describe('Members API', function () { .expect(422); }); + it('Add should fail when comped flag is passed in but Stripe is not enabled', function () { + const member = { + email: 'memberTestAdd@test.com', + comped: true + }; + + return request + .post(localUtils.API.getApiQuery(`members/`)) + .send({members: [member]}) + .set('Origin', config.get('url')) + .expect('Content-Type', /json/) + .expect('Cache-Control', testUtils.cacheRules.private) + .expect(422) + .then((res) => { + const jsonResponse = res.body; + + should.exist(jsonResponse); + should.exist(jsonResponse.errors); + + jsonResponse.errors[0].message.should.eql('Validation error, cannot save member.'); + jsonResponse.errors[0].context.should.match(/Missing Stripe connection./); + }); + }); + // NOTE: this test should be enabled and expanded once test suite fully supports Stripe mocking it.skip('Can set a "Complimentary" subscription', function () { const memberToChange = { @@ -450,7 +474,7 @@ describe('Members API', function () { jsonResponse.meta.stats.invalid.count.should.equal(2); should.equal(jsonResponse.meta.stats.invalid.errors.length, 1); - jsonResponse.meta.stats.invalid.errors[0].message.should.equal('Missing Stripe connection'); + jsonResponse.meta.stats.invalid.errors[0].message.should.match(/Missing Stripe connection/); should.not.exist(jsonResponse.meta.import_label); }); diff --git a/yarn.lock b/yarn.lock index c0fa895add..c4a4e0d62e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -383,10 +383,10 @@ dependencies: "@tryghost/errors" "^0.2.4" -"@tryghost/admin-api-schema@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@tryghost/admin-api-schema/-/admin-api-schema-1.0.1.tgz#df5b736e7f217e070d643b4a5e46eba9e95be66f" - integrity sha512-AsaBPN3mdgu2dicFS82rdBhV8idz+nxy9Z7FNKaiv0jNRvHHSu9lQyAReio/JevBxnGsywp90CH3sJFUvgOSbw== +"@tryghost/admin-api-schema@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@tryghost/admin-api-schema/-/admin-api-schema-1.1.0.tgz#97224a9f5b74d08bdd93c1f89a85dfb2bfff9379" + integrity sha512-VSn4LMtVmIAHJxXPeW380s3TKy2UbXaWwVsPaUmtYKCAtyO1DelVB20Lnh/UMuWpKOBLVdzMwI66E7V5xxj/ww== dependencies: "@tryghost/errors" "0.2.4" bluebird "^3.5.3"