mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-28 21:33:24 +03:00
Implements new Themes JSON API
closes #2592 - Add themes browse/read endpoint - Add new permissions for themes (only admin by default) - Add integration tests
This commit is contained in:
parent
169a984372
commit
628654961a
@ -10,6 +10,7 @@ var _ = require('lodash'),
|
||||
posts = require('./posts'),
|
||||
users = require('./users'),
|
||||
tags = require('./tags'),
|
||||
themes = require('./themes'),
|
||||
mail = require('./mail'),
|
||||
requestHandler,
|
||||
init;
|
||||
@ -167,6 +168,7 @@ module.exports = {
|
||||
posts: posts,
|
||||
users: users,
|
||||
tags: tags,
|
||||
themes: themes,
|
||||
notifications: notifications,
|
||||
settings: settings,
|
||||
db: db,
|
||||
|
88
core/server/api/themes.js
Normal file
88
core/server/api/themes.js
Normal file
@ -0,0 +1,88 @@
|
||||
var when = require('when'),
|
||||
_ = require('lodash'),
|
||||
canThis = require('../permissions').canThis,
|
||||
config = require('../config'),
|
||||
errors = require('../errors'),
|
||||
settings = require('./settings'),
|
||||
when = require('when'),
|
||||
themes;
|
||||
|
||||
// ## Themes
|
||||
themes = {
|
||||
|
||||
browse: function browse() {
|
||||
// **returns:** a promise for a collection of themes in a json object
|
||||
return canThis(this).browse.theme().then(function () {
|
||||
return when.all([
|
||||
settings.read.call({ internal: true }, 'activeTheme'),
|
||||
config().paths.availableThemes
|
||||
]).then(function (result) {
|
||||
var activeTheme = result[0].settings[0].value,
|
||||
availableThemes = result[1],
|
||||
themes = [],
|
||||
themeKeys = Object.keys(availableThemes);
|
||||
|
||||
_.each(themeKeys, function (key) {
|
||||
if (key.indexOf('.') !== 0
|
||||
&& key !== '_messages'
|
||||
&& key !== 'README.md'
|
||||
) {
|
||||
|
||||
var item = {
|
||||
uuid: key
|
||||
};
|
||||
|
||||
if (availableThemes[key].hasOwnProperty('package.json')) {
|
||||
item = _.merge(item, availableThemes[key]['package.json']);
|
||||
}
|
||||
|
||||
item.active = item.uuid === activeTheme;
|
||||
|
||||
themes.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
return { themes: themes };
|
||||
});
|
||||
}, function () {
|
||||
return when.reject(new errors.NoPermissionError('You do not have permission to browse themes.'));
|
||||
});
|
||||
},
|
||||
|
||||
edit: function edit(themeData) {
|
||||
var self = this,
|
||||
themeName;
|
||||
|
||||
// Check whether the request is properly formatted.
|
||||
if (!_.isArray(themeData.themes)) {
|
||||
return when.reject({type: 'BadRequest', message: 'Invalid request.'});
|
||||
}
|
||||
|
||||
themeName = themeData.themes[0].uuid;
|
||||
|
||||
return canThis(this).edit.theme().then(function () {
|
||||
return themes.browse.call(self).then(function (availableThemes) {
|
||||
var theme;
|
||||
|
||||
// Check if the theme exists
|
||||
theme = _.find(availableThemes.themes, function (currentTheme) {
|
||||
return currentTheme.uuid === themeName;
|
||||
});
|
||||
|
||||
if (!theme) {
|
||||
return when.reject(new errors.BadRequestError('Theme does not exist.'));
|
||||
}
|
||||
|
||||
// Activate the theme
|
||||
return settings.edit.call({ internal: true }, 'activeTheme', themeName).then(function () {
|
||||
theme.active = true;
|
||||
return { themes: [theme]};
|
||||
});
|
||||
});
|
||||
}, function () {
|
||||
return when.reject(new errors.NoPermissionError('You do not have permission to edit themes.'));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = themes;
|
@ -124,6 +124,16 @@ var fixtures = {
|
||||
"name": "Edit settings",
|
||||
"action_type": "edit",
|
||||
"object_type": "setting"
|
||||
},
|
||||
{
|
||||
"name": "Browse themes",
|
||||
"action_type": "browse",
|
||||
"object_type": "theme"
|
||||
},
|
||||
{
|
||||
"name": "Edit themes",
|
||||
"action_type": "edit",
|
||||
"object_type": "theme"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -20,6 +20,9 @@ module.exports = function (server) {
|
||||
server.put('/ghost/api/v0.1/users/:id/', api.requestHandler(api.users.edit));
|
||||
// #### Tags
|
||||
server.get('/ghost/api/v0.1/tags/', api.requestHandler(api.tags.browse));
|
||||
// #### Themes
|
||||
server.get('/ghost/api/v0.1/themes/', api.requestHandler(api.themes.browse));
|
||||
server.put('/ghost/api/v0.1/themes/:name', api.requestHandler(api.themes.edit));
|
||||
// #### Notifications
|
||||
server.del('/ghost/api/v0.1/notifications/:id', api.requestHandler(api.notifications.destroy));
|
||||
server.post('/ghost/api/v0.1/notifications/', api.requestHandler(api.notifications.add));
|
||||
|
98
core/test/integration/api/api_themes_spec.js
Normal file
98
core/test/integration/api/api_themes_spec.js
Normal file
@ -0,0 +1,98 @@
|
||||
/*globals describe, before, beforeEach, afterEach, it */
|
||||
var _ = require('lodash'),
|
||||
testUtils = require('../../utils'),
|
||||
rewire = require('rewire'),
|
||||
should = require('should'),
|
||||
sinon = require('sinon'),
|
||||
when = require('when'),
|
||||
|
||||
// Stuff we are testing
|
||||
permissions = require('../../../server/permissions'),
|
||||
settings = require('../../../server/api/settings'),
|
||||
ThemeAPI = rewire('../../../server/api/themes');
|
||||
|
||||
describe('Themes API', function () {
|
||||
var configStub,
|
||||
sandbox,
|
||||
settingsReadStub;
|
||||
|
||||
before(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
beforeEach(function (done) {
|
||||
testUtils.initData().then(function () {
|
||||
return testUtils.insertDefaultFixtures();
|
||||
}).then(function () {
|
||||
return permissions.init();
|
||||
}).then(function () {
|
||||
sandbox = sinon.sandbox.create();
|
||||
|
||||
// Override settings.read for activeTheme
|
||||
settingsReadStub = sandbox.stub(settings, 'read', function () {
|
||||
return when({ settings: [{value: 'casper'}] });
|
||||
});
|
||||
|
||||
configStub = sandbox.stub().returns({
|
||||
'paths': {
|
||||
'subdir': '',
|
||||
'availableThemes': {
|
||||
'casper': {
|
||||
'package.json': { name: 'Casper', version: '0.9.3' }
|
||||
},
|
||||
'rasper': {
|
||||
'package.json': { name: 'Rasper', version: '0.9.6' }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
sandbox.restore();
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('can browse', function (done) {
|
||||
var config;
|
||||
|
||||
config = ThemeAPI.__get__('config');
|
||||
_.extend(configStub, config);
|
||||
ThemeAPI.__set__('config', configStub);
|
||||
|
||||
ThemeAPI.browse.call({user: 1}).then(function (result) {
|
||||
should.exist(result);
|
||||
result.themes.length.should.be.above(0);
|
||||
testUtils.API.checkResponse(result.themes[0], 'theme');
|
||||
done();
|
||||
}, function (error) {
|
||||
done(new Error(JSON.stringify(error)));
|
||||
})
|
||||
});
|
||||
|
||||
it('can edit', function (done) {
|
||||
var config;
|
||||
|
||||
config = ThemeAPI.__get__('config');
|
||||
_.extend(configStub, config);
|
||||
ThemeAPI.__set__('config', configStub);
|
||||
|
||||
ThemeAPI.edit.call({user: 1}, {themes: [{uuid: 'rasper', active: true }]}).then(function (result) {
|
||||
should.exist(result);
|
||||
should.exist(result.themes);
|
||||
result.themes.length.should.be.above(0);
|
||||
testUtils.API.checkResponse(result.themes[0], 'theme');
|
||||
result.themes[0].uuid.should.equal('rasper');
|
||||
done();
|
||||
}, function (error) {
|
||||
done(new Error(JSON.stringify(error)));
|
||||
})
|
||||
})
|
||||
});
|
@ -104,7 +104,7 @@ describe('Permissions', function () {
|
||||
.then(function (actionsMap) {
|
||||
should.exist(actionsMap);
|
||||
|
||||
actionsMap.edit.sort().should.eql(['post', 'tag', 'user', 'page', 'setting'].sort());
|
||||
actionsMap.edit.sort().should.eql(['post', 'tag', 'user', 'page', 'theme', 'setting'].sort());
|
||||
|
||||
actionsMap.should.equal(permissions.actionsMap);
|
||||
|
||||
|
@ -14,6 +14,7 @@ var url = require('url'),
|
||||
setting: ['id', 'uuid', 'key', 'value', 'type', 'created_at', 'created_by', 'updated_at', 'updated_by'],
|
||||
tag: ['id', 'uuid', 'name', 'slug', 'description', 'parent',
|
||||
'meta_title', 'meta_description', 'created_at', 'created_by', 'updated_at', 'updated_by'],
|
||||
theme: ['uuid', 'name', 'version', 'active'],
|
||||
user: ['id', 'uuid', 'name', 'slug', 'email', 'image', 'cover', 'bio', 'website',
|
||||
'location', 'accessibility', 'status', 'language', 'meta_title', 'meta_description', 'last_login',
|
||||
'created_at', 'created_by', 'updated_at', 'updated_by'],
|
||||
|
Loading…
Reference in New Issue
Block a user