mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-03 23:00:14 -05:00
Fixed post.unpublished
when deleting all content
no issue - if you delete all content, we expect two events - `post.deleted` and `post.unpublished` - `post.unpublished` was never triggered, because the api implementation made use of `collection.invoke(`destroy`)` - what happened? - you fetch all posts (columns:id) - you destroy the post (only id column is available) - the model events are triggered - but you have no access to a default set of data - the result is that the event handler can't even tell if this is a post or a page - added a proper test to ensure which events are triggered
This commit is contained in:
parent
0ae6cbe34d
commit
c8f2dd11ba
2 changed files with 97 additions and 25 deletions
|
@ -1,6 +1,9 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
// # DB API
|
// # DB API
|
||||||
// API for DB operations
|
// API for DB operations
|
||||||
var Promise = require('bluebird'),
|
var Promise = require('bluebird'),
|
||||||
|
_ = require('lodash'),
|
||||||
pipeline = require('../lib/promise/pipeline'),
|
pipeline = require('../lib/promise/pipeline'),
|
||||||
localUtils = require('./utils'),
|
localUtils = require('./utils'),
|
||||||
exporter = require('../data/export'),
|
exporter = require('../data/export'),
|
||||||
|
@ -110,17 +113,38 @@ db = {
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NOTE:
|
||||||
|
* We fetch all posts with `columns:id` to increase the speed of this endpoint.
|
||||||
|
* And if you trigger `post.destroy(..)`, this will trigger bookshelf and model events.
|
||||||
|
* But we only have to `id` available in the model. This won't work, because:
|
||||||
|
* - model layer can't trigger event e.g. `post.page` to trigger `post|page.unpublished`.
|
||||||
|
* - `onDestroyed` or `onDestroying` can contain custom logic
|
||||||
|
*/
|
||||||
function deleteContent() {
|
function deleteContent() {
|
||||||
var collections = [
|
return models.Base.transaction(function (transacting) {
|
||||||
models.Post.findAll(queryOpts),
|
queryOpts.transacting = transacting;
|
||||||
models.Tag.findAll(queryOpts)
|
|
||||||
];
|
|
||||||
|
|
||||||
return Promise.each(collections, function then(Collection) {
|
return models.Post.findAll(queryOpts)
|
||||||
return Collection.invokeThen('destroy', queryOpts);
|
.then((response) => {
|
||||||
}).return({db: []})
|
return Promise.map(response.models, (post) => {
|
||||||
.catch(function (err) {
|
return models.Post.destroy(_.merge({id: post.id}, queryOpts));
|
||||||
throw new common.errors.GhostError({err: err});
|
}, {concurrency: 100});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return models.Tag.findAll(queryOpts);
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
return Promise.map(response.models, (tag) => {
|
||||||
|
return models.Tag.destroy(_.merge({id: tag.id}, queryOpts));
|
||||||
|
}, {concurrency: 100});
|
||||||
|
})
|
||||||
|
.return({db: []})
|
||||||
|
.catch((err) => {
|
||||||
|
throw new common.errors.GhostError({
|
||||||
|
err: err
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,85 @@
|
||||||
var should = require('should'),
|
var should = require('should'),
|
||||||
testUtils = require('../../utils'),
|
|
||||||
_ = require('lodash'),
|
_ = require('lodash'),
|
||||||
|
sinon = require('sinon'),
|
||||||
|
testUtils = require('../../utils'),
|
||||||
|
common = require('../../../server/lib/common'),
|
||||||
dbAPI = require('../../../server/api/db'),
|
dbAPI = require('../../../server/api/db'),
|
||||||
models = require('../../../server/models');
|
models = require('../../../server/models'),
|
||||||
|
sandbox = sinon.sandbox.create();
|
||||||
|
|
||||||
describe('DB API', function () {
|
describe('DB API', function () {
|
||||||
|
var eventsTriggered;
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
sandbox.restore();
|
||||||
|
});
|
||||||
|
|
||||||
// Keep the DB clean
|
// Keep the DB clean
|
||||||
before(testUtils.teardown);
|
before(testUtils.teardown);
|
||||||
afterEach(testUtils.teardown);
|
afterEach(testUtils.teardown);
|
||||||
beforeEach(testUtils.setup('users:roles', 'settings', 'posts', 'subscriber', 'perms:db', 'perms:init'));
|
beforeEach(testUtils.setup('users:roles', 'settings', 'posts', 'subscriber', 'perms:db', 'perms:init'));
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
eventsTriggered = {};
|
||||||
|
|
||||||
|
sandbox.stub(common.events, 'emit').callsFake(function (eventName, eventObj) {
|
||||||
|
if (!eventsTriggered[eventName]) {
|
||||||
|
eventsTriggered[eventName] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
eventsTriggered[eventName].push(eventObj);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
should.exist(dbAPI);
|
should.exist(dbAPI);
|
||||||
|
|
||||||
it('delete all content (owner)', function () {
|
it('delete all content (owner)', function () {
|
||||||
return dbAPI.deleteAllContent(testUtils.context.owner).then(function (result) {
|
return models.Post.findAll(testUtils.context.internal)
|
||||||
|
.then(function (results) {
|
||||||
|
results = results.toJSON();
|
||||||
|
|
||||||
|
results.length.should.eql(8);
|
||||||
|
|
||||||
|
_.filter(results, {page: false, status: 'published'}).length.should.equal(4);
|
||||||
|
_.filter(results, {page: false, status: 'draft'}).length.should.equal(1);
|
||||||
|
_.filter(results, {page: false, status: 'scheduled'}).length.should.equal(1);
|
||||||
|
_.filter(results, {page: true, status: 'published'}).length.should.equal(1);
|
||||||
|
_.filter(results, {page: true, status: 'draft'}).length.should.equal(1);
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return dbAPI.deleteAllContent(testUtils.context.owner);
|
||||||
|
})
|
||||||
|
.then(function (result) {
|
||||||
should.exist(result.db);
|
should.exist(result.db);
|
||||||
result.db.should.be.instanceof(Array);
|
result.db.should.be.instanceof(Array);
|
||||||
result.db.should.be.empty();
|
result.db.should.be.empty();
|
||||||
}).then(function () {
|
|
||||||
return models.Tag.findAll(testUtils.context.owner).then(function (results) {
|
return models.Tag.findAll(testUtils.context.internal);
|
||||||
|
})
|
||||||
|
.then(function (results) {
|
||||||
should.exist(results);
|
should.exist(results);
|
||||||
results.length.should.equal(0);
|
results.length.should.equal(0);
|
||||||
});
|
|
||||||
}).then(function () {
|
return models.Post.findAll(testUtils.context.internal);
|
||||||
return models.Post.findAll(testUtils.context.owner).then(function (results) {
|
})
|
||||||
|
.then(function (results) {
|
||||||
should.exist(results);
|
should.exist(results);
|
||||||
results.length.should.equal(0);
|
results.length.should.equal(0);
|
||||||
});
|
|
||||||
}).then(function () {
|
return models.Subscriber.findAll(testUtils.context.internal);
|
||||||
return models.Subscriber.findAll(testUtils.context.owner).then(function (results) {
|
})
|
||||||
|
.then(function (results) {
|
||||||
should.exist(results);
|
should.exist(results);
|
||||||
results.length.should.equal(1);
|
results.length.should.equal(1);
|
||||||
});
|
})
|
||||||
|
.then(function () {
|
||||||
|
eventsTriggered['post.unpublished'].length.should.eql(4);
|
||||||
|
eventsTriggered['post.deleted'].length.should.eql(6);
|
||||||
|
|
||||||
|
eventsTriggered['page.unpublished'].length.should.eql(1);
|
||||||
|
eventsTriggered['page.deleted'].length.should.eql(2);
|
||||||
|
|
||||||
|
eventsTriggered['tag.deleted'].length.should.eql(5);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue