mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
Migration adds fixtures on first run only
closes #731, closes #732 - fixtures are imported using the models, rather than knex - migration treats fresh installs differently - migration throws errors for un-initialisable databases - small amount of extra code to deal with old DBs still using currentVersion & give them a nice error message
This commit is contained in:
parent
b902f8109c
commit
02436645fe
4 changed files with 164 additions and 109 deletions
|
@ -1,11 +0,0 @@
|
|||
var uuid = require('node-uuid');
|
||||
|
||||
module.exports = {
|
||||
posts: [],
|
||||
|
||||
roles: [],
|
||||
|
||||
permissions: [],
|
||||
|
||||
permissions_roles: []
|
||||
};
|
|
@ -1,13 +0,0 @@
|
|||
var uuid = require('node-uuid');
|
||||
|
||||
module.exports = {
|
||||
posts: [],
|
||||
|
||||
settings: [],
|
||||
|
||||
roles: [],
|
||||
|
||||
permissions: [],
|
||||
|
||||
permissions_roles: []
|
||||
};
|
|
@ -1,6 +1,11 @@
|
|||
var uuid = require('node-uuid');
|
||||
var sequence = require('when/sequence'),
|
||||
_ = require('underscore'),
|
||||
Post = require('../../models/post').Post,
|
||||
Role = require('../../models/role').Role,
|
||||
Permission = require('../../models/permission').Permission,
|
||||
uuid = require('node-uuid');
|
||||
|
||||
module.exports = {
|
||||
var fixtures = {
|
||||
posts: [
|
||||
{
|
||||
"uuid": uuid.v4(),
|
||||
|
@ -14,71 +19,71 @@ module.exports = {
|
|||
"status": "published",
|
||||
"language": "en_US",
|
||||
"meta_title": null,
|
||||
"meta_description": null,
|
||||
"author_id": 1,
|
||||
"created_at": 1373578890610,
|
||||
"created_by": 1,
|
||||
"updated_at": 1373578997173,
|
||||
"updated_by": 1,
|
||||
"published_at": 1373578895817,
|
||||
"published_by": 1
|
||||
"meta_description": null
|
||||
}
|
||||
],
|
||||
|
||||
roles: [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Administrator",
|
||||
"description": "Administrators"
|
||||
"uuid": uuid.v4(),
|
||||
"name": "Administrator",
|
||||
"description": "Administrators"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Editor",
|
||||
"description": "Editors"
|
||||
"uuid": uuid.v4(),
|
||||
"name": "Editor",
|
||||
"description": "Editors"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Author",
|
||||
"description": "Authors"
|
||||
"uuid": uuid.v4(),
|
||||
"name": "Author",
|
||||
"description": "Authors"
|
||||
}
|
||||
],
|
||||
|
||||
permissions: [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Edit posts",
|
||||
"action_type": "edit",
|
||||
"object_type": "post"
|
||||
"uuid": uuid.v4(),
|
||||
"name": "Edit posts",
|
||||
"action_type": "edit",
|
||||
"object_type": "post"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Remove posts",
|
||||
"action_type": "remove",
|
||||
"object_type": "post"
|
||||
"uuid": uuid.v4(),
|
||||
"name": "Remove posts",
|
||||
"action_type": "remove",
|
||||
"object_type": "post"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Create posts",
|
||||
"action_type": "create",
|
||||
"object_type": "post"
|
||||
}
|
||||
],
|
||||
|
||||
permissions_roles: [
|
||||
{
|
||||
"id": 1,
|
||||
"permission_id": 1,
|
||||
"role_id": 1
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"permission_id": 2,
|
||||
"role_id": 1
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"permission_id": 3,
|
||||
"role_id": 1
|
||||
"uuid": uuid.v4(),
|
||||
"name": "Create posts",
|
||||
"action_type": "create",
|
||||
"object_type": "post"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
populateFixtures: function () {
|
||||
var ops = [];
|
||||
|
||||
_.each(fixtures.posts, function (post) {
|
||||
ops.push(function () {return Post.add(post); });
|
||||
});
|
||||
_.each(fixtures.roles, function (role) {
|
||||
ops.push(function () {return Role.add(role); });
|
||||
});
|
||||
_.each(fixtures.permissions, function (permission) {
|
||||
ops.push(function () {return Permission.add(permission); });
|
||||
});
|
||||
|
||||
// finally, grant admins all permissions
|
||||
ops.push(function () {
|
||||
Role.forge({id: 1}).fetch({withRelated: ['permissions']}).then(function (role) {
|
||||
role.permissions().attach([1, 2, 3]);
|
||||
});
|
||||
});
|
||||
|
||||
return sequence(ops);
|
||||
}
|
||||
};
|
|
@ -4,49 +4,105 @@ var _ = require('underscore'),
|
|||
series = require('when/sequence'),
|
||||
errors = require('../../errorHandling'),
|
||||
knex = require('../../models/base').Knex,
|
||||
initialVersion = '000',
|
||||
// This databaseVersion string should always be the current version of Ghost,
|
||||
// we could probably load it from the config file.
|
||||
// - Will be possible after default-settings.json restructure
|
||||
databaseVersion = '000';
|
||||
|
||||
defaultSettings = require('../default-settings'),
|
||||
Settings = require('../../models/settings').Settings,
|
||||
fixtures = require('../fixtures'),
|
||||
|
||||
initialVersion = '000',
|
||||
defaultDatabaseVersion;
|
||||
|
||||
// Default Database Version
|
||||
// The migration version number according to the hardcoded default settings
|
||||
// This is the version the database should be at or migrated to
|
||||
function getDefaultDatabaseVersion() {
|
||||
if (!defaultDatabaseVersion) {
|
||||
// This be the current version according to the software
|
||||
defaultDatabaseVersion = _.find(defaultSettings.core, function (setting) {
|
||||
return setting.key === 'databaseVersion';
|
||||
}).defaultValue;
|
||||
}
|
||||
|
||||
return defaultDatabaseVersion;
|
||||
}
|
||||
|
||||
// Database Current Version
|
||||
// The migration version number according to the database
|
||||
// This is what the database is currently at and may need to be updated
|
||||
function getDatabaseVersion() {
|
||||
return knex.Schema.hasTable('settings').then(function () {
|
||||
// Check for the databaseVersion from the settings table
|
||||
return knex('settings')
|
||||
.where('key', 'databaseVersion')
|
||||
.select('value')
|
||||
.then(function (databaseVersionSetting) {
|
||||
if (databaseVersionSetting && databaseVersionSetting.length > 0) {
|
||||
databaseVersionSetting = databaseVersionSetting[0].value;
|
||||
} else {
|
||||
// we didn't get a response we understood, assume initialVersion
|
||||
databaseVersionSetting = initialVersion;
|
||||
}
|
||||
return databaseVersionSetting;
|
||||
});
|
||||
return knex.Schema.hasTable('settings').then(function (exists) {
|
||||
// Check for the current version from the settings table
|
||||
if (exists) {
|
||||
// Temporary code to deal with old databases with currentVersion settings
|
||||
// TODO: remove before release
|
||||
return knex('settings')
|
||||
.where('key', 'databaseVersion')
|
||||
.orWhere('key', 'currentVersion')
|
||||
.select('value')
|
||||
.then(function (versions) {
|
||||
var databaseVersion = _.reduce(versions, function (memo, version) {
|
||||
return parseInt(version.value, 10) > parseInt(memo, 10) ? version.value : memo;
|
||||
}, initialVersion);
|
||||
|
||||
if (!databaseVersion || databaseVersion.length === 0) {
|
||||
// we didn't get a response we understood, assume initialVersion
|
||||
databaseVersion = initialVersion;
|
||||
}
|
||||
return when.resolve(databaseVersion);
|
||||
});
|
||||
}
|
||||
return when.reject('Settings table does not exist');
|
||||
});
|
||||
}
|
||||
|
||||
function setDatabaseVersion() {
|
||||
return knex('settings')
|
||||
.where('key', 'databaseVersion')
|
||||
.update({ 'value': defaultDatabaseVersion });
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
databaseVersion: databaseVersion,
|
||||
// Check for whether data is needed to be bootstrapped or not
|
||||
init: function () {
|
||||
var self = this;
|
||||
|
||||
return getDatabaseVersion().then(function (databaseVersionSetting) {
|
||||
// We are assuming here that the databaseVersionSetting will
|
||||
// always be less than the databaseVersion value.
|
||||
if (databaseVersionSetting === databaseVersion) {
|
||||
// There are 4 possibilities:
|
||||
// 1. The database exists and is up-to-date
|
||||
// 2. The database exists but is out of date
|
||||
// 3. The database exists but the currentVersion setting does not or cannot be understood
|
||||
// 4. The database has not yet been created
|
||||
return getDatabaseVersion().then(function (databaseVersion) {
|
||||
var defaultVersion = getDefaultDatabaseVersion();
|
||||
|
||||
if (databaseVersion === defaultVersion) {
|
||||
// 1. The database exists and is up-to-date
|
||||
return when.resolve();
|
||||
}
|
||||
|
||||
// Bring the data up to the latest version
|
||||
return self.migrateUpFromVersion(databaseVersion);
|
||||
}, function () {
|
||||
// If the settings table doesn't exist, bring everything up from initial version.
|
||||
return self.migrateUpFromVersion(initialVersion);
|
||||
if (databaseVersion < defaultVersion) {
|
||||
// 2. The database exists but is out of date
|
||||
return self.migrateUpFromVersion(databaseVersion);
|
||||
}
|
||||
|
||||
if (databaseVersion > defaultVersion) {
|
||||
// 3. The database exists but the currentVersion setting does not or cannot be understood
|
||||
// In this case we don't understand the version because it is too high
|
||||
errors.logError('Database is not compatible with software version.');
|
||||
process.exit(-3);
|
||||
}
|
||||
|
||||
}, function (err) {
|
||||
if (err === 'Settings table does not exist') {
|
||||
// 4. The database has not yet been created
|
||||
// Bring everything up from initial version.
|
||||
return self.migrateUpFreshDb();
|
||||
}
|
||||
|
||||
// 3. The database exists but the currentVersion setting does not or cannot be understood
|
||||
// In this case the setting was missing or there was some other problem
|
||||
errors.logError('Database is not recognisable.' + err);
|
||||
process.exit(-2);
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -55,19 +111,33 @@ module.exports = {
|
|||
reset: function () {
|
||||
var self = this;
|
||||
|
||||
return getDatabaseVersion().then(function (databaseVersionSetting) {
|
||||
// bring everything down from the databaseVersion
|
||||
return self.migrateDownFromVersion(databaseVersionSetting);
|
||||
return getDatabaseVersion().then(function (databaseVersion) {
|
||||
// bring everything down from the current version
|
||||
return self.migrateDownFromVersion(databaseVersion);
|
||||
}, function () {
|
||||
// If the settings table doesn't exist, bring everything down from initial version.
|
||||
return self.migrateDownFromVersion(initialVersion);
|
||||
});
|
||||
},
|
||||
|
||||
// Only do this if we have no database at all
|
||||
migrateUpFreshDb: function () {
|
||||
var migration = require('./' + initialVersion);
|
||||
|
||||
return migration.up().then(function () {
|
||||
// Load the fixtures
|
||||
return fixtures.populateFixtures();
|
||||
|
||||
}).then(function () {
|
||||
// Initialise the default settings
|
||||
return Settings.populateDefaults();
|
||||
});
|
||||
},
|
||||
|
||||
// Migrate from a specific version to the latest
|
||||
migrateUpFromVersion: function (version, max) {
|
||||
var versions = [],
|
||||
maxVersion = max || this.getVersionAfter(databaseVersion),
|
||||
maxVersion = max || this.getVersionAfter(getDefaultDatabaseVersion()),
|
||||
currVersion = version,
|
||||
tasks = [];
|
||||
|
||||
|
@ -91,11 +161,15 @@ module.exports = {
|
|||
});
|
||||
|
||||
// Run each migration in series
|
||||
return series(tasks);
|
||||
return series(tasks).then(function () {
|
||||
// Finally update the databases current version
|
||||
return setDatabaseVersion();
|
||||
});
|
||||
},
|
||||
|
||||
migrateDownFromVersion: function (version) {
|
||||
var versions = [],
|
||||
var self = this,
|
||||
versions = [],
|
||||
minVersion = this.getVersionBefore(initialVersion),
|
||||
currVersion = version,
|
||||
tasks = [];
|
||||
|
@ -114,7 +188,7 @@ module.exports = {
|
|||
return migration.down();
|
||||
} catch (e) {
|
||||
errors.logError(e);
|
||||
return when.reject(e);
|
||||
return self.migrateDownFromVersion(initialVersion);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue