discourse/spec/controllers/admin/backups_controller_spec.rb

265 lines
7.4 KiB
Ruby

require "rails_helper"
describe Admin::BackupsController do
it "is a subclass of AdminController" do
expect(Admin::BackupsController < Admin::AdminController).to eq(true)
end
let(:backup_filename) { "2014-02-10-065935.tar.gz" }
context "while logged in as an admin" do
before { @admin = log_in(:admin) }
describe ".index" do
context "html format" do
it "preloads important data" do
Backup.expects(:all).returns([])
subject.expects(:store_preloaded).with("backups", "[]")
BackupRestore.expects(:operations_status).returns({})
subject.expects(:store_preloaded).with("operations_status", "{}")
BackupRestore.expects(:logs).returns([])
subject.expects(:store_preloaded).with("logs", "[]")
get :index, format: :html, xhr: true
expect(response.status).to eq(200)
end
end
context "json format" do
it "returns a list of all the backups" do
Backup.expects(:all).returns([Backup.new("backup1"), Backup.new("backup2")])
get :index, format: :json, xhr: true
expect(response.status).to eq(200)
json = JSON.parse(response.body)
expect(json[0]["filename"]).to eq("backup1")
expect(json[1]["filename"]).to eq("backup2")
end
end
end
describe ".status" do
it "returns the current backups status" do
BackupRestore.expects(:operations_status)
get :status, format: :json
expect(response.status).to eq(200)
end
end
describe ".create" do
it "starts a backup" do
BackupRestore.expects(:backup!).with(@admin.id, publish_to_message_bus: true, with_uploads: false, client_id: "foo")
post :create, params: {
with_uploads: false, client_id: "foo"
}, format: :json
expect(response.status).to eq(200)
end
end
describe ".show" do
it "uses send_file to transmit the backup" do
begin
token = EmailBackupToken.set(@admin.id)
path = File.join(Backup.base_directory, backup_filename)
File.open(path, "w") { |f| f.write("hello") }
Backup.create_from_filename(backup_filename)
StaffActionLogger.any_instance.expects(:log_backup_download).once
get :show, params: { id: backup_filename, token: token }, format: :json
expect(response.headers['Content-Length']).to eq("5")
expect(response.headers['Content-Disposition']).to match(/attachment; filename/)
ensure
File.delete(path)
EmailBackupToken.del(@admin.id)
end
end
it "returns 422 when token is bad" do
begin
path = File.join(Backup.base_directory, backup_filename)
File.open(path, "w") { |f| f.write("hello") }
Backup.create_from_filename(backup_filename)
get :show, params: { id: backup_filename, token: "bad_value" }, xhr: true
expect(response.status).to eq(422)
ensure
File.delete(path)
end
end
it "returns 404 when the backup does not exist" do
token = EmailBackupToken.set(@admin.id)
Backup.expects(:[]).returns(nil)
get :show, params: { id: backup_filename, token: token }, format: :json
EmailBackupToken.del(@admin.id)
expect(response).to be_not_found
end
end
describe ".destroy" do
let(:b) { Backup.new(backup_filename) }
it "removes the backup if found" do
Backup.expects(:[]).with(backup_filename).returns(b)
b.expects(:remove)
StaffActionLogger.any_instance.expects(:log_backup_destroy).with(b).once
delete :destroy, params: { id: backup_filename }, format: :json
expect(response.status).to eq(200)
end
it "doesn't remove the backup if not found" do
Backup.expects(:[]).with(backup_filename).returns(nil)
b.expects(:remove).never
delete :destroy, params: { id: backup_filename }, format: :json
expect(response).not_to be_successful
end
end
describe ".logs" do
it "preloads important data" do
BackupRestore.expects(:operations_status).returns({})
subject.expects(:store_preloaded).with("operations_status", "{}")
BackupRestore.expects(:logs).returns([])
subject.expects(:store_preloaded).with("logs", "[]")
get :logs, format: :html, xhr: true
expect(response.status).to eq(200)
end
end
describe ".restore" do
it "starts a restore" do
expect(SiteSetting.disable_emails).to eq("no")
BackupRestore.expects(:restore!).with(@admin.id, filename: backup_filename, publish_to_message_bus: true, client_id: "foo")
post :restore, params: { id: backup_filename, client_id: "foo" }, format: :json
expect(SiteSetting.disable_emails).to eq("yes")
expect(response.status).to eq(200)
end
end
describe ".readonly" do
it "enables readonly mode" do
Discourse.expects(:enable_readonly_mode)
expect { put :readonly, params: { enable: true }, format: :json }
.to change { UserHistory.count }.by(1)
expect(response.status).to eq(200)
user_history = UserHistory.last
expect(UserHistory.last.action).to eq(UserHistory.actions[:change_readonly_mode])
expect(UserHistory.last.new_value).to eq('t')
end
it "disables readonly mode" do
Discourse.expects(:disable_readonly_mode)
expect { put :readonly, params: { enable: false }, format: :json }
.to change { UserHistory.count }.by(1)
expect(response.status).to eq(200)
user_history = UserHistory.last
expect(UserHistory.last.action).to eq(UserHistory.actions[:change_readonly_mode])
expect(UserHistory.last.new_value).to eq('f')
end
end
describe "#upload_backup_chunk" do
describe "when filename contains invalid characters" do
it "should raise an error" do
['灰色.tar.gz', '; echo \'haha\'.tar.gz'].each do |invalid_filename|
described_class.any_instance.expects(:has_enough_space_on_disk?).returns(true)
post :upload_backup_chunk, params: {
resumableFilename: invalid_filename, resumableTotalSize: 1
}
expect(response.status).to eq(415)
expect(response.body).to eq(I18n.t('backup.invalid_filename'))
end
end
end
describe "when filename is valid" do
it "should upload the file successfully" do
begin
described_class.any_instance.expects(:has_enough_space_on_disk?).returns(true)
filename = 'test_Site-0123456789.tar.gz'
post :upload_backup_chunk, params: {
resumableFilename: filename,
resumableTotalSize: 1,
resumableIdentifier: 'test',
resumableChunkNumber: '1',
resumableChunkSize: '1',
resumableCurrentChunkSize: '1',
file: fixture_file_upload(Tempfile.new)
}, format: :json
expect(response.status).to eq(200)
expect(response.body).to eq("")
ensure
begin
File.delete(
File.join(Backup.base_directory, 'tmp', 'test', "#{filename}.part1")
)
rescue Errno::ENOENT
end
end
end
end
end
end
end