diff --git a/app/assets/javascripts/admin/controllers/admin-agree-flag.js.es6 b/app/assets/javascripts/admin/controllers/admin-agree-flag.js.es6 index 703556c30..73e1238de 100644 --- a/app/assets/javascripts/admin/controllers/admin-agree-flag.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-agree-flag.js.es6 @@ -1,5 +1,4 @@ import ModalFunctionality from 'discourse/mixins/modal-functionality'; - import ObjectController from 'discourse/controllers/object'; export default ObjectController.extend(ModalFunctionality, { diff --git a/app/assets/javascripts/admin/controllers/admin-start-backup.js.es6 b/app/assets/javascripts/admin/controllers/admin-start-backup.js.es6 new file mode 100644 index 000000000..969216e38 --- /dev/null +++ b/app/assets/javascripts/admin/controllers/admin-start-backup.js.es6 @@ -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"); + } + + } + +}); diff --git a/app/assets/javascripts/admin/models/backup.js b/app/assets/javascripts/admin/models/backup.js index 28a6115a8..8c11c9fe3 100644 --- a/app/assets/javascripts/admin/models/backup.js +++ b/app/assets/javascripts/admin/models/backup.js @@ -52,8 +52,9 @@ Discourse.Backup.reopenClass({ @method start @returns {Promise} a promise that resolves when the backup has started **/ - start: function() { - return Discourse.ajax("/admin/backups", { type: "POST" }).then(function(result) { + start: function (withUploads) { + 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); } }); }, diff --git a/app/assets/javascripts/admin/routes/admin_backups_route.js b/app/assets/javascripts/admin/routes/admin_backups_route.js index bed160c63..6580ed075 100644 --- a/app/assets/javascripts/admin/routes/admin_backups_route.js +++ b/app/assets/javascripts/admin/routes/admin_backups_route.js @@ -47,22 +47,14 @@ Discourse.AdminBackupsRoute = Discourse.Route.extend({ @method startBackup **/ startBackup: function() { - var self = this; - bootbox.confirm( - I18n.t("admin.backups.operations.backup.confirm"), - I18n.t("no_value"), - I18n.t("yes_value"), - function(confirmed) { - if (confirmed) { - Discourse.User.currentProp("hideReadOnlyAlert", true); - Discourse.Backup.start().then(function() { - self.controllerFor("adminBackupsLogs").clear(); - self.modelFor("adminBackups").set("isOperationRunning", true); - self.transitionTo("admin.backups.logs"); - }); - } - } - ); + Discourse.Route.showModal(this, 'admin_start_backup'); + this.controllerFor('modal').set('modalClass', 'start-backup-modal'); + }, + + backupStarted: function () { + this.modelFor("adminBackups").set("isOperationRunning", true); + this.transitionTo("admin.backups.logs"); + this.send("closeModal"); }, /** diff --git a/app/assets/javascripts/admin/templates/modal/admin_start_backup.js.handlebars b/app/assets/javascripts/admin/templates/modal/admin_start_backup.js.handlebars new file mode 100644 index 000000000..01433b5a1 --- /dev/null +++ b/app/assets/javascripts/admin/templates/modal/admin_start_backup.js.handlebars @@ -0,0 +1,3 @@ + + + diff --git a/app/assets/javascripts/admin/views/modals/admin_start_backup_view.js b/app/assets/javascripts/admin/views/modals/admin_start_backup_view.js new file mode 100644 index 000000000..b59207f26 --- /dev/null +++ b/app/assets/javascripts/admin/views/modals/admin_start_backup_view.js @@ -0,0 +1,4 @@ +Discourse.AdminStartBackupView = Discourse.ModalBodyView.extend({ + templateName: 'admin/templates/modal/admin_start_backup', + title: I18n.t('admin.backups.operations.backup.confirm') +}); diff --git a/app/assets/stylesheets/common/admin/admin_base.scss b/app/assets/stylesheets/common/admin/admin_base.scss index 232d49905..441db8c03 100644 --- a/app/assets/stylesheets/common/admin/admin_base.scss +++ b/app/assets/stylesheets/common/admin/admin_base.scss @@ -1164,6 +1164,15 @@ button.ru { } } +.start-backup-modal { + .btn { + margin: 10px 0 10px 5px; + } + .btn:first-of-type { + margin-left: 10px; + } +} + @media all and (max-width : 850px) { .nav-stacked { diff --git a/app/controllers/admin/backups_controller.rb b/app/controllers/admin/backups_controller.rb index 453cbf2ba..9c8aa132b 100644 --- a/app/controllers/admin/backups_controller.rb +++ b/app/controllers/admin/backups_controller.rb @@ -23,7 +23,11 @@ class Admin::BackupsController < Admin::AdminController end 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 render json: failed_json.merge(message: I18n.t("backup.operation_already_running")) else diff --git a/app/jobs/scheduled/create_backup.rb b/app/jobs/scheduled/create_backup.rb index 7e47dadc2..abf08c1dc 100644 --- a/app/jobs/scheduled/create_backup.rb +++ b/app/jobs/scheduled/create_backup.rb @@ -7,7 +7,7 @@ module Jobs def execute(args) 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 diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index ae265bae9..c39c237e4 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1600,7 +1600,8 @@ en: backup: text: "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: text: "Download" title: "Download the backup" diff --git a/lib/backup_restore.rb b/lib/backup_restore.rb index feff492f2..9872cf911 100644 --- a/lib/backup_restore.rb +++ b/lib/backup_restore.rb @@ -9,14 +9,12 @@ module BackupRestore METADATA_FILE = "meta.json" LOGS_CHANNEL = "/admin/backups/logs" - def self.backup!(user_id, publish_to_message_bus = false) - exporter = Export::Exporter.new(user_id, publish_to_message_bus) - start! exporter + def self.backup!(user_id, opts={}) + start! Export::Exporter.new(user_id, opts) end - def self.restore!(user_id, filename, publish_to_message_bus = false) - importer = Import::Importer.new(user_id, filename, publish_to_message_bus) - start! importer + def self.restore!(user_id, filename, publish_to_message_bus=false) + start! Import::Importer.new(user_id, filename, publish_to_message_bus) end def self.rollback! @@ -33,7 +31,6 @@ module BackupRestore end 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") save_start_logs_message_id keep_it_running diff --git a/lib/export/exporter.rb b/lib/export/exporter.rb index 4de3e17b2..7105a96ce 100644 --- a/lib/export/exporter.rb +++ b/lib/export/exporter.rb @@ -4,8 +4,10 @@ module Export attr_reader :success - def initialize(user_id, publish_to_message_bus = false) - @user_id, @publish_to_message_bus = user_id, publish_to_message_bus + def initialize(user_id, opts={}) + @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_we_have_a_user @@ -246,11 +248,13 @@ module Export `tar --append --dereference --file #{tar_filename} #{File.basename(@dump_filename)}` end - upload_directory = "uploads/" + @current_db + if @with_uploads + upload_directory = "uploads/" + @current_db - log "Archiving uploads..." - FileUtils.cd(File.join(Rails.root, "public")) do - `tar --append --dereference --file #{tar_filename} #{upload_directory}` + log "Archiving uploads..." + FileUtils.cd(File.join(Rails.root, "public")) do + `tar --append --dereference --file #{tar_filename} #{upload_directory}` + end end log "Gzipping archive..."