Allowed for comped field when creating a member through Members API (#12278)

closes #12273

- `comped` field has been allowed when editing a member or importing from a CSV. There has been a usecase (Zapier Integration) for API client to create a member with "Complimentary" plan, which made this change necessary
- Previously the logic for comped field was to skip and continue member record creation if Stripe was not connected. Now we throw an error - same as the one we have been throwing before when stripe_customer_id field was passed in. The implication of this change is that we won't be creating any record now if comped === true and Stripe is disabled. 
- Bumped admin-api-schema-package. Contains `comped` schema change so this field gets passed through to controller
This commit is contained in:
naz 2020-10-14 13:24:09 +13:00 committed by GitHub
parent d81b9c93b2
commit 392140cb36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 17 deletions

View File

@ -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}`;

View File

@ -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": {

View File

@ -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",

View File

@ -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);
});

View File

@ -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"