mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-06 22:40:14 -05:00
Add apps permissable checks in posts and users
Closes #2738 - Re-introduce the TargetModel.permissable interface check in the regular permission flow path - Pass loadedPermissions, hasUserPermission and hasAppPermission to permissable interface to reduce logic necessary - Refactor recursive call to pass original arguments but with actual model - Refactor canThis(this.user) use in api/posts.js to just canThis(this)
This commit is contained in:
parent
cdb98241cf
commit
0dc6dc29a7
4 changed files with 42 additions and 23 deletions
|
@ -82,7 +82,7 @@ posts = {
|
||||||
var self = this,
|
var self = this,
|
||||||
include;
|
include;
|
||||||
|
|
||||||
return canThis(self.user).edit.post(postData.id).then(function () {
|
return canThis(this).edit.post(postData.id).then(function () {
|
||||||
return checkPostData(postData).then(function (checkedPostData) {
|
return checkPostData(postData).then(function (checkedPostData) {
|
||||||
|
|
||||||
if (postData.include) {
|
if (postData.include) {
|
||||||
|
@ -115,7 +115,7 @@ posts = {
|
||||||
include;
|
include;
|
||||||
|
|
||||||
// **returns:** a promise for the resulting post in a json object
|
// **returns:** a promise for the resulting post in a json object
|
||||||
return canThis(this.user).create.post().then(function () {
|
return canThis(this).create.post().then(function () {
|
||||||
return checkPostData(postData).then(function (checkedPostData) {
|
return checkPostData(postData).then(function (checkedPostData) {
|
||||||
if (postData.include) {
|
if (postData.include) {
|
||||||
include = prepareInclude(postData.include);
|
include = prepareInclude(postData.include);
|
||||||
|
@ -141,7 +141,7 @@ posts = {
|
||||||
destroy: function destroy(args) {
|
destroy: function destroy(args) {
|
||||||
var self = this;
|
var self = this;
|
||||||
// **returns:** a promise for a json response with the id of the deleted post
|
// **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 canThis(this).remove.post(args.id).then(function () {
|
||||||
// TODO: Would it be good to get rid of .call()?
|
// 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 posts.read.call({user: self.user}, {id : args.id, status: 'all'}).then(function (result) {
|
||||||
return dataProvider.Post.destroy(args.id).then(function () {
|
return dataProvider.Post.destroy(args.id).then(function () {
|
||||||
|
@ -165,7 +165,7 @@ posts = {
|
||||||
// **takes:** a string to generate the slug from
|
// **takes:** a string to generate the slug from
|
||||||
generateSlug: function generateSlug(args) {
|
generateSlug: function generateSlug(args) {
|
||||||
|
|
||||||
return canThis(this.user).slug.post().then(function () {
|
return canThis(this).slug.post().then(function () {
|
||||||
return dataProvider.Base.Model.generateSlug(dataProvider.Post, args.title, {status: 'all'}).then(function (slug) {
|
return dataProvider.Base.Model.generateSlug(dataProvider.Post, args.title, {status: 'all'}).then(function (slug) {
|
||||||
if (slug) {
|
if (slug) {
|
||||||
return slug;
|
return slug;
|
||||||
|
|
|
@ -473,21 +473,31 @@ Post = ghostBookshelf.Model.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
permissable: function (postModelOrId, context) {
|
permissable: function (postModelOrId, context, loadedPermissions, hasUserPermission, hasAppPermission) {
|
||||||
var self = this,
|
var self = this,
|
||||||
userId = context.user,
|
postModel = postModelOrId,
|
||||||
postModel = postModelOrId;
|
origArgs;
|
||||||
|
|
||||||
// If we passed in an id instead of a model, get the model
|
// If we passed in an id instead of a model, get the model
|
||||||
// then check the permissions
|
// then check the permissions
|
||||||
if (_.isNumber(postModelOrId) || _.isString(postModelOrId)) {
|
if (_.isNumber(postModelOrId) || _.isString(postModelOrId)) {
|
||||||
|
// Grab the original args without the first one
|
||||||
|
origArgs = _.toArray(arguments).slice(1);
|
||||||
|
// Get the actual post model
|
||||||
return this.findOne({id: postModelOrId, status: 'all'}).then(function (foundPostModel) {
|
return this.findOne({id: postModelOrId, status: 'all'}).then(function (foundPostModel) {
|
||||||
return self.permissable(foundPostModel, context);
|
// Build up the original args but substitute with actual model
|
||||||
|
var newArgs = [foundPostModel].concat(origArgs);
|
||||||
|
|
||||||
|
return self.permissable.apply(self, newArgs);
|
||||||
}, errors.logAndThrowError);
|
}, errors.logAndThrowError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (postModel) {
|
||||||
// If this is the author of the post, allow it.
|
// If this is the author of the post, allow it.
|
||||||
if (postModel && userId === postModel.get('author_id')) {
|
hasUserPermission = hasUserPermission || context.user === postModel.get('author_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasUserPermission && hasAppPermission) {
|
||||||
return when.resolve();
|
return when.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,23 +172,34 @@ User = ghostBookshelf.Model.extend({
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
permissable: function (userModelOrId, context) {
|
permissable: function (userModelOrId, context, loadedPermissions, hasUserPermission, hasAppPermission) {
|
||||||
var self = this,
|
var self = this,
|
||||||
userId = context.user,
|
userModel = userModelOrId,
|
||||||
userModel = userModelOrId;
|
origArgs;
|
||||||
|
|
||||||
// If we passed in an id instead of a model, get the model
|
// If we passed in an id instead of a model, get the model
|
||||||
// then check the permissions
|
// then check the permissions
|
||||||
if (_.isNumber(userModelOrId) || _.isString(userModelOrId)) {
|
if (_.isNumber(userModelOrId) || _.isString(userModelOrId)) {
|
||||||
|
// Grab the original args without the first one
|
||||||
|
origArgs = _.toArray(arguments).slice(1);
|
||||||
|
// Get the actual post model
|
||||||
return this.findOne({id: userModelOrId}).then(function (foundUserModel) {
|
return this.findOne({id: userModelOrId}).then(function (foundUserModel) {
|
||||||
return self.permissable(foundUserModel, context);
|
// Build up the original args but substitute with actual model
|
||||||
|
var newArgs = [foundUserModel].concat(origArgs);
|
||||||
|
|
||||||
|
return self.permissable.apply(self, newArgs);
|
||||||
}, errors.logAndThrowError);
|
}, errors.logAndThrowError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (userModel) {
|
||||||
// If this is the same user that requests the operation allow it.
|
// If this is the same user that requests the operation allow it.
|
||||||
if (userModel && userId === userModel.get('id')) {
|
hasUserPermission = hasUserPermission || context.user === userModel.get('id');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasUserPermission && hasAppPermission) {
|
||||||
return when.resolve();
|
return when.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
return when.reject();
|
return when.reject();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -120,16 +120,14 @@ CanThisResult.prototype.buildObjectTypeHandlers = function (obj_types, act_type,
|
||||||
hasAppPermission = _.any(appPermissions, checkPermission);
|
hasAppPermission = _.any(appPermissions, checkPermission);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Offer a chance for the TargetModel to override the results
|
||||||
|
if (TargetModel && _.isFunction(TargetModel.permissable)) {
|
||||||
|
return TargetModel.permissable(modelId, context, loadedPermissions, hasUserPermission, hasAppPermission);
|
||||||
|
}
|
||||||
|
|
||||||
if (hasUserPermission && hasAppPermission) {
|
if (hasUserPermission && hasAppPermission) {
|
||||||
return when.resolve();
|
return when.resolve();
|
||||||
}
|
}
|
||||||
return when.reject();
|
|
||||||
}).otherwise(function () {
|
|
||||||
// Check for special permissions on the model directly
|
|
||||||
if (TargetModel && _.isFunction(TargetModel.permissable)) {
|
|
||||||
return TargetModel.permissable(modelId, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return when.reject();
|
return when.reject();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue