2014-10-10 20:04:07 +02:00
require " backup_restore/backup_restore "
2014-02-12 20:33:21 -08:00
class Admin :: BackupsController < Admin :: AdminController
2014-05-28 01:44:37 +05:30
skip_before_filter :check_xhr , only : [ :index , :show , :logs , :check_backup_chunk , :upload_backup_chunk ]
2014-02-12 20:33:21 -08:00
def index
respond_to do | format |
format . html do
store_preloaded ( " backups " , MultiJson . dump ( serialize_data ( Backup . all , BackupSerializer ) ) )
store_preloaded ( " operations_status " , MultiJson . dump ( BackupRestore . operations_status ) )
2014-02-13 10:41:46 -08:00
store_preloaded ( " logs " , MultiJson . dump ( BackupRestore . logs ) )
2014-02-12 20:33:21 -08:00
render " default/empty "
end
format . json do
render_serialized ( Backup . all , BackupSerializer )
end
end
end
def status
render_json_dump ( BackupRestore . operations_status )
end
def create
2014-08-20 18:48:56 +02:00
opts = {
publish_to_message_bus : true ,
2015-08-27 20:02:13 +02:00
with_uploads : params . fetch ( :with_uploads ) == " true " ,
client_id : params [ :client_id ] ,
2014-08-20 18:48:56 +02:00
}
BackupRestore . backup! ( current_user . id , opts )
2014-02-12 20:33:21 -08:00
rescue BackupRestore :: OperationRunningError
render json : failed_json . merge ( message : I18n . t ( " backup.operation_already_running " ) )
else
2016-02-27 23:08:24 +05:30
StaffActionLogger . new ( current_user ) . log_backup_operation
2014-02-12 20:33:21 -08:00
render json : success_json
end
def cancel
BackupRestore . cancel!
rescue BackupRestore :: OperationRunningError
render json : failed_json . merge ( message : I18n . t ( " backup.operation_already_running " ) )
else
render json : success_json
end
# download
def show
filename = params . fetch ( :id )
if backup = Backup [ filename ]
2014-09-23 09:25:53 +10:00
headers [ 'Content-Length' ] = File . size ( backup . path )
2014-02-12 20:33:21 -08:00
send_file backup . path
else
render nothing : true , status : 404
end
end
def destroy
2014-03-11 17:28:12 -04:00
backup = Backup [ params . fetch ( :id ) ]
if backup
backup . remove
render nothing : true
else
render nothing : true , status : 404
end
2014-02-12 20:33:21 -08:00
end
def logs
store_preloaded ( " operations_status " , MultiJson . dump ( BackupRestore . operations_status ) )
2014-02-13 10:41:46 -08:00
store_preloaded ( " logs " , MultiJson . dump ( BackupRestore . logs ) )
2014-02-12 20:33:21 -08:00
render " default/empty "
end
def restore
2015-08-27 20:02:13 +02:00
opts = {
filename : params . fetch ( :id ) ,
client_id : params . fetch ( :client_id ) ,
publish_to_message_bus : true ,
}
2016-06-24 17:14:47 -04:00
SiteSetting . set_and_log ( :disable_emails , true , current_user )
2015-08-27 20:02:13 +02:00
BackupRestore . restore! ( current_user . id , opts )
2014-02-12 20:33:21 -08:00
rescue BackupRestore :: OperationRunningError
render json : failed_json . merge ( message : I18n . t ( " backup.operation_already_running " ) )
else
render json : success_json
end
def rollback
BackupRestore . rollback!
rescue BackupRestore :: OperationRunningError
render json : failed_json . merge ( message : I18n . t ( " backup.operation_already_running " ) )
else
render json : success_json
end
def readonly
enable = params . fetch ( :enable ) . to_s == " true "
2016-06-29 14:19:18 +08:00
enable ? Discourse . enable_readonly_mode ( user_enabled : true ) : Discourse . disable_readonly_mode ( user_enabled : true )
2014-02-12 20:33:21 -08:00
render nothing : true
end
2014-05-28 01:44:37 +05:30
def check_backup_chunk
2014-02-22 01:41:01 +01:00
identifier = params . fetch ( :resumableIdentifier )
filename = params . fetch ( :resumableFilename )
chunk_number = params . fetch ( :resumableChunkNumber )
current_chunk_size = params . fetch ( :resumableCurrentChunkSize ) . to_i
# path to chunk file
chunk = Backup . chunk_path ( identifier , filename , chunk_number )
2014-05-28 01:44:37 +05:30
# check chunk upload status
status = HandleChunkUpload . check_chunk ( chunk , current_chunk_size : current_chunk_size )
2014-02-22 01:41:01 +01:00
render nothing : true , status : status
end
2014-05-28 01:44:37 +05:30
def upload_backup_chunk
2014-02-26 19:38:06 +01:00
filename = params . fetch ( :resumableFilename )
total_size = params . fetch ( :resumableTotalSize ) . to_i
2015-04-07 15:26:47 +02:00
return render status : 415 , text : I18n . t ( " backup.backup_file_should_be_tar_gz " ) unless / \ .(tar \ .gz|t?gz)$ /i =~ filename
2014-02-26 19:38:06 +01:00
return render status : 415 , text : I18n . t ( " backup.not_enough_space_on_disk " ) unless has_enough_space_on_disk? ( total_size )
2014-02-22 01:41:01 +01:00
file = params . fetch ( :file )
identifier = params . fetch ( :resumableIdentifier )
chunk_number = params . fetch ( :resumableChunkNumber ) . to_i
chunk_size = params . fetch ( :resumableChunkSize ) . to_i
current_chunk_size = params . fetch ( :resumableCurrentChunkSize ) . to_i
# path to chunk file
chunk = Backup . chunk_path ( identifier , filename , chunk_number )
2014-05-28 01:44:37 +05:30
# upload chunk
HandleChunkUpload . upload_chunk ( chunk , file : file )
2014-02-22 01:41:01 +01:00
uploaded_file_size = chunk_number * chunk_size
# when all chunks are uploaded
if uploaded_file_size + current_chunk_size > = total_size
# merge all the chunks in a background thread
2016-03-03 12:01:13 +01:00
Jobs . enqueue_in ( 5 . seconds , :backup_chunks_merger , filename : filename , identifier : identifier , chunks : chunk_number )
2014-02-22 01:41:01 +01:00
end
render nothing : true
end
2014-02-26 19:38:06 +01:00
private
def has_enough_space_on_disk? ( size )
2015-01-27 08:25:32 +11:00
` df -Pk #{ Rails . root } /public/backups | awk 'NR==2 {print $4 * 1024;}' ` . to_i > size
2014-02-26 19:38:06 +01:00
end
2014-02-12 20:33:21 -08:00
end