mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-28 21:33:24 +03:00
Added support for ON DELETE CASCADE to the schema (#12105)
no-issue We are in the process of creating migrations to add foreign key constraints and cascading deletes to the members_stripe_* tables to make listing members and deleting members faster. As well as the migrations we need to update the database schema so that new installations have the correct indexes and constraints. Co-authored-by: Kevin Ansfield <kevin@lookingsideways.co.uk>
This commit is contained in:
parent
0eed0d8c88
commit
d15446593a
@ -40,6 +40,9 @@ function addTableColumn(tableName, table, columnName, columnSpec = schema[tableN
|
||||
// check if table exists?
|
||||
column.references(columnSpec.references);
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(columnSpec, 'cascadeDelete') && columnSpec.cascadeDelete === true) {
|
||||
column.onDelete('CASCADE');
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(columnSpec, 'defaultTo')) {
|
||||
column.defaultTo(columnSpec.defaultTo);
|
||||
}
|
||||
|
@ -387,15 +387,14 @@ module.exports = {
|
||||
},
|
||||
members_labels: {
|
||||
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
||||
member_id: {type: 'string', maxlength: 24, nullable: false, references: 'members.id'},
|
||||
label_id: {type: 'string', maxlength: 24, nullable: false, references: 'labels.id'},
|
||||
member_id: {type: 'string', maxlength: 24, nullable: false, references: 'members.id', cascadeDelete: true},
|
||||
label_id: {type: 'string', maxlength: 24, nullable: false, references: 'labels.id', cascadeDelete: true},
|
||||
sort_order: {type: 'integer', nullable: false, unsigned: true, defaultTo: 0}
|
||||
},
|
||||
members_stripe_customers: {
|
||||
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
||||
member_id: {type: 'string', maxlength: 24, nullable: false, unique: false},
|
||||
// customer_id is unique: false because mysql with innodb utf8mb4 cannot have unqiue columns larger than 191 chars
|
||||
customer_id: {type: 'string', maxlength: 255, nullable: false, unique: false},
|
||||
member_id: {type: 'string', maxlength: 24, nullable: false, unique: false, references: 'members.id', cascadeDelete: true},
|
||||
customer_id: {type: 'string', maxlength: 255, nullable: false, unique: true},
|
||||
name: {type: 'string', maxlength: 191, nullable: true},
|
||||
email: {type: 'string', maxlength: 191, nullable: true},
|
||||
created_at: {type: 'dateTime', nullable: false},
|
||||
@ -405,8 +404,8 @@ module.exports = {
|
||||
},
|
||||
members_stripe_customers_subscriptions: {
|
||||
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
||||
customer_id: {type: 'string', maxlength: 255, nullable: false, unique: false},
|
||||
subscription_id: {type: 'string', maxlength: 255, nullable: false, unique: false},
|
||||
customer_id: {type: 'string', maxlength: 255, nullable: false, unique: false, references: 'members_stripe_customers.customer_id', cascadeDelete: true},
|
||||
subscription_id: {type: 'string', maxlength: 255, nullable: false, unique: true},
|
||||
plan_id: {type: 'string', maxlength: 255, nullable: false, unique: false},
|
||||
status: {type: 'string', maxlength: 50, nullable: false},
|
||||
cancel_at_period_end: {type: 'bool', nullable: false, defaultTo: false},
|
||||
|
@ -15,8 +15,13 @@ describe('MemberStripeCustomer Model', function run() {
|
||||
// For some reason the initial .add of MemberStripeCustomer is **not** adding a StripeCustomerSubscription :(
|
||||
it.skip('Is correctly mapped to the stripe subscriptions', async function () {
|
||||
const context = testUtils.context.admin;
|
||||
|
||||
const member = await Member.add({
|
||||
email: 'test@test.test'
|
||||
});
|
||||
|
||||
await MemberStripeCustomer.add({
|
||||
member_id: 'fake_member_id',
|
||||
member_id: member.get('id'),
|
||||
customer_id: 'fake_customer_id',
|
||||
subscriptions: [{
|
||||
subscription_id: 'fake_subscription_id1',
|
||||
@ -72,13 +77,12 @@ describe('MemberStripeCustomer Model', function run() {
|
||||
describe('member', function () {
|
||||
it('Is correctly mapped to the member', async function () {
|
||||
const context = testUtils.context.admin;
|
||||
await Member.add({
|
||||
id: 'fake_member_id',
|
||||
const member = await Member.add({
|
||||
email: 'test@test.member'
|
||||
}, context);
|
||||
|
||||
await MemberStripeCustomer.add({
|
||||
member_id: 'fake_member_id',
|
||||
member_id: member.get('id'),
|
||||
customer_id: 'fake_customer_id'
|
||||
}, context);
|
||||
|
||||
@ -88,25 +92,29 @@ describe('MemberStripeCustomer Model', function run() {
|
||||
withRelated: ['member']
|
||||
}));
|
||||
|
||||
const member = customer.related('member');
|
||||
const memberFromRelation = customer.related('member');
|
||||
|
||||
should.exist(member, 'MemberStripeCustomer should have been fetched with member');
|
||||
should.exist(memberFromRelation, 'MemberStripeCustomer should have been fetched with member');
|
||||
|
||||
should.equal(member.get('id'), 'fake_member_id');
|
||||
should.equal(member.get('email'), 'test@test.member');
|
||||
should.equal(memberFromRelation.get('id'), member.get('id'));
|
||||
should.equal(memberFromRelation.get('email'), 'test@test.member');
|
||||
});
|
||||
});
|
||||
|
||||
describe('destroy', function () {
|
||||
it('Cascades to members_stripe_customers_subscriptions', async function () {
|
||||
const context = testUtils.context.admin;
|
||||
const member = await Member.add({
|
||||
email: 'test@test.member'
|
||||
}, context);
|
||||
|
||||
await MemberStripeCustomer.add({
|
||||
member_id: 'fake_member_id',
|
||||
member_id: member.get('id'),
|
||||
customer_id: 'fake_customer_id'
|
||||
}, context);
|
||||
|
||||
const customer = await MemberStripeCustomer.findOne({
|
||||
member_id: 'fake_member_id'
|
||||
customer_id: 'fake_customer_id'
|
||||
}, context);
|
||||
|
||||
should.exist(customer, 'Customer should have been created');
|
||||
@ -136,12 +144,12 @@ describe('MemberStripeCustomer Model', function run() {
|
||||
}, context));
|
||||
|
||||
const customerAfterDestroy = await MemberStripeCustomer.findOne({
|
||||
member_id: 'fake_member_id'
|
||||
customer_id: 'fake_customer_id'
|
||||
});
|
||||
should.not.exist(customerAfterDestroy, 'MemberStripeCustomer should have been destroyed');
|
||||
|
||||
const subscriptionAfterDestroy = await StripeCustomerSubscription.findOne({
|
||||
customer_id: customer.get('customer_id')
|
||||
customer_id: 'fake_customer_id'
|
||||
});
|
||||
should.not.exist(subscriptionAfterDestroy, 'StripeCustomerSubscription should have been destroyed');
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
const should = require('should');
|
||||
const {Member} = require('../../../core/server/models/member');
|
||||
const {MemberStripeCustomer} = require('../../../core/server/models/member-stripe-customer');
|
||||
const {StripeCustomerSubscription} = require('../../../core/server/models/stripe-customer-subscription');
|
||||
|
||||
@ -12,8 +13,11 @@ describe('StripeCustomerSubscription Model', function run() {
|
||||
describe('customer', function () {
|
||||
it('Is correctly mapped to the stripe customer', async function () {
|
||||
const context = testUtils.context.admin;
|
||||
const member = await Member.add({
|
||||
email: 'test@test.member'
|
||||
}, context);
|
||||
await MemberStripeCustomer.add({
|
||||
member_id: 'fake_member_id',
|
||||
member_id: member.get('id'),
|
||||
customer_id: 'fake_customer_id'
|
||||
}, context);
|
||||
|
||||
|
@ -21,7 +21,7 @@ const defaultSettings = require('../../../../core/server/data/schema/default-set
|
||||
*/
|
||||
describe('DB version integrity', function () {
|
||||
// Only these variables should need updating
|
||||
const currentSchemaHash = '134c9de4e59b31ec6b73f03638a01396';
|
||||
const currentSchemaHash = '42a966364eb4b5851e807133374821da';
|
||||
const currentFixturesHash = '3d942c46e8487c4aee1e9ac898ed29ca';
|
||||
const currentSettingsHash = 'a4ac78d3810175428b4833645231d6d5';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user