Added ENUM validation for member/subscription created events (#15312)

closes https://github.com/TryGhost/Team/issues/1842

- members_created_events: source + attribution_type
- members_subscription_created_events: attribution_type
- members_subscribe_events: source
This commit is contained in:
Simon Backx 2022-08-25 15:39:37 +02:00 committed by GitHub
parent 42dfa4c552
commit a8239bfa97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 164 additions and 4 deletions

View File

@ -483,9 +483,17 @@ module.exports = {
created_at: {type: 'dateTime', nullable: false},
member_id: {type: 'string', maxlength: 24, nullable: false, references: 'members.id', cascadeDelete: true},
attribution_id: {type: 'string', maxlength: 24, nullable: true},
attribution_type: {type: 'string', maxlength: 50, nullable: true},
attribution_type: {
type: 'string', maxlength: 50, nullable: true, validations: {
isIn: [['url', 'post', 'page', 'author', 'tag']]
}
},
attribution_url: {type: 'string', maxlength: 2000, nullable: true},
source: {type: 'string', maxlength: 50, nullable: false}
source: {
type: 'string', maxlength: 50, nullable: false, validations: {
isIn: [['member', 'import', 'system', 'api', 'admin']]
}
}
},
members_cancel_events: {
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
@ -613,7 +621,11 @@ module.exports = {
member_id: {type: 'string', maxlength: 24, nullable: false, references: 'members.id', cascadeDelete: true},
subscription_id: {type: 'string', maxlength: 24, nullable: false, references: 'members_stripe_customers_subscriptions.id', cascadeDelete: true},
attribution_id: {type: 'string', maxlength: 24, nullable: true},
attribution_type: {type: 'string', maxlength: 50, nullable: true},
attribution_type: {
type: 'string', maxlength: 50, nullable: true, validations: {
isIn: [['url', 'post', 'page', 'author', 'tag']]
}
},
attribution_url: {type: 'string', maxlength: 2000, nullable: true}
},
offer_redemptions: {
@ -628,7 +640,11 @@ module.exports = {
member_id: {type: 'string', maxlength: 24, nullable: false, unique: false, references: 'members.id', cascadeDelete: true},
subscribed: {type: 'bool', nullable: false, defaultTo: true},
created_at: {type: 'dateTime', nullable: false},
source: {type: 'string', maxlength: 50, nullable: true},
source: {
type: 'string', maxlength: 50, nullable: true, validations: {
isIn: [['member', 'import', 'system', 'api', 'admin']]
}
},
newsletter_id: {type: 'string', maxlength: 24, nullable: true, references: 'newsletters.id', cascadeDelete: false}
},
stripe_products: {

View File

@ -0,0 +1,64 @@
const should = require('should');
const sinon = require('sinon');
const errors = require('@tryghost/errors');
const models = require('../../../../core/server/models');
describe('Unit: models/MemberCreatedEvent', function () {
before(function () {
models.init();
});
afterEach(function () {
sinon.restore();
});
describe('validation', function () {
it('throws error for invalid attribution_type', function () {
return models.MemberCreatedEvent.add({attribution_type: 'invalid', source: 'member', member_id: '123'})
.then(function () {
throw new Error('expected ValidationError');
})
.catch(function (err) {
should(err).lengthOf(1);
(err[0] instanceof errors.ValidationError).should.eql(true);
err[0].context.should.match(/members_created_events\.attribution_type/);
});
});
it('throws if member_id is missing', function () {
return models.MemberCreatedEvent.add({attribution_type: 'post', source: 'member'})
.then(function () {
throw new Error('expected ValidationError');
})
.catch(function (err) {
should(err).lengthOf(1);
(err[0] instanceof errors.ValidationError).should.eql(true);
err[0].context.should.match(/members_created_events\.member_id/);
});
});
it('throws if source is missing', function () {
return models.MemberCreatedEvent.add({attribution_type: 'post', member_id: '123'})
.then(function () {
throw new Error('expected ValidationError');
})
.catch(function (err) {
should(err).lengthOf(1);
(err[0] instanceof errors.ValidationError).should.eql(true);
err[0].context.should.match(/members_created_events\.source/);
});
});
it('throws if source is invalid', function () {
return models.MemberCreatedEvent.add({attribution_type: 'post', member_id: '123', source: 'invalid'})
.then(function () {
throw new Error('expected ValidationError');
})
.catch(function (err) {
should(err).lengthOf(1);
(err[0] instanceof errors.ValidationError).should.eql(true);
err[0].context.should.match(/members_created_events\.source/);
});
});
});
});

View File

@ -0,0 +1,28 @@
const should = require('should');
const sinon = require('sinon');
const errors = require('@tryghost/errors');
const models = require('../../../../core/server/models');
describe('Unit: models/MemberSubscribeEvent', function () {
before(function () {
models.init();
});
afterEach(function () {
sinon.restore();
});
describe('validation', function () {
it('throws if source is invalid', function () {
return models.MemberSubscribeEvent.add({member_id: '123', source: 'invalid'})
.then(function () {
throw new Error('expected ValidationError');
})
.catch(function (err) {
should(err).lengthOf(1);
(err[0] instanceof errors.ValidationError).should.eql(true);
err[0].context.should.match(/members_subscribe_events\.source/);
});
});
});
});

View File

@ -0,0 +1,52 @@
const should = require('should');
const sinon = require('sinon');
const errors = require('@tryghost/errors');
const models = require('../../../../core/server/models');
describe('Unit: models/SubscriptionCreatedEvent', function () {
before(function () {
models.init();
});
afterEach(function () {
sinon.restore();
});
describe('validation', function () {
it('throws error for invalid attribution_type', function () {
return models.SubscriptionCreatedEvent.add({attribution_type: 'invalid', member_id: '123', subscription_id: '123'})
.then(function () {
throw new Error('expected ValidationError');
})
.catch(function (err) {
should(err).lengthOf(1);
(err[0] instanceof errors.ValidationError).should.eql(true);
err[0].context.should.match(/members_subscription_created_events\.attribution_type/);
});
});
it('throws if member_id is missing', function () {
return models.SubscriptionCreatedEvent.add({attribution_type: 'post', subscription_id: '123'})
.then(function () {
throw new Error('expected ValidationError');
})
.catch(function (err) {
should(err).lengthOf(1);
(err[0] instanceof errors.ValidationError).should.eql(true);
err[0].context.should.match(/members_subscription_created_events\.member_id/);
});
});
it('throws if subscription_id is missing', function () {
return models.SubscriptionCreatedEvent.add({attribution_type: 'post', member_id: '123'})
.then(function () {
throw new Error('expected ValidationError');
})
.catch(function (err) {
should(err).lengthOf(1);
(err[0] instanceof errors.ValidationError).should.eql(true);
err[0].context.should.match(/members_subscription_created_events\.subscription_id/);
});
});
});
});