Skip to content

Commit

Permalink
Merge pull request TryGhost#3841 from halfdan/3619-configuration-api
Browse files Browse the repository at this point in the history
Implements new Configuration API
  • Loading branch information
sebgie committed Sep 1, 2014
2 parents 6ea7ab3 + 688b391 commit 57b5f4d
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 0 deletions.
78 changes: 78 additions & 0 deletions core/server/api/configuration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// # Configuration API
// RESTful API for browsing the configuration
var _ = require('lodash'),
canThis = require('../permissions').canThis,
config = require('../config'),
errors = require('../errors'),
parsePackageJson = require('../require-tree').parsePackageJson,
Promise = require('bluebird'),

configuration;

function getValidKeys() {
var validKeys = {
'fileStorage': config.fileStorage === false ? false : true,
'apps': config.apps || false,
'version': false,
'environment': process.env.NODE_ENV,
'database': config.database.client,
'mail': _.isObject(config.mail) ? config.mail.transport : '',
'blogUrl': config.url
};

return parsePackageJson('package.json').then(function (json) {
validKeys.version = json.version;
return validKeys;
});
}

/**
* ## Configuration API Methods
*
* **See:** [API Methods](index.js.html#api%20methods)
*/
configuration = {

/**
* ### Browse
* Fetch all configuration keys
* @returns {Promise(Configurations)}
*/
browse: function browse(options) {
return canThis(options.context).browse.configuration().then(function () {
return getValidKeys().then(function (result) {
return { 'configuration': _.map(result, function (value, key) {
return {
key: key,
value: value
};
})};
});
}, function () {
return Promise.reject(new errors.NoPermissionError('You do not have permission to browse the configuration.'));
});
},

/**
* ### Read
*
*/
read: function read(options) {
return canThis(options.context).read.configuration().then(function () {
return getValidKeys().then(function (result) {
if (_.has(result, options.key)) {
return { 'configuration': [{
key: options.key,
value: result[options.key]
}]};
} else {
return Promise.reject(new errors.NotFoundError('Invalid key'));
}
});
}, function () {
return Promise.reject(new errors.NoPermissionError('You do not have permission to read the configuration.'));
});
}
};

module.exports = configuration;
2 changes: 2 additions & 0 deletions core/server/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var _ = require('lodash'),
Promise = require('bluebird'),
config = require('../config'),
// Include Endpoints
configuration = require('./configuration'),
db = require('./db'),
mail = require('./mail'),
notifications = require('./notifications'),
Expand Down Expand Up @@ -278,6 +279,7 @@ module.exports = {
init: init,
http: http,
// API Endpoints
configuration: configuration,
db: db,
mail: mail,
notifications: notifications,
Expand Down
13 changes: 13 additions & 0 deletions core/server/data/fixtures/permissions/permissions.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
{
"permissions": {
"configuration": [
{
"name": "Browse configuration",
"action_type": "browse"
},
{
"name": "Read configuration",
"action_type": "read"
}
],
"db": [
{
"name": "Export database",
Expand Down Expand Up @@ -143,6 +153,7 @@
},
"permissions_roles": {
"Administrator": {
"configuration": "all",
"db": "all",
"mail": "all",
"notification": "all",
Expand All @@ -155,6 +166,7 @@
"role": "all"
},
"Editor": {
"configuration": "all",
"post": "all",
"setting": ["browse", "read"],
"slug": "all",
Expand All @@ -164,6 +176,7 @@
"role": "all"
},
"Author": {
"configuration": "all",
"post": ["browse", "read", "add"],
"setting": ["browse", "read"],
"slug": "all",
Expand Down
4 changes: 4 additions & 0 deletions core/server/routes/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ apiRoutes = function (middleware) {
// alias delete with del
router.del = router.delete;

// ## Configuration
router.get('/configuration', api.http(api.configuration.browse));
router.get('/configuration/:key', api.http(api.configuration.read));

// ## Posts
router.get('/posts', api.http(api.posts.browse));
router.post('/posts', api.http(api.posts.add));
Expand Down
75 changes: 75 additions & 0 deletions core/test/integration/api/api_configuration_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*globals describe, before, beforeEach, afterEach, it */
/*jshint expr:true*/
var testUtils = require('../../utils'),
should = require('should'),
sinon = require('sinon'),


rewire = require('rewire'),
_ = require('lodash'),
config = rewire('../../../server/config'),

// Stuff we are testing
ConfigurationAPI = rewire('../../../server/api/configuration');

describe('Configuration API', function () {
var newConfig = {
'fileStorage': true,
'apps': true,
'version': '0.5.0',
'environment': process.env.NODE_ENV,
'database': {
'client': 'mysql'
},
'mail': {
'transport': 'SMTP'
},
'blogUrl': 'http://local.tryghost.org'
};

// Keep the DB clean
before(testUtils.teardown);
afterEach(testUtils.teardown);

beforeEach(testUtils.setup('users','users:roles', 'perms:user', 'perms:role', 'perms:configuration', 'perms:init'));

should.exist(ConfigurationAPI);

it('can browse config', function (done) {
var existingConfig = ConfigurationAPI.__get__('config'),
updatedConfig = _.extend(config, newConfig);
config.set(updatedConfig);
ConfigurationAPI.__set__('config', updatedConfig);

ConfigurationAPI.browse(testUtils.context.owner).then(function (response) {
should.exist(response);
should.exist(response.configuration);
testUtils.API.checkResponse(response.configuration[0], 'configuration');
/*jshint unused:false */
done();
}).catch(function (error) {
console.log(JSON.stringify(error));
done();
}).catch(done);
});

it('can read config', function (done) {
var existingConfig = ConfigurationAPI.__get__('config'),
updatedConfig = _.extend(config, newConfig);
config.set(updatedConfig);
ConfigurationAPI.__set__('config', updatedConfig);

ConfigurationAPI.read(_.extend(testUtils.context.owner, { key: 'database' })).then(function (response) {
should.exist(response);
should.exist(response.configuration);
testUtils.API.checkResponse(response.configuration[0], 'configuration');
response.configuration[0].key.should.equal('database');
response.configuration[0].value.should.equal('mysql');
/*jshint unused:false */
done();
}).catch(function (error) {
console.log(JSON.stringify(error));
done();
}).catch(done);
});
});
1 change: 1 addition & 0 deletions core/test/utils/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var url = require('url'),
port = config.server.port,
schema = 'http://',
expectedProperties = {
configuration: ['key', 'value'],
posts: ['posts', 'meta'],
users: ['users', 'meta'],
roles: ['roles'],
Expand Down

0 comments on commit 57b5f4d

Please sign in to comment.