mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-23 10:53:34 +03:00
closes #33 - api example
Moving towards using an API which we can both expose publicly, and use internally. Due to issues with JugglingDB, this breaks updating contentHTML on edit Also, language, status, featured etc are all no long set / updated.
This commit is contained in:
parent
e7b37f8671
commit
bb6880ea49
13
app.js
13
app.js
@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
// Module dependencies.
|
// Module dependencies.
|
||||||
var express = require('express'),
|
var express = require('express'),
|
||||||
fs = require('fs'),
|
|
||||||
admin = require('./core/admin/controllers'),
|
admin = require('./core/admin/controllers'),
|
||||||
frontend = require('./core/frontend/controllers'),
|
frontend = require('./core/frontend/controllers'),
|
||||||
|
api = require('./core/shared/api'),
|
||||||
flash = require('connect-flash'),
|
flash = require('connect-flash'),
|
||||||
Ghost = require('./core/ghost'),
|
Ghost = require('./core/ghost'),
|
||||||
I18n = require('./core/lang/i18n'),
|
I18n = require('./core/lang/i18n'),
|
||||||
@ -46,11 +46,13 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* API routes..
|
* API routes..
|
||||||
* @todo convert these into a RESTful, public, authenticated API!
|
* @todo auth should be public auth not user auth
|
||||||
*/
|
*/
|
||||||
ghost.app().post('/api/v0.1/posts/create', auth, admin.posts.create);
|
ghost.app().get('/api/v0.1/posts', auth, api.requestHandler(api.posts.browse));
|
||||||
ghost.app().post('/api/v0.1/posts/edit', auth, admin.posts.edit);
|
ghost.app().get('/api/v0.1/posts/:id', auth, api.requestHandler(api.posts.read));
|
||||||
ghost.app().get('/api/v0.1/posts', auth, admin.posts.index);
|
ghost.app().post('/api/v0.1/posts/create', auth, api.requestHandler(api.posts.add));
|
||||||
|
ghost.app().put('/api/v0.1/posts/edit', auth, api.requestHandler(api.posts.edit));
|
||||||
|
ghost.app()['delete']('/api/v0.1/posts/:id', auth, api.requestHandler(api.posts.destroy));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Admin routes..
|
* Admin routes..
|
||||||
@ -75,6 +77,5 @@
|
|||||||
|
|
||||||
ghost.app().listen(3333, function () {
|
ghost.app().listen(3333, function () {
|
||||||
console.log("Express server listening on port " + 3333);
|
console.log("Express server listening on port " + 3333);
|
||||||
console.log('process: ', process.env);
|
|
||||||
});
|
});
|
||||||
}());
|
}());
|
@ -56,7 +56,7 @@
|
|||||||
function save() {
|
function save() {
|
||||||
var entry = {
|
var entry = {
|
||||||
title: document.getElementById('entry-title').value,
|
title: document.getElementById('entry-title').value,
|
||||||
markdown: editor.getValue()
|
content: editor.getValue()
|
||||||
},
|
},
|
||||||
urlSegments = window.location.pathname.split('/');
|
urlSegments = window.location.pathname.split('/');
|
||||||
|
|
||||||
@ -64,7 +64,7 @@
|
|||||||
entry.id = urlSegments[3];
|
entry.id = urlSegments[3];
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/api/v0.1/posts/edit',
|
url: '/api/v0.1/posts/edit',
|
||||||
method: 'POST',
|
method: 'PUT',
|
||||||
data: entry,
|
data: entry,
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
console.log('response', data);
|
console.log('response', data);
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
|
/*global require, module */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var Ghost = require('../../ghost'),
|
var Ghost = require('../../ghost'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
Showdown = require('showdown'),
|
when = require('when/node/function'),
|
||||||
converter = new Showdown.converter(),
|
api = require('../../shared/api'),
|
||||||
|
|
||||||
ghost = new Ghost(),
|
ghost = new Ghost(),
|
||||||
adminNavbar,
|
adminNavbar,
|
||||||
@ -60,7 +61,8 @@
|
|||||||
},
|
},
|
||||||
'editor': function (req, res) {
|
'editor': function (req, res) {
|
||||||
if (req.params.id !== undefined) {
|
if (req.params.id !== undefined) {
|
||||||
ghost.dataProvider().posts.findOne({'id': parseInt(req.params.id, 10)}, function (error, post) {
|
api.posts.read(parseInt(req.params.id, 10))
|
||||||
|
.then(function (post) {
|
||||||
res.render('editor', {
|
res.render('editor', {
|
||||||
bodyClass: 'editor',
|
bodyClass: 'editor',
|
||||||
adminNav: setSelected(adminNavbar, 'blog'),
|
adminNav: setSelected(adminNavbar, 'blog'),
|
||||||
@ -76,7 +78,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
'blog': function (req, res) {
|
'blog': function (req, res) {
|
||||||
ghost.dataProvider().posts.findAll(function (error, posts) {
|
api.posts.browse()
|
||||||
|
.then(function (posts) {
|
||||||
res.render('blog', {
|
res.render('blog', {
|
||||||
bodyClass: 'manage',
|
bodyClass: 'manage',
|
||||||
adminNav: setSelected(adminNavbar, 'blog'),
|
adminNav: setSelected(adminNavbar, 'blog'),
|
||||||
@ -119,47 +122,6 @@
|
|||||||
res.redirect('/ghost/debug');
|
res.redirect('/ghost/debug');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
|
||||||
'posts': {
|
|
||||||
'index': function (req, res) {
|
|
||||||
|
|
||||||
},
|
|
||||||
'create': function (req, res) {
|
|
||||||
var entry = {
|
|
||||||
title: req.body.title,
|
|
||||||
content: req.body.markdown,
|
|
||||||
contentHtml: '',
|
|
||||||
language: ghost.config().defaultLang,
|
|
||||||
status: ghost.statuses().draft,
|
|
||||||
featured: false
|
|
||||||
};
|
|
||||||
|
|
||||||
entry.contentHtml = converter.makeHtml(entry.content);
|
|
||||||
|
|
||||||
ghost.dataProvider().posts.add(entry, function (error, post) {
|
|
||||||
if (!error) {
|
|
||||||
console.log('added', post);
|
|
||||||
res.json({id: post.id});
|
|
||||||
} else {
|
|
||||||
res.json(400, {error: post.errors});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
'edit': function (req, res) {
|
|
||||||
var entry = {
|
|
||||||
id: parseInt(req.body.id, 10),
|
|
||||||
title: req.body.title,
|
|
||||||
content: req.body.markdown,
|
|
||||||
contentHtml: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
entry.contentHtml = converter.makeHtml(entry.content);
|
|
||||||
|
|
||||||
ghost.dataProvider().posts.edit(entry, function (error, post) {
|
|
||||||
console.log('edited', post);
|
|
||||||
res.json({id: parseInt(post.id, 10)});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
77
core/shared/api.js
Normal file
77
core/shared/api.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// # Ghost Data API
|
||||||
|
// Provides access to the data model
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is intended to replace the old dataProvider files and should access & manipulate the models directly
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*global module, require */
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Ghost = require('../ghost'),
|
||||||
|
when = require('when/node/function'),
|
||||||
|
_ = require('underscore'),
|
||||||
|
|
||||||
|
ghost = new Ghost(),
|
||||||
|
posts,
|
||||||
|
users,
|
||||||
|
requestHandler;
|
||||||
|
|
||||||
|
// # Posts
|
||||||
|
posts = {
|
||||||
|
// takes filter / pagination parameters
|
||||||
|
// returns a list of posts in a json response
|
||||||
|
browse: function (options) {
|
||||||
|
return when.call(ghost.dataProvider().posts.findAll);
|
||||||
|
},
|
||||||
|
// takes an identifier (id or slug?)
|
||||||
|
// returns a single post in a json response
|
||||||
|
read: function (id) {
|
||||||
|
return when.call(ghost.dataProvider().posts.findOne, {id: id});
|
||||||
|
},
|
||||||
|
// takes a json object with all the properties which should be updated
|
||||||
|
// returns the resulting post in a json response
|
||||||
|
edit: function (postData) {
|
||||||
|
console.log('edit data', postData);
|
||||||
|
return when.call(ghost.dataProvider().posts.edit, postData);
|
||||||
|
},
|
||||||
|
// takes a json object representing a post,
|
||||||
|
// returns the resulting post in a json response
|
||||||
|
add: function (postData) {
|
||||||
|
console.log('data', postData);
|
||||||
|
return when.call(ghost.dataProvider().posts.add, postData);
|
||||||
|
},
|
||||||
|
// takes an identifier (id or slug?)
|
||||||
|
// returns a json response with the id of the deleted post
|
||||||
|
destroy: function (id) {
|
||||||
|
return when.call(ghost.dataProvider().posts.destroy, id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// # Users
|
||||||
|
users = {};
|
||||||
|
// settings: {},
|
||||||
|
// categories: {},
|
||||||
|
// post_categories: {}
|
||||||
|
|
||||||
|
|
||||||
|
// requestHandler
|
||||||
|
// decorator for api functions which are called via an HTTP request
|
||||||
|
// takes the API method and wraps it so that it gets data from the request and returns a sensible JSON response
|
||||||
|
requestHandler = function (apiMethod) {
|
||||||
|
return function (req, res) {
|
||||||
|
var options = _.extend(req.body, req.params);
|
||||||
|
return apiMethod(options).then(function (result) {
|
||||||
|
res.json(result);
|
||||||
|
}, function (error) {
|
||||||
|
res.json(400, {error: error});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module.exports.posts = posts;
|
||||||
|
module.exports.users = users;
|
||||||
|
module.exports.requestHandler = requestHandler;
|
||||||
|
}());
|
@ -101,6 +101,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Naive find one where args match
|
* Naive find one where args match
|
||||||
|
* @param args
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
DataProvider.prototype.posts.findOne = function (args, callback) {
|
DataProvider.prototype.posts.findOne = function (args, callback) {
|
||||||
@ -109,7 +110,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Naive add
|
* Naive add
|
||||||
* @param post
|
* @param _post
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
DataProvider.prototype.posts.add = function (_post, callback) {
|
DataProvider.prototype.posts.add = function (_post, callback) {
|
||||||
@ -122,7 +123,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Naive edit
|
* Naive edit
|
||||||
* @param post
|
* @param _post
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
DataProvider.prototype.posts.edit = function (_post, callback) {
|
DataProvider.prototype.posts.edit = function (_post, callback) {
|
||||||
@ -133,6 +134,13 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
DataProvider.prototype.posts.destroy = function (_identifier, callback) {
|
||||||
|
schema.models.Post.findOne({where: {id: _identifier}}, function (error, post) {
|
||||||
|
schema.models.Post.destroy(post.id, callback);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
DataProvider.prototype.populateData = populateData;
|
DataProvider.prototype.populateData = populateData;
|
||||||
|
|
||||||
module.exports = DataProvider;
|
module.exports = DataProvider;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Vastly incomplete!
|
* Vastly incomplete!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*globals module, require */
|
/*global module, require */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -12,6 +12,8 @@
|
|||||||
schema = new Schema('sqlite3', {
|
schema = new Schema('sqlite3', {
|
||||||
database: __dirname + '/../data/datastore.db'
|
database: __dirname + '/../data/datastore.db'
|
||||||
}),
|
}),
|
||||||
|
Showdown = require('showdown'),
|
||||||
|
converter = new Showdown.converter(),
|
||||||
Post,
|
Post,
|
||||||
User,
|
User,
|
||||||
Setting;
|
Setting;
|
||||||
@ -39,16 +41,15 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
Post.prototype.preCreate = function (next) {
|
Post.prototype.preCreate = function (next) {
|
||||||
console.log('pre create 1', this);
|
//console.log('pre create 1', this);
|
||||||
|
|
||||||
if (this.createdAt === undefined) {
|
this.createdAt = this.createdAt || new Date();
|
||||||
this.createdAt = new Date();
|
this.slug = this.slug || this.generateSlug();
|
||||||
}
|
// this.language = this.language || ghost.config().defaultLang;
|
||||||
if (this.slug === undefined) {
|
// this.status = this.status || ghost.statuses().draft
|
||||||
this.slug = this.generateSlug();
|
this.featured = false;
|
||||||
}
|
|
||||||
|
|
||||||
console.log('pre create 2', this);
|
// console.log('pre create 2', this);
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,11 +60,12 @@
|
|||||||
//Post.validatesUniquenessOf('slug');
|
//Post.validatesUniquenessOf('slug');
|
||||||
//Post.validatesLengthOf('language', {min: 2, max: 5}, "The language code should be between 2 and 5 chars long, E.g. 'en' or 'en_GB' ");
|
//Post.validatesLengthOf('language', {min: 2, max: 5}, "The language code should be between 2 and 5 chars long, E.g. 'en' or 'en_GB' ");
|
||||||
|
|
||||||
|
// doesn't get run on update
|
||||||
Post.beforeSave = function (next, data) {
|
Post.beforeSave = Post.beforeUpdate = function (next, data) {
|
||||||
console.log('before s1', data);
|
console.log('before s1', data);
|
||||||
// set updated
|
// set updated
|
||||||
data.updatedAt = new Date();
|
data.updatedAt = new Date();
|
||||||
|
data.contentHtml = converter.makeHtml(data.content);
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
"moment": "*",
|
"moment": "*",
|
||||||
"underscore": "*",
|
"underscore": "*",
|
||||||
"showdown": "*",
|
"showdown": "*",
|
||||||
|
"when": "*",
|
||||||
"sqlite3": "2.1.7",
|
"sqlite3": "2.1.7",
|
||||||
"jugglingdb": "0.2.x",
|
"jugglingdb": "0.2.0-29",
|
||||||
"jugglingdb-sqlite3": "git+https://github.com/jugglingdb/sqlite3-adapter.git#master"
|
"jugglingdb-sqlite3": "git+https://github.com/jugglingdb/sqlite3-adapter.git#master"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
Loading…
Reference in New Issue
Block a user