mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-27 18:52:14 +03:00
add small permission improvements
no issue - do not check client type in auth middleware - offer filtering for findAll function in base - add isInternalContext to base model
This commit is contained in:
parent
2744fed5d8
commit
f644d99460
@ -113,7 +113,7 @@ db = {
|
||||
*/
|
||||
deleteAllContent: function (options) {
|
||||
var tasks,
|
||||
queryOpts = {columns: 'id'};
|
||||
queryOpts = {columns: 'id', context: {internal: true}};
|
||||
|
||||
options = options || {};
|
||||
|
||||
|
@ -65,7 +65,7 @@ auth = {
|
||||
delete req.body.client_id;
|
||||
delete req.body.client_secret;
|
||||
|
||||
if (!client || client.type !== 'ua') {
|
||||
if (!client) {
|
||||
errors.logError(
|
||||
i18n.t('errors.middleware.auth.clientAuthenticationFailed'),
|
||||
i18n.t('errors.middleware.auth.clientCredentialsNotValid'),
|
||||
|
@ -233,14 +233,24 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||
|
||||
/**
|
||||
* ### Find All
|
||||
* Naive find all fetches all the data for a particular model
|
||||
* Fetches all the data for a particular model
|
||||
* @param {Object} options (optional)
|
||||
* @return {Promise(ghostBookshelf.Collection)} Collection of all Models
|
||||
*/
|
||||
findAll: function findAll(options) {
|
||||
options = this.filterOptions(options, 'findAll');
|
||||
options.withRelated = _.union(options.withRelated, options.include);
|
||||
return this.forge().fetchAll(options).then(function then(result) {
|
||||
|
||||
var itemCollection = this.forge(null, {context: options.context});
|
||||
|
||||
// transforms fictive keywords like 'all' (status:all) into correct allowed values
|
||||
if (this.processOptions) {
|
||||
this.processOptions(options);
|
||||
}
|
||||
|
||||
itemCollection.applyDefaultAndCustomFilters(options);
|
||||
|
||||
return itemCollection.fetchAll(options).then(function then(result) {
|
||||
if (options.include) {
|
||||
_.each(result.models, function each(item) {
|
||||
item.include = options.include;
|
||||
@ -290,7 +300,7 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||
this.processOptions(options);
|
||||
|
||||
// Add Filter behaviour
|
||||
itemCollection.applyFilters(options);
|
||||
itemCollection.applyDefaultAndCustomFilters(options);
|
||||
|
||||
// Handle related objects
|
||||
// TODO: this should just be done for all methods @ the API level
|
||||
@ -306,7 +316,6 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||
} else {
|
||||
options.order = self.orderDefaultOptions();
|
||||
}
|
||||
|
||||
return itemCollection.fetchPage(options).then(function formatResponse(response) {
|
||||
var data = {};
|
||||
|
||||
|
@ -11,6 +11,7 @@ module.exports = function (Bookshelf) {
|
||||
* Cached copy of the context setup for this model instance
|
||||
*/
|
||||
_context: null,
|
||||
|
||||
/**
|
||||
* ## Is Public Context?
|
||||
* A helper to determine if this is a public request or not
|
||||
@ -18,6 +19,10 @@ module.exports = function (Bookshelf) {
|
||||
*/
|
||||
isPublicContext: function isPublicContext() {
|
||||
return !!(this._context && this._context.public);
|
||||
},
|
||||
|
||||
isInternalContext: function isInternalContext() {
|
||||
return !!(this._context && this._context.internal);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -118,6 +118,7 @@ filter = function filter(Bookshelf) {
|
||||
.query('join', 'users as author', 'author.id', '=', 'posts.author_id');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* ## fetchAndCombineFilters
|
||||
* Helper method, uses the combineFilters util to apply filters to the current model instance
|
||||
@ -137,6 +138,7 @@ filter = function filter(Bookshelf) {
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* ## Apply Filters
|
||||
* Method which makes the necessary query builder calls (through knex) for the filters set
|
||||
@ -144,7 +146,7 @@ filter = function filter(Bookshelf) {
|
||||
* @param {Object} options
|
||||
* @returns {Bookshelf.Model}
|
||||
*/
|
||||
applyFilters: function applyFilters(options) {
|
||||
applyDefaultAndCustomFilters: function applyDefaultAndCustomFilters(options) {
|
||||
var self = this;
|
||||
|
||||
// @TODO figure out a better place/way to trigger loading filters
|
||||
|
@ -394,6 +394,10 @@ Post = ghostBookshelf.Model.extend({
|
||||
return this.isPublicContext() ? 'status:published' : null;
|
||||
},
|
||||
defaultFilters: function defaultFilters() {
|
||||
if (this.isInternalContext()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.isPublicContext() ? 'page:false' : 'page:false+status:published';
|
||||
}
|
||||
}, {
|
||||
@ -458,7 +462,7 @@ Post = ghostBookshelf.Model.extend({
|
||||
validOptions = {
|
||||
findOne: ['columns', 'importing', 'withRelated', 'require'],
|
||||
findPage: ['page', 'limit', 'columns', 'filter', 'order', 'status', 'staticPages'],
|
||||
findAll: ['columns'],
|
||||
findAll: ['columns', 'filter'],
|
||||
add: ['importing']
|
||||
};
|
||||
|
||||
@ -636,6 +640,7 @@ Post = ghostBookshelf.Model.extend({
|
||||
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 then(foundPostModel) {
|
||||
// Build up the original args but substitute with actual model
|
||||
|
@ -170,9 +170,15 @@ User = ghostBookshelf.Model.extend({
|
||||
return role.get('name') === roleName;
|
||||
});
|
||||
},
|
||||
|
||||
enforcedFilters: function enforcedFilters() {
|
||||
if (this.isInternalContext()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.isPublicContext() ? 'status:[' + activeStates.join(',') + ']' : null;
|
||||
},
|
||||
|
||||
defaultFilters: function defaultFilters() {
|
||||
return this.isPublicContext() ? null : 'status:[' + activeStates.join(',') + ']';
|
||||
}
|
||||
@ -235,7 +241,8 @@ User = ghostBookshelf.Model.extend({
|
||||
findOne: ['withRelated', 'status'],
|
||||
setup: ['id'],
|
||||
edit: ['withRelated', 'id'],
|
||||
findPage: ['page', 'limit', 'columns', 'filter', 'order', 'status']
|
||||
findPage: ['page', 'limit', 'columns', 'filter', 'order', 'status'],
|
||||
findAll: ['filter']
|
||||
};
|
||||
|
||||
if (validOptions[methodName]) {
|
||||
|
@ -139,12 +139,13 @@ describe('Database Migration (special functions)', function () {
|
||||
|
||||
describe('Populate', function () {
|
||||
beforeEach(testUtils.setup());
|
||||
|
||||
it('should populate all fixtures correctly', function (done) {
|
||||
fixtures.populate(loggerStub).then(function () {
|
||||
var props = {
|
||||
posts: Models.Post.findAll({include: ['tags']}),
|
||||
tags: Models.Tag.findAll(),
|
||||
users: Models.User.findAll({include: ['roles']}),
|
||||
users: Models.User.findAll({filter: 'status:inactive', context: {internal:true}, include: ['roles']}),
|
||||
clients: Models.Client.findAll(),
|
||||
roles: Models.Role.findAll(),
|
||||
permissions: Models.Permission.findAll({include: ['roles']})
|
||||
@ -181,6 +182,7 @@ describe('Database Migration (special functions)', function () {
|
||||
should.exist(result.users);
|
||||
result.users.length.should.eql(1);
|
||||
result.users.at(0).get('name').should.eql('Ghost Owner');
|
||||
result.users.at(0).get('status').should.eql('inactive');
|
||||
result.users.at(0).related('roles').length.should.eql(1);
|
||||
result.users.at(0).related('roles').at(0).get('name').should.eql('Owner');
|
||||
|
||||
|
@ -1324,14 +1324,14 @@ describe('Post Model', function () {
|
||||
// We're going to delete all posts by user 1
|
||||
var authorData = {id: 1};
|
||||
|
||||
PostModel.findAll().then(function (found) {
|
||||
PostModel.findAll({context:{internal:true}}).then(function (found) {
|
||||
// There are 50 posts to begin with
|
||||
found.length.should.equal(50);
|
||||
return PostModel.destroyByAuthor(authorData);
|
||||
}).then(function (results) {
|
||||
// User 1 has 13 posts in the database
|
||||
results.length.should.equal(13);
|
||||
return PostModel.findAll();
|
||||
return PostModel.findAll({context:{internal:true}});
|
||||
}).then(function (found) {
|
||||
// Only 37 should remain
|
||||
found.length.should.equal(37);
|
||||
|
@ -153,7 +153,7 @@ describe('Filter', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Apply Filters', function () {
|
||||
describe('Apply Default and Custom Filters', function () {
|
||||
var fetchSpy,
|
||||
restoreGQL,
|
||||
filterGQL;
|
||||
@ -174,7 +174,7 @@ describe('Filter', function () {
|
||||
});
|
||||
|
||||
it('should call fetchAndCombineFilters if _filters not set', function () {
|
||||
var result = ghostBookshelf.Model.prototype.applyFilters();
|
||||
var result = ghostBookshelf.Model.prototype.applyDefaultAndCustomFilters();
|
||||
|
||||
fetchSpy.calledOnce.should.be.true();
|
||||
should(result._filters).be.null();
|
||||
@ -183,7 +183,7 @@ describe('Filter', function () {
|
||||
it('should NOT call fetchAndCombineFilters if _filters IS set', function () {
|
||||
ghostBookshelf.Model.prototype._filters = 'test';
|
||||
|
||||
var result = ghostBookshelf.Model.prototype.applyFilters();
|
||||
var result = ghostBookshelf.Model.prototype.applyDefaultAndCustomFilters();
|
||||
|
||||
fetchSpy.called.should.be.false();
|
||||
result._filters.should.eql('test');
|
||||
@ -193,7 +193,7 @@ describe('Filter', function () {
|
||||
ghostBookshelf.Model.prototype._filters = {statements: [
|
||||
{prop: 'title', op: '=', value: 'Hello Word'}
|
||||
]};
|
||||
ghostBookshelf.Model.prototype.applyFilters();
|
||||
ghostBookshelf.Model.prototype.applyDefaultAndCustomFilters();
|
||||
|
||||
fetchSpy.called.should.be.false();
|
||||
filterGQL.knexify.called.should.be.true();
|
||||
@ -208,7 +208,7 @@ describe('Filter', function () {
|
||||
{prop: 'tags', op: 'IN', value: ['photo', 'video']}
|
||||
]};
|
||||
|
||||
ghostBookshelf.Model.prototype.applyFilters();
|
||||
ghostBookshelf.Model.prototype.applyDefaultAndCustomFilters();
|
||||
filterGQL.json.printStatements.calledOnce.should.be.true();
|
||||
filterGQL.json.printStatements.firstCall.args[0].should.eql([
|
||||
{prop: 'tags', op: 'IN', value: ['photo', 'video']}
|
||||
|
Loading…
Reference in New Issue
Block a user