mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-06 22:40:14 -05:00
Merge pull request #1860 from sebgie/issue#1854
This commit is contained in:
commit
80eac65e9b
7 changed files with 70 additions and 58 deletions
|
@ -8,6 +8,59 @@
|
||||||
"click .js-delete": "handleDeleteClick"
|
"click .js-delete": "handleDeleteClick"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
// Disable import button and initizalize BlueImp file upload
|
||||||
|
$('#startupload').prop('disabled', true);
|
||||||
|
$('#importfile').fileupload({
|
||||||
|
url: Ghost.paths.apiRoot + '/db/',
|
||||||
|
limitMultiFileUploads: 1,
|
||||||
|
replaceFileInput: false,
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-Token': $("meta[name='csrf-param']").attr('content')
|
||||||
|
},
|
||||||
|
dataType: 'json',
|
||||||
|
add: function (e, data) {
|
||||||
|
/*jslint unparam:true*/
|
||||||
|
data.context = $('#startupload').prop('disabled', false)
|
||||||
|
.click(function () {
|
||||||
|
$('#startupload').prop('disabled', true);
|
||||||
|
data.context = $('#startupload').text('Importing');
|
||||||
|
data.submit();
|
||||||
|
// unregister click event to allow different subsequent uploads
|
||||||
|
$('#startupload').off('click');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
done: function (e, data) {
|
||||||
|
/*jslint unparam:true*/
|
||||||
|
$('#startupload').text('Import');
|
||||||
|
if (!data.result) {
|
||||||
|
throw new Error('No response received from server.');
|
||||||
|
}
|
||||||
|
if (!data.result.message) {
|
||||||
|
throw new Error('Unknown error');
|
||||||
|
}
|
||||||
|
|
||||||
|
Ghost.notifications.addItem({
|
||||||
|
type: 'success',
|
||||||
|
message: data.result.message,
|
||||||
|
status: 'passive'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
error: function (response) {
|
||||||
|
$('#startupload').text('Import');
|
||||||
|
var responseJSON = response.responseJSON,
|
||||||
|
message = responseJSON && responseJSON.error ? responseJSON.error : 'unknown';
|
||||||
|
Ghost.notifications.addItem({
|
||||||
|
type: 'error',
|
||||||
|
message: ['A problem was encountered while importing new content to your blog. Error: ', message].join(''),
|
||||||
|
status: 'passive'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
handleMenuClick: function (ev) {
|
handleMenuClick: function (ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
|
@ -21,6 +74,7 @@
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
handleDeleteClick: function (ev) {
|
handleDeleteClick: function (ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this.addSubview(new Ghost.Views.Modal({
|
this.addSubview(new Ghost.Views.Modal({
|
||||||
|
|
|
@ -16,7 +16,7 @@ api.notifications = require('./notifications');
|
||||||
api.settings = require('./settings');
|
api.settings = require('./settings');
|
||||||
|
|
||||||
db = {
|
db = {
|
||||||
'export': function (req, res) {
|
'exportContent': function (req, res) {
|
||||||
/*jslint unparam:true*/
|
/*jslint unparam:true*/
|
||||||
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
|
||||||
|
@ -44,11 +44,10 @@ db = {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
'import': function (req, res) {
|
'importContent': function (options) {
|
||||||
var notification,
|
var databaseVersion;
|
||||||
databaseVersion;
|
|
||||||
|
|
||||||
if (!req.files.importfile || !req.files.importfile.path || req.files.importfile.name.indexOf('json') === -1) {
|
if (!options.importfile || !options.importfile.path || options.importfile.name.indexOf('json') === -1) {
|
||||||
/**
|
/**
|
||||||
* Notify of an error if it occurs
|
* Notify of an error if it occurs
|
||||||
*
|
*
|
||||||
|
@ -57,30 +56,17 @@ db = {
|
||||||
* - If there is no path
|
* - If there is no path
|
||||||
* - If the name doesn't have json in it
|
* - If the name doesn't have json in it
|
||||||
*/
|
*/
|
||||||
return api.notifications.browse().then(function (notifications) {
|
return when.reject({errorCode: 500, message: 'Please select a .json file to import.'});
|
||||||
notification = {
|
|
||||||
type: 'error',
|
|
||||||
message: "Must select a .json file to import",
|
|
||||||
status: 'persistent',
|
|
||||||
id: 'per-' + (notifications.length + 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return api.notifications.add(notification).then(function () {
|
|
||||||
res.redirect(configPaths().debugPath);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
api.settings.read({ key: 'databaseVersion' }).then(function (setting) {
|
return api.settings.read({ key: 'databaseVersion' }).then(function (setting) {
|
||||||
return when(setting.value);
|
return when(setting.value);
|
||||||
}, function () {
|
}, function () {
|
||||||
return when('001');
|
return when('001');
|
||||||
}).then(function (version) {
|
}).then(function (version) {
|
||||||
databaseVersion = version;
|
databaseVersion = version;
|
||||||
// Read the file contents
|
// Read the file contents
|
||||||
return nodefn.call(fs.readFile, req.files.importfile.path);
|
return nodefn.call(fs.readFile, options.importfile.path);
|
||||||
}).then(function (fileContents) {
|
}).then(function (fileContents) {
|
||||||
var importData,
|
var importData,
|
||||||
error = '',
|
error = '',
|
||||||
|
@ -132,32 +118,9 @@ db = {
|
||||||
}).then(function importSuccess() {
|
}).then(function importSuccess() {
|
||||||
return api.settings.updateSettingsCache();
|
return api.settings.updateSettingsCache();
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
return api.notifications.browse();
|
return when.resolve({message: 'Posts, tags and other data successfully imported'});
|
||||||
}).then(function (notifications) {
|
|
||||||
notification = {
|
|
||||||
type: 'success',
|
|
||||||
message: "Posts, tags and other data successfully imported",
|
|
||||||
status: 'persistent',
|
|
||||||
id: 'per-' + (notifications.length + 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
return api.notifications.add(notification).then(function () {
|
|
||||||
res.redirect(configPaths().debugPath);
|
|
||||||
});
|
|
||||||
}).otherwise(function importFailure(error) {
|
}).otherwise(function importFailure(error) {
|
||||||
return api.notifications.browse().then(function (notifications) {
|
return when.reject({errorCode: 500, message: error.message || error});
|
||||||
// Notify of an error if it occurs
|
|
||||||
notification = {
|
|
||||||
type: 'error',
|
|
||||||
message: error.message || error,
|
|
||||||
status: 'persistent',
|
|
||||||
id: 'per-' + (notifications.length + 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
return api.notifications.add(notification).then(function () {
|
|
||||||
res.redirect(configPaths().debugPath);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
'deleteAllContent': function () {
|
'deleteAllContent': function () {
|
||||||
|
|
|
@ -45,7 +45,7 @@ function cacheInvalidationHeader(req, result) {
|
||||||
// takes the API method and wraps it so that it gets data from the request and returns a sensible JSON response
|
// takes the API method and wraps it so that it gets data from the request and returns a sensible JSON response
|
||||||
requestHandler = function (apiMethod) {
|
requestHandler = function (apiMethod) {
|
||||||
return function (req, res) {
|
return function (req, res) {
|
||||||
var options = _.extend(req.body, req.query, req.params),
|
var options = _.extend(req.body, req.files, req.query, req.params),
|
||||||
apiContext = {
|
apiContext = {
|
||||||
user: req.session && req.session.user
|
user: req.session && req.session.user
|
||||||
};
|
};
|
||||||
|
|
|
@ -233,9 +233,6 @@ module.exports = function (server, dbHash) {
|
||||||
expressServer.use(express.json());
|
expressServer.use(express.json());
|
||||||
expressServer.use(express.urlencoded());
|
expressServer.use(express.urlencoded());
|
||||||
|
|
||||||
expressServer.use(subdir + '/ghost/upload/', middleware.busboy);
|
|
||||||
expressServer.use(subdir + '/ghost/api/v0.1/db/', middleware.busboy);
|
|
||||||
|
|
||||||
// ### Sessions
|
// ### Sessions
|
||||||
cookie = {
|
cookie = {
|
||||||
path: subdir + '/ghost',
|
path: subdir + '/ghost',
|
||||||
|
|
|
@ -43,8 +43,7 @@ module.exports = function (server) {
|
||||||
server.get('/ghost/settings*', middleware.auth, admin.settings);
|
server.get('/ghost/settings*', middleware.auth, admin.settings);
|
||||||
server.get('/ghost/debug/', middleware.auth, admin.debug.index);
|
server.get('/ghost/debug/', middleware.auth, admin.debug.index);
|
||||||
|
|
||||||
// We don't want to register bodyParser globally b/c of security concerns, so use multipart only here
|
server.post('/ghost/upload/', middleware.auth, middleware.busboy, admin.uploader);
|
||||||
server.post('/ghost/upload/', middleware.auth, admin.uploader);
|
|
||||||
|
|
||||||
// redirect to /ghost and let that do the authentication to prevent redirects to /ghost//admin etc.
|
// redirect to /ghost and let that do the authentication to prevent redirects to /ghost//admin etc.
|
||||||
server.get(/\/((ghost-admin|admin|wp-admin|dashboard|signin)\/?)$/, function (req, res) {
|
server.get(/\/((ghost-admin|admin|wp-admin|dashboard|signin)\/?)$/, function (req, res) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ module.exports = function (server) {
|
||||||
server.del('/ghost/api/v0.1/notifications/:id', middleware.authAPI, api.requestHandler(api.notifications.destroy));
|
server.del('/ghost/api/v0.1/notifications/:id', middleware.authAPI, api.requestHandler(api.notifications.destroy));
|
||||||
server.post('/ghost/api/v0.1/notifications/', middleware.authAPI, api.requestHandler(api.notifications.add));
|
server.post('/ghost/api/v0.1/notifications/', middleware.authAPI, api.requestHandler(api.notifications.add));
|
||||||
// #### Import/Export
|
// #### Import/Export
|
||||||
server.get('/ghost/api/v0.1/db/', middleware.auth, api.db['export']);
|
server.get('/ghost/api/v0.1/db/', middleware.auth, api.db.exportContent);
|
||||||
server.post('/ghost/api/v0.1/db/', middleware.auth, api.db['import']);
|
server.post('/ghost/api/v0.1/db/', middleware.authAPI, middleware.busboy, api.requestHandler(api.db.importContent));
|
||||||
server.del('/ghost/api/v0.1/db/', middleware.authAPI, api.requestHandler(api.db.deleteAllContent));
|
server.del('/ghost/api/v0.1/db/', middleware.authAPI, api.requestHandler(api.db.deleteAllContent));
|
||||||
};
|
};
|
|
@ -25,13 +25,12 @@
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
<form id="settings-import" method="post" action="{{adminUrl}}/api/v0.1/db/" enctype="multipart/form-data">
|
<form id="settings-import" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="_csrf" value="{{csrfToken}}" />
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Import</label>
|
<label>Import</label>
|
||||||
<input type="file" class="button-add" name="importfile" />
|
<input type="file" class="button-add" name="importfile" id="importfile" />
|
||||||
<input type="submit" class="button-save" value="Import" />
|
<button type="submit" class="button-save" value="Import" id="startupload" >Import</button>
|
||||||
<p>Import from another Ghost installation. If you import a user, this will replace the current user & log you out.</p>
|
<p>Import from another Ghost installation. If you import a user, this will replace the current user & log you out.</p>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
Loading…
Reference in a new issue