mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-01 13:54:35 +03:00
🐛🎨 Theme API minor improvements (#8197)
no issue 🎨 🐛 Ensure cache is updated correctly for themes - Insure the cache invalidation headers are always set correctly for the themes API 📖 Theme API comments / function naming - this is an update for clarity, so we can see what further improvements can be made 🐛 🎨 Add permissions to themes.browse
This commit is contained in:
parent
4e3e1bdfc9
commit
fad0ac7213
@ -36,8 +36,18 @@ var _ = require('lodash'),
|
|||||||
contentDispositionHeaderExport,
|
contentDispositionHeaderExport,
|
||||||
contentDispositionHeaderSubscribers;
|
contentDispositionHeaderSubscribers;
|
||||||
|
|
||||||
function isActiveThemeOverride(method, endpoint, result) {
|
function isActiveThemeUpdate(method, endpoint, result) {
|
||||||
return method === 'POST' && endpoint === 'themes' && result.themes && result.themes[0] && result.themes[0].active === true;
|
if (endpoint === 'themes') {
|
||||||
|
if (method === 'PUT') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method === 'POST' && result.themes && result.themes[0] && result.themes[0].active === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,7 +74,7 @@ cacheInvalidationHeader = function cacheInvalidationHeader(req, result) {
|
|||||||
hasStatusChanged,
|
hasStatusChanged,
|
||||||
wasPublishedUpdated;
|
wasPublishedUpdated;
|
||||||
|
|
||||||
if (isActiveThemeOverride(method, endpoint, result)) {
|
if (isActiveThemeUpdate(method, endpoint, result)) {
|
||||||
// Special case for if we're overwriting an active theme
|
// Special case for if we're overwriting an active theme
|
||||||
// @TODO: remove this crazy DIRTY HORRIBLE HACK
|
// @TODO: remove this crazy DIRTY HORRIBLE HACK
|
||||||
req.app.set('activeTheme', null);
|
req.app.set('activeTheme', null);
|
||||||
|
@ -23,8 +23,15 @@ var debug = require('debug')('ghost:api:themes'),
|
|||||||
* **See:** [API Methods](index.js.html#api%20methods)
|
* **See:** [API Methods](index.js.html#api%20methods)
|
||||||
*/
|
*/
|
||||||
themes = {
|
themes = {
|
||||||
browse: function browse() {
|
browse: function browse(options) {
|
||||||
return Promise.resolve(themeUtils.toJSON());
|
return apiUtils
|
||||||
|
// Permissions
|
||||||
|
.handlePermissions('themes', 'browse')(options)
|
||||||
|
// Main action
|
||||||
|
.then(function makeApiResult() {
|
||||||
|
// Return JSON result
|
||||||
|
return themeUtils.toJSON();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
activate: function activate(options) {
|
activate: function activate(options) {
|
||||||
@ -37,8 +44,10 @@ themes = {
|
|||||||
checkedTheme;
|
checkedTheme;
|
||||||
|
|
||||||
return apiUtils
|
return apiUtils
|
||||||
|
// Permissions
|
||||||
.handlePermissions('themes', 'activate')(options)
|
.handlePermissions('themes', 'activate')(options)
|
||||||
.then(function activateTheme() {
|
// Validation
|
||||||
|
.then(function validateTheme() {
|
||||||
loadedTheme = themeList.get(themeName);
|
loadedTheme = themeList.get(themeName);
|
||||||
|
|
||||||
if (!loadedTheme) {
|
if (!loadedTheme) {
|
||||||
@ -50,16 +59,19 @@ themes = {
|
|||||||
|
|
||||||
return themeUtils.validate.check(loadedTheme);
|
return themeUtils.validate.check(loadedTheme);
|
||||||
})
|
})
|
||||||
.then(function haveValidTheme(_checkedTheme) {
|
// Update setting
|
||||||
|
.then(function changeActiveThemeSetting(_checkedTheme) {
|
||||||
checkedTheme = _checkedTheme;
|
checkedTheme = _checkedTheme;
|
||||||
// We use the model, not the API here, as we don't want to trigger permissions
|
// We use the model, not the API here, as we don't want to trigger permissions
|
||||||
return settingsModel.edit(newSettings, options);
|
return settingsModel.edit(newSettings, options);
|
||||||
})
|
})
|
||||||
|
// Call activate
|
||||||
.then(function hasEditedSetting() {
|
.then(function hasEditedSetting() {
|
||||||
// Activate! (sort of)
|
// Activate! (sort of)
|
||||||
debug('Activating theme (method B on API "activate")', themeName);
|
debug('Activating theme (method B on API "activate")', themeName);
|
||||||
themeUtils.activate(loadedTheme, checkedTheme);
|
themeUtils.activate(loadedTheme, checkedTheme);
|
||||||
|
|
||||||
|
// Return JSON result
|
||||||
return themeUtils.toJSON(themeName, checkedTheme);
|
return themeUtils.toJSON(themeName, checkedTheme);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -83,22 +95,27 @@ themes = {
|
|||||||
throw new errors.ValidationError({message: i18n.t('errors.api.themes.overrideCasper')});
|
throw new errors.ValidationError({message: i18n.t('errors.api.themes.overrideCasper')});
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiUtils.handlePermissions('themes', 'add')(options)
|
return apiUtils
|
||||||
|
// Permissions
|
||||||
|
.handlePermissions('themes', 'add')(options)
|
||||||
|
// Validation
|
||||||
.then(function validateTheme() {
|
.then(function validateTheme() {
|
||||||
return themeUtils.validate.check(zip, true);
|
return themeUtils.validate.check(zip, true);
|
||||||
})
|
})
|
||||||
|
// More validation (existence check)
|
||||||
.then(function checkExists(_checkedTheme) {
|
.then(function checkExists(_checkedTheme) {
|
||||||
checkedTheme = _checkedTheme;
|
checkedTheme = _checkedTheme;
|
||||||
|
|
||||||
return storageAdapter.exists(utils.url.urlJoin(config.getContentPath('themes'), zip.shortName));
|
return storageAdapter.exists(utils.url.urlJoin(config.getContentPath('themes'), zip.shortName));
|
||||||
})
|
})
|
||||||
.then(function (themeExists) {
|
// If the theme existed we need to delete it
|
||||||
|
.then(function removeOldTheme(themeExists) {
|
||||||
// delete existing theme
|
// delete existing theme
|
||||||
if (themeExists) {
|
if (themeExists) {
|
||||||
return storageAdapter.delete(zip.shortName, config.getContentPath('themes'));
|
return storageAdapter.delete(zip.shortName, config.getContentPath('themes'));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function storeNewTheme() {
|
||||||
events.emit('theme.uploaded', zip.shortName);
|
events.emit('theme.uploaded', zip.shortName);
|
||||||
// store extracted theme
|
// store extracted theme
|
||||||
return storageAdapter.save({
|
return storageAdapter.save({
|
||||||
@ -106,12 +123,12 @@ themes = {
|
|||||||
path: checkedTheme.path
|
path: checkedTheme.path
|
||||||
}, config.getContentPath('themes'));
|
}, config.getContentPath('themes'));
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function loadNewTheme() {
|
||||||
// Loads the theme from the filesystem
|
// Loads the theme from the filesystem
|
||||||
// Sets the theme on the themeList
|
// Sets the theme on the themeList
|
||||||
return themeUtils.loadOne(zip.shortName);
|
return themeUtils.loadOne(zip.shortName);
|
||||||
})
|
})
|
||||||
.then(function (loadedTheme) {
|
.then(function activateAndReturn(loadedTheme) {
|
||||||
// If this is the active theme, we are overriding
|
// If this is the active theme, we are overriding
|
||||||
// This is a special case of activation
|
// This is a special case of activation
|
||||||
if (zip.shortName === settingsCache.get('activeTheme')) {
|
if (zip.shortName === settingsCache.get('activeTheme')) {
|
||||||
@ -153,8 +170,10 @@ themes = {
|
|||||||
return Promise.reject(new errors.BadRequestError({message: i18n.t('errors.api.themes.invalidRequest')}));
|
return Promise.reject(new errors.BadRequestError({message: i18n.t('errors.api.themes.invalidRequest')}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiUtils.handlePermissions('themes', 'read')(options)
|
return apiUtils
|
||||||
.then(function () {
|
// Permissions
|
||||||
|
.handlePermissions('themes', 'read')(options)
|
||||||
|
.then(function sendTheme() {
|
||||||
events.emit('theme.downloaded', themeName);
|
events.emit('theme.downloaded', themeName);
|
||||||
return storageAdapter.serve({isTheme: true, name: themeName});
|
return storageAdapter.serve({isTheme: true, name: themeName});
|
||||||
});
|
});
|
||||||
@ -165,31 +184,36 @@ themes = {
|
|||||||
* remove theme folder
|
* remove theme folder
|
||||||
*/
|
*/
|
||||||
destroy: function destroy(options) {
|
destroy: function destroy(options) {
|
||||||
var name = options.name,
|
var themeName = options.name,
|
||||||
theme,
|
theme,
|
||||||
storageAdapter = storage.getStorage('themes');
|
storageAdapter = storage.getStorage('themes');
|
||||||
|
|
||||||
return apiUtils.handlePermissions('themes', 'destroy')(options)
|
return apiUtils
|
||||||
.then(function () {
|
// Permissions
|
||||||
if (name === 'casper') {
|
.handlePermissions('themes', 'destroy')(options)
|
||||||
|
// Validation
|
||||||
|
.then(function validateTheme() {
|
||||||
|
if (themeName === 'casper') {
|
||||||
throw new errors.ValidationError({message: i18n.t('errors.api.themes.destroyCasper')});
|
throw new errors.ValidationError({message: i18n.t('errors.api.themes.destroyCasper')});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name === settingsCache.get('activeTheme')) {
|
if (themeName === settingsCache.get('activeTheme')) {
|
||||||
throw new errors.ValidationError({message: i18n.t('errors.api.themes.destroyActive')});
|
throw new errors.ValidationError({message: i18n.t('errors.api.themes.destroyActive')});
|
||||||
}
|
}
|
||||||
|
|
||||||
theme = themeList.get(name);
|
theme = themeList.get(themeName);
|
||||||
|
|
||||||
if (!theme) {
|
if (!theme) {
|
||||||
throw new errors.NotFoundError({message: i18n.t('errors.api.themes.themeDoesNotExist')});
|
throw new errors.NotFoundError({message: i18n.t('errors.api.themes.themeDoesNotExist')});
|
||||||
}
|
}
|
||||||
|
|
||||||
return storageAdapter.delete(name, config.getContentPath('themes'));
|
// Actually do the deletion here
|
||||||
|
return storageAdapter.delete(themeName, config.getContentPath('themes'));
|
||||||
})
|
})
|
||||||
.then(function () {
|
// And some extra stuff to maintain state here
|
||||||
themeList.del(name);
|
.then(function deleteTheme() {
|
||||||
events.emit('theme.deleted', name);
|
themeList.del(themeName);
|
||||||
|
events.emit('theme.deleted', themeName);
|
||||||
// Delete returns an empty 204 response
|
// Delete returns an empty 204 response
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user