mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-27 17:46:05 -05:00
FEATURE: backup without uploads
This commit is contained in:
parent
7a621d97b9
commit
8a20d05ba5
12 changed files with 82 additions and 35 deletions
|
@ -1,5 +1,4 @@
|
||||||
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||||
|
|
||||||
import ObjectController from 'discourse/controllers/object';
|
import ObjectController from 'discourse/controllers/object';
|
||||||
|
|
||||||
export default ObjectController.extend(ModalFunctionality, {
|
export default ObjectController.extend(ModalFunctionality, {
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||||
|
import Controller from 'discourse/controllers/controller';
|
||||||
|
|
||||||
|
export default Controller.extend(ModalFunctionality, {
|
||||||
|
|
||||||
|
needs: ["adminBackupsLogs"],
|
||||||
|
|
||||||
|
_startBackup: function (withUploads) {
|
||||||
|
var self = this;
|
||||||
|
Discourse.User.currentProp("hideReadOnlyAlert", true);
|
||||||
|
Discourse.Backup.start(withUploads).then(function() {
|
||||||
|
self.get("controllers.adminBackupsLogs").clear();
|
||||||
|
self.send("backupStarted");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
|
||||||
|
startBackup: function () {
|
||||||
|
return this._startBackup();
|
||||||
|
},
|
||||||
|
|
||||||
|
startBackupWithoutUpload: function () {
|
||||||
|
return this._startBackup(false);
|
||||||
|
},
|
||||||
|
|
||||||
|
cancel: function () {
|
||||||
|
this.send("closeModal");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
|
@ -52,8 +52,9 @@ Discourse.Backup.reopenClass({
|
||||||
@method start
|
@method start
|
||||||
@returns {Promise} a promise that resolves when the backup has started
|
@returns {Promise} a promise that resolves when the backup has started
|
||||||
**/
|
**/
|
||||||
start: function() {
|
start: function (withUploads) {
|
||||||
return Discourse.ajax("/admin/backups", { type: "POST" }).then(function(result) {
|
if (withUploads === undefined) { withUploads = true; }
|
||||||
|
return Discourse.ajax("/admin/backups", { type: "POST", data: { with_uploads: withUploads } }).then(function(result) {
|
||||||
if (!result.success) { bootbox.alert(result.message); }
|
if (!result.success) { bootbox.alert(result.message); }
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -47,22 +47,14 @@ Discourse.AdminBackupsRoute = Discourse.Route.extend({
|
||||||
@method startBackup
|
@method startBackup
|
||||||
**/
|
**/
|
||||||
startBackup: function() {
|
startBackup: function() {
|
||||||
var self = this;
|
Discourse.Route.showModal(this, 'admin_start_backup');
|
||||||
bootbox.confirm(
|
this.controllerFor('modal').set('modalClass', 'start-backup-modal');
|
||||||
I18n.t("admin.backups.operations.backup.confirm"),
|
},
|
||||||
I18n.t("no_value"),
|
|
||||||
I18n.t("yes_value"),
|
backupStarted: function () {
|
||||||
function(confirmed) {
|
this.modelFor("adminBackups").set("isOperationRunning", true);
|
||||||
if (confirmed) {
|
this.transitionTo("admin.backups.logs");
|
||||||
Discourse.User.currentProp("hideReadOnlyAlert", true);
|
this.send("closeModal");
|
||||||
Discourse.Backup.start().then(function() {
|
|
||||||
self.controllerFor("adminBackupsLogs").clear();
|
|
||||||
self.modelFor("adminBackups").set("isOperationRunning", true);
|
|
||||||
self.transitionTo("admin.backups.logs");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<button {{action startBackup}} class="btn btn-primary">{{i18n yes_value}}</button>
|
||||||
|
<button {{action startBackupWithoutUpload}} class="btn">{{i18n admin.backups.operations.backup.without_uploads}}</button>
|
||||||
|
<button {{action cancel}} class="btn">{{i18n no_value}}</button>
|
|
@ -0,0 +1,4 @@
|
||||||
|
Discourse.AdminStartBackupView = Discourse.ModalBodyView.extend({
|
||||||
|
templateName: 'admin/templates/modal/admin_start_backup',
|
||||||
|
title: I18n.t('admin.backups.operations.backup.confirm')
|
||||||
|
});
|
|
@ -1164,6 +1164,15 @@ button.ru {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.start-backup-modal {
|
||||||
|
.btn {
|
||||||
|
margin: 10px 0 10px 5px;
|
||||||
|
}
|
||||||
|
.btn:first-of-type {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media all
|
@media all
|
||||||
and (max-width : 850px) {
|
and (max-width : 850px) {
|
||||||
.nav-stacked {
|
.nav-stacked {
|
||||||
|
|
|
@ -23,7 +23,11 @@ class Admin::BackupsController < Admin::AdminController
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
BackupRestore.backup!(current_user.id, true)
|
opts = {
|
||||||
|
publish_to_message_bus: true,
|
||||||
|
with_uploads: params.fetch(:with_uploads) == "true"
|
||||||
|
}
|
||||||
|
BackupRestore.backup!(current_user.id, opts)
|
||||||
rescue BackupRestore::OperationRunningError
|
rescue BackupRestore::OperationRunningError
|
||||||
render json: failed_json.merge(message: I18n.t("backup.operation_already_running"))
|
render json: failed_json.merge(message: I18n.t("backup.operation_already_running"))
|
||||||
else
|
else
|
||||||
|
|
|
@ -7,7 +7,7 @@ module Jobs
|
||||||
|
|
||||||
def execute(args)
|
def execute(args)
|
||||||
return unless SiteSetting.backup_daily?
|
return unless SiteSetting.backup_daily?
|
||||||
BackupRestore.backup!(Discourse.system_user.id, false)
|
BackupRestore.backup!(Discourse.system_user.id, publish_to_message_bus: false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1600,7 +1600,8 @@ en:
|
||||||
backup:
|
backup:
|
||||||
text: "Backup"
|
text: "Backup"
|
||||||
title: "Create a backup"
|
title: "Create a backup"
|
||||||
confirm: "Are you sure you want to start a new backup?"
|
confirm: "Do you want to start a new backup?"
|
||||||
|
without_uploads: "Yes (without upload)"
|
||||||
download:
|
download:
|
||||||
text: "Download"
|
text: "Download"
|
||||||
title: "Download the backup"
|
title: "Download the backup"
|
||||||
|
|
|
@ -9,14 +9,12 @@ module BackupRestore
|
||||||
METADATA_FILE = "meta.json"
|
METADATA_FILE = "meta.json"
|
||||||
LOGS_CHANNEL = "/admin/backups/logs"
|
LOGS_CHANNEL = "/admin/backups/logs"
|
||||||
|
|
||||||
def self.backup!(user_id, publish_to_message_bus = false)
|
def self.backup!(user_id, opts={})
|
||||||
exporter = Export::Exporter.new(user_id, publish_to_message_bus)
|
start! Export::Exporter.new(user_id, opts)
|
||||||
start! exporter
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.restore!(user_id, filename, publish_to_message_bus = false)
|
def self.restore!(user_id, filename, publish_to_message_bus=false)
|
||||||
importer = Import::Importer.new(user_id, filename, publish_to_message_bus)
|
start! Import::Importer.new(user_id, filename, publish_to_message_bus)
|
||||||
start! importer
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.rollback!
|
def self.rollback!
|
||||||
|
@ -33,7 +31,6 @@ module BackupRestore
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.mark_as_running!
|
def self.mark_as_running!
|
||||||
# TODO: for extra safety, it should acquire a lock and raise an exception if already running
|
|
||||||
$redis.setex(running_key, 60, "1")
|
$redis.setex(running_key, 60, "1")
|
||||||
save_start_logs_message_id
|
save_start_logs_message_id
|
||||||
keep_it_running
|
keep_it_running
|
||||||
|
|
|
@ -4,8 +4,10 @@ module Export
|
||||||
|
|
||||||
attr_reader :success
|
attr_reader :success
|
||||||
|
|
||||||
def initialize(user_id, publish_to_message_bus = false)
|
def initialize(user_id, opts={})
|
||||||
@user_id, @publish_to_message_bus = user_id, publish_to_message_bus
|
@user_id = user_id
|
||||||
|
@publish_to_message_bus = opts[:publish_to_message_bus] || false
|
||||||
|
@with_uploads = opts[:with_uploads].nil? ? true : opts[:with_uploads]
|
||||||
|
|
||||||
ensure_no_operation_is_running
|
ensure_no_operation_is_running
|
||||||
ensure_we_have_a_user
|
ensure_we_have_a_user
|
||||||
|
@ -246,11 +248,13 @@ module Export
|
||||||
`tar --append --dereference --file #{tar_filename} #{File.basename(@dump_filename)}`
|
`tar --append --dereference --file #{tar_filename} #{File.basename(@dump_filename)}`
|
||||||
end
|
end
|
||||||
|
|
||||||
upload_directory = "uploads/" + @current_db
|
if @with_uploads
|
||||||
|
upload_directory = "uploads/" + @current_db
|
||||||
|
|
||||||
log "Archiving uploads..."
|
log "Archiving uploads..."
|
||||||
FileUtils.cd(File.join(Rails.root, "public")) do
|
FileUtils.cd(File.join(Rails.root, "public")) do
|
||||||
`tar --append --dereference --file #{tar_filename} #{upload_directory}`
|
`tar --append --dereference --file #{tar_filename} #{upload_directory}`
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
log "Gzipping archive..."
|
log "Gzipping archive..."
|
||||||
|
|
Loading…
Reference in a new issue