mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
commit
94fca08500
5 changed files with 112 additions and 54 deletions
|
@ -19,9 +19,12 @@ var _ = require('lodash'),
|
||||||
slugs = require('./slugs'),
|
slugs = require('./slugs'),
|
||||||
authentication = require('./authentication'),
|
authentication = require('./authentication'),
|
||||||
uploads = require('./upload'),
|
uploads = require('./upload'),
|
||||||
|
dataExport = require('../data/export'),
|
||||||
|
errors = require('../errors'),
|
||||||
|
|
||||||
http,
|
http,
|
||||||
formatHttpErrors,
|
formatHttpErrors,
|
||||||
|
addHeaders,
|
||||||
cacheInvalidationHeader,
|
cacheInvalidationHeader,
|
||||||
locationHeader,
|
locationHeader,
|
||||||
contentDispositionHeader,
|
contentDispositionHeader,
|
||||||
|
@ -135,9 +138,9 @@ locationHeader = function (req, result) {
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
contentDispositionHeader = function () {
|
contentDispositionHeader = function () {
|
||||||
// replace ':' with '_' for OS that don't support it
|
return dataExport.fileName().then(function (filename) {
|
||||||
var now = (new Date()).toJSON().replace(/:/g, '_');
|
return 'Attachment; filename="' + filename + '"';
|
||||||
return 'Attachment; filename="ghost-' + now + '.json"';
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -172,6 +175,51 @@ formatHttpErrors = function (error) {
|
||||||
return {errors: errors, statusCode: statusCode};
|
return {errors: errors, statusCode: statusCode};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
addHeaders = function (apiMethod, req, res, result) {
|
||||||
|
var ops = [],
|
||||||
|
cacheInvalidation,
|
||||||
|
location,
|
||||||
|
contentDisposition;
|
||||||
|
|
||||||
|
cacheInvalidation = cacheInvalidationHeader(req, result)
|
||||||
|
.then(function addCacheHeader(header) {
|
||||||
|
if (header) {
|
||||||
|
res.set({'X-Cache-Invalidate': header});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ops.push(cacheInvalidation);
|
||||||
|
|
||||||
|
if (req.method === 'POST') {
|
||||||
|
location = locationHeader(req, result)
|
||||||
|
.then(function addLocationHeader(header) {
|
||||||
|
if (header) {
|
||||||
|
res.set({'Location': header});
|
||||||
|
// The location header indicates that a new object was created.
|
||||||
|
// In this case the status code should be 201 Created
|
||||||
|
res.status(201);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ops.push(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apiMethod === db.exportContent) {
|
||||||
|
contentDisposition = contentDispositionHeader()
|
||||||
|
.then(function addContentDispositionHeader(header) {
|
||||||
|
// Add Content-Disposition Header
|
||||||
|
if (apiMethod === db.exportContent) {
|
||||||
|
res.set({
|
||||||
|
'Content-Disposition': header
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ops.push(contentDisposition);
|
||||||
|
}
|
||||||
|
|
||||||
|
return when.all(ops);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ### HTTP
|
* ### HTTP
|
||||||
*
|
*
|
||||||
|
@ -186,6 +234,7 @@ http = function (apiMethod) {
|
||||||
return function (req, res) {
|
return function (req, res) {
|
||||||
// We define 2 properties for using as arguments in API calls:
|
// We define 2 properties for using as arguments in API calls:
|
||||||
var object = req.body,
|
var object = req.body,
|
||||||
|
response,
|
||||||
options = _.extend({}, req.files, req.query, req.params, {
|
options = _.extend({}, req.files, req.query, req.params, {
|
||||||
context: {
|
context: {
|
||||||
user: (req.user && req.user.id) ? req.user.id : null
|
user: (req.user && req.user.id) ? req.user.id : null
|
||||||
|
@ -202,35 +251,16 @@ http = function (apiMethod) {
|
||||||
return apiMethod(object, options)
|
return apiMethod(object, options)
|
||||||
// Handle adding headers
|
// Handle adding headers
|
||||||
.then(function onSuccess(result) {
|
.then(function onSuccess(result) {
|
||||||
|
response = result;
|
||||||
// Add X-Cache-Invalidate header
|
// Add X-Cache-Invalidate header
|
||||||
return cacheInvalidationHeader(req, result)
|
return addHeaders(apiMethod, req, res, result);
|
||||||
.then(function addCacheHeader(header) {
|
}).then(function () {
|
||||||
if (header) {
|
// #### Success
|
||||||
res.set({'X-Cache-Invalidate': header});
|
// Send a properly formatting HTTP response containing the data with correct headers
|
||||||
}
|
console.log(response);
|
||||||
|
res.json(response || {});
|
||||||
// Add Location header
|
|
||||||
return locationHeader(req, result);
|
|
||||||
}).then(function addLocationHeader(header) {
|
|
||||||
if (header) {
|
|
||||||
res.set({'Location': header});
|
|
||||||
// The location header indicates that a new object was created.
|
|
||||||
// In this case the status code should be 201 Created
|
|
||||||
res.status(201);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Content-Disposition Header
|
|
||||||
if (apiMethod === db.exportContent) {
|
|
||||||
res.set({
|
|
||||||
'Content-Disposition': contentDispositionHeader()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// #### Success
|
|
||||||
// Send a properly formatting HTTP response containing the data with correct headers
|
|
||||||
res.json(result || {});
|
|
||||||
});
|
|
||||||
}).catch(function onError(error) {
|
}).catch(function onError(error) {
|
||||||
|
errors.logError(error);
|
||||||
// #### Error
|
// #### Error
|
||||||
var httpErrors = formatHttpErrors(error);
|
var httpErrors = formatHttpErrors(error);
|
||||||
// Send a properly formatted HTTP response containing the errors
|
// Send a properly formatted HTTP response containing the errors
|
||||||
|
|
|
@ -1,11 +1,31 @@
|
||||||
var _ = require('lodash'),
|
var _ = require('lodash'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
versioning = require('../versioning'),
|
|
||||||
config = require('../../config'),
|
|
||||||
utils = require('../utils'),
|
|
||||||
|
|
||||||
excludedTables = [],
|
versioning = require('../versioning'),
|
||||||
exporter;
|
config = require('../../config'),
|
||||||
|
utils = require('../utils'),
|
||||||
|
serverUtils = require('../../utils'),
|
||||||
|
errors = require('../../errors'),
|
||||||
|
settings = require('../../api/settings'),
|
||||||
|
|
||||||
|
excludedTables = ['accesstokens', 'refreshtokens', 'clients'],
|
||||||
|
exporter,
|
||||||
|
exportFileName;
|
||||||
|
|
||||||
|
exportFileName = function () {
|
||||||
|
var datetime = (new Date()).toJSON().substring(0, 10),
|
||||||
|
title = '';
|
||||||
|
|
||||||
|
return settings.read({key: 'title', context: {internal: true}}).then(function (result) {
|
||||||
|
if (result) {
|
||||||
|
title = serverUtils.safeString(result.settings[0].value) + '.';
|
||||||
|
}
|
||||||
|
return title + 'ghost.' + datetime + '.json';
|
||||||
|
}).catch(function (err) {
|
||||||
|
errors.logError(err);
|
||||||
|
return 'ghost.' + datetime + '.json';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
exporter = function () {
|
exporter = function () {
|
||||||
return when.join(versioning.getDatabaseVersion(), utils.getTables()).then(function (results) {
|
return when.join(versioning.getDatabaseVersion(), utils.getTables()).then(function (results) {
|
||||||
|
@ -34,9 +54,10 @@ exporter = function () {
|
||||||
|
|
||||||
return when.resolve(exportData);
|
return when.resolve(exportData);
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
console.log('Error exporting data: ' + err);
|
errors.logAndThrowError(err, 'Error exporting data', '');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = exporter;
|
module.exports = exporter;
|
||||||
|
module.exports.fileName = exportFileName;
|
||||||
|
|
|
@ -44,7 +44,7 @@ backupDatabase = function backupDatabase() {
|
||||||
logInfo('Creating database backup');
|
logInfo('Creating database backup');
|
||||||
return dataExport().then(function (exportedData) {
|
return dataExport().then(function (exportedData) {
|
||||||
// Save the exported data to the file system for download
|
// Save the exported data to the file system for download
|
||||||
var fileName = path.resolve(config().paths.contentPath + '/data/exported-' + (new Date().getTime()) + '.json');
|
var fileName = path.resolve(config().paths.contentPath + '/data/' + dataExport.fileName());
|
||||||
|
|
||||||
return nodefn.call(fs.writeFile, fileName, JSON.stringify(exportedData)).then(function () {
|
return nodefn.call(fs.writeFile, fileName, JSON.stringify(exportedData)).then(function () {
|
||||||
logInfo('Database backup written to: ' + fileName);
|
logInfo('Database backup written to: ' + fileName);
|
||||||
|
|
|
@ -11,7 +11,7 @@ var bookshelf = require('bookshelf'),
|
||||||
_ = require('lodash'),
|
_ = require('lodash'),
|
||||||
uuid = require('node-uuid'),
|
uuid = require('node-uuid'),
|
||||||
config = require('../config'),
|
config = require('../config'),
|
||||||
unidecode = require('unidecode'),
|
utils = require('../utils'),
|
||||||
sanitize = require('validator').sanitize,
|
sanitize = require('validator').sanitize,
|
||||||
schema = require('../data/schema'),
|
schema = require('../data/schema'),
|
||||||
validation = require('../data/validation'),
|
validation = require('../data/validation'),
|
||||||
|
@ -343,19 +343,7 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
slug = base.trim();
|
slug = utils.safeString(base);
|
||||||
|
|
||||||
// Remove non ascii characters
|
|
||||||
slug = unidecode(slug);
|
|
||||||
|
|
||||||
// Remove URL reserved chars: `:/?#[]@!$&'()*+,;=` as well as `\%<>|^~£"`
|
|
||||||
slug = slug.replace(/[:\/\?#\[\]@!$&'()*+,;=\\%<>\|\^~£"]/g, '')
|
|
||||||
// Replace dots and spaces with a dash
|
|
||||||
.replace(/(\s|\.)/g, '-')
|
|
||||||
// Convert 2 or more dashes into a single dash
|
|
||||||
.replace(/-+/g, '-')
|
|
||||||
// Make the whole thing lowercase
|
|
||||||
.toLowerCase();
|
|
||||||
|
|
||||||
// Remove trailing hyphen
|
// Remove trailing hyphen
|
||||||
slug = slug.charAt(slug.length - 1) === '-' ? slug.substr(0, slug.length - 1) : slug;
|
slug = slug.charAt(slug.length - 1) === '-' ? slug.substr(0, slug.length - 1) : slug;
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
var utils,
|
var unidecode = require('unidecode'),
|
||||||
|
|
||||||
|
utils,
|
||||||
getRandomInt;
|
getRandomInt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,6 +37,23 @@ utils = {
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf.join('');
|
return buf.join('');
|
||||||
|
},
|
||||||
|
safeString: function (string) {
|
||||||
|
string = string.trim();
|
||||||
|
|
||||||
|
// Remove non ascii characters
|
||||||
|
string = unidecode(string);
|
||||||
|
|
||||||
|
// Remove URL reserved chars: `:/?#[]@!$&'()*+,;=` as well as `\%<>|^~£"`
|
||||||
|
string = string.replace(/[:\/\?#\[\]@!$&'()*+,;=\\%<>\|\^~£"]/g, '')
|
||||||
|
// Replace dots and spaces with a dash
|
||||||
|
.replace(/(\s|\.)/g, '-')
|
||||||
|
// Convert 2 or more dashes into a single dash
|
||||||
|
.replace(/-+/g, '-')
|
||||||
|
// Make the whole thing lowercase
|
||||||
|
.toLowerCase();
|
||||||
|
|
||||||
|
return string;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue