discourse/app/models/backup.rb

100 lines
2.5 KiB
Ruby

class Backup
include UrlHelper
include ActiveModel::SerializerSupport
attr_reader :filename
attr_accessor :size, :path, :link
def initialize(filename)
@filename = filename
end
def self.all
Dir.glob(File.join(Backup.base_directory, "*.tar.gz"))
.sort_by { |file| File.mtime(file) }
.reverse
.map { |backup| Backup.create_from_filename(File.basename(backup)) }
end
def self.[](filename)
path = File.join(Backup.base_directory, filename)
if File.exists?(path)
Backup.create_from_filename(filename)
else
nil
end
end
def remove
File.delete(@path) if File.exists?(path)
after_remove_hook
end
def after_create_hook
upload_to_s3 if SiteSetting.enable_s3_backups?
end
def after_remove_hook
remove_from_s3 if SiteSetting.enable_s3_backups?
end
def upload_to_s3
return unless fog_directory
fog_directory.files.create(key: @filename, public: false, body: File.read(@path))
end
def remove_from_s3
return unless fog
fog.delete_object(SiteSetting.s3_backup_bucket, @filename)
end
def self.base_directory
File.join(Rails.root, "public", "backups", RailsMultisite::ConnectionManagement.current_db)
end
def self.chunk_path(identifier, filename, chunk_number)
File.join(Backup.base_directory, "tmp", identifier, "#{filename}.part#{chunk_number}")
end
def self.create_from_filename(filename)
Backup.new(filename).tap do |b|
b.path = File.join(Backup.base_directory, b.filename)
b.link = b.schemaless "#{Discourse.base_url}/admin/backups/#{b.filename}"
b.size = File.size(b.path)
end
end
def self.remove_old
all_backups = Backup.all
return unless all_backups.size > SiteSetting.maximum_backups
all_backups[SiteSetting.maximum_backups..-1].each(&:remove)
end
private
def s3_options
{
provider: 'AWS',
aws_access_key_id: SiteSetting.s3_access_key_id,
aws_secret_access_key: SiteSetting.s3_secret_access_key,
region: SiteSetting.s3_region.blank? ? "us-east-1" : SiteSetting.s3_region,
}
end
def fog
return @fog if @fog
return unless SiteSetting.s3_access_key_id.present? &&
SiteSetting.s3_secret_access_key.present? &&
SiteSetting.s3_backup_bucket.present?
require 'fog'
@fog = Fog::Storage.new(s3_options)
end
def fog_directory
return @fog_directory if @fog_directory
return unless fog
@fog_directory ||= fog.directories.get(SiteSetting.s3_backup_bucket)
end
end