mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-13 22:41:32 -05:00
35e2387541
Closes #1977, Refs #3473 - Ensure that import operations are run in sequence. Previously the operations were started in order but subsequent ops were allowed to begin before the previous finished, which would result in out-of-order execution. - Fix bug in attach() where a model property was being passed in instead of a transaction object. If the call was made when a transaction was in process, it could cause bookshelf/knex to hang and never finish the transaction.
181 lines
5.5 KiB
JavaScript
181 lines
5.5 KiB
JavaScript
var Promise = require('bluebird'),
|
|
_ = require('lodash'),
|
|
models = require('../../models'),
|
|
utils = require('./utils'),
|
|
|
|
Importer000;
|
|
|
|
|
|
Importer000 = function () {
|
|
_.bindAll(this, 'doImport');
|
|
|
|
this.version = '000';
|
|
|
|
this.importFrom = {
|
|
'000': this.doImport,
|
|
'001': this.doImport,
|
|
'002': this.doImport,
|
|
'003': this.doImport
|
|
};
|
|
};
|
|
|
|
Importer000.prototype.importData = function (data) {
|
|
return this.canImport(data)
|
|
.then(function (importerFunc) {
|
|
return importerFunc(data);
|
|
});
|
|
};
|
|
|
|
Importer000.prototype.canImport = function (data) {
|
|
if (data.meta && data.meta.version && this.importFrom[data.meta.version]) {
|
|
return Promise.resolve(this.importFrom[data.meta.version]);
|
|
}
|
|
|
|
return Promise.reject('Unsupported version of data: ' + data.meta.version);
|
|
};
|
|
|
|
|
|
Importer000.prototype.loadUsers = function () {
|
|
var users = {all: {}};
|
|
|
|
return models.User.findAll({include: 'roles'}).then(function (_users) {
|
|
_users.forEach(function (user) {
|
|
users.all[user.get('email')] = {'realId': user.get('id')};
|
|
if (user.related('roles').toJSON()[0] && user.related('roles').toJSON()[0].name === 'Owner') {
|
|
users.owner = user.toJSON();
|
|
}
|
|
});
|
|
|
|
if (!users.owner) {
|
|
return Promise.reject('Unable to find an owner');
|
|
}
|
|
|
|
return users;
|
|
});
|
|
};
|
|
|
|
//Importer000.prototype.importerFunction = function (t) {
|
|
//
|
|
//};
|
|
|
|
Importer000.prototype.doUserImport = function (t, tableData, users, errors) {
|
|
var userOps = [],
|
|
imported = [];
|
|
|
|
if (tableData.users && tableData.users.length) {
|
|
if (tableData.roles_users && tableData.roles_users.length) {
|
|
tableData = utils.preProcessRolesUsers(tableData);
|
|
}
|
|
|
|
// Import users, deduplicating with already present users
|
|
userOps = utils.importUsers(tableData.users, users, t);
|
|
|
|
return Promise.settle(userOps).then(function (descriptors) {
|
|
descriptors.forEach(function (d) {
|
|
if (d.isRejected()) {
|
|
errors = errors.concat(d.reason());
|
|
} else {
|
|
imported.push(d.value().toJSON());
|
|
}
|
|
});
|
|
|
|
// If adding the users fails,
|
|
if (errors.length > 0) {
|
|
t.rollback(errors);
|
|
} else {
|
|
return imported;
|
|
}
|
|
});
|
|
}
|
|
|
|
return Promise.resolve({});
|
|
};
|
|
|
|
Importer000.prototype.doImport = function (data) {
|
|
var self = this,
|
|
tableData = data.data,
|
|
imported = {},
|
|
errors = [],
|
|
users = {},
|
|
owner = {};
|
|
|
|
return self.loadUsers().then(function (result) {
|
|
owner = result.owner;
|
|
users = result.all;
|
|
|
|
return models.Base.transaction(function (t) {
|
|
|
|
// Step 1: Attempt to handle adding new users
|
|
self.doUserImport(t, tableData, users, errors).then(function (result) {
|
|
var importResults = [];
|
|
|
|
imported.users = result;
|
|
|
|
_.each(imported.users, function (user) {
|
|
users[user.email] = {realId: user.id};
|
|
});
|
|
|
|
// process user data - need to figure out what users we have available for assigning stuff to etc
|
|
try {
|
|
tableData = utils.processUsers(tableData, owner, users, ['posts', 'tags']);
|
|
} catch (error) {
|
|
return t.rollback([error]);
|
|
}
|
|
|
|
// Do any pre-processing of relationships (we can't depend on ids)
|
|
if (tableData.posts_tags && tableData.posts && tableData.tags) {
|
|
tableData = utils.preProcessPostTags(tableData);
|
|
}
|
|
|
|
// Import things in the right order
|
|
|
|
return utils.importTags(tableData.tags, t).then(function (results) {
|
|
if (results) {
|
|
importResults = importResults.concat(results);
|
|
}
|
|
|
|
return utils.importPosts(tableData.posts, t);
|
|
}).then(function (results) {
|
|
if (results) {
|
|
importResults = importResults.concat(results);
|
|
}
|
|
|
|
return utils.importSettings(tableData.settings, t);
|
|
}).then(function (results) {
|
|
if (results) {
|
|
importResults = importResults.concat(results);
|
|
}
|
|
}).then(function () {
|
|
importResults.forEach(function (p) {
|
|
if (p.isRejected()) {
|
|
errors = errors.concat(p.reason());
|
|
}
|
|
});
|
|
|
|
if (errors.length === 0) {
|
|
t.commit();
|
|
} else {
|
|
t.rollback(errors);
|
|
}
|
|
});
|
|
|
|
/** do nothing with these tables, the data shouldn't have changed from the fixtures
|
|
* permissions
|
|
* roles
|
|
* permissions_roles
|
|
* permissions_users
|
|
*/
|
|
});
|
|
}).then(function () {
|
|
//TODO: could return statistics of imported items
|
|
return Promise.resolve();
|
|
});
|
|
});
|
|
};
|
|
|
|
module.exports = {
|
|
Importer000: Importer000,
|
|
importData: function (data) {
|
|
return new Importer000().importData(data);
|
|
}
|
|
};
|