mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-14 09:52:09 +03:00
Merge branch 'apps-perms' into master
This commit is contained in:
commit
9c1fe62173
@ -7,6 +7,7 @@ var dataExport = require('../data/export'),
|
||||
_ = require('lodash'),
|
||||
validation = require('../data/validation'),
|
||||
errors = require('../../server/errorHandling'),
|
||||
canThis = require('../permissions').canThis,
|
||||
api = {},
|
||||
db;
|
||||
|
||||
@ -15,85 +16,102 @@ api.settings = require('./settings');
|
||||
|
||||
db = {
|
||||
'exportContent': function () {
|
||||
var self = this;
|
||||
|
||||
// Export data, otherwise send error 500
|
||||
return dataExport().otherwise(function (error) {
|
||||
return when.reject({errorCode: 500, message: error.message || error});
|
||||
return canThis(self.user).exportContent.db().then(function () {
|
||||
return dataExport().otherwise(function (error) {
|
||||
return when.reject({errorCode: 500, message: error.message || error});
|
||||
});
|
||||
}, function () {
|
||||
return when.reject({code: 403, message: 'You do not have permission to export data. (no rights)'});
|
||||
});
|
||||
},
|
||||
'importContent': function (options) {
|
||||
var databaseVersion;
|
||||
var databaseVersion,
|
||||
self = this;
|
||||
|
||||
if (!options.importfile || !options.importfile.path || options.importfile.name.indexOf('json') === -1) {
|
||||
/**
|
||||
* Notify of an error if it occurs
|
||||
*
|
||||
* - If there's no file (although if you don't select anything, the input is still submitted, so
|
||||
* !req.files.importfile will always be false)
|
||||
* - If there is no path
|
||||
* - If the name doesn't have json in it
|
||||
*/
|
||||
return when.reject({code: 500, message: 'Please select a .json file to import.'});
|
||||
}
|
||||
|
||||
return api.settings.read({ key: 'databaseVersion' }).then(function (setting) {
|
||||
return when(setting.value);
|
||||
}, function () {
|
||||
return when('002');
|
||||
}).then(function (version) {
|
||||
databaseVersion = version;
|
||||
// Read the file contents
|
||||
return nodefn.call(fs.readFile, options.importfile.path);
|
||||
}).then(function (fileContents) {
|
||||
var importData,
|
||||
error = '';
|
||||
|
||||
// Parse the json data
|
||||
try {
|
||||
importData = JSON.parse(fileContents);
|
||||
} catch (e) {
|
||||
errors.logError(e, "API DB import content", "check that the import file is valid JSON.");
|
||||
return when.reject(new Error("Failed to parse the import JSON file"));
|
||||
return canThis(self.user).importContent.db().then(function () {
|
||||
if (!options.importfile || !options.importfile.path || options.importfile.name.indexOf('json') === -1) {
|
||||
/**
|
||||
* Notify of an error if it occurs
|
||||
*
|
||||
* - If there's no file (although if you don't select anything, the input is still submitted, so
|
||||
* !req.files.importfile will always be false)
|
||||
* - If there is no path
|
||||
* - If the name doesn't have json in it
|
||||
*/
|
||||
return when.reject({code: 500, message: 'Please select a .json file to import.'});
|
||||
}
|
||||
|
||||
if (!importData.meta || !importData.meta.version) {
|
||||
return when.reject(new Error("Import data does not specify version"));
|
||||
}
|
||||
return api.settings.read({ key: 'databaseVersion' }).then(function (setting) {
|
||||
return when(setting.value);
|
||||
}, function () {
|
||||
return when('002');
|
||||
}).then(function (version) {
|
||||
databaseVersion = version;
|
||||
// Read the file contents
|
||||
return nodefn.call(fs.readFile, options.importfile.path);
|
||||
}).then(function (fileContents) {
|
||||
var importData,
|
||||
error = '';
|
||||
|
||||
_.each(_.keys(importData.data), function (tableName) {
|
||||
_.each(importData.data[tableName], function (importValues) {
|
||||
try {
|
||||
validation.validateSchema(tableName, importValues);
|
||||
} catch (err) {
|
||||
error += error !== "" ? "<br>" : "";
|
||||
error += err.message;
|
||||
}
|
||||
// Parse the json data
|
||||
try {
|
||||
importData = JSON.parse(fileContents);
|
||||
} catch (e) {
|
||||
errors.logError(e, "API DB import content", "check that the import file is valid JSON.");
|
||||
return when.reject(new Error("Failed to parse the import JSON file"));
|
||||
}
|
||||
|
||||
if (!importData.meta || !importData.meta.version) {
|
||||
return when.reject(new Error("Import data does not specify version"));
|
||||
}
|
||||
|
||||
_.each(_.keys(importData.data), function (tableName) {
|
||||
_.each(importData.data[tableName], function (importValues) {
|
||||
try {
|
||||
validation.validateSchema(tableName, importValues);
|
||||
} catch (err) {
|
||||
error += error !== "" ? "<br>" : "";
|
||||
error += err.message;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (error !== "") {
|
||||
return when.reject(new Error(error));
|
||||
}
|
||||
// Import for the current version
|
||||
return dataImport(databaseVersion, importData);
|
||||
|
||||
}).then(function importSuccess() {
|
||||
return api.settings.updateSettingsCache();
|
||||
}).then(function () {
|
||||
return when.resolve({message: 'Posts, tags and other data successfully imported'});
|
||||
}).otherwise(function importFailure(error) {
|
||||
return when.reject({code: 500, message: error.message || error});
|
||||
}).finally(function () {
|
||||
// Unlink the file after import
|
||||
return nodefn.call(fs.unlink, options.importfile.path);
|
||||
});
|
||||
|
||||
if (error !== "") {
|
||||
return when.reject(new Error(error));
|
||||
}
|
||||
// Import for the current version
|
||||
return dataImport(databaseVersion, importData);
|
||||
|
||||
}).then(function importSuccess() {
|
||||
return api.settings.updateSettingsCache();
|
||||
}).then(function () {
|
||||
return when.resolve({message: 'Posts, tags and other data successfully imported'});
|
||||
}).otherwise(function importFailure(error) {
|
||||
return when.reject({code: 500, message: error.message || error});
|
||||
}).finally(function () {
|
||||
// Unlink the file after import
|
||||
return nodefn.call(fs.unlink, options.importfile.path);
|
||||
}, function () {
|
||||
return when.reject({code: 403, message: 'You do not have permission to export data. (no rights)'});
|
||||
});
|
||||
},
|
||||
'deleteAllContent': function () {
|
||||
return when(dataProvider.deleteAllContent())
|
||||
.then(function () {
|
||||
return when.resolve({message: 'Successfully deleted all content from your blog.'});
|
||||
}, function (error) {
|
||||
return when.reject({code: 500, message: error.message || error});
|
||||
});
|
||||
var self = this;
|
||||
|
||||
return canThis(self.user).deleteAllContent.db().then(function () {
|
||||
return when(dataProvider.deleteAllContent())
|
||||
.then(function () {
|
||||
return when.resolve({message: 'Successfully deleted all content from your blog.'});
|
||||
}, function (error) {
|
||||
return when.reject({code: 500, message: error.message || error});
|
||||
});
|
||||
}, function () {
|
||||
return when.reject({code: 403, message: 'You do not have permission to export data. (no rights)'});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -47,17 +47,17 @@ requestHandler = function (apiMethod) {
|
||||
return function (req, res) {
|
||||
var options = _.extend(req.body, req.files, req.query, req.params),
|
||||
apiContext = {
|
||||
user: req.session && req.session.user
|
||||
user: (req.session && req.session.user) ? req.session.user : null
|
||||
};
|
||||
|
||||
return apiMethod.call(apiContext, options).then(function (result) {
|
||||
res.json(result || {});
|
||||
return cacheInvalidationHeader(req, result).then(function (header) {
|
||||
if (header) {
|
||||
res.set({
|
||||
"X-Cache-Invalidate": header
|
||||
});
|
||||
}
|
||||
res.json(result || {});
|
||||
});
|
||||
}, function (error) {
|
||||
var errorCode = error.code || 500,
|
||||
|
@ -20,8 +20,10 @@ posts = {
|
||||
browse: function browse(options) {
|
||||
options = options || {};
|
||||
|
||||
if (!this.user) {
|
||||
options.status = 'published';
|
||||
}
|
||||
// **returns:** a promise for a page of posts in a json object
|
||||
|
||||
return dataProvider.Post.findPage(options).then(function (result) {
|
||||
var i = 0,
|
||||
omitted = result;
|
||||
@ -35,10 +37,15 @@ posts = {
|
||||
|
||||
// #### Read
|
||||
// **takes:** an identifier (id or slug?)
|
||||
read: function read(args) {
|
||||
// **returns:** a promise for a single post in a json object
|
||||
read: function read(options) {
|
||||
options = options || {};
|
||||
if (!this.user) {
|
||||
// only published posts for
|
||||
options.status = 'published';
|
||||
}
|
||||
|
||||
return dataProvider.Post.findOne(args).then(function (result) {
|
||||
// **returns:** a promise for a single post in a json object
|
||||
return dataProvider.Post.findOne(options).then(function (result) {
|
||||
var omitted;
|
||||
|
||||
if (result) {
|
||||
@ -51,26 +58,15 @@ posts = {
|
||||
});
|
||||
},
|
||||
|
||||
generateSlug: function getSlug(args) {
|
||||
return dataProvider.Base.Model.generateSlug(dataProvider.Post, args.title, {status: 'all'}).then(function (slug) {
|
||||
if (slug) {
|
||||
return slug;
|
||||
}
|
||||
return when.reject({code: 500, message: 'Could not generate slug'});
|
||||
});
|
||||
},
|
||||
|
||||
// #### Edit
|
||||
// **takes:** a json object with all the properties which should be updated
|
||||
edit: function edit(postData) {
|
||||
// **returns:** a promise for the resulting post in a json object
|
||||
if (!this.user) {
|
||||
return when.reject({code: 403, message: 'You do not have permission to edit this post.'});
|
||||
}
|
||||
var self = this;
|
||||
|
||||
return canThis(self.user).edit.post(postData.id).then(function () {
|
||||
return checkPostData(postData).then(function (checkedPostData) {
|
||||
return dataProvider.Post.edit(checkedPostData.posts[0]);
|
||||
return dataProvider.Post.edit(checkedPostData.posts[0], {user: self.user});
|
||||
}).then(function (result) {
|
||||
if (result) {
|
||||
var omitted = result.toJSON();
|
||||
@ -87,14 +83,11 @@ posts = {
|
||||
// #### Add
|
||||
// **takes:** a json object representing a post,
|
||||
add: function add(postData) {
|
||||
var self = this;
|
||||
// **returns:** a promise for the resulting post in a json object
|
||||
if (!this.user) {
|
||||
return when.reject({code: 403, message: 'You do not have permission to add posts.'});
|
||||
}
|
||||
|
||||
return canThis(this.user).create.post().then(function () {
|
||||
return checkPostData(postData).then(function (checkedPostData) {
|
||||
return dataProvider.Post.add(checkedPostData.posts[0]);
|
||||
return dataProvider.Post.add(checkedPostData.posts[0], {user: self.user});
|
||||
}).then(function (result) {
|
||||
var omitted = result.toJSON();
|
||||
omitted.author = _.omit(omitted.author, filteredUserAttributes);
|
||||
@ -108,13 +101,11 @@ posts = {
|
||||
// #### Destroy
|
||||
// **takes:** an identifier (id or slug?)
|
||||
destroy: function destroy(args) {
|
||||
var self = this;
|
||||
// **returns:** a promise for a json response with the id of the deleted post
|
||||
if (!this.user) {
|
||||
return when.reject({code: 403, message: 'You do not have permission to remove posts.'});
|
||||
}
|
||||
|
||||
return canThis(this.user).remove.post(args.id).then(function () {
|
||||
return posts.read({id : args.id, status: 'all'}).then(function (result) {
|
||||
// TODO: Would it be good to get rid of .call()?
|
||||
return posts.read.call({user: self.user}, {id : args.id, status: 'all'}).then(function (result) {
|
||||
return dataProvider.Post.destroy(args.id).then(function () {
|
||||
var deletedObj = result;
|
||||
return deletedObj;
|
||||
@ -123,7 +114,25 @@ posts = {
|
||||
}, function () {
|
||||
return when.reject({code: 403, message: 'You do not have permission to remove posts.'});
|
||||
});
|
||||
},
|
||||
|
||||
// #### Generate slug
|
||||
|
||||
// **takes:** a string to generate the slug from
|
||||
generateSlug: function generateSlug(args) {
|
||||
|
||||
return canThis(this.user).slug.post().then(function () {
|
||||
return dataProvider.Base.Model.generateSlug(dataProvider.Post, args.title, {status: 'all'}).then(function (slug) {
|
||||
if (slug) {
|
||||
return slug;
|
||||
}
|
||||
return when.reject({code: 500, message: 'Could not generate slug'});
|
||||
});
|
||||
}, function () {
|
||||
return when.reject({code: 403, message: 'You do not have permission.'});
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = posts;
|
@ -181,16 +181,19 @@ settings = {
|
||||
|
||||
// **takes:** either a json object representing a collection of settings, or a key and value pair
|
||||
edit: function edit(key, value) {
|
||||
var self = this,
|
||||
type;
|
||||
|
||||
// Check for passing a collection of settings first
|
||||
if (_.isObject(key)) {
|
||||
//clean data
|
||||
var type = key.type;
|
||||
type = key.type;
|
||||
delete key.type;
|
||||
delete key.availableThemes;
|
||||
delete key.availableApps;
|
||||
|
||||
key = settingsCollection(key);
|
||||
return dataProvider.Settings.edit(key).then(function (result) {
|
||||
return dataProvider.Settings.edit(key, {user: self.user}).then(function (result) {
|
||||
result.models = result;
|
||||
return when(readSettingsResult(result)).then(function (settings) {
|
||||
updateSettingsCache(settings);
|
||||
@ -216,7 +219,7 @@ settings = {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
setting.set('value', value);
|
||||
return dataProvider.Settings.edit(setting).then(function (result) {
|
||||
return dataProvider.Settings.edit(setting, {user: self.user}).then(function (result) {
|
||||
settingsCache[_.first(result).attributes.key].value = _.first(result).attributes.value;
|
||||
}).then(function () {
|
||||
return config.theme.update(settings, config().url).then(function () {
|
||||
|
@ -2,6 +2,7 @@ var when = require('when'),
|
||||
_ = require('lodash'),
|
||||
dataProvider = require('../models'),
|
||||
settings = require('./settings'),
|
||||
canThis = require('../permissions').canThis,
|
||||
ONE_DAY = 86400000,
|
||||
filteredAttributes = ['password', 'created_by', 'updated_by', 'last_login'],
|
||||
users;
|
||||
@ -13,20 +14,23 @@ users = {
|
||||
// **takes:** options object
|
||||
browse: function browse(options) {
|
||||
// **returns:** a promise for a collection of users in a json object
|
||||
return canThis(this.user).browse.user().then(function () {
|
||||
return dataProvider.User.browse(options).then(function (result) {
|
||||
var i = 0,
|
||||
omitted = {};
|
||||
|
||||
return dataProvider.User.browse(options).then(function (result) {
|
||||
var i = 0,
|
||||
omitted = {};
|
||||
if (result) {
|
||||
omitted = result.toJSON();
|
||||
}
|
||||
|
||||
if (result) {
|
||||
omitted = result.toJSON();
|
||||
}
|
||||
for (i = 0; i < omitted.length; i = i + 1) {
|
||||
omitted[i] = _.omit(omitted[i], filteredAttributes);
|
||||
}
|
||||
|
||||
for (i = 0; i < omitted.length; i = i + 1) {
|
||||
omitted[i] = _.omit(omitted[i], filteredAttributes);
|
||||
}
|
||||
|
||||
return omitted;
|
||||
return omitted;
|
||||
});
|
||||
}, function () {
|
||||
return when.reject({code: 403, message: 'You do not have permission to browse users.'});
|
||||
});
|
||||
},
|
||||
|
||||
@ -52,22 +56,44 @@ users = {
|
||||
// **takes:** a json object representing a user
|
||||
edit: function edit(userData) {
|
||||
// **returns:** a promise for the resulting user in a json object
|
||||
var self = this;
|
||||
userData.id = this.user;
|
||||
return dataProvider.User.edit(userData).then(function (result) {
|
||||
if (result) {
|
||||
var omitted = _.omit(result.toJSON(), filteredAttributes);
|
||||
return omitted;
|
||||
}
|
||||
return when.reject({code: 404, message: 'User not found'});
|
||||
return canThis(this.user).edit.user(userData.id).then(function () {
|
||||
return dataProvider.User.edit(userData, {user: self.user}).then(function (result) {
|
||||
if (result) {
|
||||
var omitted = _.omit(result.toJSON(), filteredAttributes);
|
||||
return omitted;
|
||||
}
|
||||
return when.reject({code: 404, message: 'User not found'});
|
||||
});
|
||||
}, function () {
|
||||
return when.reject({code: 403, message: 'You do not have permission to edit this users.'});
|
||||
});
|
||||
},
|
||||
|
||||
// #### Add
|
||||
// **takes:** a json object representing a user
|
||||
add: function add(userData) {
|
||||
|
||||
// **returns:** a promise for the resulting user in a json object
|
||||
return dataProvider.User.add(userData);
|
||||
var self = this;
|
||||
return canThis(this.user).add.user().then(function () {
|
||||
// if the user is created by users.register(), use id: 1
|
||||
// as the creator for now
|
||||
if (self.user === 'internal') {
|
||||
self.user = 1;
|
||||
}
|
||||
return dataProvider.User.add(userData, {user: self.user});
|
||||
}, function () {
|
||||
return when.reject({code: 403, message: 'You do not have permission to add a users.'});
|
||||
});
|
||||
},
|
||||
|
||||
// #### Register
|
||||
// **takes:** a json object representing a user
|
||||
register: function register(userData) {
|
||||
// TODO: if we want to prevent users from being created with the signup form
|
||||
// this is the right place to do it
|
||||
return users.add.call({user: 'internal'}, userData);
|
||||
},
|
||||
|
||||
// #### Check
|
||||
@ -103,6 +129,15 @@ users = {
|
||||
return settings.read('dbHash').then(function (dbHash) {
|
||||
return dataProvider.User.resetPassword(token, newPassword, ne2Password, dbHash);
|
||||
});
|
||||
},
|
||||
|
||||
doesUserExist: function doesUserExist() {
|
||||
return dataProvider.User.browse().then(function (users) {
|
||||
if (users.length === 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -26,7 +26,7 @@ function saveInstalledApps(installedApps) {
|
||||
return getInstalledApps().then(function (currentInstalledApps) {
|
||||
var updatedAppsInstalled = _.uniq(installedApps.concat(currentInstalledApps));
|
||||
|
||||
return api.settings.edit('installedApps', updatedAppsInstalled);
|
||||
return api.settings.edit.call({user: 1}, 'installedApps', updatedAppsInstalled);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ var path = require('path'),
|
||||
config = require('../config'),
|
||||
AppSandbox = require('./sandbox'),
|
||||
AppDependencies = require('./dependencies'),
|
||||
AppPermissions = require('./permissions'),
|
||||
loader;
|
||||
|
||||
// Get the full path to an app by name
|
||||
@ -48,37 +49,53 @@ loader = {
|
||||
// Load a app and return the instantiated app
|
||||
installAppByName: function (name) {
|
||||
// Install the apps dependendencies first
|
||||
var deps = new AppDependencies(getAppAbsolutePath(name));
|
||||
return deps.install().then(function () {
|
||||
var app = getAppByName(name);
|
||||
var appPath = getAppAbsolutePath(name),
|
||||
deps = new AppDependencies(appPath);
|
||||
|
||||
// Check for an install() method on the app.
|
||||
if (!_.isFunction(app.install)) {
|
||||
return when.reject(new Error("Error loading app named " + name + "; no install() method defined."));
|
||||
}
|
||||
return deps.install()
|
||||
.then(function () {
|
||||
// Load app permissions
|
||||
var perms = new AppPermissions(appPath);
|
||||
|
||||
// Run the app.install() method
|
||||
// Wrapping the install() with a when because it's possible
|
||||
// to not return a promise from it.
|
||||
return when(app.install(appProxy)).then(function () {
|
||||
return when.resolve(app);
|
||||
return perms.read().otherwise(function (err) {
|
||||
// Provide a helpful error about which app
|
||||
return when.reject(new Error("Error loading app named " + name + "; problem reading permissions: " + err.message));
|
||||
});
|
||||
})
|
||||
.then(function (appPerms) {
|
||||
var app = getAppByName(name, appPerms);
|
||||
|
||||
// Check for an install() method on the app.
|
||||
if (!_.isFunction(app.install)) {
|
||||
return when.reject(new Error("Error loading app named " + name + "; no install() method defined."));
|
||||
}
|
||||
|
||||
// Run the app.install() method
|
||||
// Wrapping the install() with a when because it's possible
|
||||
// to not return a promise from it.
|
||||
return when(app.install(appProxy)).then(function () {
|
||||
return when.resolve(app);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// Activate a app and return it
|
||||
activateAppByName: function (name) {
|
||||
var app = getAppByName(name);
|
||||
var perms = new AppPermissions(getAppAbsolutePath(name));
|
||||
|
||||
// Check for an activate() method on the app.
|
||||
if (!_.isFunction(app.activate)) {
|
||||
return when.reject(new Error("Error loading app named " + name + "; no activate() method defined."));
|
||||
}
|
||||
return perms.read().then(function (appPerms) {
|
||||
var app = getAppByName(name, appPerms);
|
||||
|
||||
// Wrapping the activate() with a when because it's possible
|
||||
// to not return a promise from it.
|
||||
return when(app.activate(appProxy)).then(function () {
|
||||
return when.resolve(app);
|
||||
// Check for an activate() method on the app.
|
||||
if (!_.isFunction(app.activate)) {
|
||||
return when.reject(new Error("Error loading app named " + name + "; no activate() method defined."));
|
||||
}
|
||||
|
||||
// Wrapping the activate() with a when because it's possible
|
||||
// to not return a promise from it.
|
||||
return when(app.activate(appProxy)).then(function () {
|
||||
return when.resolve(app);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
75
core/server/apps/permissions.js
Normal file
75
core/server/apps/permissions.js
Normal file
@ -0,0 +1,75 @@
|
||||
|
||||
var fs = require('fs'),
|
||||
when = require('when'),
|
||||
path = require('path'),
|
||||
parsePackageJson = require('../require-tree').parsePackageJson;
|
||||
|
||||
function AppPermissions(appPath) {
|
||||
this.appPath = appPath;
|
||||
this.packagePath = path.join(this.appPath, 'package.json');
|
||||
}
|
||||
|
||||
AppPermissions.prototype.read = function () {
|
||||
var self = this,
|
||||
def = when.defer();
|
||||
|
||||
this.checkPackageContentsExists()
|
||||
.then(function (exists) {
|
||||
if (!exists) {
|
||||
// If no package.json, return default permissions
|
||||
return def.resolve(AppPermissions.DefaultPermissions);
|
||||
}
|
||||
|
||||
// Read and parse the package.json
|
||||
self.getPackageContents()
|
||||
.then(function (parsed) {
|
||||
// If no permissions in the package.json then return the default permissions.
|
||||
if (!(parsed.ghost && parsed.ghost.permissions)) {
|
||||
return def.resolve(AppPermissions.DefaultPermissions);
|
||||
}
|
||||
|
||||
// TODO: Validation on permissions object?
|
||||
|
||||
def.resolve(parsed.ghost.permissions);
|
||||
})
|
||||
.otherwise(def.reject);
|
||||
})
|
||||
.otherwise(def.reject);
|
||||
|
||||
return def.promise;
|
||||
};
|
||||
|
||||
AppPermissions.prototype.checkPackageContentsExists = function () {
|
||||
// Mostly just broken out for stubbing in unit tests
|
||||
var def = when.defer();
|
||||
|
||||
fs.exists(this.packagePath, function (exists) {
|
||||
def.resolve(exists);
|
||||
});
|
||||
|
||||
return def.promise;
|
||||
};
|
||||
|
||||
// Get the contents of the package.json in the appPath root
|
||||
AppPermissions.prototype.getPackageContents = function () {
|
||||
var messages = {
|
||||
errors: [],
|
||||
warns: []
|
||||
};
|
||||
|
||||
return parsePackageJson(this.packagePath, messages)
|
||||
.then(function (parsed) {
|
||||
if (!parsed) {
|
||||
return when.reject(new Error(messages.errors[0].message));
|
||||
}
|
||||
|
||||
return parsed;
|
||||
});
|
||||
};
|
||||
|
||||
// Default permissions for an App.
|
||||
AppPermissions.DefaultPermissions = {
|
||||
posts: ['browse', 'read']
|
||||
};
|
||||
|
||||
module.exports = AppPermissions;
|
@ -122,7 +122,7 @@ adminControllers = {
|
||||
}).otherwise(function (err) {
|
||||
var notification = {
|
||||
type: 'error',
|
||||
message: 'Your export file could not be generated.',
|
||||
message: 'Your export file could not be generated. Error: ' + err.message,
|
||||
status: 'persistent',
|
||||
id: 'errorexport'
|
||||
};
|
||||
@ -244,12 +244,12 @@ adminControllers = {
|
||||
email = req.body.email,
|
||||
password = req.body.password;
|
||||
|
||||
api.users.add({
|
||||
api.users.register({
|
||||
name: name,
|
||||
email: email,
|
||||
password: password
|
||||
}).then(function (user) {
|
||||
api.settings.edit('email', email).then(function () {
|
||||
api.settings.edit.call({user: 1}, 'email', email).then(function () {
|
||||
var message = {
|
||||
to: email,
|
||||
subject: 'Your New Ghost Blog',
|
||||
|
@ -266,7 +266,7 @@ frontendControllers = {
|
||||
|
||||
// TODO: needs refactor for multi user to not use first user as default
|
||||
return when.settle([
|
||||
api.users.read({id : 1}),
|
||||
api.users.read.call({user : 'internal'}, {id : 1}),
|
||||
api.settings.read('title'),
|
||||
api.settings.read('description'),
|
||||
api.settings.read('permalinks')
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"core": {
|
||||
"databaseVersion": {
|
||||
"defaultValue": "002"
|
||||
"defaultValue": "003"
|
||||
},
|
||||
"dbHash": {
|
||||
"defaultValue": null
|
||||
|
@ -1,9 +1,13 @@
|
||||
var sequence = require('when/sequence'),
|
||||
_ = require('lodash'),
|
||||
Post = require('../../models/post').Post,
|
||||
Tag = require('../../models/tag').Tag,
|
||||
Role = require('../../models/role').Role,
|
||||
Permission = require('../../models/permission').Permission;
|
||||
var sequence = require('when/sequence'),
|
||||
_ = require('lodash'),
|
||||
Post = require('../../models/post').Post,
|
||||
Tag = require('../../models/tag').Tag,
|
||||
Role = require('../../models/role').Role,
|
||||
Permission = require('../../models/permission').Permission,
|
||||
Permissions = require('../../models/permission').Permissions,
|
||||
|
||||
populateFixtures,
|
||||
updateFixtures;
|
||||
|
||||
var fixtures = {
|
||||
posts: [
|
||||
@ -63,42 +67,226 @@ var fixtures = {
|
||||
"action_type": "create",
|
||||
"object_type": "post"
|
||||
}
|
||||
],
|
||||
|
||||
permissions003: [
|
||||
{
|
||||
"name": "Get slug",
|
||||
"action_type": "slug",
|
||||
"object_type": "post"
|
||||
},
|
||||
{
|
||||
"name": "Export database",
|
||||
"action_type": "exportContent",
|
||||
"object_type": "db"
|
||||
},
|
||||
{
|
||||
"name": "Import database",
|
||||
"action_type": "importContent",
|
||||
"object_type": "db"
|
||||
},
|
||||
{
|
||||
"name": "Delete all content",
|
||||
"action_type": "deleteAllContent",
|
||||
"object_type": "db"
|
||||
},
|
||||
{
|
||||
"name": "Browse users",
|
||||
"action_type": "browse",
|
||||
"object_type": "user"
|
||||
},
|
||||
{
|
||||
"name": "Read users",
|
||||
"action_type": "read",
|
||||
"object_type": "user"
|
||||
},
|
||||
{
|
||||
"name": "Edit users",
|
||||
"action_type": "edit",
|
||||
"object_type": "user"
|
||||
},
|
||||
{
|
||||
"name": "Add users",
|
||||
"action_type": "add",
|
||||
"object_type": "user"
|
||||
},
|
||||
{
|
||||
"name": "Browse settings",
|
||||
"action_type": "browse",
|
||||
"object_type": "setting"
|
||||
},
|
||||
{
|
||||
"name": "Read settings",
|
||||
"action_type": "read",
|
||||
"object_type": "setting"
|
||||
},
|
||||
{
|
||||
"name": "Edit settings",
|
||||
"action_type": "edit",
|
||||
"object_type": "setting"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
populateFixtures: function () {
|
||||
var ops = [];
|
||||
populateFixtures = function () {
|
||||
var ops = [],
|
||||
relations = [];
|
||||
|
||||
_.each(fixtures.posts, function (post) {
|
||||
ops.push(function () {return Post.add(post); });
|
||||
});
|
||||
_.each(fixtures.posts, function (post) {
|
||||
ops.push(function () {return Post.add(post, {user: 1}); });
|
||||
});
|
||||
|
||||
_.each(fixtures.tags, function (tag) {
|
||||
ops.push(function () {return Tag.add(tag); });
|
||||
});
|
||||
_.each(fixtures.tags, function (tag) {
|
||||
ops.push(function () {return Tag.add(tag, {user: 1}); });
|
||||
});
|
||||
|
||||
_.each(fixtures.roles, function (role) {
|
||||
ops.push(function () {return Role.add(role); });
|
||||
});
|
||||
_.each(fixtures.permissions, function (permission) {
|
||||
ops.push(function () {return Permission.add(permission); });
|
||||
});
|
||||
_.each(fixtures.roles, function (role) {
|
||||
ops.push(function () {return Role.add(role, {user: 1}); });
|
||||
});
|
||||
|
||||
// add the tag to the post
|
||||
ops.push(function () {
|
||||
Post.forge({id: 1}).fetch({withRelated: ['tags']}).then(function (post) {
|
||||
post.tags().attach([1]);
|
||||
_.each(fixtures.permissions, function (permission) {
|
||||
ops.push(function () {return Permission.add(permission, {user: 1}); });
|
||||
});
|
||||
|
||||
_.each(fixtures.permissions003, function (permission) {
|
||||
ops.push(function () {return Permission.add(permission, {user: 1}); });
|
||||
});
|
||||
|
||||
// add the tag to the post
|
||||
relations.push(function () {
|
||||
Post.forge({id: 1}).fetch({withRelated: ['tags']}).then(function (post) {
|
||||
post.tags().attach([1]);
|
||||
});
|
||||
});
|
||||
|
||||
//grant permissions to roles
|
||||
relations.push(function () {
|
||||
// admins gets all permissions
|
||||
Role.forge({name: 'Administrator'}).fetch({withRelated: ['permissions']}).then(function (role) {
|
||||
Permissions.forge().fetch().then(function (perms) {
|
||||
var admin_perm = _.map(perms.toJSON(), function (perm) {
|
||||
return perm.id;
|
||||
});
|
||||
return role.permissions().attach(_.compact(admin_perm));
|
||||
});
|
||||
});
|
||||
|
||||
// finally, grant admins all permissions
|
||||
ops.push(function () {
|
||||
Role.forge({id: 1}).fetch({withRelated: ['permissions']}).then(function (role) {
|
||||
role.permissions().attach([1, 2, 3]);
|
||||
// editor gets access to posts, users and settings.browse, settings.read
|
||||
Role.forge({name: 'Editor'}).fetch({withRelated: ['permissions']}).then(function (role) {
|
||||
Permissions.forge().fetch().then(function (perms) {
|
||||
var editor_perm = _.map(perms.toJSON(), function (perm) {
|
||||
if (perm.object_type === 'post' || perm.object_type === 'user') {
|
||||
return perm.id;
|
||||
}
|
||||
if (perm.object_type === 'setting' &&
|
||||
(perm.action_type === 'browse' || perm.action_type === 'read')) {
|
||||
return perm.id;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
return role.permissions().attach(_.compact(editor_perm));
|
||||
});
|
||||
});
|
||||
|
||||
return sequence(ops);
|
||||
}
|
||||
// author gets access to post.add, post.slug, settings.browse, settings.read, users.browse and users.read
|
||||
Role.forge({name: 'Author'}).fetch({withRelated: ['permissions']}).then(function (role) {
|
||||
Permissions.forge().fetch().then(function (perms) {
|
||||
var author_perm = _.map(perms.toJSON(), function (perm) {
|
||||
if (perm.object_type === 'post' &&
|
||||
(perm.action_type === 'add' || perm.action_type === 'slug')) {
|
||||
return perm.id;
|
||||
}
|
||||
if (perm.object_type === 'setting' &&
|
||||
(perm.action_type === 'browse' || perm.action_type === 'read')) {
|
||||
return perm.id;
|
||||
}
|
||||
if (perm.object_type === 'user' &&
|
||||
(perm.action_type === 'browse' || perm.action_type === 'read')) {
|
||||
return perm.id;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
return role.permissions().attach(_.compact(author_perm));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return sequence(ops).then(function () {
|
||||
sequence(relations);
|
||||
});
|
||||
};
|
||||
|
||||
updateFixtures = function () {
|
||||
var ops = [],
|
||||
relations = [];
|
||||
|
||||
_.each(fixtures.permissions003, function (permission) {
|
||||
ops.push(function () {return Permission.add(permission, {user: 1}); });
|
||||
});
|
||||
|
||||
relations.push(function () {
|
||||
// admin gets all new permissions
|
||||
Role.forge({name: 'Administrator'}).fetch({withRelated: ['permissions']}).then(function (role) {
|
||||
Permissions.forge().fetch().then(function (perms) {
|
||||
var admin_perm = _.map(perms.toJSON(), function (perm) {
|
||||
var result = fixtures.permissions003.filter(function (object) {
|
||||
return object.object_type === perm.object_type && object.action_type === perm.action_type;
|
||||
});
|
||||
if (!_.isEmpty(result)) {
|
||||
return perm.id;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
return role.permissions().attach(_.compact(admin_perm));
|
||||
});
|
||||
});
|
||||
|
||||
// editor gets access to posts, users and settings.browse, settings.read
|
||||
Role.forge({name: 'Editor'}).fetch({withRelated: ['permissions']}).then(function (role) {
|
||||
Permissions.forge().fetch().then(function (perms) {
|
||||
var editor_perm = _.map(perms.toJSON(), function (perm) {
|
||||
if (perm.object_type === 'post' || perm.object_type === 'user') {
|
||||
return perm.id;
|
||||
}
|
||||
if (perm.object_type === 'setting' &&
|
||||
(perm.action_type === 'browse' || perm.action_type === 'read')) {
|
||||
return perm.id;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
return role.permissions().attach(_.compact(editor_perm));
|
||||
});
|
||||
});
|
||||
|
||||
// author gets access to post.add, post.slug, settings.browse, settings.read, users.browse and users.read
|
||||
Role.forge({name: 'Author'}).fetch({withRelated: ['permissions']}).then(function (role) {
|
||||
Permissions.forge().fetch().then(function (perms) {
|
||||
var author_perm = _.map(perms.toJSON(), function (perm) {
|
||||
if (perm.object_type === 'post' &&
|
||||
(perm.action_type === 'add' || perm.action_type === 'slug')) {
|
||||
return perm.id;
|
||||
}
|
||||
if (perm.object_type === 'setting' &&
|
||||
(perm.action_type === 'browse' || perm.action_type === 'read')) {
|
||||
return perm.id;
|
||||
}
|
||||
if (perm.object_type === 'user' &&
|
||||
(perm.action_type === 'browse' || perm.action_type === 'read')) {
|
||||
return perm.id;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
return role.permissions().attach(_.compact(author_perm));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return sequence(ops).then(function () {
|
||||
sequence(relations);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
populateFixtures: populateFixtures,
|
||||
updateFixtures: updateFixtures
|
||||
};
|
||||
|
@ -12,7 +12,8 @@ Importer000 = function () {
|
||||
this.importFrom = {
|
||||
'000': this.basicImport,
|
||||
'001': this.basicImport,
|
||||
'002': this.basicImport
|
||||
'002': this.basicImport,
|
||||
'003': this.basicImport
|
||||
};
|
||||
};
|
||||
|
||||
@ -35,6 +36,7 @@ Importer000.prototype.canImport = function (data) {
|
||||
|
||||
|
||||
function stripProperties(properties, data) {
|
||||
data = _.clone(data, true);
|
||||
_.each(data, function (obj) {
|
||||
_.each(properties, function (property) {
|
||||
delete obj[property];
|
||||
@ -82,7 +84,7 @@ 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, {user: 1, transacting: transaction})
|
||||
// add pass-through error handling so that bluebird doesn't think we've dropped it
|
||||
.otherwise(function (error) { return when.reject(error); });
|
||||
}
|
||||
@ -94,7 +96,7 @@ 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, {user: 1, 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); }));
|
||||
});
|
||||
@ -104,7 +106,7 @@ function importUsers(ops, tableData, transaction) {
|
||||
// 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], {user: 1, transacting: transaction})
|
||||
// add pass-through error handling so that bluebird doesn't think we've dropped it
|
||||
.otherwise(function (error) { return when.reject(error); }));
|
||||
}
|
||||
@ -119,12 +121,52 @@ function importSettings(ops, tableData, transaction) {
|
||||
tableData = _.filter(tableData, function (data) {
|
||||
return blackList.indexOf(data.type) === -1;
|
||||
});
|
||||
|
||||
ops.push(models.Settings.edit(tableData, transaction)
|
||||
ops.push(models.Settings.edit(tableData, {user: 1, 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 importApps(ops, tableData, transaction) {
|
||||
tableData = stripProperties(['id'], tableData);
|
||||
_.each(tableData, function (app) {
|
||||
// Avoid duplicates
|
||||
ops.push(models.App.findOne({name: app.name}, {transacting: transaction}).then(function (_app) {
|
||||
if (!_app) {
|
||||
return models.App.add(app, {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(_app);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
// function importAppSettings(ops, tableData, transaction) {
|
||||
// var appsData = tableData.apps,
|
||||
// appSettingsData = tableData.app_settings,
|
||||
// appName;
|
||||
//
|
||||
// appSettingsData = stripProperties(['id'], appSettingsData);
|
||||
//
|
||||
// _.each(appSettingsData, function (appSetting) {
|
||||
// // Find app to attach settings to
|
||||
// appName = _.find(appsData, function (app) {
|
||||
// return app.id === appSetting.app_id;
|
||||
// }).name;
|
||||
// ops.push(models.App.findOne({name: appName}, {transacting: transaction}).then(function (_app) {
|
||||
// if (_app) {
|
||||
// // Fix app_id
|
||||
// appSetting.app_id = _app.id;
|
||||
// return models.AppSetting.add(appSetting, {transacting: transaction})
|
||||
// // add pass-through error handling so that bluebird doesn't think we've dropped it
|
||||
// .otherwise(function (error) { return when.reject(error); });
|
||||
// }
|
||||
// // Gracefully ignore missing apps
|
||||
// return when.resolve(_app);
|
||||
// }));
|
||||
// });
|
||||
// }
|
||||
|
||||
// No data needs modifying, we just import whatever tables are available
|
||||
Importer000.prototype.basicImport = function (data) {
|
||||
var ops = [],
|
||||
@ -153,6 +195,20 @@ Importer000.prototype.basicImport = function (data) {
|
||||
importSettings(ops, tableData.settings, t);
|
||||
}
|
||||
|
||||
if (tableData.apps && tableData.apps.length) {
|
||||
importApps(ops, tableData.apps, t);
|
||||
|
||||
// ToDo: This is rather complicated
|
||||
// Only import settings if there are apps defined
|
||||
//if (tableData.app_settings && tableData.app_settings.length) {
|
||||
// importAppSettings(ops, _.pick(tableData, 'apps', 'app_settings'), t);
|
||||
//}
|
||||
|
||||
//if (tableData.app_fields && tableData.app_fields.length) {
|
||||
// importAppFields(ops, _.pick(tableData, 'apps', 'posts', 'app_fields'), t);
|
||||
//}
|
||||
}
|
||||
|
||||
/** do nothing with these tables, the data shouldn't have changed from the fixtures
|
||||
* permissions
|
||||
* roles
|
||||
@ -177,10 +233,10 @@ Importer000.prototype.basicImport = function (data) {
|
||||
rej = true;
|
||||
}
|
||||
});
|
||||
if (rej) {
|
||||
t.rollback(error);
|
||||
} else {
|
||||
if (!rej) {
|
||||
t.commit();
|
||||
} else {
|
||||
t.rollback(error);
|
||||
}
|
||||
});
|
||||
}).then(function () {
|
||||
|
8
core/server/data/import/003.js
Normal file
8
core/server/data/import/003.js
Normal file
@ -0,0 +1,8 @@
|
||||
var Importer000 = require('./000');
|
||||
|
||||
module.exports = {
|
||||
Importer003: Importer000,
|
||||
importData: function (data) {
|
||||
return new Importer000.importData(data);
|
||||
}
|
||||
};
|
@ -252,7 +252,7 @@ function checkMySQLPostTable() {
|
||||
// Migrate from a specific version to the latest
|
||||
migrateUp = function () {
|
||||
return getTables().then(function (oldTables) {
|
||||
// if tables exist and lient is mysqls check if posts table is okay
|
||||
// if tables exist and client is mysqls check if posts table is okay
|
||||
if (!_.isEmpty(oldTables) && client === 'mysql') {
|
||||
return checkMySQLPostTable().then(function () {
|
||||
return oldTables;
|
||||
@ -274,6 +274,8 @@ migrateUp = function () {
|
||||
return sequence(commands);
|
||||
}
|
||||
return;
|
||||
}).then(function () {
|
||||
return fixtures.updateFixtures();
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -81,6 +81,11 @@ var db = {
|
||||
role_id: {type: 'integer', nullable: false},
|
||||
permission_id: {type: 'integer', nullable: false}
|
||||
},
|
||||
permissions_apps: {
|
||||
id: {type: 'increments', nullable: false, primary: true},
|
||||
app_id: {type: 'integer', nullable: false},
|
||||
permission_id: {type: 'integer', nullable: false}
|
||||
},
|
||||
sessions: {
|
||||
id: {type: 'string', nullable: false, primary: true},
|
||||
expires: {type: 'bigInteger', nullable: false},
|
||||
@ -115,12 +120,49 @@ var db = {
|
||||
id: {type: 'increments', nullable: false, primary: true},
|
||||
post_id: {type: 'integer', nullable: false, unsigned: true, references: 'id', inTable: 'posts'},
|
||||
tag_id: {type: 'integer', nullable: false, unsigned: true, references: 'id', inTable: 'tags'}
|
||||
},
|
||||
apps: {
|
||||
id: {type: 'increments', nullable: false, primary: true},
|
||||
uuid: {type: 'string', maxlength: 36, nullable: false},
|
||||
name: {type: 'string', maxlength: 150, nullable: false, unique: true},
|
||||
slug: {type: 'string', maxlength: 150, nullable: false, unique: true},
|
||||
version: {type: 'string', maxlength: 150, nullable: false},
|
||||
status: {type: 'string', maxlength: 150, nullable: false, defaultTo: 'inactive'},
|
||||
created_at: {type: 'dateTime', nullable: false},
|
||||
created_by: {type: 'integer', nullable: false},
|
||||
updated_at: {type: 'dateTime', nullable: true},
|
||||
updated_by: {type: 'integer', nullable: true}
|
||||
},
|
||||
app_settings: {
|
||||
id: {type: 'increments', nullable: false, primary: true},
|
||||
uuid: {type: 'string', maxlength: 36, nullable: false},
|
||||
key: {type: 'string', maxlength: 150, nullable: false, unique: true},
|
||||
value: {type: 'text', maxlength: 65535, nullable: true},
|
||||
app_id: {type: 'integer', nullable: false, unsigned: true, references: 'id', inTable: 'apps'},
|
||||
created_at: {type: 'dateTime', nullable: false},
|
||||
created_by: {type: 'integer', nullable: false},
|
||||
updated_at: {type: 'dateTime', nullable: true},
|
||||
updated_by: {type: 'integer', nullable: true}
|
||||
},
|
||||
app_fields: {
|
||||
id: {type: 'increments', nullable: false, primary: true},
|
||||
uuid: {type: 'string', maxlength: 36, nullable: false},
|
||||
key: {type: 'string', maxlength: 150, nullable: false},
|
||||
value: {type: 'text', maxlength: 65535, nullable: true},
|
||||
type: {type: 'string', maxlength: 150, nullable: false, defaultTo: 'html'},
|
||||
app_id: {type: 'integer', nullable: false, unsigned: true, references: 'id', inTable: 'apps'},
|
||||
relatable_id: {type: 'integer', nullable: false, unsigned: true},
|
||||
relatable_type: {type: 'string', maxlength: 150, nullable: false, defaultTo: 'posts'},
|
||||
created_at: {type: 'dateTime', nullable: false},
|
||||
created_by: {type: 'integer', nullable: false},
|
||||
updated_at: {type: 'dateTime', nullable: true},
|
||||
updated_by: {type: 'integer', nullable: true}
|
||||
}
|
||||
};
|
||||
|
||||
function isPost(jsonData) {
|
||||
return jsonData.hasOwnProperty('html') && jsonData.hasOwnProperty('markdown')
|
||||
&& jsonData.hasOwnProperty('title') && jsonData.hasOwnProperty('slug');
|
||||
return jsonData.hasOwnProperty('html') && jsonData.hasOwnProperty('markdown') &&
|
||||
jsonData.hasOwnProperty('title') && jsonData.hasOwnProperty('slug');
|
||||
}
|
||||
|
||||
function isTag(jsonData) {
|
||||
|
@ -60,7 +60,7 @@ function initDbHashAndFirstRun() {
|
||||
|
||||
if (dbHash === null) {
|
||||
var initHash = uuid.v4();
|
||||
return when(api.settings.edit('dbHash', initHash)).then(function (settings) {
|
||||
return when(api.settings.edit.call({user: 1}, 'dbHash', initHash)).then(function (settings) {
|
||||
dbHash = settings.dbHash;
|
||||
return dbHash;
|
||||
}).then(doFirstRun);
|
||||
|
@ -39,7 +39,7 @@ function ghostLocals(req, res, next) {
|
||||
if (res.isAdmin) {
|
||||
res.locals.csrfToken = req.csrfToken();
|
||||
when.all([
|
||||
api.users.read({id: req.session.user}),
|
||||
api.users.read.call({user: req.session.user}, {id: req.session.user}),
|
||||
api.notifications.browse()
|
||||
]).then(function (values) {
|
||||
var currentUser = values[0],
|
||||
@ -159,8 +159,9 @@ function manageAdminAndTheme(req, res, next) {
|
||||
// Redirect to signup if no users are currently created
|
||||
function redirectToSignup(req, res, next) {
|
||||
/*jslint unparam:true*/
|
||||
api.users.browse().then(function (users) {
|
||||
if (users.length === 0) {
|
||||
|
||||
api.users.doesUserExist().then(function (exists) {
|
||||
if (!exists) {
|
||||
return res.redirect(config().paths.subdir + '/ghost/signup/');
|
||||
}
|
||||
next();
|
||||
|
26
core/server/models/app.js
Normal file
26
core/server/models/app.js
Normal file
@ -0,0 +1,26 @@
|
||||
var ghostBookshelf = require('./base'),
|
||||
AppSetting = require('./appSetting'),
|
||||
App,
|
||||
Apps;
|
||||
|
||||
App = ghostBookshelf.Model.extend({
|
||||
tableName: 'apps',
|
||||
|
||||
permissions: function () {
|
||||
// Have to use the require here because of circular dependencies
|
||||
return this.belongsToMany(require('./permission').Permission, 'permissions_apps');
|
||||
},
|
||||
|
||||
settings: function () {
|
||||
return this.belongsToMany(AppSetting, 'app_settings');
|
||||
}
|
||||
});
|
||||
|
||||
Apps = ghostBookshelf.Collection.extend({
|
||||
model: App
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
App: App,
|
||||
Apps: Apps
|
||||
};
|
21
core/server/models/appField.js
Normal file
21
core/server/models/appField.js
Normal file
@ -0,0 +1,21 @@
|
||||
var ghostBookshelf = require('./base'),
|
||||
Post = require('./post').Post,
|
||||
AppField,
|
||||
AppFields;
|
||||
|
||||
AppField = ghostBookshelf.Model.extend({
|
||||
tableName: 'app_fields',
|
||||
|
||||
post: function () {
|
||||
return this.morphOne(Post, 'relatable');
|
||||
}
|
||||
});
|
||||
|
||||
AppFields = ghostBookshelf.Collection.extend({
|
||||
model: AppField
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
AppField: AppField,
|
||||
AppFields: AppFields
|
||||
};
|
21
core/server/models/appSetting.js
Normal file
21
core/server/models/appSetting.js
Normal file
@ -0,0 +1,21 @@
|
||||
var ghostBookshelf = require('./base'),
|
||||
App = require('./app'),
|
||||
AppSetting,
|
||||
AppSettings;
|
||||
|
||||
AppSetting = ghostBookshelf.Model.extend({
|
||||
tableName: 'app_settings',
|
||||
|
||||
app: function () {
|
||||
return this.belongsTo(App);
|
||||
}
|
||||
});
|
||||
|
||||
AppSettings = ghostBookshelf.Collection.extend({
|
||||
model: AppSetting
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
AppSetting: AppSetting,
|
||||
AppSettings: AppSettings
|
||||
};
|
@ -47,20 +47,16 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||
validation.validateSchema(this.tableName, this.toJSON());
|
||||
},
|
||||
|
||||
creating: function () {
|
||||
creating: function (newObj, attr, options) {
|
||||
if (!this.get('created_by')) {
|
||||
this.set('created_by', 1);
|
||||
this.set('created_by', options.user);
|
||||
}
|
||||
},
|
||||
|
||||
saving: function () {
|
||||
// Remove any properties which don't belong on the model
|
||||
saving: function (newObj, attr, options) {
|
||||
// Remove any properties which don't belong on the model
|
||||
this.attributes = this.pick(this.permittedAttributes());
|
||||
|
||||
// sessions do not have 'updated_by' column
|
||||
if (this.tableName !== 'sessions') {
|
||||
this.set('updated_by', 1);
|
||||
}
|
||||
this.set('updated_by', options.user);
|
||||
},
|
||||
|
||||
// Base prototype properties will go here
|
||||
|
@ -11,6 +11,9 @@ module.exports = {
|
||||
Tag: require('./tag').Tag,
|
||||
Base: require('./base'),
|
||||
Session: require('./session').Session,
|
||||
App: require('./app').App,
|
||||
AppField: require('./appField').AppField,
|
||||
AppSetting: require('./appSetting').AppSetting,
|
||||
|
||||
init: function () {
|
||||
return migrations.init();
|
||||
|
@ -1,6 +1,7 @@
|
||||
var ghostBookshelf = require('./base'),
|
||||
User = require('./user').User,
|
||||
Role = require('./role').Role,
|
||||
App = require('./app').App,
|
||||
|
||||
Permission,
|
||||
Permissions;
|
||||
@ -15,6 +16,10 @@ Permission = ghostBookshelf.Model.extend({
|
||||
|
||||
users: function () {
|
||||
return this.belongsToMany(User);
|
||||
},
|
||||
|
||||
apps: function () {
|
||||
return this.belongsToMany(App);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -5,6 +5,7 @@ var _ = require('lodash'),
|
||||
Showdown = require('showdown'),
|
||||
ghostgfm = require('../../shared/lib/showdown/extensions/ghostgfm'),
|
||||
converter = new Showdown.converter({extensions: [ghostgfm]}),
|
||||
AppField = require('./appField').AppField,
|
||||
User = require('./user').User,
|
||||
Tag = require('./tag').Tag,
|
||||
Tags = require('./tag').Tags,
|
||||
@ -52,6 +53,7 @@ Post = ghostBookshelf.Model.extend({
|
||||
tagsToCheck,
|
||||
i;
|
||||
|
||||
options = options || {};
|
||||
// keep tags for 'saved' event and deduplicate upper/lowercase tags
|
||||
tagsToCheck = this.get('tags');
|
||||
this.myTags = [];
|
||||
@ -64,7 +66,7 @@ Post = ghostBookshelf.Model.extend({
|
||||
self.myTags.push(item);
|
||||
});
|
||||
|
||||
ghostBookshelf.Model.prototype.saving.call(this);
|
||||
ghostBookshelf.Model.prototype.saving.call(this, newPage, attr, options);
|
||||
|
||||
this.set('html', converter.makeHtml(this.get('markdown')));
|
||||
|
||||
@ -77,7 +79,7 @@ Post = ghostBookshelf.Model.extend({
|
||||
this.set('published_at', new Date());
|
||||
}
|
||||
// This will need to go elsewhere in the API layer.
|
||||
this.set('published_by', 1);
|
||||
this.set('published_by', options.user);
|
||||
}
|
||||
|
||||
if (this.hasChanged('slug') || !this.get('slug')) {
|
||||
@ -93,13 +95,14 @@ Post = ghostBookshelf.Model.extend({
|
||||
|
||||
creating: function (newPage, attr, options) {
|
||||
/*jshint unused:false*/
|
||||
options = options || {};
|
||||
|
||||
// set any dynamic default properties
|
||||
if (!this.get('author_id')) {
|
||||
this.set('author_id', 1);
|
||||
this.set('author_id', options.user);
|
||||
}
|
||||
|
||||
ghostBookshelf.Model.prototype.creating.call(this);
|
||||
ghostBookshelf.Model.prototype.creating.call(this, newPage, attr, options);
|
||||
},
|
||||
|
||||
updateTags: function (newPost, attr, options) {
|
||||
@ -127,7 +130,9 @@ Post = ghostBookshelf.Model.extend({
|
||||
});
|
||||
|
||||
if (tagsToDetach.length > 0) {
|
||||
tagOperations.push(newPost.tags().detach(tagsToDetach, options));
|
||||
// _.omit(options, 'query') is a fix for using bookshelf 0.6.8
|
||||
// (https://github.com/tgriesser/bookshelf/issues/294)
|
||||
tagOperations.push(newPost.tags().detach(tagsToDetach, _.omit(options, 'query')));
|
||||
}
|
||||
|
||||
// Next check if new tags are all exactly the same as what is set on the model
|
||||
@ -141,7 +146,9 @@ Post = ghostBookshelf.Model.extend({
|
||||
if (!_.isEmpty(tagsToAttach)) {
|
||||
return Tags.forge().query('whereIn', 'name', _.pluck(tagsToAttach, 'name')).fetch(options).then(function (matchingTags) {
|
||||
_.each(matchingTags.toJSON(), function (matchingTag) {
|
||||
tagOperations.push(newPost.tags().attach(matchingTag.id, options));
|
||||
// _.omit(options, 'query') is a fix for using bookshelf 0.6.8
|
||||
// (https://github.com/tgriesser/bookshelf/issues/294)
|
||||
tagOperations.push(newPost.tags().attach(matchingTag.id, _.omit(options, 'query')));
|
||||
tagsToAttach = _.reject(tagsToAttach, function (tagToAttach) {
|
||||
return tagToAttach.name === matchingTag.name;
|
||||
});
|
||||
@ -170,7 +177,9 @@ Post = ghostBookshelf.Model.extend({
|
||||
|
||||
// Attach each newly created tag
|
||||
_.each(createdTagsToAttach, function (tagToAttach) {
|
||||
newPost.tags().attach(tagToAttach.id, tagToAttach.name, options);
|
||||
// _.omit(options, 'query') is a fix for using bookshelf 0.6.8
|
||||
// (https://github.com/tgriesser/bookshelf/issues/294)
|
||||
newPost.tags().attach(tagToAttach.id, tagToAttach.name, _.omit(options, 'query'));
|
||||
});
|
||||
|
||||
}
|
||||
@ -198,6 +207,10 @@ Post = ghostBookshelf.Model.extend({
|
||||
|
||||
tags: function () {
|
||||
return this.belongsToMany(Tag);
|
||||
},
|
||||
|
||||
fields: function () {
|
||||
return this.morphMany(AppField, 'relatable');
|
||||
}
|
||||
|
||||
}, {
|
||||
@ -206,7 +219,8 @@ Post = ghostBookshelf.Model.extend({
|
||||
// Extends base model findAll to eager-fetch author and user relationships.
|
||||
findAll: function (options) {
|
||||
options = options || {};
|
||||
options.withRelated = [ 'author', 'tags' ];
|
||||
|
||||
options.withRelated = [ 'author', 'tags', 'fields' ];
|
||||
return ghostBookshelf.Model.findAll.call(this, options);
|
||||
},
|
||||
|
||||
@ -223,7 +237,7 @@ Post = ghostBookshelf.Model.extend({
|
||||
delete args.status;
|
||||
}
|
||||
|
||||
options.withRelated = [ 'author', 'tags' ];
|
||||
options.withRelated = [ 'author', 'tags', 'fields' ];
|
||||
return ghostBookshelf.Model.findOne.call(this, args, options);
|
||||
},
|
||||
|
||||
@ -289,7 +303,7 @@ Post = ghostBookshelf.Model.extend({
|
||||
}
|
||||
|
||||
// Fetch related models
|
||||
opts.withRelated = [ 'author', 'tags' ];
|
||||
opts.withRelated = [ 'author', 'tags', 'fields' ];
|
||||
|
||||
// If a query param for a tag is attached
|
||||
// we need to fetch the tag model to find its id
|
||||
@ -380,52 +394,29 @@ Post = ghostBookshelf.Model.extend({
|
||||
.catch(errors.logAndThrowError);
|
||||
},
|
||||
|
||||
permissable: function (postModelOrId, userId, action_type, userPermissions) {
|
||||
permissable: function (postModelOrId, context) {
|
||||
var self = this,
|
||||
hasPermission,
|
||||
userId = context.user,
|
||||
postModel = postModelOrId;
|
||||
|
||||
// If we passed in an id instead of a model, get the model
|
||||
// then check the permissions
|
||||
if (_.isNumber(postModelOrId) || _.isString(postModelOrId)) {
|
||||
return this.read({id: postModelOrId}).then(function (foundPostModel) {
|
||||
return self.permissable(foundPostModel, userId, action_type, userPermissions);
|
||||
return this.read({id: postModelOrId, status: 'all'}).then(function (foundPostModel) {
|
||||
return self.permissable(foundPostModel, context);
|
||||
}, errors.logAndThrowError);
|
||||
}
|
||||
|
||||
// Check if any permissions apply for this user and post.
|
||||
hasPermission = _.any(userPermissions, function (perm) {
|
||||
// Check for matching action type and object type
|
||||
if (perm.get('action_type') !== action_type ||
|
||||
perm.get('object_type') !== 'post') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If asking whether we can create posts,
|
||||
// and we have a create posts permission then go ahead and say yes
|
||||
if (action_type === 'create' && perm.get('action_type') === action_type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for either no object id or a matching one
|
||||
return !perm.get('object_id') || perm.get('object_id') === postModel.id;
|
||||
});
|
||||
|
||||
// If this is the author of the post, allow it.
|
||||
// Moved below the permissions checks because there may not be a postModel
|
||||
// in the case like canThis(user).create.post()
|
||||
hasPermission = hasPermission || (postModel && userId === postModel.get('author_id'));
|
||||
|
||||
// Resolve if we have appropriate permissions
|
||||
if (hasPermission) {
|
||||
if (postModel && userId === postModel.get('author_id')) {
|
||||
return when.resolve();
|
||||
}
|
||||
|
||||
// Otherwise, you shall not pass.
|
||||
return when.reject();
|
||||
},
|
||||
add: function (newPostData, options) {
|
||||
var self = this;
|
||||
options = options || {};
|
||||
|
||||
return ghostBookshelf.Model.add.call(this, newPostData, options).then(function (post) {
|
||||
return self.findOne({status: 'all', id: post.id}, options);
|
||||
@ -433,6 +424,7 @@ Post = ghostBookshelf.Model.extend({
|
||||
},
|
||||
edit: function (editedPost, options) {
|
||||
var self = this;
|
||||
options = options || {};
|
||||
|
||||
return ghostBookshelf.Model.edit.call(this, editedPost, options).then(function (post) {
|
||||
if (post) {
|
||||
@ -442,6 +434,7 @@ Post = ghostBookshelf.Model.extend({
|
||||
},
|
||||
destroy: function (_identifier, options) {
|
||||
options = options || {};
|
||||
|
||||
return this.forge({id: _identifier}).fetch({withRelated: ['tags']}).then(function destroyTags(post) {
|
||||
var tagIds = _.pluck(post.related('tags').toJSON(), 'id');
|
||||
if (tagIds) {
|
||||
|
@ -5,7 +5,21 @@ var ghostBookshelf = require('./base'),
|
||||
|
||||
Session = ghostBookshelf.Model.extend({
|
||||
|
||||
tableName: 'sessions'
|
||||
tableName: 'sessions',
|
||||
|
||||
// override for base function since we don't have
|
||||
// a created_by field for sessions
|
||||
creating: function (newObj, attr, options) {
|
||||
/*jshint unused:false*/
|
||||
},
|
||||
|
||||
// override for base function since we don't have
|
||||
// a updated_by field for sessions
|
||||
saving: function (newObj, attr, options) {
|
||||
/*jshint unused:false*/
|
||||
// Remove any properties which don't belong on the model
|
||||
this.attributes = this.pick(this.permittedAttributes());
|
||||
},
|
||||
|
||||
}, {
|
||||
destroyAll: function (options) {
|
||||
|
@ -48,7 +48,6 @@ Settings = ghostBookshelf.Model.extend({
|
||||
|
||||
|
||||
saving: function () {
|
||||
|
||||
// disabling sanitization until we can implement a better version
|
||||
// All blog setting keys that need their values to be escaped.
|
||||
// if (this.get('type') === 'blog' && _.contains(['title', 'description', 'email'], this.get('key'))) {
|
||||
@ -69,20 +68,22 @@ Settings = ghostBookshelf.Model.extend({
|
||||
});
|
||||
},
|
||||
|
||||
edit: function (_data, t) {
|
||||
var settings = this;
|
||||
edit: function (_data, options) {
|
||||
|
||||
if (!Array.isArray(_data)) {
|
||||
_data = [_data];
|
||||
}
|
||||
|
||||
return when.map(_data, function (item) {
|
||||
// Accept an array of models as input
|
||||
if (item.toJSON) { item = item.toJSON(); }
|
||||
return settings.forge({ key: item.key }).fetch({transacting: t}).then(function (setting) {
|
||||
return Settings.forge({ key: item.key }).fetch(options).then(function (setting) {
|
||||
|
||||
if (setting) {
|
||||
return setting.set('value', item.value).save(null, {transacting: t});
|
||||
return setting.save({value: item.value}, options);
|
||||
}
|
||||
return settings.forge({ key: item.key, value: item.value }).save(null, {transacting: t});
|
||||
|
||||
return Settings.forge({ key: item.key, value: item.value }).save(null, options);
|
||||
|
||||
}, errors.logAndThrowError);
|
||||
});
|
||||
@ -101,7 +102,7 @@ Settings = ghostBookshelf.Model.extend({
|
||||
}
|
||||
if (isMissingFromDB) {
|
||||
defaultSetting.value = defaultSetting.defaultValue;
|
||||
insertOperations.push(Settings.forge(defaultSetting).save());
|
||||
insertOperations.push(Settings.forge(defaultSetting).save(null, {user: 1}));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -81,7 +81,7 @@ User = ghostBookshelf.Model.extend({
|
||||
*
|
||||
* Hashes the password provided before saving to the database.
|
||||
*/
|
||||
add: function (_user) {
|
||||
add: function (_user, options) {
|
||||
|
||||
var self = this,
|
||||
// Clone the _user so we don't expose the hashed password unnecessarily
|
||||
@ -108,7 +108,7 @@ User = ghostBookshelf.Model.extend({
|
||||
return self.gravatarLookup(userData);
|
||||
}).then(function (userData) {
|
||||
// Save the user with the hashed password
|
||||
return ghostBookshelf.Model.add.call(self, userData);
|
||||
return ghostBookshelf.Model.add.call(self, userData, options);
|
||||
}).then(function (addedUser) {
|
||||
// Assign the userData to our created user so we can pass it back
|
||||
userData = addedUser;
|
||||
@ -140,6 +140,26 @@ User = ghostBookshelf.Model.extend({
|
||||
|
||||
},
|
||||
|
||||
permissable: function (userModelOrId, context) {
|
||||
var self = this,
|
||||
userId = context.user,
|
||||
userModel = userModelOrId;
|
||||
|
||||
// If we passed in an id instead of a model, get the model
|
||||
// then check the permissions
|
||||
if (_.isNumber(userModelOrId) || _.isString(userModelOrId)) {
|
||||
return this.read({id: userModelOrId, status: 'all'}).then(function (foundUserModel) {
|
||||
return self.permissable(foundUserModel, context);
|
||||
}, errors.logAndThrowError);
|
||||
}
|
||||
|
||||
// If this is the same user that requests the operation allow it.
|
||||
if (userModel && userId === userModel.get('id')) {
|
||||
return when.resolve();
|
||||
}
|
||||
return when.reject();
|
||||
},
|
||||
|
||||
setWarning: function (user) {
|
||||
var status = user.get('status'),
|
||||
regexp = /warn-(\d+)/i,
|
||||
@ -334,35 +354,6 @@ User = ghostBookshelf.Model.extend({
|
||||
});
|
||||
},
|
||||
|
||||
effectivePermissions: function (id) {
|
||||
return this.read({id: id}, { withRelated: ['permissions', 'roles.permissions'] })
|
||||
.then(function (foundUser) {
|
||||
var seenPerms = {},
|
||||
rolePerms = _.map(foundUser.related('roles').models, function (role) {
|
||||
return role.related('permissions').models;
|
||||
}),
|
||||
allPerms = [];
|
||||
|
||||
rolePerms.push(foundUser.related('permissions').models);
|
||||
|
||||
_.each(rolePerms, function (rolePermGroup) {
|
||||
_.each(rolePermGroup, function (perm) {
|
||||
var key = perm.get('action_type') + '-' + perm.get('object_type') + '-' + perm.get('object_id');
|
||||
|
||||
// Only add perms once
|
||||
if (seenPerms[key]) {
|
||||
return;
|
||||
}
|
||||
|
||||
allPerms.push(perm);
|
||||
seenPerms[key] = true;
|
||||
});
|
||||
});
|
||||
|
||||
return when.resolve(allPerms);
|
||||
}, errors.logAndThrowError);
|
||||
},
|
||||
|
||||
gravatarLookup: function (userData) {
|
||||
var gravatarUrl = '//www.gravatar.com/avatar/' +
|
||||
crypto.createHash('md5').update(userData.email.toLowerCase().trim()).digest('hex') +
|
||||
|
49
core/server/permissions/effective.js
Normal file
49
core/server/permissions/effective.js
Normal file
@ -0,0 +1,49 @@
|
||||
var _ = require('lodash'),
|
||||
Models = require('../models'),
|
||||
errors = require('../errorHandling'),
|
||||
User = Models.User,
|
||||
App = Models.App;
|
||||
|
||||
var effective = {
|
||||
user: function (id) {
|
||||
return User.read({id: id}, { withRelated: ['permissions', 'roles.permissions'] })
|
||||
.then(function (foundUser) {
|
||||
var seenPerms = {},
|
||||
rolePerms = _.map(foundUser.related('roles').models, function (role) {
|
||||
return role.related('permissions').models;
|
||||
}),
|
||||
allPerms = [];
|
||||
|
||||
rolePerms.push(foundUser.related('permissions').models);
|
||||
|
||||
_.each(rolePerms, function (rolePermGroup) {
|
||||
_.each(rolePermGroup, function (perm) {
|
||||
var key = perm.get('action_type') + '-' + perm.get('object_type') + '-' + perm.get('object_id');
|
||||
|
||||
// Only add perms once
|
||||
if (seenPerms[key]) {
|
||||
return;
|
||||
}
|
||||
|
||||
allPerms.push(perm);
|
||||
seenPerms[key] = true;
|
||||
});
|
||||
});
|
||||
|
||||
return allPerms;
|
||||
}, errors.logAndThrowError);
|
||||
},
|
||||
|
||||
app: function (appName) {
|
||||
return App.read({name: appName}, { withRelated: ['permissions'] })
|
||||
.then(function (foundApp) {
|
||||
if (!foundApp) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return foundApp.related('permissions').models;
|
||||
}, errors.logAndThrowError);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = effective;
|
@ -5,7 +5,7 @@ var _ = require('lodash'),
|
||||
when = require('when'),
|
||||
Models = require('../models'),
|
||||
objectTypeModelMap = require('./objectTypeModelMap'),
|
||||
UserProvider = Models.User,
|
||||
effectivePerms = require('./effective'),
|
||||
PermissionsProvider = Models.Permission,
|
||||
init,
|
||||
refresh,
|
||||
@ -22,17 +22,44 @@ function hasActionsMap() {
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: Move this to its own file so others can use it?
|
||||
function parseContext(context) {
|
||||
// Parse what's passed to canThis.beginCheck for standard user and app scopes
|
||||
var parsed = {
|
||||
internal: false,
|
||||
user: null,
|
||||
app: null
|
||||
};
|
||||
|
||||
if (context && (context === 'internal' || context.internal)) {
|
||||
parsed.internal = true;
|
||||
}
|
||||
|
||||
// @TODO: Refactor canThis() references to pass { user: id } explicitly instead of primitives.
|
||||
if (context && context.id) {
|
||||
// Handle passing of just user.id string
|
||||
parsed.user = context.id;
|
||||
} else if (_.isNumber(context)) {
|
||||
// Handle passing of just user id number
|
||||
parsed.user = context;
|
||||
} else if (_.isObject(context)) {
|
||||
// Otherwise, use the new hotness { user: id, app: id } format
|
||||
parsed.user = context.user;
|
||||
parsed.app = context.app;
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
// Base class for canThis call results
|
||||
CanThisResult = function () {
|
||||
this.userPermissionLoad = false;
|
||||
return;
|
||||
};
|
||||
|
||||
CanThisResult.prototype.buildObjectTypeHandlers = function (obj_types, act_type, userId) {
|
||||
var self = this,
|
||||
obj_type_handlers = {};
|
||||
|
||||
CanThisResult.prototype.buildObjectTypeHandlers = function (obj_types, act_type, context, permissionLoad) {
|
||||
// Iterate through the object types, i.e. ['post', 'tag', 'user']
|
||||
_.each(obj_types, function (obj_type) {
|
||||
return _.reduce(obj_types, function (obj_type_handlers, obj_type) {
|
||||
// Grab the TargetModel through the objectTypeModelMap
|
||||
var TargetModel = objectTypeModelMap[obj_type];
|
||||
|
||||
// Create the 'handler' for the object type;
|
||||
@ -40,6 +67,11 @@ CanThisResult.prototype.buildObjectTypeHandlers = function (obj_types, act_type,
|
||||
obj_type_handlers[obj_type] = function (modelOrId) {
|
||||
var modelId;
|
||||
|
||||
// If it's an internal request, resolve immediately
|
||||
if (context.internal) {
|
||||
return when.resolve();
|
||||
}
|
||||
|
||||
if (_.isNumber(modelOrId) || _.isString(modelOrId)) {
|
||||
// It's an id already, do nothing
|
||||
modelId = modelOrId;
|
||||
@ -47,80 +79,108 @@ CanThisResult.prototype.buildObjectTypeHandlers = function (obj_types, act_type,
|
||||
// It's a model, get the id
|
||||
modelId = modelOrId.id;
|
||||
}
|
||||
|
||||
// Wait for the user loading to finish
|
||||
return self.userPermissionLoad.then(function (userPermissions) {
|
||||
return permissionLoad.then(function (loadedPermissions) {
|
||||
// Iterate through the user permissions looking for an affirmation
|
||||
var hasPermission;
|
||||
var userPermissions = loadedPermissions.user,
|
||||
appPermissions = loadedPermissions.app,
|
||||
hasUserPermission,
|
||||
hasAppPermission,
|
||||
checkPermission = function (perm) {
|
||||
var permObjId;
|
||||
|
||||
// Allow for a target model to implement a "Permissable" interface
|
||||
if (TargetModel && _.isFunction(TargetModel.permissable)) {
|
||||
return TargetModel.permissable(modelId, userId, act_type, userPermissions);
|
||||
// Look for a matching action type and object type first
|
||||
if (perm.get('action_type') !== act_type || perm.get('object_type') !== obj_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab the object id (if specified, could be null)
|
||||
permObjId = perm.get('object_id');
|
||||
|
||||
// If we didn't specify a model (any thing)
|
||||
// or the permission didn't have an id scope set
|
||||
// then the "thing" has permission
|
||||
if (!modelId || !permObjId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, check if the id's match
|
||||
// TODO: String vs Int comparison possibility here?
|
||||
return modelId === permObjId;
|
||||
};
|
||||
|
||||
// Check user permissions for matching action, object and id.
|
||||
if (!_.isEmpty(userPermissions)) {
|
||||
hasUserPermission = _.any(userPermissions, checkPermission);
|
||||
}
|
||||
|
||||
// Otherwise, check all the permissions for matching object id
|
||||
hasPermission = _.any(userPermissions, function (userPermission) {
|
||||
var permObjId;
|
||||
// Check app permissions if they were passed
|
||||
hasAppPermission = true;
|
||||
if (!_.isNull(appPermissions)) {
|
||||
hasAppPermission = _.any(appPermissions, checkPermission);
|
||||
}
|
||||
|
||||
// Look for a matching action type and object type first
|
||||
if (userPermission.get('action_type') !== act_type || userPermission.get('object_type') !== obj_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab the object id (if specified, could be null)
|
||||
permObjId = userPermission.get('object_id');
|
||||
|
||||
// If we didn't specify a model (any thing)
|
||||
// or the permission didn't have an id scope set
|
||||
// then the user has permission
|
||||
if (!modelId || !permObjId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, check if the id's match
|
||||
// TODO: String vs Int comparison possibility here?
|
||||
return modelId === permObjId;
|
||||
});
|
||||
|
||||
if (hasPermission) {
|
||||
if (hasUserPermission && hasAppPermission) {
|
||||
return when.resolve();
|
||||
}
|
||||
|
||||
return when.reject();
|
||||
}).otherwise(function () {
|
||||
// No permissions loaded, or error loading permissions
|
||||
|
||||
// Still check for permissable without permissions
|
||||
// Check for special permissions on the model directly
|
||||
if (TargetModel && _.isFunction(TargetModel.permissable)) {
|
||||
return TargetModel.permissable(modelId, userId, act_type, []);
|
||||
return TargetModel.permissable(modelId, context);
|
||||
}
|
||||
|
||||
return when.reject();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
return obj_type_handlers;
|
||||
return obj_type_handlers;
|
||||
}, {});
|
||||
};
|
||||
|
||||
CanThisResult.prototype.beginCheck = function (user) {
|
||||
CanThisResult.prototype.beginCheck = function (context) {
|
||||
var self = this,
|
||||
userId = user.id || user;
|
||||
userPermissionLoad,
|
||||
appPermissionLoad,
|
||||
permissionsLoad;
|
||||
|
||||
// Get context.user and context.app
|
||||
context = parseContext(context);
|
||||
|
||||
if (!hasActionsMap()) {
|
||||
throw new Error("No actions map found, please call permissions.init() before use.");
|
||||
}
|
||||
|
||||
// TODO: Switch logic based on object type; user, role, post.
|
||||
// Kick off loading of effective user permissions if necessary
|
||||
if (context.user) {
|
||||
userPermissionLoad = effectivePerms.user(context.user);
|
||||
} else {
|
||||
// Resolve null if no context.user to prevent db call
|
||||
userPermissionLoad = when.resolve(null);
|
||||
}
|
||||
|
||||
|
||||
// Kick off the fetching of the user data
|
||||
this.userPermissionLoad = UserProvider.effectivePermissions(userId);
|
||||
// Kick off loading of effective app permissions if necessary
|
||||
if (context.app) {
|
||||
appPermissionLoad = effectivePerms.app(context.app);
|
||||
} else {
|
||||
// Resolve null if no context.app
|
||||
appPermissionLoad = when.resolve(null);
|
||||
}
|
||||
|
||||
// Wait for both user and app permissions to load
|
||||
permissionsLoad = when.all([userPermissionLoad, appPermissionLoad]).then(function (result) {
|
||||
return {
|
||||
user: result[0],
|
||||
app: result[1]
|
||||
};
|
||||
});
|
||||
|
||||
// Iterate through the actions and their related object types
|
||||
_.each(exported.actionsMap, function (obj_types, act_type) {
|
||||
// Build up the object type handlers;
|
||||
// the '.post()' parts in canThis(user).edit.post()
|
||||
var obj_type_handlers = self.buildObjectTypeHandlers(obj_types, act_type, userId);
|
||||
var obj_type_handlers = self.buildObjectTypeHandlers(obj_types, act_type, context, permissionsLoad);
|
||||
|
||||
// Define a property for the action on the result;
|
||||
// the '.edit' in canThis(user).edit.post()
|
||||
@ -136,10 +196,10 @@ CanThisResult.prototype.beginCheck = function (user) {
|
||||
return this;
|
||||
};
|
||||
|
||||
canThis = function (user) {
|
||||
canThis = function (context) {
|
||||
var result = new CanThisResult();
|
||||
|
||||
return result.beginCheck(user);
|
||||
return result.beginCheck(context);
|
||||
};
|
||||
|
||||
init = refresh = function () {
|
||||
|
@ -143,10 +143,10 @@ function updateCheckRequest() {
|
||||
function updateCheckResponse(response) {
|
||||
var ops = [];
|
||||
|
||||
ops.push(api.settings.edit('nextUpdateCheck', response.next_check)
|
||||
ops.push(api.settings.edit.call({user: 1}, 'nextUpdateCheck', response.next_check)
|
||||
.otherwise(errors.rejectError));
|
||||
|
||||
ops.push(api.settings.edit('displayUpdateNotification', response.version)
|
||||
ops.push(api.settings.edit.call({user: 1}, 'displayUpdateNotification', response.version)
|
||||
.otherwise(errors.rejectError));
|
||||
|
||||
return when.settle(ops).then(function (descriptors) {
|
||||
|
@ -591,8 +591,6 @@ describe('Post API', function () {
|
||||
.send(newPost)
|
||||
.expect(200)
|
||||
.end(function (err ,res) {
|
||||
console.log("end");
|
||||
console.log(err);
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
@ -3,10 +3,11 @@ var testUtils = require('../../utils'),
|
||||
should = require('should'),
|
||||
|
||||
// Stuff we are testing
|
||||
DataGenerator = require('../../utils/fixtures/data-generator'),
|
||||
dbAPI = require('../../../server/api/db');
|
||||
TagsAPI = require('../../../server/api/tags');
|
||||
PostAPI = require('../../../server/api/posts');
|
||||
permissions = require('../../../server/permissions'),
|
||||
DataGenerator = require('../../utils/fixtures/data-generator'),
|
||||
dbAPI = require('../../../server/api/db');
|
||||
TagsAPI = require('../../../server/api/tags');
|
||||
PostAPI = require('../../../server/api/posts');
|
||||
|
||||
describe('DB API', function () {
|
||||
|
||||
@ -17,13 +18,15 @@ describe('DB API', function () {
|
||||
});
|
||||
|
||||
beforeEach(function (done) {
|
||||
testUtils.initData()
|
||||
.then(function () {
|
||||
return testUtils.insertDefaultFixtures();
|
||||
})
|
||||
.then(function () {
|
||||
done();
|
||||
}, done);
|
||||
testUtils.initData().then(function () {
|
||||
return testUtils.insertDefaultFixtures();
|
||||
}).then(function () {
|
||||
return testUtils.insertEditorUser();
|
||||
}).then(function () {
|
||||
return testUtils.insertAuthorUser();
|
||||
}).then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
@ -33,8 +36,9 @@ describe('DB API', function () {
|
||||
});
|
||||
|
||||
it('delete all content', function (done) {
|
||||
|
||||
dbAPI.deleteAllContent().then(function (result){
|
||||
permissions.init().then(function () {
|
||||
return dbAPI.deleteAllContent.call({user: 1});
|
||||
}).then(function (result){
|
||||
should.exist(result.message);
|
||||
result.message.should.equal('Successfully deleted all content from your blog.')
|
||||
}).then(function () {
|
||||
@ -48,6 +52,71 @@ describe('DB API', function () {
|
||||
results.posts.length.should.equal(0);
|
||||
done();
|
||||
});
|
||||
}).then(null, done);
|
||||
}).otherwise(function (error) {
|
||||
done(new Error(JSON.stringify(error)));
|
||||
});
|
||||
});
|
||||
|
||||
it('delete all content is denied', function (done) {
|
||||
permissions.init().then(function () {
|
||||
return dbAPI.deleteAllContent.call({user: 2});
|
||||
}).then(function (){
|
||||
done(new Error("Delete all content is not denied for editor."));
|
||||
}, function (error) {
|
||||
error.code.should.eql(403);
|
||||
return dbAPI.deleteAllContent.call({user: 3});
|
||||
}).then(function (){
|
||||
done(new Error("Delete all content is not denied for author."));
|
||||
}, function (error) {
|
||||
error.code.should.eql(403);
|
||||
return dbAPI.deleteAllContent();
|
||||
}).then(function (){
|
||||
done(new Error("Delete all content is not denied without authentication."));
|
||||
}, function (error) {
|
||||
error.code.should.eql(403);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('export content is denied', function (done) {
|
||||
permissions.init().then(function () {
|
||||
return dbAPI.exportContent.call({user: 2});
|
||||
}).then(function (){
|
||||
done(new Error("Export content is not denied for editor."));
|
||||
}, function (error) {
|
||||
error.code.should.eql(403);
|
||||
return dbAPI.exportContent.call({user: 3});
|
||||
}).then(function (){
|
||||
done(new Error("Export content is not denied for author."));
|
||||
}, function (error) {
|
||||
error.code.should.eql(403);
|
||||
return dbAPI.exportContent();
|
||||
}).then(function (){
|
||||
done(new Error("Export content is not denied without authentication."));
|
||||
}, function (error) {
|
||||
error.code.should.eql(403);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('import content is denied', function (done) {
|
||||
permissions.init().then(function () {
|
||||
return dbAPI.importContent.call({user: 2});
|
||||
}).then(function (result){
|
||||
done(new Error("Import content is not denied for editor."));
|
||||
}, function (error) {
|
||||
error.code.should.eql(403);
|
||||
return dbAPI.importContent.call({user: 3});
|
||||
}).then(function (result){
|
||||
done(new Error("Import content is not denied for author."));
|
||||
}, function (error) {
|
||||
error.code.should.eql(403);
|
||||
return dbAPI.importContent();
|
||||
}).then(function (result){
|
||||
done(new Error("Import content is not denied without authentication."));
|
||||
}, function (error) {
|
||||
error.code.should.eql(403);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
@ -30,7 +30,7 @@ describe('Post API', function () {
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('can browse', function (done) {
|
||||
it('browse', function (done) {
|
||||
PostAPI.browse().then(function (results) {
|
||||
should.exist(results);
|
||||
testUtils.API.checkResponse(results, 'posts');
|
||||
@ -41,7 +41,7 @@ describe('Post API', function () {
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can read', function (done) {
|
||||
it('read', function (done) {
|
||||
var firstPost;
|
||||
|
||||
PostAPI.browse().then(function (results) {
|
||||
|
@ -3,8 +3,9 @@ var testUtils = require('../../utils'),
|
||||
should = require('should'),
|
||||
|
||||
// Stuff we are testing
|
||||
permissions = require('../../../server/permissions'),
|
||||
DataGenerator = require('../../utils/fixtures/data-generator'),
|
||||
UsersAPI = require('../../../server/api/users');
|
||||
UsersAPI = require('../../../server/api/users');
|
||||
|
||||
describe('Users API', function () {
|
||||
|
||||
@ -15,13 +16,15 @@ describe('Users API', function () {
|
||||
});
|
||||
|
||||
beforeEach(function (done) {
|
||||
testUtils.initData()
|
||||
.then(function () {
|
||||
return testUtils.insertDefaultFixtures();
|
||||
})
|
||||
.then(function () {
|
||||
done();
|
||||
}, done);
|
||||
testUtils.initData().then(function () {
|
||||
return testUtils.insertDefaultFixtures();
|
||||
}).then(function () {
|
||||
return testUtils.insertEditorUser();
|
||||
}).then(function () {
|
||||
return testUtils.insertAuthorUser();
|
||||
}).then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
@ -30,12 +33,77 @@ describe('Users API', function () {
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('can browse', function (done) {
|
||||
UsersAPI.browse().then(function (results) {
|
||||
it('browse', function (done) {
|
||||
permissions.init().then(function () {
|
||||
return UsersAPI.browse.call({user: 1});
|
||||
}).then(function (results) {
|
||||
should.exist(results);
|
||||
results.length.should.be.above(0);
|
||||
testUtils.API.checkResponse(results[0], 'user');
|
||||
}, function (error) {
|
||||
done(new Error(JSON.stringify(error)));
|
||||
}).then(function () {
|
||||
return UsersAPI.browse.call({user: 2});
|
||||
}).then(function (results) {
|
||||
should.exist(results);
|
||||
results.length.should.be.above(0);
|
||||
testUtils.API.checkResponse(results[0], 'user');
|
||||
}, function (error) {
|
||||
done(new Error(JSON.stringify(error)));
|
||||
}).then(function () {
|
||||
return UsersAPI.browse.call({user: 3});
|
||||
}).then(function (results) {
|
||||
should.exist(results);
|
||||
results.length.should.be.above(0);
|
||||
testUtils.API.checkResponse(results[0], 'user');
|
||||
done();
|
||||
}).then(null, done);
|
||||
}, function (error) {
|
||||
done(new Error(JSON.stringify(error)));
|
||||
})
|
||||
});
|
||||
it('browse denied', function (done) {
|
||||
permissions.init().then(function () {
|
||||
return UsersAPI.browse();
|
||||
}).then(function (results) {
|
||||
done(new Error("Browse user is not denied without authentication."));
|
||||
}, function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('read', function (done) {
|
||||
permissions.init().then(function () {
|
||||
return UsersAPI.read.call({user: 1}, {id: 1});
|
||||
}).then(function (result) {
|
||||
should.exist(result);
|
||||
result.id.should.eql(1);
|
||||
testUtils.API.checkResponse(result, 'user');
|
||||
}, function (error) {
|
||||
done(new Error(JSON.stringify(error)));
|
||||
}).then(function () {
|
||||
return UsersAPI.read.call({user: 2}, {id: 1});
|
||||
}).then(function (result) {
|
||||
should.exist(result);
|
||||
result.id.should.eql(1);
|
||||
testUtils.API.checkResponse(result, 'user');
|
||||
}, function (error) {
|
||||
done(new Error(JSON.stringify(error)));
|
||||
}).then(function () {
|
||||
return UsersAPI.read.call({user: 3}, {id: 1});
|
||||
}).then(function (result) {
|
||||
should.exist(result);
|
||||
result.id.should.eql(1);
|
||||
testUtils.API.checkResponse(result, 'user');
|
||||
}, function (error) {
|
||||
done(new Error(JSON.stringify(error)));
|
||||
}).then(function () {
|
||||
return UsersAPI.read({id: 1});
|
||||
}).then(function (result) {
|
||||
should.exist(result);
|
||||
result.id.should.eql(1);
|
||||
testUtils.API.checkResponse(result, 'user');
|
||||
done();
|
||||
}, function (error) {
|
||||
done(new Error(JSON.stringify(error)));
|
||||
});
|
||||
});
|
||||
});
|
76
core/test/integration/model/model_app_fields_spec.js
Normal file
76
core/test/integration/model/model_app_fields_spec.js
Normal file
@ -0,0 +1,76 @@
|
||||
/*globals describe, before, beforeEach, afterEach, it*/
|
||||
var testUtils = require('../../utils'),
|
||||
should = require('should'),
|
||||
_ = require("lodash"),
|
||||
|
||||
// Stuff we are testing
|
||||
Models = require('../../../server/models'),
|
||||
knex = require('../../../server/models/base').knex;
|
||||
|
||||
describe('App Fields Model', function () {
|
||||
|
||||
var AppFieldsModel = Models.AppField;
|
||||
|
||||
before(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
beforeEach(function (done) {
|
||||
testUtils.initData()
|
||||
.then(function () {
|
||||
return testUtils.insertApps();
|
||||
})
|
||||
.then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('can browse', function (done) {
|
||||
AppFieldsModel.browse().then(function (results) {
|
||||
|
||||
should.exist(results);
|
||||
|
||||
results.length.should.be.above(0);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can read', function (done) {
|
||||
AppFieldsModel.read({id: 1}).then(function (foundAppField) {
|
||||
should.exist(foundAppField);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can edit', function (done) {
|
||||
AppFieldsModel.read({id: 1}).then(function (foundAppField) {
|
||||
should.exist(foundAppField);
|
||||
|
||||
return foundAppField.set({value: "350"}).save();
|
||||
}).then(function () {
|
||||
return AppFieldsModel.read({id: 1});
|
||||
}).then(function (updatedAppField) {
|
||||
should.exist(updatedAppField);
|
||||
|
||||
updatedAppField.get("value").should.equal("350");
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
});
|
76
core/test/integration/model/model_app_settings_spec.js
Normal file
76
core/test/integration/model/model_app_settings_spec.js
Normal file
@ -0,0 +1,76 @@
|
||||
/*globals describe, before, beforeEach, afterEach, it*/
|
||||
var testUtils = require('../../utils'),
|
||||
should = require('should'),
|
||||
_ = require("lodash"),
|
||||
|
||||
// Stuff we are testing
|
||||
Models = require('../../../server/models'),
|
||||
knex = require('../../../server/models/base').knex;
|
||||
|
||||
describe('App Setting Model', function () {
|
||||
|
||||
var AppSettingModel = Models.AppSetting;
|
||||
|
||||
before(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
beforeEach(function (done) {
|
||||
testUtils.initData()
|
||||
.then(function () {
|
||||
return testUtils.insertAppWithSettings();
|
||||
})
|
||||
.then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('can browse', function (done) {
|
||||
AppSettingModel.browse().then(function (results) {
|
||||
|
||||
should.exist(results);
|
||||
|
||||
results.length.should.be.above(0);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can read', function (done) {
|
||||
AppSettingModel.read({id: 1}).then(function (foundAppSetting) {
|
||||
should.exist(foundAppSetting);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can edit', function (done) {
|
||||
AppSettingModel.read({id: 1}).then(function (foundAppSetting) {
|
||||
should.exist(foundAppSetting);
|
||||
|
||||
return foundAppSetting.set({value: "350"}).save();
|
||||
}).then(function () {
|
||||
return AppSettingModel.read({id: 1});
|
||||
}).then(function (updatedAppSetting) {
|
||||
should.exist(updatedAppSetting);
|
||||
|
||||
updatedAppSetting.get("value").should.equal("350");
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
});
|
106
core/test/integration/model/model_apps_spec.js
Normal file
106
core/test/integration/model/model_apps_spec.js
Normal file
@ -0,0 +1,106 @@
|
||||
/*globals describe, before, beforeEach, afterEach, it*/
|
||||
var testUtils = require('../../utils'),
|
||||
should = require('should'),
|
||||
_ = require("lodash"),
|
||||
|
||||
// Stuff we are testing
|
||||
Models = require('../../../server/models'),
|
||||
knex = require('../../../server/models/base').knex;
|
||||
|
||||
describe('App Model', function () {
|
||||
|
||||
var AppModel = Models.App;
|
||||
|
||||
before(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
beforeEach(function (done) {
|
||||
testUtils.initData()
|
||||
.then(function () {
|
||||
return testUtils.insertDefaultApp();
|
||||
})
|
||||
.then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('can browse', function (done) {
|
||||
AppModel.browse().then(function (results) {
|
||||
|
||||
should.exist(results);
|
||||
|
||||
results.length.should.be.above(0);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can read', function (done) {
|
||||
AppModel.read({id: 1}).then(function (foundApp) {
|
||||
should.exist(foundApp);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can edit', function (done) {
|
||||
AppModel.read({id: 1}).then(function (foundApp) {
|
||||
should.exist(foundApp);
|
||||
|
||||
return foundApp.set({name: "New App"}).save();
|
||||
}).then(function () {
|
||||
return AppModel.read({id: 1});
|
||||
}).then(function (updatedApp) {
|
||||
should.exist(updatedApp);
|
||||
|
||||
updatedApp.get("name").should.equal("New App");
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it("can add", function (done) {
|
||||
var newApp = testUtils.DataGenerator.forKnex.createApp(testUtils.DataGenerator.Content.apps[1]);
|
||||
|
||||
AppModel.add(newApp).then(function (createdApp) {
|
||||
should.exist(createdApp);
|
||||
|
||||
createdApp.attributes.name.should.equal(newApp.name);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it("can delete", function (done) {
|
||||
AppModel.read({id: 1}).then(function (foundApp) {
|
||||
should.exist(foundApp);
|
||||
|
||||
return AppModel['delete'](1);
|
||||
}).then(function () {
|
||||
return AppModel.browse();
|
||||
}).then(function (foundApp) {
|
||||
var hasRemovedId = foundApp.any(function (foundApp) {
|
||||
return foundApp.id === 1;
|
||||
});
|
||||
|
||||
hasRemovedId.should.equal(false);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
});
|
@ -71,7 +71,7 @@ describe("Permission Model", function () {
|
||||
action_type: 'test'
|
||||
};
|
||||
|
||||
PermissionModel.add(newPerm).then(function (createdPerm) {
|
||||
PermissionModel.add(newPerm, {user: 1}).then(function (createdPerm) {
|
||||
should.exist(createdPerm);
|
||||
|
||||
createdPerm.attributes.name.should.equal(newPerm.name);
|
||||
|
@ -6,13 +6,12 @@ var testUtils = require('../../utils'),
|
||||
sequence = require('when/sequence'),
|
||||
|
||||
// Stuff we are testing
|
||||
DataGenerator = require('../../utils/fixtures/data-generator'),
|
||||
Models = require('../../../server/models');
|
||||
Models = require('../../../server/models'),
|
||||
DataGenerator = testUtils.DataGenerator;
|
||||
|
||||
describe('Post Model', function () {
|
||||
|
||||
var PostModel = Models.Post,
|
||||
UserModel = Models.User;
|
||||
var PostModel = Models.Post;
|
||||
|
||||
before(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
@ -66,7 +65,7 @@ describe('Post Model', function () {
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can findAll, returning author and user data', function (done) {
|
||||
it('can findAll, returning author, user and field data', function (done) {
|
||||
var firstPost;
|
||||
|
||||
PostModel.findAll({}).then(function (results) {
|
||||
@ -75,13 +74,15 @@ describe('Post Model', function () {
|
||||
firstPost = results.models[0].toJSON();
|
||||
|
||||
firstPost.author.should.be.an.Object;
|
||||
firstPost.fields.should.be.an.Array;
|
||||
firstPost.author.name.should.equal(DataGenerator.Content.users[0].name);
|
||||
firstPost.fields[0].key.should.equal(DataGenerator.Content.app_fields[0].key);
|
||||
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('can findOne, returning author and user data', function (done) {
|
||||
it('can findOne, returning author, user and field data', function (done) {
|
||||
var firstPost;
|
||||
|
||||
PostModel.findOne({}).then(function (result) {
|
||||
@ -89,7 +90,9 @@ describe('Post Model', function () {
|
||||
firstPost = result.toJSON();
|
||||
|
||||
firstPost.author.should.be.an.Object;
|
||||
firstPost.fields.should.be.an.Array;
|
||||
firstPost.author.name.should.equal(testUtils.DataGenerator.Content.users[0].name);
|
||||
firstPost.fields[0].key.should.equal(DataGenerator.Content.app_fields[0].key);
|
||||
|
||||
done();
|
||||
}, done);
|
||||
@ -117,7 +120,7 @@ describe('Post Model', function () {
|
||||
newPost = testUtils.DataGenerator.forModel.posts[2],
|
||||
newPostDB = testUtils.DataGenerator.Content.posts[2];
|
||||
|
||||
PostModel.add(newPost).then(function (createdPost) {
|
||||
PostModel.add(newPost, {user: 1}).then(function (createdPost) {
|
||||
return new PostModel({id: createdPost.id}).fetch();
|
||||
}).then(function (createdPost) {
|
||||
should.exist(createdPost);
|
||||
@ -148,7 +151,7 @@ describe('Post Model', function () {
|
||||
createdPostUpdatedDate = createdPost.get('updated_at');
|
||||
|
||||
// Set the status to published to check that `published_at` is set.
|
||||
return createdPost.save({status: 'published'});
|
||||
return createdPost.save({status: 'published'}, {user: 1});
|
||||
}).then(function (publishedPost) {
|
||||
publishedPost.get('published_at').should.be.instanceOf(Date);
|
||||
publishedPost.get('published_by').should.equal(1);
|
||||
@ -169,7 +172,7 @@ describe('Post Model', function () {
|
||||
published_at: previousPublishedAtDate,
|
||||
title: 'published_at test',
|
||||
markdown: 'This is some content'
|
||||
}).then(function (newPost) {
|
||||
}, {user: 1}).then(function (newPost) {
|
||||
|
||||
should.exist(newPost);
|
||||
new Date(newPost.get('published_at')).getTime().should.equal(previousPublishedAtDate.getTime());
|
||||
@ -187,7 +190,7 @@ describe('Post Model', function () {
|
||||
markdown: 'Test Content'
|
||||
};
|
||||
|
||||
PostModel.add(newPost).then(function (createdPost) {
|
||||
PostModel.add(newPost, {user: 1}).then(function (createdPost) {
|
||||
return new PostModel({ id: createdPost.id }).fetch();
|
||||
}).then(function (createdPost) {
|
||||
should.exist(createdPost);
|
||||
@ -213,7 +216,7 @@ describe('Post Model', function () {
|
||||
return PostModel.add({
|
||||
title: 'Test Title',
|
||||
markdown: 'Test Content ' + (i+1)
|
||||
});
|
||||
}, {user: 1});
|
||||
};
|
||||
})).then(function (createdPosts) {
|
||||
// Should have created 12 posts
|
||||
@ -243,7 +246,7 @@ describe('Post Model', function () {
|
||||
markdown: 'Test Content 1'
|
||||
};
|
||||
|
||||
PostModel.add(newPost).then(function (createdPost) {
|
||||
PostModel.add(newPost, {user: 1}).then(function (createdPost) {
|
||||
|
||||
createdPost.get('slug').should.equal('apprehensive-titles-have-too-many-spaces-and-m-dashes-and-also-n-dashes');
|
||||
|
||||
@ -257,7 +260,7 @@ describe('Post Model', function () {
|
||||
markdown: 'Test Content 1'
|
||||
};
|
||||
|
||||
PostModel.add(newPost).then(function (createdPost) {
|
||||
PostModel.add(newPost, {user: 1}).then(function (createdPost) {
|
||||
createdPost.get('slug').should.not.equal('rss');
|
||||
done();
|
||||
});
|
||||
@ -269,7 +272,7 @@ describe('Post Model', function () {
|
||||
markdown: 'Test Content 1'
|
||||
};
|
||||
|
||||
PostModel.add(newPost).then(function (createdPost) {
|
||||
PostModel.add(newPost, {user: 1}).then(function (createdPost) {
|
||||
createdPost.get('slug').should.equal('bhute-dhddkii-bhrvnnaaraa-aahet');
|
||||
done();
|
||||
});
|
||||
@ -286,13 +289,13 @@ describe('Post Model', function () {
|
||||
};
|
||||
|
||||
// Create the first post
|
||||
PostModel.add(firstPost)
|
||||
PostModel.add(firstPost, {user: 1})
|
||||
.then(function (createdFirstPost) {
|
||||
// Store the slug for later
|
||||
firstPost.slug = createdFirstPost.get('slug');
|
||||
|
||||
// Create the second post
|
||||
return PostModel.add(secondPost);
|
||||
return PostModel.add(secondPost, {user: 1});
|
||||
}).then(function (createdSecondPost) {
|
||||
// Store the slug for comparison later
|
||||
secondPost.slug = createdSecondPost.get('slug');
|
||||
|
@ -70,7 +70,7 @@ describe("Role Model", function () {
|
||||
description: "test1 description"
|
||||
};
|
||||
|
||||
RoleModel.add(newRole).then(function (createdRole) {
|
||||
RoleModel.add(newRole, {user: 1}).then(function (createdRole) {
|
||||
should.exist(createdRole);
|
||||
|
||||
createdRole.attributes.name.should.equal(newRole.name);
|
||||
|
@ -141,7 +141,7 @@ describe('Settings Model', function () {
|
||||
value: 'Test Content 1'
|
||||
};
|
||||
|
||||
SettingsModel.add(newSetting).then(function (createdSetting) {
|
||||
SettingsModel.add(newSetting, {user: 1}).then(function (createdSetting) {
|
||||
|
||||
should.exist(createdSetting);
|
||||
createdSetting.has('uuid').should.equal(true);
|
||||
@ -218,7 +218,7 @@ describe('Settings Model', function () {
|
||||
});
|
||||
|
||||
it('doesn\'t overwrite any existing settings', function (done) {
|
||||
SettingsModel.edit({key: 'description', value: 'Adam\'s Blog'}).then(function () {
|
||||
SettingsModel.edit({key: 'description', value: 'Adam\'s Blog'}, {user: 1}).then(function () {
|
||||
return SettingsModel.populateDefaults();
|
||||
}).then(function () {
|
||||
return SettingsModel.read('description');
|
||||
|
@ -40,8 +40,8 @@ describe('Tag Model', function () {
|
||||
createdPostID;
|
||||
|
||||
when.all([
|
||||
PostModel.add(newPost),
|
||||
TagModel.add(newTag)
|
||||
PostModel.add(newPost, {user: 1}),
|
||||
TagModel.add(newTag, {user: 1})
|
||||
]).then(function (models) {
|
||||
var createdPost = models[0],
|
||||
createdTag = models[1];
|
||||
@ -67,8 +67,8 @@ describe('Tag Model', function () {
|
||||
createdPostID;
|
||||
|
||||
when.all([
|
||||
PostModel.add(newPost),
|
||||
TagModel.add(newTag)
|
||||
PostModel.add(newPost, {user: 1}),
|
||||
TagModel.add(newTag, {user: 1})
|
||||
]).then(function (models) {
|
||||
var createdPost = models[0],
|
||||
createdTag = models[1];
|
||||
@ -95,10 +95,10 @@ describe('Tag Model', function () {
|
||||
|
||||
function seedTags(tagNames) {
|
||||
var createOperations = [
|
||||
PostModel.add(testUtils.DataGenerator.forModel.posts[0])
|
||||
PostModel.add(testUtils.DataGenerator.forModel.posts[0], {user: 1})
|
||||
];
|
||||
|
||||
var tagModels = tagNames.map(function (tagName) { return TagModel.add({name: tagName}); });
|
||||
var tagModels = tagNames.map(function (tagName) { return TagModel.add({name: tagName}, {user: 1}); });
|
||||
createOperations = createOperations.concat(tagModels);
|
||||
|
||||
return when.all(createOperations).then(function (models) {
|
||||
@ -165,7 +165,7 @@ describe('Tag Model', function () {
|
||||
|
||||
seedTags(seededTagNames).then(function (_postModel) {
|
||||
postModel = _postModel;
|
||||
return TagModel.add({name: 'tag3'});
|
||||
return TagModel.add({name: 'tag3'}, {user: 1});
|
||||
}).then(function () {
|
||||
// the tag API expects tags to be provided like {id: 1, name: 'draft'}
|
||||
var tagData = seededTagNames.map(function (tagName, i) { return {id: i + 1, name: tagName}; });
|
||||
@ -198,7 +198,7 @@ describe('Tag Model', function () {
|
||||
|
||||
// add the additional tag, and save
|
||||
tagData.push({id: null, name: 'tag3'});
|
||||
return postModel.set('tags', tagData).save();
|
||||
return postModel.set('tags', tagData).save(null, {user: 1});
|
||||
}).then(function (postModel) {
|
||||
return PostModel.read({id: postModel.id, status: 'all'}, { withRelated: ['tags']});
|
||||
}).then(function (reloadedPost) {
|
||||
@ -219,7 +219,7 @@ describe('Tag Model', function () {
|
||||
// add the additional tags, and save
|
||||
tagData.push({id: null, name: 'tag2'});
|
||||
tagData.push({id: null, name: 'tag3'});
|
||||
return postModel.set('tags', tagData).save();
|
||||
return postModel.set('tags', tagData).save(null, {user: 1});
|
||||
}).then(function (postModel) {
|
||||
return PostModel.read({id: postModel.id, status: 'all'}, { withRelated: ['tags']});
|
||||
}).then(function (reloadedPost) {
|
||||
@ -236,7 +236,7 @@ describe('Tag Model', function () {
|
||||
|
||||
seedTags(seededTagNames).then(function (_postModel) {
|
||||
postModel = _postModel;
|
||||
return TagModel.add({name: 'tag2'});
|
||||
return TagModel.add({name: 'tag2'}, {user: 1});
|
||||
}).then(function () {
|
||||
// the tag API expects tags to be provided like {id: 1, name: 'draft'}
|
||||
var tagData = seededTagNames.map(function (tagName, i) { return {id: i + 1, name: tagName}; });
|
||||
@ -247,7 +247,7 @@ describe('Tag Model', function () {
|
||||
// Add the tag that doesn't exist in the database
|
||||
tagData.push({id: 3, name: 'tag3'});
|
||||
|
||||
return postModel.set('tags', tagData).save();
|
||||
return postModel.set('tags', tagData).save(null, {user: 1});
|
||||
}).then(function () {
|
||||
return PostModel.read({id: postModel.id, status: 'all'}, { withRelated: ['tags']});
|
||||
}).then(function (reloadedPost) {
|
||||
@ -271,7 +271,7 @@ describe('Tag Model', function () {
|
||||
|
||||
seedTags(seededTagNames).then(function (_postModel) {
|
||||
postModel = _postModel;
|
||||
return TagModel.add({name: 'tag2'});
|
||||
return TagModel.add({name: 'tag2'}, {user: 1});
|
||||
}).then(function () {
|
||||
// the tag API expects tags to be provided like {id: 1, name: 'draft'}
|
||||
var tagData = seededTagNames.map(function (tagName, i) { return {id: i + 1, name: tagName}; });
|
||||
@ -283,7 +283,7 @@ describe('Tag Model', function () {
|
||||
tagData.push({id: 3, name: 'tag3'});
|
||||
tagData.push({id: 4, name: 'tag4'});
|
||||
|
||||
return postModel.set('tags', tagData).save();
|
||||
return postModel.set('tags', tagData).save(null, {user: 1});
|
||||
}).then(function () {
|
||||
return PostModel.read({id: postModel.id, status: 'all'}, { withRelated: ['tags']});
|
||||
}).then(function (reloadedPost) {
|
||||
@ -304,7 +304,7 @@ describe('Tag Model', function () {
|
||||
it('can add a tag to a post on creation', function (done) {
|
||||
var newPost = _.extend(testUtils.DataGenerator.forModel.posts[0], {tags: [{name: 'test_tag_1'}]})
|
||||
|
||||
PostModel.add(newPost).then(function (createdPost) {
|
||||
PostModel.add(newPost, {user: 1}).then(function (createdPost) {
|
||||
return PostModel.read({id: createdPost.id, status: 'all'}, { withRelated: ['tags']});
|
||||
}).then(function (postWithTag) {
|
||||
postWithTag.related('tags').length.should.equal(1);
|
||||
|
@ -39,7 +39,7 @@ describe('User Model', function run() {
|
||||
return when.resolve(userData);
|
||||
});
|
||||
|
||||
UserModel.add(userData).then(function (createdUser) {
|
||||
UserModel.add(userData, {user: 1}).then(function (createdUser) {
|
||||
should.exist(createdUser);
|
||||
createdUser.has('uuid').should.equal(true);
|
||||
createdUser.attributes.password.should.not.equal(userData.password, "password was hashed");
|
||||
@ -55,7 +55,7 @@ describe('User Model', function run() {
|
||||
return when.resolve(userData);
|
||||
});
|
||||
|
||||
UserModel.add(userData).then(function (createdUser) {
|
||||
UserModel.add(userData, {user: 1}).then(function (createdUser) {
|
||||
should.exist(createdUser);
|
||||
createdUser.has('uuid').should.equal(true);
|
||||
createdUser.attributes.email.should.eql(userData.email, "email address correct");
|
||||
@ -67,11 +67,11 @@ describe('User Model', function run() {
|
||||
it('can find gravatar', function (done) {
|
||||
var userData = testUtils.DataGenerator.forModel.users[4],
|
||||
gravatarStub = sinon.stub(UserModel, 'gravatarLookup', function (userData) {
|
||||
userData.image = 'http://www.gravatar.com/avatar/2fab21a4c4ed88e76add10650c73bae1?d=404'
|
||||
userData.image = 'http://www.gravatar.com/avatar/2fab21a4c4ed88e76add10650c73bae1?d=404';
|
||||
return when.resolve(userData);
|
||||
});
|
||||
|
||||
UserModel.add(userData).then(function (createdUser) {
|
||||
UserModel.add(userData, {user: 1}).then(function (createdUser) {
|
||||
should.exist(createdUser);
|
||||
createdUser.has('uuid').should.equal(true);
|
||||
createdUser.attributes.image.should.eql('http://www.gravatar.com/avatar/2fab21a4c4ed88e76add10650c73bae1?d=404', 'Gravatar found');
|
||||
@ -86,7 +86,7 @@ describe('User Model', function run() {
|
||||
return when.resolve(userData);
|
||||
});
|
||||
|
||||
UserModel.add(userData).then(function (createdUser) {
|
||||
UserModel.add(userData, {user: 1}).then(function (createdUser) {
|
||||
should.exist(createdUser);
|
||||
createdUser.has('uuid').should.equal(true);
|
||||
should.not.exist(createdUser.image);
|
||||
@ -99,7 +99,7 @@ describe('User Model', function run() {
|
||||
var userData = testUtils.DataGenerator.forModel.users[2],
|
||||
email = testUtils.DataGenerator.forModel.users[2].email;
|
||||
|
||||
UserModel.add(userData).then(function () {
|
||||
UserModel.add(userData, {user: 1}).then(function () {
|
||||
// Test same case
|
||||
return UserModel.getByEmail(email).then(function (user) {
|
||||
should.exist(user);
|
||||
@ -153,7 +153,7 @@ describe('User Model', function run() {
|
||||
it('can\'t add second', function (done) {
|
||||
var userData = testUtils.DataGenerator.forModel.users[1];
|
||||
|
||||
return UserModel.add(userData).then(done, function (failure) {
|
||||
return UserModel.add(userData, {user: 1}).then(done, function (failure) {
|
||||
failure.message.should.eql('A user is already registered. Only one user for now!');
|
||||
done();
|
||||
}).then(null, done);
|
||||
@ -220,16 +220,6 @@ describe('User Model', function run() {
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it("can get effective permissions", function (done) {
|
||||
UserModel.effectivePermissions(1).then(function (effectivePermissions) {
|
||||
should.exist(effectivePermissions);
|
||||
|
||||
effectivePermissions.length.should.be.above(0);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can delete', function (done) {
|
||||
var firstUserId;
|
||||
|
||||
|
@ -5,13 +5,15 @@ var fs = require('fs'),
|
||||
should = require('should'),
|
||||
sinon = require('sinon'),
|
||||
_ = require('lodash'),
|
||||
when = require('when'),
|
||||
helpers = require('../../server/helpers'),
|
||||
filters = require('../../server/filters'),
|
||||
|
||||
// Stuff we are testing
|
||||
appProxy = require('../../server/apps/proxy'),
|
||||
AppSandbox = require('../../server/apps/sandbox'),
|
||||
AppDependencies = require('../../server/apps/dependencies');
|
||||
AppDependencies = require('../../server/apps/dependencies'),
|
||||
AppPermissions = require('../../server/apps/permissions');
|
||||
|
||||
describe('Apps', function () {
|
||||
|
||||
@ -189,4 +191,127 @@ describe('Apps', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Permissions', function () {
|
||||
var noGhostPackageJson = {
|
||||
"name": "myapp",
|
||||
"version": "0.0.1",
|
||||
"description": "My example app",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Ghost",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ghost-app": "0.0.1"
|
||||
}
|
||||
},
|
||||
validGhostPackageJson = {
|
||||
"name": "myapp",
|
||||
"version": "0.0.1",
|
||||
"description": "My example app",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Ghost",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ghost-app": "0.0.1"
|
||||
},
|
||||
"ghost": {
|
||||
"permissions": {
|
||||
"posts": ["browse", "read", "edit", "add", "delete"],
|
||||
"users": ["browse", "read", "edit", "add", "delete"],
|
||||
"settings": ["browse", "read", "edit", "add", "delete"]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
it('has default permissions to read and browse posts', function () {
|
||||
should.exist(AppPermissions.DefaultPermissions);
|
||||
|
||||
should.exist(AppPermissions.DefaultPermissions.posts);
|
||||
|
||||
AppPermissions.DefaultPermissions.posts.should.contain('browse');
|
||||
AppPermissions.DefaultPermissions.posts.should.contain('read');
|
||||
|
||||
// Make it hurt to add more so additional checks are added here
|
||||
_.keys(AppPermissions.DefaultPermissions).length.should.equal(1);
|
||||
});
|
||||
it('uses default permissions if no package.json', function (done) {
|
||||
var perms = new AppPermissions("test");
|
||||
|
||||
// No package.json in this directory
|
||||
sandbox.stub(perms, "checkPackageContentsExists").returns(when.resolve(false));
|
||||
|
||||
perms.read().then(function (readPerms) {
|
||||
should.exist(readPerms);
|
||||
|
||||
readPerms.should.equal(AppPermissions.DefaultPermissions);
|
||||
|
||||
done();
|
||||
}).otherwise(done);
|
||||
});
|
||||
it('uses default permissions if no ghost object in package.json', function (done) {
|
||||
var perms = new AppPermissions("test"),
|
||||
noGhostPackageJsonContents = JSON.stringify(noGhostPackageJson, null, 2);
|
||||
|
||||
// package.json IS in this directory
|
||||
sandbox.stub(perms, "checkPackageContentsExists").returns(when.resolve(true));
|
||||
// no ghost property on package
|
||||
sandbox.stub(perms, "getPackageContents").returns(when.resolve(noGhostPackageJsonContents));
|
||||
|
||||
perms.read().then(function (readPerms) {
|
||||
should.exist(readPerms);
|
||||
|
||||
readPerms.should.equal(AppPermissions.DefaultPermissions);
|
||||
|
||||
done();
|
||||
}).otherwise(done);
|
||||
});
|
||||
it('rejects when reading malformed package.json', function (done) {
|
||||
var perms = new AppPermissions("test");
|
||||
|
||||
// package.json IS in this directory
|
||||
sandbox.stub(perms, "checkPackageContentsExists").returns(when.resolve(true));
|
||||
// malformed JSON on package
|
||||
sandbox.stub(perms, "getPackageContents").returns(when.reject(new Error('package.json file is malformed')));
|
||||
|
||||
perms.read().then(function (readPerms) {
|
||||
done(new Error('should not resolve'));
|
||||
}).otherwise(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('reads from package.json in root of app directory', function (done) {
|
||||
var perms = new AppPermissions("test"),
|
||||
validGhostPackageJsonContents = validGhostPackageJson;
|
||||
|
||||
// package.json IS in this directory
|
||||
sandbox.stub(perms, "checkPackageContentsExists").returns(when.resolve(true));
|
||||
// valid ghost property on package
|
||||
sandbox.stub(perms, "getPackageContents").returns(when.resolve(validGhostPackageJsonContents));
|
||||
|
||||
perms.read().then(function (readPerms) {
|
||||
should.exist(readPerms);
|
||||
|
||||
readPerms.should.not.equal(AppPermissions.DefaultPermissions);
|
||||
|
||||
should.exist(readPerms.posts);
|
||||
readPerms.posts.length.should.equal(5);
|
||||
|
||||
should.exist(readPerms.users);
|
||||
readPerms.users.length.should.equal(5);
|
||||
|
||||
should.exist(readPerms.settings);
|
||||
readPerms.settings.length.should.equal(5);
|
||||
|
||||
_.keys(readPerms).length.should.equal(3);
|
||||
|
||||
done();
|
||||
}).otherwise(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -15,6 +15,8 @@ describe("Exporter", function () {
|
||||
|
||||
should.exist(exporter);
|
||||
|
||||
var sandbox;
|
||||
|
||||
before(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
@ -22,12 +24,14 @@ describe("Exporter", function () {
|
||||
});
|
||||
|
||||
beforeEach(function (done) {
|
||||
sandbox = sinon.sandbox.create();
|
||||
testUtils.initData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
sandbox.restore();
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
@ -35,8 +39,8 @@ describe("Exporter", function () {
|
||||
|
||||
it("exports data", function (done) {
|
||||
// Stub migrations to return 000 as the current database version
|
||||
var migrationStub = sinon.stub(migration, "getDatabaseVersion", function () {
|
||||
return when.resolve("002");
|
||||
var migrationStub = sandbox.stub(migration, "getDatabaseVersion", function () {
|
||||
return when.resolve("003");
|
||||
});
|
||||
|
||||
exporter().then(function (exportData) {
|
||||
@ -48,8 +52,8 @@ describe("Exporter", function () {
|
||||
should.exist(exportData.meta);
|
||||
should.exist(exportData.data);
|
||||
|
||||
exportData.meta.version.should.equal("002");
|
||||
_.findWhere(exportData.data.settings, {key: "databaseVersion"}).value.should.equal("002");
|
||||
exportData.meta.version.should.equal("003");
|
||||
_.findWhere(exportData.data.settings, {key: "databaseVersion"}).value.should.equal("003");
|
||||
|
||||
_.each(tables, function (name) {
|
||||
should.exist(exportData.data[name]);
|
||||
|
@ -1,37 +1,45 @@
|
||||
/*globals describe, beforeEach, it*/
|
||||
var testUtils = require('../utils'),
|
||||
should = require('should'),
|
||||
sinon = require('sinon'),
|
||||
when = require('when'),
|
||||
assert = require('assert'),
|
||||
_ = require("lodash"),
|
||||
errors = require('../../server/errorHandling'),
|
||||
should = require('should'),
|
||||
sinon = require('sinon'),
|
||||
when = require('when'),
|
||||
assert = require('assert'),
|
||||
_ = require("lodash"),
|
||||
errors = require('../../server/errorHandling'),
|
||||
|
||||
// Stuff we are testing
|
||||
knex = require("../../server/models/base").knex,
|
||||
migration = require('../../server/data/migration'),
|
||||
exporter = require('../../server/data/export'),
|
||||
importer = require('../../server/data/import'),
|
||||
knex = require("../../server/models/base").knex,
|
||||
migration = require('../../server/data/migration'),
|
||||
exporter = require('../../server/data/export'),
|
||||
importer = require('../../server/data/import'),
|
||||
Importer000 = require('../../server/data/import/000'),
|
||||
Importer001 = require('../../server/data/import/001'),
|
||||
Importer002 = require('../../server/data/import/002'),
|
||||
fixtures = require('../../server/data/fixtures'),
|
||||
Settings = require('../../server/models/settings').Settings;
|
||||
Importer003 = require('../../server/data/import/003'),
|
||||
fixtures = require('../../server/data/fixtures'),
|
||||
Settings = require('../../server/models/settings').Settings;
|
||||
|
||||
describe("Import", function () {
|
||||
|
||||
should.exist(exporter);
|
||||
should.exist(importer);
|
||||
|
||||
var sandbox;
|
||||
|
||||
beforeEach(function (done) {
|
||||
sandbox = sinon.sandbox.create();
|
||||
// clear database... we need to initialise it manually for each test
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it("resolves 000", function (done) {
|
||||
var importStub = sinon.stub(Importer000, "importData", function () {
|
||||
var importStub = sandbox.stub(Importer000, "importData", function () {
|
||||
return when.resolve();
|
||||
}),
|
||||
fakeData = { test: true };
|
||||
@ -46,7 +54,7 @@ describe("Import", function () {
|
||||
});
|
||||
|
||||
it("resolves 001", function (done) {
|
||||
var importStub = sinon.stub(Importer001, "importData", function () {
|
||||
var importStub = sandbox.stub(Importer001, "importData", function () {
|
||||
return when.resolve();
|
||||
}),
|
||||
fakeData = { test: true };
|
||||
@ -61,7 +69,7 @@ describe("Import", function () {
|
||||
});
|
||||
|
||||
it("resolves 002", function (done) {
|
||||
var importStub = sinon.stub(Importer002, "importData", function () {
|
||||
var importStub = sandbox.stub(Importer002, "importData", function () {
|
||||
return when.resolve();
|
||||
}),
|
||||
fakeData = { test: true };
|
||||
@ -75,18 +83,27 @@ describe("Import", function () {
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it("resolves 003", function (done) {
|
||||
var importStub = sandbox.stub(Importer003, "importData", function () {
|
||||
return when.resolve();
|
||||
}),
|
||||
fakeData = { test: true };
|
||||
|
||||
importer("003", fakeData).then(function () {
|
||||
importStub.calledWith(fakeData).should.equal(true);
|
||||
|
||||
importStub.restore();
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
describe("000", function () {
|
||||
should.exist(Importer000);
|
||||
|
||||
beforeEach(function (done) {
|
||||
// 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 () {
|
||||
migration.migrateUpFreshDb().then(function () {
|
||||
return testUtils.insertDefaultUser();
|
||||
}).then(function () {
|
||||
done();
|
||||
@ -96,7 +113,7 @@ describe("Import", function () {
|
||||
|
||||
it("imports data from 000", function (done) {
|
||||
var exportData,
|
||||
migrationStub = sinon.stub(migration, "getDatabaseVersion", function () {
|
||||
migrationStub = sandbox.stub(migration, "getDatabaseVersion", function () {
|
||||
return when.resolve("000");
|
||||
});
|
||||
|
||||
@ -129,7 +146,7 @@ describe("Import", function () {
|
||||
|
||||
// test settings
|
||||
settings.length.should.be.above(0, 'Wrong number of settings');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("002", 'Wrong database version');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("003", 'Wrong database version');
|
||||
|
||||
// test tags
|
||||
tags.length.should.equal(exportData.data.tags.length, 'no new tags');
|
||||
@ -146,13 +163,7 @@ describe("Import", function () {
|
||||
|
||||
beforeEach(function (done) {
|
||||
// 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 () {
|
||||
migration.migrateUpFreshDb().then(function () {
|
||||
return testUtils.insertDefaultUser();
|
||||
}).then(function () {
|
||||
done();
|
||||
@ -207,7 +218,7 @@ describe("Import", function () {
|
||||
|
||||
// test settings
|
||||
settings.length.should.be.above(0, 'Wrong number of settings');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("002", 'Wrong database version');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("003", 'Wrong database version');
|
||||
|
||||
// activeTheme should NOT have been overridden
|
||||
_.findWhere(settings, {key: "activeTheme"}).value.should.equal("casper", 'Wrong theme');
|
||||
@ -270,7 +281,7 @@ describe("Import", function () {
|
||||
|
||||
// test settings
|
||||
settings.length.should.be.above(0, 'Wrong number of settings');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("002", 'Wrong database version');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("003", 'Wrong database version');
|
||||
|
||||
// test tags
|
||||
tags.length.should.equal(exportData.data.tags.length, 'no new tags');
|
||||
@ -316,7 +327,7 @@ describe("Import", function () {
|
||||
|
||||
// test settings
|
||||
settings.length.should.be.above(0, 'Wrong number of settings');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("002", 'Wrong database version');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("003", 'Wrong database version');
|
||||
|
||||
// test tags
|
||||
tags.length.should.equal(exportData.data.tags.length, 'no new tags');
|
||||
@ -329,17 +340,11 @@ describe("Import", function () {
|
||||
});
|
||||
|
||||
describe("002", function () {
|
||||
should.exist(Importer001);
|
||||
should.exist(Importer002);
|
||||
|
||||
beforeEach(function (done) {
|
||||
// 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 () {
|
||||
migration.migrateUpFreshDb().then(function () {
|
||||
return testUtils.insertDefaultUser();
|
||||
}).then(function () {
|
||||
done();
|
||||
@ -394,7 +399,7 @@ describe("Import", function () {
|
||||
|
||||
// test settings
|
||||
settings.length.should.be.above(0, 'Wrong number of settings');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("002", 'Wrong database version');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("003", 'Wrong database version');
|
||||
|
||||
// activeTheme should NOT have been overridden
|
||||
_.findWhere(settings, {key: "activeTheme"}).value.should.equal("casper", 'Wrong theme');
|
||||
@ -416,7 +421,9 @@ describe("Import", function () {
|
||||
assert.equal(new Date(posts[1].published_at).getTime(), timestamp);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
}).otherwise(function (error) {
|
||||
done(new Error(error));
|
||||
})
|
||||
});
|
||||
|
||||
it("doesn't import invalid post data from 002", function (done) {
|
||||
@ -457,7 +464,7 @@ describe("Import", function () {
|
||||
|
||||
// test settings
|
||||
settings.length.should.be.above(0, 'Wrong number of settings');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("002", 'Wrong database version');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("003", 'Wrong database version');
|
||||
|
||||
// test tags
|
||||
tags.length.should.equal(exportData.data.tags.length, 'no new tags');
|
||||
@ -503,7 +510,7 @@ describe("Import", function () {
|
||||
|
||||
// test settings
|
||||
settings.length.should.be.above(0, 'Wrong number of settings');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("002", 'Wrong database version');
|
||||
_.findWhere(settings, {key: "databaseVersion"}).value.should.equal("003", 'Wrong database version');
|
||||
|
||||
// test tags
|
||||
tags.length.should.equal(exportData.data.tags.length, 'no new tags');
|
||||
@ -514,4 +521,47 @@ describe("Import", function () {
|
||||
}).then(null, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("003", function () {
|
||||
should.exist(Importer003);
|
||||
|
||||
beforeEach(function (done) {
|
||||
// migrate to current version
|
||||
migration.migrateUpFreshDb().then(function () {
|
||||
return testUtils.insertDefaultUser();
|
||||
}).then(function () {
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it("safely imports data from 003", function (done) {
|
||||
var exportData;
|
||||
|
||||
testUtils.loadExportFixture('export-003').then(function (exported) {
|
||||
exportData = exported;
|
||||
return importer("003", exportData);
|
||||
}).then(function () {
|
||||
// Grab the data from tables
|
||||
return when.all([
|
||||
knex("apps").select(),
|
||||
knex("app_settings").select()
|
||||
]);
|
||||
}).then(function (importedData) {
|
||||
should.exist(importedData);
|
||||
|
||||
importedData.length.should.equal(2, 'Did not get data successfully');
|
||||
|
||||
var apps = importedData[0],
|
||||
app_settings = importedData[1];
|
||||
|
||||
// test apps
|
||||
apps.length.should.equal(exportData.data.apps.length, 'imported apps');
|
||||
|
||||
// test app settings
|
||||
// app_settings.length.should.equal(exportData.data.app_settings.length, 'imported app settings');
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -8,6 +8,7 @@ var testUtils = require('../utils'),
|
||||
|
||||
// Stuff we are testing
|
||||
permissions = require('../../server/permissions'),
|
||||
effectivePerms = require('../../server/permissions/effective'),
|
||||
Models = require('../../server/models'),
|
||||
UserProvider = Models.User,
|
||||
PermissionsProvider = Models.Permission,
|
||||
@ -15,6 +16,8 @@ var testUtils = require('../utils'),
|
||||
|
||||
describe('Permissions', function () {
|
||||
|
||||
var sandbox;
|
||||
|
||||
before(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
@ -22,13 +25,17 @@ describe('Permissions', function () {
|
||||
});
|
||||
|
||||
beforeEach(function (done) {
|
||||
sandbox = sinon.sandbox.create();
|
||||
testUtils.initData()
|
||||
.then(testUtils.insertDefaultUser).then(function () {
|
||||
.then(testUtils.insertDefaultUser)
|
||||
.then(testUtils.insertDefaultApp)
|
||||
.then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
sandbox.restore();
|
||||
testUtils.clearData()
|
||||
.then(function () {
|
||||
done();
|
||||
@ -80,7 +87,7 @@ describe('Permissions', function () {
|
||||
object_type: obj
|
||||
};
|
||||
|
||||
return PermissionsProvider.add(newPerm);
|
||||
return PermissionsProvider.add(newPerm, {user: 1});
|
||||
},
|
||||
createTestPermissions = function () {
|
||||
var createActions = _.map(testPerms, function (testPerm) {
|
||||
@ -97,7 +104,7 @@ describe('Permissions', function () {
|
||||
.then(function (actionsMap) {
|
||||
should.exist(actionsMap);
|
||||
|
||||
actionsMap.edit.sort().should.eql(['post', 'tag', 'user', 'page'].sort());
|
||||
actionsMap.edit.sort().should.eql(['post', 'tag', 'user', 'page', 'setting'].sort());
|
||||
|
||||
actionsMap.should.equal(permissions.actionsMap);
|
||||
|
||||
@ -120,7 +127,7 @@ describe('Permissions', function () {
|
||||
|
||||
existingUserRoles = foundUser.related('roles').length;
|
||||
|
||||
return testRole.save().then(function () {
|
||||
return testRole.save(null, {user: 1}).then(function () {
|
||||
return foundUser.roles().attach(testRole);
|
||||
});
|
||||
}).then(function () {
|
||||
@ -144,7 +151,7 @@ describe('Permissions', function () {
|
||||
|
||||
testUser.related('permissions').length.should.equal(0);
|
||||
|
||||
return testPermission.save().then(function () {
|
||||
return testPermission.save(null, {user: 1}).then(function () {
|
||||
return testUser.permissions().attach(testPermission);
|
||||
});
|
||||
}).then(function () {
|
||||
@ -164,7 +171,7 @@ describe('Permissions', function () {
|
||||
description: "test2 description"
|
||||
});
|
||||
|
||||
testRole.save()
|
||||
testRole.save(null, {user: 1})
|
||||
.then(function () {
|
||||
return testRole.load('permissions');
|
||||
})
|
||||
@ -177,7 +184,7 @@ describe('Permissions', function () {
|
||||
|
||||
testRole.related('permissions').length.should.equal(0);
|
||||
|
||||
return rolePermission.save().then(function () {
|
||||
return rolePermission.save(null, {user: 1}).then(function () {
|
||||
return testRole.permissions().attach(rolePermission);
|
||||
});
|
||||
})
|
||||
@ -233,7 +240,7 @@ describe('Permissions', function () {
|
||||
object_type: "post"
|
||||
});
|
||||
|
||||
return newPerm.save().then(function () {
|
||||
return newPerm.save(null, {user: 1}).then(function () {
|
||||
return foundUser.permissions().attach(newPerm);
|
||||
});
|
||||
})
|
||||
@ -243,7 +250,6 @@ describe('Permissions', function () {
|
||||
.then(function (updatedUser) {
|
||||
|
||||
// TODO: Verify updatedUser.related('permissions') has the permission?
|
||||
|
||||
var canThisResult = permissions.canThis(updatedUser.id);
|
||||
|
||||
should.exist(canThisResult.edit);
|
||||
@ -258,21 +264,22 @@ describe('Permissions', function () {
|
||||
|
||||
it('can use permissable function on Model to allow something', function (done) {
|
||||
var testUser,
|
||||
permissableStub = sinon.stub(PostProvider, 'permissable', function () {
|
||||
permissableStub = sandbox.stub(PostProvider, 'permissable', function () {
|
||||
return when.resolve();
|
||||
});
|
||||
|
||||
// createTestUser()
|
||||
UserProvider.browse()
|
||||
testUtils.insertAuthorUser()
|
||||
.then(function () {
|
||||
return UserProvider.browse();
|
||||
})
|
||||
.then(function (foundUser) {
|
||||
testUser = foundUser.models[0];
|
||||
testUser = foundUser.models[1];
|
||||
|
||||
return permissions.canThis(testUser).edit.post(123);
|
||||
})
|
||||
.then(function () {
|
||||
permissableStub.restore();
|
||||
|
||||
permissableStub.calledWith(123, testUser.id, 'edit').should.equal(true);
|
||||
permissableStub.calledWith(123, { user: testUser.id, app: null, internal: false }).should.equal(true);
|
||||
|
||||
done();
|
||||
})
|
||||
@ -286,29 +293,151 @@ describe('Permissions', function () {
|
||||
|
||||
it('can use permissable function on Model to forbid something', function (done) {
|
||||
var testUser,
|
||||
permissableStub = sinon.stub(PostProvider, 'permissable', function () {
|
||||
permissableStub = sandbox.stub(PostProvider, 'permissable', function () {
|
||||
return when.reject();
|
||||
});
|
||||
|
||||
|
||||
// createTestUser()
|
||||
UserProvider.browse()
|
||||
testUtils.insertAuthorUser()
|
||||
.then(function () {
|
||||
return UserProvider.browse();
|
||||
})
|
||||
.then(function (foundUser) {
|
||||
testUser = foundUser.models[0];
|
||||
|
||||
testUser = foundUser.models[1];
|
||||
|
||||
return permissions.canThis(testUser).edit.post(123);
|
||||
})
|
||||
.then(function () {
|
||||
permissableStub.restore();
|
||||
|
||||
errors.logError(new Error("Allowed testUser to edit post"));
|
||||
done(new Error("Allowed testUser to edit post"));
|
||||
})
|
||||
.otherwise(function () {
|
||||
permissableStub.restore();
|
||||
permissableStub.calledWith(123, testUser.id, 'edit').should.equal(true);
|
||||
|
||||
permissableStub.calledWith(123, { user: testUser.id, app: null, internal: false }).should.equal(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("can get effective user permissions", function (done) {
|
||||
effectivePerms.user(1).then(function (effectivePermissions) {
|
||||
should.exist(effectivePermissions);
|
||||
|
||||
effectivePermissions.length.should.be.above(0);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can check an apps effective permissions', function (done) {
|
||||
effectivePerms.app('Kudos')
|
||||
.then(function (effectivePermissions) {
|
||||
should.exist(effectivePermissions);
|
||||
|
||||
effectivePermissions.length.should.be.above(0);
|
||||
|
||||
done();
|
||||
})
|
||||
.otherwise(done);
|
||||
});
|
||||
|
||||
it('does not allow an app to edit a post without permission', function (done) {
|
||||
// Change the author of the post so the author override doesn't affect the test
|
||||
PostProvider.edit({id: 1, 'author_id': 2})
|
||||
.then(function (updatedPost) {
|
||||
// Add user permissions
|
||||
return Models.User.read({id: 1})
|
||||
.then(function (foundUser) {
|
||||
var newPerm = new Models.Permission({
|
||||
name: "app test edit post",
|
||||
action_type: "edit",
|
||||
object_type: "post"
|
||||
});
|
||||
|
||||
return newPerm.save(null, {user: 1}).then(function () {
|
||||
return foundUser.permissions().attach(newPerm).then(function () {
|
||||
return when.all([updatedPost, foundUser]);
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
.then(function (results) {
|
||||
var updatedPost = results[0],
|
||||
updatedUser = results[1];
|
||||
|
||||
return permissions.canThis({ user: updatedUser.id })
|
||||
.edit
|
||||
.post(updatedPost.id)
|
||||
.then(function () {
|
||||
return results;
|
||||
})
|
||||
.otherwise(function (err) {
|
||||
done(new Error("Did not allow user 1 to edit post 1"));
|
||||
});
|
||||
})
|
||||
.then(function (results) {
|
||||
var updatedPost = results[0],
|
||||
updatedUser = results[1];
|
||||
|
||||
// Confirm app cannot edit it.
|
||||
return permissions.canThis({ app: 'Hemingway', user: updatedUser.id })
|
||||
.edit
|
||||
.post(updatedPost.id)
|
||||
.then(function () {
|
||||
done(new Error("Allowed an edit of post 1"));
|
||||
})
|
||||
.otherwise(function () {
|
||||
done();
|
||||
});
|
||||
}).otherwise(done);
|
||||
});
|
||||
|
||||
it('allows an app to edit a post with permission', function (done) {
|
||||
permissions.canThis({ app: 'Kudos', user: 1 })
|
||||
.edit
|
||||
.post(1)
|
||||
.then(function () {
|
||||
done();
|
||||
})
|
||||
.otherwise(function () {
|
||||
done(new Error("Allowed an edit of post 1"));
|
||||
});
|
||||
});
|
||||
|
||||
it('checks for null context passed and rejects', function (done) {
|
||||
permissions.canThis(undefined)
|
||||
.edit
|
||||
.post(1)
|
||||
.then(function () {
|
||||
done(new Error("Should not allow editing post"));
|
||||
})
|
||||
.otherwise(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('allows \'internal\' to be passed for internal requests', function (done) {
|
||||
// Using tag here because post implements the custom permissable interface
|
||||
permissions.canThis('internal')
|
||||
.edit
|
||||
.tag(1)
|
||||
.then(function () {
|
||||
done();
|
||||
})
|
||||
.otherwise(function () {
|
||||
done(new Error("Should allow editing post with 'internal'"));
|
||||
});
|
||||
});
|
||||
|
||||
it('allows { internal: true } to be passed for internal requests', function (done) {
|
||||
// Using tag here because post implements the custom permissable interface
|
||||
permissions.canThis({ internal: true })
|
||||
.edit
|
||||
.tag(1)
|
||||
.then(function () {
|
||||
done();
|
||||
})
|
||||
.otherwise(function () {
|
||||
done(new Error("Should allow editing post with { internal: true }"));
|
||||
});
|
||||
});
|
||||
});
|
@ -8,7 +8,7 @@ var _ = require('lodash'),
|
||||
posts: ['posts', 'page', 'limit', 'pages', 'total'],
|
||||
post: ['id', 'uuid', 'title', 'slug', 'markdown', 'html', 'meta_title', 'meta_description',
|
||||
'featured', 'image', 'status', 'language', 'author_id', 'created_at', 'created_by', 'updated_at',
|
||||
'updated_by', 'published_at', 'published_by', 'page', 'author', 'tags'],
|
||||
'updated_by', 'published_at', 'published_by', 'page', 'author', 'tags', 'fields'],
|
||||
// TODO: remove databaseVersion, dbHash
|
||||
settings: ['databaseVersion', 'dbHash', 'title', 'description', 'email', 'logo', 'cover', 'defaultLang',
|
||||
"permalinks", 'postsPerPage', 'forceI18n', 'activeTheme', 'activeApps', 'installedApps',
|
||||
|
@ -101,6 +101,51 @@ DataGenerator.Content = {
|
||||
email: 'info@ghost.org',
|
||||
password: '$2a$10$.pZeeBE0gHXd0PTnbT/ph.GEKgd0Wd3q2pWna3ynTGBkPKnGIKZL6'
|
||||
}
|
||||
],
|
||||
|
||||
apps: [
|
||||
{
|
||||
name: 'Kudos',
|
||||
slug: 'kudos',
|
||||
version: '0.0.1',
|
||||
status: 'installed'
|
||||
},
|
||||
{
|
||||
name: 'Importer',
|
||||
slug: 'importer',
|
||||
version: '0.1.0',
|
||||
status: 'inactive'
|
||||
},
|
||||
{
|
||||
name: 'Hemingway',
|
||||
slug: 'hemingway',
|
||||
version: '1.0.0',
|
||||
status: 'installed'
|
||||
}
|
||||
],
|
||||
|
||||
app_fields: [
|
||||
{
|
||||
key: 'count',
|
||||
value: '120',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
key: 'words',
|
||||
value: '512',
|
||||
type: 'number'
|
||||
}
|
||||
],
|
||||
|
||||
app_settings: [
|
||||
{
|
||||
key: 'color',
|
||||
value: 'ghosty'
|
||||
},
|
||||
{
|
||||
key: 'setting',
|
||||
value: 'value'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
@ -108,7 +153,9 @@ DataGenerator.forKnex = (function () {
|
||||
|
||||
var posts,
|
||||
tags,
|
||||
posts_tags;
|
||||
posts_tags,
|
||||
apps,
|
||||
app_fields;
|
||||
|
||||
function createPost(overrides) {
|
||||
return _.defaults(overrides, {
|
||||
@ -185,6 +232,33 @@ DataGenerator.forKnex = (function () {
|
||||
};
|
||||
}
|
||||
|
||||
function createApp(overrides) {
|
||||
return _.defaults(overrides, {
|
||||
uuid: uuid.v4(),
|
||||
created_by: 1,
|
||||
created_at: new Date()
|
||||
});
|
||||
}
|
||||
|
||||
function createAppField(overrides) {
|
||||
return _.defaults(overrides, {
|
||||
uuid: uuid.v4(),
|
||||
created_by: 1,
|
||||
created_at: new Date(),
|
||||
app_id: 1,
|
||||
relatable_id: 1,
|
||||
relatable_type: 'posts'
|
||||
});
|
||||
}
|
||||
|
||||
function createAppSetting(overrides) {
|
||||
return _.defaults(overrides, {
|
||||
uuid: uuid.v4(),
|
||||
created_by: 1,
|
||||
created_at: new Date()
|
||||
});
|
||||
}
|
||||
|
||||
posts = [
|
||||
createPost(DataGenerator.Content.posts[0]),
|
||||
createPost(DataGenerator.Content.posts[1]),
|
||||
@ -212,6 +286,17 @@ DataGenerator.forKnex = (function () {
|
||||
{ post_id: 5, tag_id: 5 }
|
||||
];
|
||||
|
||||
apps = [
|
||||
createApp(DataGenerator.Content.apps[0]),
|
||||
createApp(DataGenerator.Content.apps[1]),
|
||||
createApp(DataGenerator.Content.apps[2])
|
||||
];
|
||||
|
||||
app_fields = [
|
||||
createAppField(DataGenerator.Content.app_fields[0]),
|
||||
createAppField(DataGenerator.Content.app_fields[1])
|
||||
];
|
||||
|
||||
return {
|
||||
createPost: createPost,
|
||||
createGenericPost: createGenericPost,
|
||||
@ -220,10 +305,15 @@ DataGenerator.forKnex = (function () {
|
||||
createGenericUser: createGenericUser,
|
||||
createUserRole: createUserRole,
|
||||
createPostsTags: createPostsTags,
|
||||
createApp: createApp,
|
||||
createAppField: createAppField,
|
||||
createAppSetting: createAppSetting,
|
||||
|
||||
posts: posts,
|
||||
tags: tags,
|
||||
posts_tags: posts_tags
|
||||
posts_tags: posts_tags,
|
||||
apps: apps,
|
||||
app_fields: app_fields
|
||||
};
|
||||
|
||||
}());
|
||||
|
369
core/test/utils/fixtures/export-003.json
Normal file
369
core/test/utils/fixtures/export-003.json
Normal file
@ -0,0 +1,369 @@
|
||||
{
|
||||
"meta": {
|
||||
"exported_on": 1388318311015,
|
||||
"version": "003"
|
||||
},
|
||||
"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": "activeApps",
|
||||
"value": "[]",
|
||||
"type": "plugin",
|
||||
"created_at": 1388318310831,
|
||||
"created_by": 1,
|
||||
"updated_at": 1388318310831,
|
||||
"updated_by": 1
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"uuid": "2ea560a3-2304-449d-a62b-f7b622987510",
|
||||
"key": "installedApps",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"apps": [
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "4d7557f0-0949-4946-9fe8-ec030e0727f0",
|
||||
"name": "Kudos",
|
||||
"slug": "kudos",
|
||||
"version": "0.0.1",
|
||||
"status": "installed",
|
||||
"created_at": 1388318312790,
|
||||
"created_by": 1,
|
||||
"updated_at": 1388318312790,
|
||||
"updated_by": 1
|
||||
}
|
||||
],
|
||||
"app_settings": [
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "790e4551-b9cc-4954-8f5d-b6e651bc7342",
|
||||
"key": "position",
|
||||
"value": "bottom",
|
||||
"app_id": 1,
|
||||
"created_at": 1388318312790,
|
||||
"created_by": 1,
|
||||
"updated_at": 1388318312790,
|
||||
"updated_by": 1
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"uuid": "29682b66-cdeb-4773-9821-bcf40ea93b58",
|
||||
"key": "size",
|
||||
"value": "60",
|
||||
"app_id": 1,
|
||||
"created_at": 1388318312790,
|
||||
"created_by": 1,
|
||||
"updated_at": 1388318312790,
|
||||
"updated_by": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ function clearData() {
|
||||
}
|
||||
|
||||
function insertPosts() {
|
||||
// ToDo: Get rid of pyramid of doom
|
||||
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);
|
||||
@ -91,15 +92,105 @@ 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('users')
|
||||
.insert(users)
|
||||
.then(function () {
|
||||
return knex('roles_users').insert(userRoles);
|
||||
});
|
||||
}
|
||||
|
||||
function insertEditorUser() {
|
||||
var users = [],
|
||||
userRoles = [];
|
||||
|
||||
users.push(DataGenerator.forKnex.createUser(DataGenerator.Content.users[1]));
|
||||
userRoles.push(DataGenerator.forKnex.createUserRole(2, 2));
|
||||
return knex('users')
|
||||
.insert(users)
|
||||
.then(function () {
|
||||
return knex('roles_users').insert(userRoles);
|
||||
});
|
||||
}
|
||||
|
||||
function insertAuthorUser() {
|
||||
var users = [],
|
||||
userRoles = [];
|
||||
|
||||
users.push(DataGenerator.forKnex.createUser(DataGenerator.Content.users[2]));
|
||||
userRoles.push(DataGenerator.forKnex.createUserRole(3, 3));
|
||||
return knex('users')
|
||||
.insert(users)
|
||||
.then(function () {
|
||||
return knex('roles_users').insert(userRoles);
|
||||
});
|
||||
}
|
||||
|
||||
function insertDefaultApp() {
|
||||
var apps = [];
|
||||
|
||||
apps.push(DataGenerator.forKnex.createApp(DataGenerator.Content.apps[0]));
|
||||
|
||||
return knex('apps')
|
||||
.insert(apps)
|
||||
.then(function () {
|
||||
return knex('permissions_apps')
|
||||
.insert({
|
||||
app_id: 1,
|
||||
permission_id: 1
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function insertApps() {
|
||||
return knex('apps').insert(DataGenerator.forKnex.apps).then(function () {
|
||||
return knex('app_fields').insert(DataGenerator.forKnex.app_fields);
|
||||
});
|
||||
}
|
||||
|
||||
function insertAppWithSettings() {
|
||||
var apps = [], app_settings = [];
|
||||
|
||||
apps.push(DataGenerator.forKnex.createApp(DataGenerator.Content.apps[0]));
|
||||
app_settings.push(DataGenerator.forKnex.createAppSetting(DataGenerator.Content.app_settings[0]));
|
||||
app_settings.push(DataGenerator.forKnex.createAppSetting(DataGenerator.Content.app_settings[1]));
|
||||
|
||||
return knex('apps').insert(apps, 'id')
|
||||
.then(function (results) {
|
||||
var appId = results[0];
|
||||
|
||||
for (var i = 0; i < app_settings.length; i++) {
|
||||
app_settings[i].app_id = appId;
|
||||
}
|
||||
|
||||
return knex('app_settings').insert(app_settings);
|
||||
});
|
||||
}
|
||||
function insertAppWithFields() {
|
||||
var apps = [], app_fields = [];
|
||||
|
||||
apps.push(DataGenerator.forKnex.createApp(DataGenerator.Content.apps[0]));
|
||||
app_fields.push(DataGenerator.forKnex.createAppField(DataGenerator.Content.app_fields[0]));
|
||||
app_fields.push(DataGenerator.forKnex.createAppField(DataGenerator.Content.app_fields[1]));
|
||||
|
||||
return knex('apps').insert(apps, 'id')
|
||||
.then(function (results) {
|
||||
var appId = results[0];
|
||||
|
||||
for (var i = 0; i < app_fields.length; i++) {
|
||||
app_fields[i].app_id = appId;
|
||||
}
|
||||
|
||||
return knex('app_fields').insert(app_fields);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function insertDefaultFixtures() {
|
||||
return when(insertDefaultUser().then(function () {
|
||||
return insertPosts();
|
||||
}));
|
||||
return insertDefaultUser().then(function () {
|
||||
return insertPosts()
|
||||
}).then(function () {
|
||||
return insertApps();
|
||||
});
|
||||
}
|
||||
|
||||
function loadExportFixture(filename) {
|
||||
@ -127,6 +218,12 @@ module.exports = {
|
||||
insertMorePosts: insertMorePosts,
|
||||
insertMorePostsTags: insertMorePostsTags,
|
||||
insertDefaultUser: insertDefaultUser,
|
||||
insertEditorUser: insertEditorUser,
|
||||
insertAuthorUser: insertAuthorUser,
|
||||
insertDefaultApp: insertDefaultApp,
|
||||
insertApps: insertApps,
|
||||
insertAppWithSettings: insertAppWithSettings,
|
||||
insertAppWithFields: insertAppWithFields,
|
||||
|
||||
loadExportFixture: loadExportFixture,
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
"engineStrict": true,
|
||||
"dependencies": {
|
||||
"bcryptjs": "0.7.10",
|
||||
"bookshelf": "0.6.1",
|
||||
"bookshelf": "0.6.8",
|
||||
"busboy": "0.0.12",
|
||||
"colors": "0.6.2",
|
||||
"connect-slashes": "1.2.0",
|
||||
|
Loading…
Reference in New Issue
Block a user