diff --git a/app/assets/javascripts/admin/controllers/admin-backups-index.js.es6 b/app/assets/javascripts/admin/controllers/admin-backups-index.js.es6 index 8eceb0bb7d0..6a440571217 100644 --- a/app/assets/javascripts/admin/controllers/admin-backups-index.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-backups-index.js.es6 @@ -1,20 +1,20 @@ export default Ember.ArrayController.extend({ needs: ["adminBackups"], status: Em.computed.alias("controllers.adminBackups"), - isOperationRunning: Em.computed.alias("status.isOperationRunning"), - restoreDisabled: Em.computed.alias("status.restoreDisabled"), + isOperationRunning: Em.computed.alias("status.model.isOperationRunning"), + restoreDisabled: Em.computed.alias("status.model.restoreDisabled"), uploadLabel: function() { return I18n.t("admin.backups.upload.label"); }.property(), restoreTitle: function() { - if (!this.get('status.allowRestore')) { + if (!this.get('status.model.allowRestore')) { return "admin.backups.operations.restore.is_disabled"; - } else if (this.get("status.isOperationRunning")) { + } else if (this.get("status.model.isOperationRunning")) { return "admin.backups.operations.is_running"; } else { return "admin.backups.operations.restore.title"; } - }.property("status.{allowRestore,isOperationRunning}"), + }.property("status.model.{allowRestore,isOperationRunning}"), actions: { diff --git a/app/assets/javascripts/admin/controllers/admin-backups.js.es6 b/app/assets/javascripts/admin/controllers/admin-backups.js.es6 index 64bb7ad105b..287ac92e468 100644 --- a/app/assets/javascripts/admin/controllers/admin-backups.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-backups.js.es6 @@ -1,5 +1,5 @@ export default Ember.ObjectController.extend({ - noOperationIsRunning: Em.computed.not("isOperationRunning"), - rollbackEnabled: Em.computed.and("canRollback", "restoreEnabled", "noOperationIsRunning"), + noOperationIsRunning: Em.computed.not("model.isOperationRunning"), + rollbackEnabled: Em.computed.and("model.canRollback", "model.restoreEnabled", "noOperationIsRunning"), rollbackDisabled: Em.computed.not("rollbackEnabled") }); diff --git a/app/assets/javascripts/admin/routes/admin-backups.js.es6 b/app/assets/javascripts/admin/routes/admin-backups.js.es6 index 981dc5394b0..a48d16f16e6 100644 --- a/app/assets/javascripts/admin/routes/admin-backups.js.es6 +++ b/app/assets/javascripts/admin/routes/admin-backups.js.es6 @@ -10,14 +10,14 @@ export default Discourse.Route.extend({ _processLogMessage(log) { if (log.message === "[STARTED]") { - this.controllerFor("adminBackups").set("isOperationRunning", true); + this.controllerFor("adminBackups").set("model.isOperationRunning", true); this.controllerFor("adminBackupsLogs").clear(); } else if (log.message === "[FAILED]") { - this.controllerFor("adminBackups").set("isOperationRunning", false); + this.controllerFor("adminBackups").set("model.isOperationRunning", false); bootbox.alert(I18n.t("admin.backups.operations.failed", { operation: log.operation })); } else if (log.message === "[SUCCESS]") { Discourse.User.currentProp("hideReadOnlyAlert", false); - this.controllerFor("adminBackups").set("isOperationRunning", false); + this.controllerFor("adminBackups").set("model.isOperationRunning", false); if (log.operation === "restore") { // redirect to homepage when the restore is done (session might be lost) window.location.pathname = Discourse.getURL("/"); @@ -30,7 +30,7 @@ export default Discourse.Route.extend({ model() { return PreloadStore.getAndRemove("operations_status", function() { return Discourse.ajax("/admin/backups/status.json"); - }).then(function (status) { + }).then(status => { return Discourse.BackupStatus.create({ isOperationRunning: status.is_operation_running, canRollback: status.can_rollback, @@ -99,7 +99,7 @@ export default Discourse.Route.extend({ function(confirmed) { if (confirmed) { Discourse.Backup.cancel().then(function() { - self.controllerFor("adminBackups").set("isOperationRunning", false); + self.modelFor("adminBackups").set("isOperationRunning", false); }); } } diff --git a/app/assets/javascripts/admin/templates/backups.hbs b/app/assets/javascripts/admin/templates/backups.hbs index d274285b2b6..7562754c08c 100644 --- a/app/assets/javascripts/admin/templates/backups.hbs +++ b/app/assets/javascripts/admin/templates/backups.hbs @@ -6,7 +6,7 @@
"); buffer.push(formattedLogs); @@ -38,13 +38,13 @@ export default Discourse.View.extend({ buffer.push("" + I18n.t("admin.backups.logs.none") + "
"); } // add a loading indicator - if (this.get("controller.status.isOperationRunning")) { + if (this.get("controller.status.model.isOperationRunning")) { buffer.push(renderSpinner('small')); } }, _forceScrollToBottom: function() { - var $div = this.$()[0]; + const $div = this.$()[0]; $div.scrollTop = $div.scrollHeight; }.on("didInsertElement") diff --git a/app/jobs/regular/create_daily_backup.rb b/app/jobs/regular/create_backup.rb similarity index 71% rename from app/jobs/regular/create_daily_backup.rb rename to app/jobs/regular/create_backup.rb index 40024fc76db..d455e6ab8c1 100644 --- a/app/jobs/regular/create_daily_backup.rb +++ b/app/jobs/regular/create_backup.rb @@ -1,11 +1,11 @@ require "backup_restore/backup_restore" module Jobs - class CreateDailyBackup < Jobs::Base + class CreateBackup < Jobs::Base sidekiq_options retry: false def execute(args) - return unless SiteSetting.backup_daily? + return unless SiteSetting.backups_enabled? BackupRestore.backup!(Discourse.system_user.id, publish_to_message_bus: false) end end diff --git a/app/jobs/scheduled/schedule_backup.rb b/app/jobs/scheduled/schedule_backup.rb index 7408641e54d..fa1584b6a02 100644 --- a/app/jobs/scheduled/schedule_backup.rb +++ b/app/jobs/scheduled/schedule_backup.rb @@ -5,8 +5,14 @@ module Jobs sidekiq_options retry: false def execute(args) - return unless SiteSetting.backup_daily? - Jobs.enqueue_in(rand(10.minutes), :create_daily_backup) + return unless SiteSetting.backups_enabled? + + if latest_backup = Backup.all[0] + date = Date.parse(latest_backup.filename[/\d{4}-\d{2}-\d{2}/]) + return if date + SiteSetting.backup_frequency.days > Time.now + end + + Jobs.enqueue_in(rand(10.minutes), :create_backup) end end end diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb index 02dad62554d..56c1cb5f95c 100644 --- a/app/models/site_setting.rb +++ b/app/models/site_setting.rb @@ -111,6 +111,10 @@ class SiteSetting < ActiveRecord::Base false end + def self.backups_enabled? + SiteSetting.backup_frequency > 0 + end + end # == Schema Information diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 63034613e8a..7d10fb4eaf5 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -938,7 +938,7 @@ en: allow_restore: "Allow restore, which can replace ALL site data! Leave false unless you plan to restore a backup" maximum_backups: "The maximum amount of backups to keep on disk. Older backups are automatically deleted" - backup_daily: "Automatically create a site backup once a day." + backup_frequency: "How frequently we create a site backup, in days." enable_s3_backups: "Upload backups to S3 when complete. IMPORTANT: requires valid S3 credentials entered in Files settings." s3_backup_bucket: "The remote bucket to hold backups. WARNING: Make sure it is a private bucket." diff --git a/config/site_settings.yml b/config/site_settings.yml index 2bf7eb4369c..e000630c937 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -43,7 +43,6 @@ required: client: true default: '/images/d-logo-sketch-small.png' digest_logo_url: - client: false default: '' mobile_logo_url: client: true @@ -70,7 +69,6 @@ basic: default: 5 min: 0 limit_suggested_to_category: - client: false default: false default_external_links_in_new_tab: false track_external_right_clicks: @@ -789,19 +787,17 @@ legal: backups: allow_restore: - client: false default: false maximum_backups: client: true default: 7 - backup_daily: - client: false - default: false + backup_frequency: + min: 0 + max: 7 + default: 1 enable_s3_backups: - client: false default: false s3_backup_bucket: - client: false default: '' regex: "^[^A-Z_.]+$" # can't use '.' when using HTTPS diff --git a/spec/jobs/create_daily_backup_spec.rb b/spec/jobs/create_daily_backup_spec.rb deleted file mode 100644 index 0430f367d01..00000000000 --- a/spec/jobs/create_daily_backup_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'spec_helper' - -require_dependency 'jobs/regular/create_daily_backup' - -describe Jobs::CreateDailyBackup do - it "does nothing when daily backups are disabled" do - SiteSetting.stubs(:backup_daily?).returns(false) - BackupRestore.expects(:backup!).never - Jobs::CreateDailyBackup.new.execute({}) - end - - it "calls `backup!` when the daily backups are enabled" do - SiteSetting.stubs(:backup_daily?).returns(true) - BackupRestore.expects(:backup!).with(Discourse.system_user.id, { publish_to_message_bus: false }).once - Jobs::CreateDailyBackup.new.execute({}) - end -end -