0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-04-01 02:41:39 -05:00

Update import tool to be safe

closes #1681

- import doesn't override user credentials
- import doesn't override theme
- import doesn't kill session
- import does refresh the settings cache
- updated tests, they now use a fixture instead of a generated export
- tests check to ensure import is safe
This commit is contained in:
Hannah Wolfe 2013-12-28 20:13:47 +00:00
parent 64cf2b1b24
commit d50354dde3
6 changed files with 679 additions and 121 deletions

View file

@ -1,8 +1,8 @@
var dataExport = require('../data/export'),
dataImport = require('../data/import'),
dataProvider = require('../models'),
apiNotifications = require('./notifications'),
apiSettings = require('./settings'),
notifications = require('./notifications'),
settings = require('./settings'),
fs = require('fs-extra'),
path = require('path'),
when = require('when'),
@ -29,7 +29,7 @@ db = {
res.download(exportedFilePath, 'GhostData.json');
}).otherwise(function (error) {
// Notify of an error if it occurs
return apiNotifications.browse().then(function (notifications) {
return notifications.browse().then(function (notifications) {
var notification = {
type: 'error',
message: error.message || error,
@ -37,7 +37,7 @@ db = {
id: 'per-' + (notifications.length + 1)
};
return apiNotifications.add(notification).then(function () {
return notifications.add(notification).then(function () {
res.redirect(debugPath);
});
});
@ -56,7 +56,7 @@ db = {
* - If there is no path
* - If the name doesn't have json in it
*/
return apiNotifications.browse().then(function (notifications) {
return notifications.browse().then(function (notifications) {
notification = {
type: 'error',
message: "Must select a .json file to import",
@ -64,13 +64,13 @@ db = {
id: 'per-' + (notifications.length + 1)
};
return apiNotifications.add(notification).then(function () {
return notifications.add(notification).then(function () {
res.redirect(debugPath);
});
});
}
apiSettings.read({ key: 'databaseVersion' }).then(function (setting) {
settings.read({ key: 'databaseVersion' }).then(function (setting) {
return when(setting.value);
}, function () {
return when('001');
@ -100,17 +100,15 @@ db = {
for (prop in elem) {
if (elem.hasOwnProperty(prop)) {
if (schema[constkey].hasOwnProperty(prop)) {
if (elem.hasOwnProperty(prop)) {
if (!_.isNull(elem[prop])) {
if (elem[prop].length > schema[constkey][prop].maxlength) {
error += error !== "" ? "<br>" : "";
error += "Property '" + prop + "' exceeds maximum length of " + schema[constkey][prop].maxlength + " (element:" + constkey + " / id:" + elem.id + ")";
}
} else {
if (!schema[constkey][prop].nullable) {
error += error !== "" ? "<br>" : "";
error += "Property '" + prop + "' is not nullable (element:" + constkey + " / id:" + elem.id + ")";
}
if (!_.isNull(elem[prop])) {
if (elem[prop].length > schema[constkey][prop].maxlength) {
error += error !== "" ? "<br>" : "";
error += "Property '" + prop + "' exceeds maximum length of " + schema[constkey][prop].maxlength + " (element:" + constkey + " / id:" + elem.id + ")";
}
} else {
if (!schema[constkey][prop].nullable) {
error += error !== "" ? "<br>" : "";
error += "Property '" + prop + "' is not nullable (element:" + constkey + " / id:" + elem.id + ")";
}
}
} else {
@ -127,25 +125,24 @@ db = {
}
// Import for the current version
return dataImport(databaseVersion, importData);
}).then(function importSuccess() {
return apiNotifications.browse();
return settings.updateSettingsCache();
}).then(function () {
return notifications.browse();
}).then(function (notifications) {
notification = {
type: 'success',
message: "Data imported. Log in with the user details you imported",
message: "Posts, tags and other data successfully imported",
status: 'persistent',
id: 'per-' + (notifications.length + 1)
};
return apiNotifications.add(notification).then(function () {
req.session.destroy();
res.set({
"X-Cache-Invalidate": "/*"
});
res.redirect(config.paths().subdir + '/ghost/signin/');
return notifications.add(notification).then(function () {
res.redirect(debugPath);
});
}).otherwise(function importFailure(error) {
return apiNotifications.browse().then(function (notifications) {
return notifications.browse().then(function (notifications) {
// Notify of an error if it occurs
notification = {
type: 'error',
@ -154,7 +151,7 @@ db = {
id: 'per-' + (notifications.length + 1)
};
return apiNotifications.add(notification).then(function () {
return notifications.add(notification).then(function () {
res.redirect(debugPath);
});
});

View file

@ -82,7 +82,9 @@ function importTags(ops, tableData, transaction) {
_.each(tableData, function (tag) {
ops.push(models.Tag.findOne({name: tag.name}, {transacting: transaction}).then(function (_tag) {
if (!_tag) {
return models.Tag.add(tag, {transacting: transaction});
return models.Tag.add(tag, {transacting: transaction})
// add pass-through error handling so that bluebird doesn't think we've dropped it
.otherwise(function (error) { return when.reject(error); });
}
return when.resolve(_tag);
}));
@ -92,26 +94,35 @@ function importTags(ops, tableData, transaction) {
function importPosts(ops, tableData, transaction) {
tableData = stripProperties(['id'], tableData);
_.each(tableData, function (post) {
ops.push(models.Post.add(post, {transacting: transaction, importing: true}));
ops.push(models.Post.add(post, {transacting: transaction, importing: true})
// add pass-through error handling so that bluebird doesn't think we've dropped it
.otherwise(function (error) { return when.reject(error); }));
});
}
function importUsers(ops, tableData, transaction) {
tableData = stripProperties(['id'], tableData);
// don't override the users credentials
tableData = stripProperties(['id', 'email', 'password'], tableData);
tableData[0].id = 1;
ops.push(models.User.edit(tableData[0], {transacting: transaction}));
ops.push(models.User.edit(tableData[0], {transacting: transaction})
// add pass-through error handling so that bluebird doesn't think we've dropped it
.otherwise(function (error) { return when.reject(error); }));
}
function importSettings(ops, tableData, transaction) {
// for settings we need to update individual settings, and insert any missing ones
// the one setting we MUST NOT update is the databaseVersion settings
var blackList = ['databaseVersion'];
// settings we MUST NOT update are the databaseVersion, dbHash, and activeTheme
// as all of these will cause side effects which don't make sense for an import
var blackList = ['databaseVersion', 'dbHash', 'activeTheme'];
tableData = stripProperties(['id'], tableData);
tableData = _.filter(tableData, function (data) {
return blackList.indexOf(data.key) === -1;
});
ops.push(models.Settings.edit(tableData, transaction));
ops.push(models.Settings.edit(tableData, transaction)
// add pass-through error handling so that bluebird doesn't think we've dropped it
.otherwise(function (error) { return when.reject(error); }));
}
// No data needs modifying, we just import whatever tables are available

View file

@ -62,12 +62,7 @@ describe("Import", function () {
describe("000", function () {
should.exist(Importer000);
it("imports data from 001", function (done) {
var exportData;
var migrationStub = sinon.stub(migration, "getDatabaseVersion", function () {
return when.resolve("000");
});
beforeEach(function (done) {
// migrate to current version
migration.migrateUp().then(function () {
// Load the fixtures
@ -76,10 +71,20 @@ describe("Import", function () {
// Initialise the default settings
return Settings.populateDefaults();
}).then(function () {
// export the version 000 data ready to import
// TODO: Should have static test data here?
return exporter();
}).then(function (exported) {
return testUtils.insertDefaultUser();
}).then(function () {
done();
}).then(null, done);
});
it("imports data from 000", function (done) {
var exportData,
migrationStub = sinon.stub(migration, "getDatabaseVersion", function () {
return when.resolve("000");
});
testUtils.loadExportFixture('export-000').then(function (exported) {
exportData = exported;
return importer("000", exportData);
@ -92,21 +97,28 @@ describe("Import", function () {
knex("tags").select()
]);
}).then(function (importedData) {
should.exist(importedData);
importedData.length.should.equal(4, 'Did not get data successfully');
// we always have 0 users as there isn't one in fixtures
importedData[0].length.should.equal(0, 'There should not be a user');
var users = importedData[0],
posts = importedData[1],
settings = importedData[2],
tags = importedData[3];
// we always have 1 user, the default user we added
users.length.should.equal(1, 'There should only be one user');
// import no longer requires all data to be dropped, and adds posts
importedData[1].length.should.equal(exportData.data.posts.length + 1, 'Wrong number of posts');
posts.length.should.equal(exportData.data.posts.length + 1, 'Wrong number of posts');
// test settings
importedData[2].length.should.be.above(0, 'Wrong number of settings');
_.findWhere(importedData[2], {key: "databaseVersion"}).value.should.equal("001", 'Wrong database version');
settings.length.should.be.above(0, 'Wrong number of settings');
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("001", 'Wrong database version');
// test tags
importedData[3].length.should.equal(exportData.data.tags.length, 'no new tags');
tags.length.should.equal(exportData.data.tags.length, 'no new tags');
migrationStub.restore();
done();
}).then(null, done);
@ -116,22 +128,26 @@ describe("Import", function () {
describe("001", function () {
should.exist(Importer001);
it("imports data from 001", function (done) {
var exportData,
timestamp = 1349928000000;
// Migrate to version 001
beforeEach(function (done) {
// migrate to current version
migration.migrateUp().then(function () {
// Load the fixtures
return fixtures.populateFixtures();
}).then(function () {
// Initialise the default settings
// Initialise the default settings
return Settings.populateDefaults();
}).then(function () {
// export the version 000 data ready to import
// TODO: Should have static test data here?
return exporter();
}).then(function (exported) {
return testUtils.insertDefaultUser();
}).then(function () {
done();
}).then(null, done);
});
it("safely imports data from 001", function (done) {
var exportData,
timestamp = 1349928000000;
testUtils.loadExportFixture('export-001').then(function (exported) {
exportData = exported;
// Modify timestamp data for testing
@ -156,10 +172,20 @@ describe("Import", function () {
var users = importedData[0],
posts = importedData[1],
settings = importedData[2],
tags = importedData[3];
tags = importedData[3],
exportEmail;
// we always have 1 user, the default user we added
users.length.should.equal(1, 'There should only be one user');
// user should still have the credentials from the original insert, not the import
users[0].email.should.equal(testUtils.DataGenerator.Content.users[0].email);
users[0].password.should.equal(testUtils.DataGenerator.Content.users[0].password);
// but the name, slug, and bio should have been overridden
users[0].name.should.equal(exportData.data.users[0].name);
users[0].slug.should.equal(exportData.data.users[0].slug);
users[0].bio.should.equal(exportData.data.users[0].bio);
// we always have 0 users as there isn't one in fixtures
users.length.should.equal(0, 'There should not be a user');
// import no longer requires all data to be dropped, and adds posts
posts.length.should.equal(exportData.data.posts.length + 1, 'Wrong number of posts');
@ -167,6 +193,13 @@ describe("Import", function () {
settings.length.should.be.above(0, 'Wrong number of settings');
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("001", 'Wrong database version');
// activeTheme should NOT have been overridden
_.findWhere(settings, {key: "activeTheme"}).value.should.equal("casper", 'Wrong theme');
// email address should have been overridden
exportEmail = _.findWhere(exportData.data.settings, {key: "email"}).value;
_.findWhere(settings, {key: "email"}).value.should.equal(exportEmail, 'Wrong email in settings');
// test tags
tags.length.should.equal(exportData.data.tags.length, 'no new tags');
@ -175,9 +208,9 @@ describe("Import", function () {
// in MySQL we're returned a date object.
// We pass the returned post always through the date object
// to ensure the return is consistant for all DBs.
assert.equal( new Date(posts[1].created_at).getTime(), timestamp);
assert.equal( new Date(posts[1].updated_at).getTime(), timestamp);
assert.equal( new Date(posts[1].published_at).getTime(), timestamp);
assert.equal(new Date(posts[1].created_at).getTime(), timestamp);
assert.equal(new Date(posts[1].updated_at).getTime(), timestamp);
assert.equal(new Date(posts[1].published_at).getTime(), timestamp);
done();
}).then(null, done);
@ -185,19 +218,11 @@ describe("Import", function () {
it("doesn't import invalid post data from 001", function (done) {
var exportData;
// migrate to current version
migration.migrateUp().then(function () {
// Load the fixtures
return fixtures.populateFixtures();
}).then(function () {
// Initialise the default settings
return Settings.populateDefaults();
}).then(function () {
// export the version 000 data ready to import
// TODO: Should have static test data here?
return exporter();
}).then(function (exported) {
testUtils.loadExportFixture('export-001').then(function (exported) {
exportData = exported;
//change title to 151 characters
exportData.data.posts[0].title = new Array(152).join('a');
exportData.data.posts[0].tags = 'Tag';
@ -214,40 +239,36 @@ describe("Import", function () {
knex("tags").select()
]).then(function (importedData) {
should.exist(importedData);
importedData.length.should.equal(4, 'Did not get data successfully');
// we always have 0 users as there isn't one in fixtures
importedData[0].length.should.equal(0, 'There should not be a user');
var users = importedData[0],
posts = importedData[1],
settings = importedData[2],
tags = importedData[3];
// we always have 1 user, the default user we added
users.length.should.equal(1, 'There should only be one user');
// import no longer requires all data to be dropped, and adds posts
importedData[1].length.should.equal(exportData.data.posts.length, 'Wrong number of posts');
posts.length.should.equal(exportData.data.posts.length, 'Wrong number of posts');
// test settings
importedData[2].length.should.be.above(0, 'Wrong number of settings');
_.findWhere(importedData[2], {key: "databaseVersion"}).value.should.equal("001", 'Wrong database version');
settings.length.should.be.above(0, 'Wrong number of settings');
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("001", 'Wrong database version');
// test tags
importedData[3].length.should.equal(exportData.data.tags.length, 'no new tags');
tags.length.should.equal(exportData.data.tags.length, 'no new tags');
done();
});
}).then(null, done);
});
it("doesn't import invalid settings data from 001", function (done) {
var exportData;
// migrate to current version
migration.migrateUp().then(function () {
// Load the fixtures
return fixtures.populateFixtures();
}).then(function () {
// Initialise the default settings
return Settings.populateDefaults();
}).then(function () {
// export the version 000 data ready to import
// TODO: Should have static test data here?
return exporter();
}).then(function (exported) {
testUtils.loadExportFixture('export-001').then(function (exported) {
exportData = exported;
//change to blank settings key
exportData.data.settings[3].key = null;
@ -256,6 +277,7 @@ describe("Import", function () {
(1).should.eql(0, 'Data import should not resolve promise.');
}, function (error) {
error.should.eql('Error importing data: Setting key cannot be blank');
when.all([
knex("users").select(),
knex("posts").select(),
@ -263,19 +285,25 @@ describe("Import", function () {
knex("tags").select()
]).then(function (importedData) {
should.exist(importedData);
importedData.length.should.equal(4, 'Did not get data successfully');
// we always have 0 users as there isn't one in fixtures
importedData[0].length.should.equal(0, 'There should not be a user');
var users = importedData[0],
posts = importedData[1],
settings = importedData[2],
tags = importedData[3];
// we always have 1 user, the default user we added
users.length.should.equal(1, 'There should only be one user');
// import no longer requires all data to be dropped, and adds posts
importedData[1].length.should.equal(exportData.data.posts.length, 'Wrong number of posts');
posts.length.should.equal(exportData.data.posts.length, 'Wrong number of posts');
// test settings
importedData[2].length.should.be.above(0, 'Wrong number of settings');
_.findWhere(importedData[2], {key: "databaseVersion"}).value.should.equal("001", 'Wrong database version');
settings.length.should.be.above(0, 'Wrong number of settings');
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("001", 'Wrong database version');
// test tags
importedData[3].length.should.equal(exportData.data.tags.length, 'no new tags');
tags.length.should.equal(exportData.data.tags.length, 'no new tags');
done();
});

View file

@ -0,0 +1,169 @@
{
"meta": {
"exported_on": 1388318311015,
"version": "000"
},
"data": {
"posts": [
{
"id": 1,
"uuid": "8492fbba-1102-4b53-8e3e-abe207952f0c",
"title": "Welcome to Ghost",
"slug": "welcome-to-ghost",
"markdown": "You're live! Nice.",
"html": "<p>You're live! Nice.</p>",
"image": null,
"featured": 0,
"page": 0,
"status": "published",
"language": "en_US",
"meta_title": null,
"meta_description": null,
"author_id": 1,
"created_at": 1388318310782,
"created_by": 1,
"updated_at": 1388318310782,
"updated_by": 1,
"published_at": 1388318310783,
"published_by": 1
}
],
"users": [],
"roles": [
{
"id": 1,
"uuid": "d2ea9c7f-7e6b-4cae-b009-35c298206852",
"name": "Administrator",
"description": "Administrators",
"created_at": 1388318310794,
"created_by": 1,
"updated_at": 1388318310794,
"updated_by": 1
},
{
"id": 2,
"uuid": "b0d7d6b0-5b88-45b5-b0e5-a487741b843d",
"name": "Editor",
"description": "Editors",
"created_at": 1388318310796,
"created_by": 1,
"updated_at": 1388318310796,
"updated_by": 1
},
{
"id": 3,
"uuid": "9f72e817-5490-4ccf-bc78-c557dc9613ca",
"name": "Author",
"description": "Authors",
"created_at": 1388318310799,
"created_by": 1,
"updated_at": 1388318310799,
"updated_by": 1
}
],
"roles_users": [],
"permissions": [
{
"id": 1,
"uuid": "bdfbd261-e0fb-4c8e-abab-aece7a9e8e34",
"name": "Edit posts",
"object_type": "post",
"action_type": "edit",
"object_id": null,
"created_at": 1388318310803,
"created_by": 1,
"updated_at": 1388318310803,
"updated_by": 1
},
{
"id": 2,
"uuid": "580d31c4-e3db-40f3-969d-9a1caea9d1bb",
"name": "Remove posts",
"object_type": "post",
"action_type": "remove",
"object_id": null,
"created_at": 1388318310814,
"created_by": 1,
"updated_at": 1388318310814,
"updated_by": 1
},
{
"id": 3,
"uuid": "c1f8b024-e383-494a-835d-6fb673f143db",
"name": "Create posts",
"object_type": "post",
"action_type": "create",
"object_id": null,
"created_at": 1388318310818,
"created_by": 1,
"updated_at": 1388318310818,
"updated_by": 1
}
],
"permissions_users": [],
"permissions_roles": [
{
"id": 1,
"role_id": 1,
"permission_id": 1
},
{
"id": 2,
"role_id": 1,
"permission_id": 2
},
{
"id": 3,
"role_id": 1,
"permission_id": 3
}
],
"settings": [
{
"id": 1,
"uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e",
"key": "databaseVersion",
"value": "000",
"type": "core",
"created_at": 1388318310829,
"created_by": 1,
"updated_at": 1388318310829,
"updated_by": 1
},
{
"id": 3,
"uuid": "c356fbde-0bc5-4fe1-9309-2510291aa34d",
"key": "title",
"value": "Ghost",
"type": "blog",
"created_at": 1388318310830,
"created_by": 1,
"updated_at": 1388318310830,
"updated_by": 1
}
],
"tags": [
{
"id": 1,
"uuid": "a950117a-9735-4584-931d-25a28015a80d",
"name": "Getting Started",
"slug": "getting-started",
"description": null,
"parent_id": null,
"meta_title": null,
"meta_description": null,
"created_at": 1388318310790,
"created_by": 1,
"updated_at": 1388318310790,
"updated_by": 1
}
],
"posts_tags": [
{
"id": 1,
"post_id": 1,
"tag_id": 1
}
]
}
}

View file

@ -0,0 +1,331 @@
{
"meta": {
"exported_on": 1388318311015,
"version": "001"
},
"data": {
"posts": [
{
"id": 1,
"uuid": "8492fbba-1102-4b53-8e3e-abe207952f0c",
"title": "Welcome to Ghost",
"slug": "welcome-to-ghost",
"markdown": "You're live! Nice.",
"html": "<p>You're live! Nice.</p>",
"image": null,
"featured": 0,
"page": 0,
"status": "published",
"language": "en_US",
"meta_title": null,
"meta_description": null,
"author_id": 1,
"created_at": 1388318310782,
"created_by": 1,
"updated_at": 1388318310782,
"updated_by": 1,
"published_at": 1388318310783,
"published_by": 1
}
],
"users": [
{
"id": 1,
"uuid": "e5188224-4742-4c32-a2d6-e9c5c5d4c123",
"name": "Josephine Bloggs",
"slug": "josephine-blogs",
"password": "$2a$10$.pZeeBE0gHXd0PTnbT/ph.GEKgd0Wd3q2pWna3ynTGBkPKnGIKABC",
"email": "josephinebloggs@example.com",
"image": null,
"cover": null,
"bio": "A blogger",
"website": null,
"location": null,
"accessibility": null,
"status": "active",
"language": "en_US",
"meta_title": null,
"meta_description": null,
"last_login": null,
"created_at": 1388319501897,
"created_by": 1,
"updated_at": null,
"updated_by": null
}
],
"roles": [
{
"id": 1,
"uuid": "d2ea9c7f-7e6b-4cae-b009-35c298206852",
"name": "Administrator",
"description": "Administrators",
"created_at": 1388318310794,
"created_by": 1,
"updated_at": 1388318310794,
"updated_by": 1
},
{
"id": 2,
"uuid": "b0d7d6b0-5b88-45b5-b0e5-a487741b843d",
"name": "Editor",
"description": "Editors",
"created_at": 1388318310796,
"created_by": 1,
"updated_at": 1388318310796,
"updated_by": 1
},
{
"id": 3,
"uuid": "9f72e817-5490-4ccf-bc78-c557dc9613ca",
"name": "Author",
"description": "Authors",
"created_at": 1388318310799,
"created_by": 1,
"updated_at": 1388318310799,
"updated_by": 1
}
],
"roles_users": [
{
"id": 1,
"role_id": 1,
"user_id": 1
}
],
"permissions": [
{
"id": 1,
"uuid": "bdfbd261-e0fb-4c8e-abab-aece7a9e8e34",
"name": "Edit posts",
"object_type": "post",
"action_type": "edit",
"object_id": null,
"created_at": 1388318310803,
"created_by": 1,
"updated_at": 1388318310803,
"updated_by": 1
},
{
"id": 2,
"uuid": "580d31c4-e3db-40f3-969d-9a1caea9d1bb",
"name": "Remove posts",
"object_type": "post",
"action_type": "remove",
"object_id": null,
"created_at": 1388318310814,
"created_by": 1,
"updated_at": 1388318310814,
"updated_by": 1
},
{
"id": 3,
"uuid": "c1f8b024-e383-494a-835d-6fb673f143db",
"name": "Create posts",
"object_type": "post",
"action_type": "create",
"object_id": null,
"created_at": 1388318310818,
"created_by": 1,
"updated_at": 1388318310818,
"updated_by": 1
}
],
"permissions_users": [],
"permissions_roles": [
{
"id": 1,
"role_id": 1,
"permission_id": 1
},
{
"id": 2,
"role_id": 1,
"permission_id": 2
},
{
"id": 3,
"role_id": 1,
"permission_id": 3
}
],
"settings": [
{
"id": 1,
"uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e",
"key": "databaseVersion",
"value": "001",
"type": "core",
"created_at": 1388318310829,
"created_by": 1,
"updated_at": 1388318310829,
"updated_by": 1
},
{
"id": 2,
"uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5",
"key": "dbHash",
"value": null,
"type": "core",
"created_at": 1388318310829,
"created_by": 1,
"updated_at": 1388318310829,
"updated_by": 1
},
{
"id": 3,
"uuid": "c356fbde-0bc5-4fe1-9309-2510291aa34d",
"key": "title",
"value": "Ghost",
"type": "blog",
"created_at": 1388318310830,
"created_by": 1,
"updated_at": 1388318310830,
"updated_by": 1
},
{
"id": 4,
"uuid": "858dc11f-8f9e-4011-99ee-d94c48d5a2ce",
"key": "description",
"value": "Just a blogging platform.",
"type": "blog",
"created_at": 1388318310830,
"created_by": 1,
"updated_at": 1388318310830,
"updated_by": 1
},
{
"id": 5,
"uuid": "37ca5ae7-bca6-4dd5-8021-4ef6c6dcb097",
"key": "email",
"value": "josephinebloggs@example.com",
"type": "blog",
"created_at": 1388318310830,
"created_by": 1,
"updated_at": 1388318310830,
"updated_by": 1
},
{
"id": 6,
"uuid": "1672d62c-fab7-4f22-b333-8cf760189f67",
"key": "logo",
"value": "",
"type": "blog",
"created_at": 1388318310830,
"created_by": 1,
"updated_at": 1388318310830,
"updated_by": 1
},
{
"id": 7,
"uuid": "cd8b0456-578b-467a-857e-551bad17a14d",
"key": "cover",
"value": "",
"type": "blog",
"created_at": 1388318310830,
"created_by": 1,
"updated_at": 1388318310830,
"updated_by": 1
},
{
"id": 8,
"uuid": "c4a074a4-05c7-49f7-83eb-068302c15d82",
"key": "defaultLang",
"value": "en_US",
"type": "blog",
"created_at": 1388318310830,
"created_by": 1,
"updated_at": 1388318310830,
"updated_by": 1
},
{
"id": 9,
"uuid": "21f2f5da-9bee-4dae-b3b7-b8d7baf8be33",
"key": "postsPerPage",
"value": "6",
"type": "blog",
"created_at": 1388318310830,
"created_by": 1,
"updated_at": 1388318310830,
"updated_by": 1
},
{
"id": 10,
"uuid": "2d21b736-f85a-4119-a0e3-5fc898b1bf47",
"key": "forceI18n",
"value": "true",
"type": "blog",
"created_at": 1388318310831,
"created_by": 1,
"updated_at": 1388318310831,
"updated_by": 1
},
{
"id": 11,
"uuid": "5c5b91b8-6062-4104-b855-9e121f72b0f0",
"key": "permalinks",
"value": "/:slug/",
"type": "blog",
"created_at": 1388318310831,
"created_by": 1,
"updated_at": 1388318310831,
"updated_by": 1
},
{
"id": 12,
"uuid": "795cb328-3e38-4906-81a8-fcdff19d914f",
"key": "activeTheme",
"value": "notcasper",
"type": "theme",
"created_at": 1388318310831,
"created_by": 1,
"updated_at": 1388318310831,
"updated_by": 1
},
{
"id": 13,
"uuid": "f3afce35-5166-453e-86c3-50dfff74dca7",
"key": "activePlugins",
"value": "[]",
"type": "plugin",
"created_at": 1388318310831,
"created_by": 1,
"updated_at": 1388318310831,
"updated_by": 1
},
{
"id": 14,
"uuid": "2ea560a3-2304-449d-a62b-f7b622987510",
"key": "installedPlugins",
"value": "[]",
"type": "plugin",
"created_at": 1388318310831,
"created_by": 1,
"updated_at": 1388318310831,
"updated_by": 1
}
],
"tags": [
{
"id": 1,
"uuid": "a950117a-9735-4584-931d-25a28015a80d",
"name": "Getting Started",
"slug": "getting-started",
"description": null,
"parent_id": null,
"meta_title": null,
"meta_description": null,
"created_at": 1388318310790,
"created_by": 1,
"updated_at": 1388318310790,
"updated_by": 1
}
],
"posts_tags": [
{
"id": 1,
"post_id": 1,
"tag_id": 1
}
]
}
}

View file

@ -1,9 +1,12 @@
var knex = require('../../server/models/base').knex,
when = require('when'),
migration = require("../../server/data/migration/"),
Settings = require('../../server/models/settings').Settings,
var knex = require('../../server/models/base').knex,
when = require('when'),
nodefn = require('when/node/function'),
fs = require('fs-extra'),
path = require('path'),
migration = require("../../server/data/migration/"),
Settings = require('../../server/models/settings').Settings,
DataGenerator = require('./fixtures/data-generator'),
API = require('./api');
API = require('./api');
function initData() {
return migration.init();
@ -14,18 +17,12 @@ function clearData() {
return migration.reset();
}
function insertDefaultFixtures() {
return when(insertDefaultUser().then(function(){
return insertPosts();
}));
}
function insertPosts() {
return when(knex('posts').insert(DataGenerator.forKnex.posts).then(function () {
return knex('tags').insert(DataGenerator.forKnex.tags).then(function () {
return knex('posts_tags').insert(DataGenerator.forKnex.posts_tags);
});
}));
return knex('tags').insert(DataGenerator.forKnex.tags).then(function () {
return knex('posts_tags').insert(DataGenerator.forKnex.posts_tags);
});
}));
}
function insertMorePosts() {
@ -58,8 +55,31 @@ function insertDefaultUser() {
users.push(DataGenerator.forKnex.createUser(DataGenerator.Content.users[0]));
userRoles.push(DataGenerator.forKnex.createUserRole(1, 1));
return when(knex('users').insert(users).then(function () {
return knex('roles_users').insert(userRoles);
}));
return knex('roles_users').insert(userRoles);
}));
}
function insertDefaultFixtures() {
return when(insertDefaultUser().then(function () {
return insertPosts();
}));
}
function loadExportFixture(filename) {
var filepath = path.resolve(__dirname + '/fixtures/' + filename + '.json');
return nodefn.call(fs.readFile, filepath).then(function (fileContents) {
var data;
// Parse the json data
try {
data = JSON.parse(fileContents);
} catch (e) {
return when.reject(new Error("Failed to parse the file"));
}
return data;
});
}
module.exports = {
@ -70,6 +90,8 @@ module.exports = {
insertMorePosts: insertMorePosts,
insertDefaultUser: insertDefaultUser,
loadExportFixture: loadExportFixture,
DataGenerator: DataGenerator,
API: API
};