mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Add permissions to API
closes #2264 - added permissions check to db, users and posts - added register method to users - added doesUserExist method to users - added user from session to internal calls - changed permissible to overwrite canThis - removed action map and action type from permissable method
This commit is contained in:
parent
61e94a6e8b
commit
e47e9c62d0
15 changed files with 259 additions and 180 deletions
|
@ -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)'});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -51,13 +51,13 @@ requestHandler = function (apiMethod) {
|
|||
};
|
||||
|
||||
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,6 +20,9 @@ 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,
|
||||
|
@ -34,9 +37,15 @@ posts = {
|
|||
|
||||
// #### Read
|
||||
// **takes:** an identifier (id or slug?)
|
||||
read: function read(args) {
|
||||
read: function read(options) {
|
||||
options = options || {};
|
||||
if (!this.user) {
|
||||
// only published posts for
|
||||
options.status = 'published';
|
||||
}
|
||||
|
||||
// **returns:** a promise for a single post in a json object
|
||||
return dataProvider.Post.findOne(args).then(function (result) {
|
||||
return dataProvider.Post.findOne(options).then(function (result) {
|
||||
var omitted;
|
||||
|
||||
if (result) {
|
||||
|
@ -49,15 +58,6 @@ 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) {
|
||||
|
@ -101,9 +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
|
||||
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;
|
||||
|
@ -112,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;
|
|
@ -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,36 @@ 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, {user: this.user}).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, {user: this.user});
|
||||
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
|
||||
|
@ -75,7 +93,7 @@ users = {
|
|||
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: 1}, userData);
|
||||
return users.add.call({user: 'internal'}, userData);
|
||||
},
|
||||
|
||||
// #### Check
|
||||
|
@ -111,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;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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'
|
||||
};
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -394,59 +394,24 @@ Post = ghostBookshelf.Model.extend({
|
|||
.catch(errors.logAndThrowError);
|
||||
},
|
||||
|
||||
permissable: function (postModelOrId, context, action_type, loadedPermissions) {
|
||||
permissable: function (postModelOrId, context) {
|
||||
var self = this,
|
||||
userId = context.user,
|
||||
isAuthor,
|
||||
hasPermission,
|
||||
userPermissions = loadedPermissions.user,
|
||||
appPermissions = loadedPermissions.app,
|
||||
postModel = postModelOrId,
|
||||
checkPermission = 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;
|
||||
};
|
||||
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, context, action_type, loadedPermissions);
|
||||
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, checkPermission);
|
||||
|
||||
// If we have already have user permission and we passed in appPermissions check them
|
||||
if (hasPermission && !_.isNull(appPermissions)) {
|
||||
hasPermission = _.any(appPermissions, checkPermission);
|
||||
}
|
||||
|
||||
// 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()
|
||||
isAuthor = (postModel && userId === postModel.get('author_id'));
|
||||
hasPermission = hasPermission || isAuthor;
|
||||
|
||||
// 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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -79,10 +79,8 @@ 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 permissionLoad.then(function (loadedPermissions) {
|
||||
|
||||
// Iterate through the user permissions looking for an affirmation
|
||||
var userPermissions = loadedPermissions.user,
|
||||
appPermissions = loadedPermissions.app,
|
||||
|
@ -111,22 +109,11 @@ CanThisResult.prototype.buildObjectTypeHandlers = function (obj_types, act_type,
|
|||
return modelId === permObjId;
|
||||
};
|
||||
|
||||
// Allow for a target model to implement a "Permissable" interface
|
||||
if (TargetModel && _.isFunction(TargetModel.permissable)) {
|
||||
return TargetModel.permissable(modelId, context, act_type, loadedPermissions);
|
||||
}
|
||||
|
||||
// Check user permissions for matching action, object and id.
|
||||
if (!_.isEmpty(userPermissions)) {
|
||||
hasUserPermission = _.any(userPermissions, checkPermission);
|
||||
}
|
||||
|
||||
// If we already checked user permissions and they failed,
|
||||
// no need to check app permissions
|
||||
if (hasUserPermission === false) {
|
||||
return when.reject();
|
||||
}
|
||||
|
||||
// Check app permissions if they were passed
|
||||
hasAppPermission = true;
|
||||
if (!_.isNull(appPermissions)) {
|
||||
|
@ -136,12 +123,11 @@ CanThisResult.prototype.buildObjectTypeHandlers = function (obj_types, act_type,
|
|||
if (hasUserPermission && hasAppPermission) {
|
||||
return when.resolve();
|
||||
}
|
||||
|
||||
return when.reject();
|
||||
}).otherwise(function () {
|
||||
// Still check for permissable without permissions
|
||||
// Check for special permissions on the model directly
|
||||
if (TargetModel && _.isFunction(TargetModel.permissable)) {
|
||||
return TargetModel.permissable(modelId, context, act_type, []);
|
||||
return TargetModel.permissable(modelId, context);
|
||||
}
|
||||
|
||||
return when.reject();
|
||||
|
|
|
@ -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 () {
|
||||
|
||||
|
@ -33,8 +34,9 @@ describe('DB API', function () {
|
|||
});
|
||||
|
||||
it('delete all content', function (done) {
|
||||
|
||||
dbAPI.deleteAllContent().then(function (result){
|
||||
permissions.init().then(function () {
|
||||
return dbAPI.deleteAllContent();
|
||||
}).then(function (result){
|
||||
should.exist(result.message);
|
||||
result.message.should.equal('Successfully deleted all content from your blog.')
|
||||
}).then(function () {
|
||||
|
@ -48,6 +50,8 @@ describe('DB API', function () {
|
|||
results.posts.length.should.equal(0);
|
||||
done();
|
||||
});
|
||||
}).then(null, done);
|
||||
}).otherwise(function () {
|
||||
done()
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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 () {
|
||||
|
||||
|
@ -31,11 +32,15 @@ describe('Users API', function () {
|
|||
});
|
||||
|
||||
it('can browse', function (done) {
|
||||
UsersAPI.browse().then(function (results) {
|
||||
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');
|
||||
done();
|
||||
}).then(null, done);
|
||||
}).otherwise(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -421,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) {
|
||||
|
|
|
@ -268,17 +268,18 @@ describe('Permissions', 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();
|
||||
})
|
||||
|
@ -296,10 +297,12 @@ describe('Permissions', 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);
|
||||
})
|
||||
|
@ -310,7 +313,7 @@ describe('Permissions', function () {
|
|||
})
|
||||
.otherwise(function () {
|
||||
permissableStub.restore();
|
||||
permissableStub.calledWith(123, { user: testUser.id, app: null, internal: false }, 'edit').should.equal(true);
|
||||
permissableStub.calledWith(123, { user: testUser.id, app: null, internal: false }).should.equal(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -99,6 +99,32 @@ function insertDefaultUser() {
|
|||
});
|
||||
}
|
||||
|
||||
function insertEditorUser() {
|
||||
var users = [],
|
||||
userRoles = [];
|
||||
|
||||
users.push(DataGenerator.forKnex.createUser(DataGenerator.Content.users[1]));
|
||||
userRoles.push(DataGenerator.forKnex.createUserRole(1, 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(1, 3));
|
||||
return knex('users')
|
||||
.insert(users)
|
||||
.then(function () {
|
||||
return knex('roles_users').insert(userRoles);
|
||||
});
|
||||
}
|
||||
|
||||
function insertDefaultApp() {
|
||||
var apps = [];
|
||||
|
||||
|
@ -192,6 +218,8 @@ module.exports = {
|
|||
insertMorePosts: insertMorePosts,
|
||||
insertMorePostsTags: insertMorePostsTags,
|
||||
insertDefaultUser: insertDefaultUser,
|
||||
insertEditorUser: insertEditorUser,
|
||||
insertAuthorUser: insertAuthorUser,
|
||||
insertDefaultApp: insertDefaultApp,
|
||||
insertApps: insertApps,
|
||||
insertAppWithSettings: insertAppWithSettings,
|
||||
|
|
Loading…
Add table
Reference in a new issue