mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-27 22:49:56 -05:00
d15f1f8961
Further changes to the data model to ensure created_by, author_id and updated_by are all set to user 1 Updated settings such that the default type is always 'general', and changed the types in the fixtures to be slightly more useful Added additional assertions to tests to cover more assumptions about data
207 lines
No EOL
6.4 KiB
JavaScript
207 lines
No EOL
6.4 KiB
JavaScript
(function () {
|
|
|
|
"use strict";
|
|
|
|
var Post,
|
|
Posts,
|
|
_ = require('underscore'),
|
|
uuid = require('node-uuid'),
|
|
when = require('when'),
|
|
errors = require('../errorHandling'),
|
|
Showdown = require('showdown'),
|
|
converter = new Showdown.converter(),
|
|
User = require('./user').User,
|
|
GhostBookshelf = require('./base');
|
|
|
|
Post = GhostBookshelf.Model.extend({
|
|
|
|
tableName: 'posts',
|
|
|
|
hasTimestamps: true,
|
|
|
|
defaults: function () {
|
|
return {
|
|
uuid: uuid.v4(),
|
|
status: 'draft'
|
|
// TODO: language: ghost.config().defaultLang);
|
|
};
|
|
},
|
|
|
|
initialize: function () {
|
|
this.on('creating', this.creating, this);
|
|
this.on('saving', this.saving, this);
|
|
},
|
|
|
|
saving: function () {
|
|
if (!this.get('title')) {
|
|
throw new Error('Post title cannot be blank');
|
|
}
|
|
this.set('content_html', converter.makeHtml(this.get('content')));
|
|
|
|
if (this.hasChanged('status') && this.get('status') === 'published') {
|
|
this.set('published_at', new Date());
|
|
// This will need to go elsewhere in the API layer.
|
|
this.set('published_by', 1);
|
|
}
|
|
|
|
this.set('updated_by', 1);
|
|
// refactoring of ghost required in order to make these details available here
|
|
},
|
|
|
|
creating: function () {
|
|
if (!this.get('slug')) {
|
|
this.generateSlug();
|
|
}
|
|
|
|
if (!this.get('created_by')) {
|
|
this.set('created_by', 1);
|
|
}
|
|
|
|
if (!this.get('author_id')) {
|
|
this.set('author_id', 1);
|
|
}
|
|
},
|
|
|
|
generateSlug: function () {
|
|
return this.set('slug', this.get('title').replace(/\:/g, '').replace(/\s/g, '-').toLowerCase());
|
|
},
|
|
|
|
user: function () {
|
|
return this.belongsTo(User, 'created_by');
|
|
},
|
|
|
|
author: function () {
|
|
return this.belongsTo(User, 'author_id');
|
|
}
|
|
|
|
}, {
|
|
|
|
/**
|
|
* Find results by page - returns an object containing the
|
|
* information about the request (page, limit), along with the
|
|
* info needed for pagination (pages, total).
|
|
*
|
|
* {
|
|
* posts: [
|
|
* {...}, {...}, {...}
|
|
* ],
|
|
* page: __,
|
|
* limit: __,
|
|
* pages: __,
|
|
* total: __
|
|
* }
|
|
*
|
|
* @params opts
|
|
*/
|
|
findPage: function (opts) {
|
|
var postCollection;
|
|
|
|
// Allow findPage(n)
|
|
if (_.isString(opts) || _.isNumber(opts)) {
|
|
opts = {page: opts};
|
|
}
|
|
|
|
opts = _.extend({
|
|
page: 1,
|
|
limit: 15,
|
|
where: {},
|
|
status: 'published',
|
|
orderBy: ['published_at', 'DESC']
|
|
}, opts);
|
|
|
|
postCollection = Posts.forge();
|
|
|
|
// Unless `all` is passed as an option, filter on
|
|
// the status provided.
|
|
if (opts.status !== 'all') {
|
|
opts.where.status = opts.status;
|
|
}
|
|
|
|
// If there are where conditionals specified, add those
|
|
// to the query.
|
|
if (opts.where) {
|
|
postCollection.query('where', opts.where);
|
|
}
|
|
|
|
// Set the limit & offset for the query, fetching
|
|
// with the opts (to specify any eager relations, etc.)
|
|
// Omitting the `page`, `limit`, `where` just to be sure
|
|
// aren't used for other purposes.
|
|
return postCollection
|
|
.query('limit', opts.limit)
|
|
.query('offset', opts.limit * (opts.page - 1))
|
|
.query('orderBy', opts.orderBy[0], opts.orderBy[1])
|
|
.fetch(_.omit(opts, 'page', 'limit', 'where', 'status', 'orderBy'))
|
|
.then(function (collection) {
|
|
var qb;
|
|
|
|
// After we're done, we need to figure out what
|
|
// the limits are for the pagination values.
|
|
qb = GhostBookshelf.Knex(_.result(collection, 'tableName'));
|
|
|
|
if (opts.where) {
|
|
qb.where(opts.where);
|
|
}
|
|
|
|
return qb.count(_.result(collection, 'idAttribute')).then(function (resp) {
|
|
var totalPosts = resp[0].aggregate;
|
|
return {
|
|
posts: collection.toJSON(),
|
|
page: opts.page,
|
|
limit: opts.limit,
|
|
pages: Math.ceil(totalPosts / opts.limit),
|
|
total: totalPosts
|
|
};
|
|
}, errors.logAndThrowError);
|
|
}, errors.logAndThrowError);
|
|
},
|
|
|
|
permissable: function (postModelOrId, userId, action_type, userPermissions) {
|
|
var self = this,
|
|
hasPermission,
|
|
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);
|
|
}, errors.logAndThrowError);
|
|
}
|
|
|
|
// TODO: This logic is temporary, will probably need to be updated
|
|
|
|
hasPermission = _.any(userPermissions, function (perm) {
|
|
if (perm.get('object_type') !== 'post') {
|
|
return false;
|
|
}
|
|
|
|
// True, if no object_id specified, or it matches
|
|
return !perm.get('object_id') || perm.get('object_id') === postModel.id;
|
|
});
|
|
|
|
// If this is the author of the post, allow it.
|
|
hasPermission = hasPermission || userId === postModel.get('author_id');
|
|
|
|
if (hasPermission) {
|
|
return when.resolve();
|
|
}
|
|
|
|
// Otherwise, you shall not pass.
|
|
return when.reject();
|
|
}
|
|
|
|
});
|
|
|
|
Posts = GhostBookshelf.Collection.extend({
|
|
|
|
model: Post
|
|
|
|
});
|
|
|
|
module.exports = {
|
|
Post: Post,
|
|
Posts: Posts
|
|
};
|
|
|
|
}()); |