Added /members/validate ednpoint to Admin API

no issue

- This endpoint is meant to be used for validation of imported members
- Main function at the moment is to validate if stripe_customer_id present in the dataset exists in connected Stripe account
This commit is contained in:
Nazar Gargol 2020-06-12 16:33:45 +12:00
parent 11a686d734
commit 589d826afd
6 changed files with 90 additions and 8 deletions

View File

@ -219,7 +219,7 @@ const members = {
const isStripeLinkingError = error.message && error.message.match(/customer|plan|subscription|Stripe account/g);
if (model && isStripeLinkingError) {
if (error.message.indexOf('customer') && error.code === 'resource_missing') {
error.message = `Member not imported, ${error.message}`;
error.message = `Member not imported. ${error.message}`;
error.context = i18n.t('errors.api.members.stripeCustomerNotFound.context');
error.help = i18n.t('errors.api.members.stripeCustomerNotFound.help');
}
@ -344,6 +344,42 @@ const members = {
}
},
validateImport: {
permissions: {
method: 'add'
},
headers: {},
async query(frame) {
const importedMembers = frame.data.members;
await Promise.map(importedMembers, (async (entry) => {
if (entry.stripe_customer_id) {
if (!membersService.config.isStripeConnected()) {
throw new errors.ValidationError({
message: i18n.t('errors.api.members.stripeNotConnected.message', {
id: entry.stripe_customer_id
}),
context: i18n.t('errors.api.members.stripeNotConnected.context'),
help: i18n.t('errors.api.members.stripeNotConnected.help')
});
}
try {
await membersService.api.members.getStripeCustomer(entry.stripe_customer_id);
} catch (error) {
throw new errors.ValidationError({
message: `Member not imported. ${error.message}`,
context: i18n.t('errors.api.members.stripeCustomerNotFound.context'),
help: i18n.t('errors.api.members.stripeCustomerNotFound.help')
});
}
}
}));
return null;
}
},
importCSV: {
statusCode: 201,
permissions: {

View File

@ -45,10 +45,10 @@ module.exports = {
};
},
exportCSV(models, apiConfig, frame) {
exportCSV(data, apiConfig, frame) {
debug('exportCSV');
const members = models.members.map((member) => {
const members = data.members.map((member) => {
member = mapper.mapMember(member, frame);
let stripeCustomerId;

View File

@ -90,6 +90,7 @@ module.exports = function apiRoutes() {
router.get('/members/stats', shared.middlewares.labs.members, mw.authAdminApi, http(apiCanary.members.stats));
router.post('/members/validate', shared.middlewares.labs.members, mw.authAdminApi, http(apiCanary.members.validateImport));
router.get('/members/csv', shared.middlewares.labs.members, mw.authAdminApi, http(apiCanary.members.exportCSV));
router.post('/members/csv',
shared.middlewares.labs.members,

View File

@ -52,7 +52,7 @@
"@tryghost/kg-markdown-html-renderer": "2.0.1",
"@tryghost/kg-mobiledoc-html-renderer": "3.0.1",
"@tryghost/magic-link": "^0.4.8",
"@tryghost/members-api": "0.20.1",
"@tryghost/members-api": "0.21.0",
"@tryghost/members-ssr": "0.8.1",
"@tryghost/mw-session-from-token": "0.1.4",
"@tryghost/session-service": "0.1.4",

View File

@ -239,6 +239,51 @@ describe('Members API', function () {
});
});
it('Can validate import data', function () {
const member = {
name: 'test',
email: 'memberTestAdd@test.com'
};
return request
.post(localUtils.API.getApiQuery(`members/validate`))
.send({members: [member]})
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.then((res) => {
should.not.exist(res.headers['x-cache-invalidate']);
const jsonResponse = res.body;
should.exist(jsonResponse);
should.not.exist(jsonResponse.members);
});
});
it('Fails to validate import data when stripe_customer_id is present but Stripe is not connected', function () {
const member = {
name: 'test',
email: 'memberTestAdd@test.com',
stripe_customer_id: 'cus_XXXXX'
};
return request
.post(localUtils.API.getApiQuery(`members/validate`))
.send({members: [member]})
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(422)
.then((res) => {
should.not.exist(res.headers['x-cache-invalidate']);
const jsonResponse = res.body;
should.exist(jsonResponse);
should.exist(jsonResponse.errors);
jsonResponse.errors[0].message.should.match(/Member not imported/i);
jsonResponse.errors[0].context.should.match(/no Stripe account connected/i);
});
});
it('Can export CSV', function () {
return request
.get(localUtils.API.getApiQuery(`members/csv/`))

View File

@ -496,10 +496,10 @@
jsonwebtoken "^8.5.1"
lodash "^4.17.15"
"@tryghost/members-api@0.20.1":
version "0.20.1"
resolved "https://registry.npmjs.org/@tryghost/members-api/-/members-api-0.20.1.tgz#a4477eb77ac9657a0a238148cf95ac0056d3607a"
integrity sha512-IDZGHwKutebCAQq0Oya+sdxFsFw79X/NWg+MfEULJCtLvW09bFdtBc1RWyXrXiPBkFbnKu+zOkhIg1I5Lx48Nw==
"@tryghost/members-api@0.21.0":
version "0.21.0"
resolved "https://registry.yarnpkg.com/@tryghost/members-api/-/members-api-0.21.0.tgz#778a747e02de888118ef937861493a7d135f5784"
integrity sha512-0NJmgHxINsTiWfiyV4jCMcWgLp42Fy5lAdHQxLHgcYnmk2Xggqrs0sKl2kfQ/JNMZwej7gorXyd0Xirf8gtBdQ==
dependencies:
"@tryghost/magic-link" "^0.4.9"
bluebird "^3.5.4"