From 34557310abd813764a702d30f172ba7155559d52 Mon Sep 17 00:00:00 2001 From: Nafies Luthfi Date: Fri, 20 Oct 2017 22:02:16 +0800 Subject: [PATCH] Update database backup and restore system feature --- app/Entities/Backups/BackupsRepository.php | 92 ------------ app/Http/Controllers/BackupsController.php | 171 ++++++++++++---------- app/Http/Requests/Backups/BackupUploadRequest.php | 52 ------- app/Http/Requests/Backups/CreateRequest.php | 31 ---- app/Http/Requests/Backups/DeleteRequest.php | 31 ---- resources/lang/en/backup.php | 40 +++++ resources/views/backups/delete.blade.php | 21 --- resources/views/backups/forms.blade.php | 70 +++++++++ resources/views/backups/index.blade.php | 95 ++++++------ resources/views/backups/restore.blade.php | 22 --- routes/web.php | 13 +- routes/web/backup.php | 14 -- 12 files changed, 258 insertions(+), 394 deletions(-) delete mode 100755 app/Entities/Backups/BackupsRepository.php delete mode 100644 app/Http/Requests/Backups/BackupUploadRequest.php delete mode 100644 app/Http/Requests/Backups/CreateRequest.php delete mode 100644 app/Http/Requests/Backups/DeleteRequest.php create mode 100644 resources/lang/en/backup.php delete mode 100755 resources/views/backups/delete.blade.php create mode 100644 resources/views/backups/forms.blade.php mode change 100755 => 100644 resources/views/backups/index.blade.php delete mode 100755 resources/views/backups/restore.blade.php delete mode 100644 routes/web/backup.php diff --git a/app/Entities/Backups/BackupsRepository.php b/app/Entities/Backups/BackupsRepository.php deleted file mode 100755 index d69c1aa..0000000 --- a/app/Entities/Backups/BackupsRepository.php +++ /dev/null @@ -1,92 +0,0 @@ -storageType = 'local'; - $this->storage = Storage::disk($this->storageType); - } - - public function getAllFiles() - { - $backups = \File::allFiles(storage_path('app/backup/db')); - - // Sort files by modified time DESC - usort($backups, function($a, $b) { - return -1 * strcmp($a->getMTime(), $b->getMTime()); - }); - - return $backups; - } - - public function create($backupData) - { - $manager = app()->make(Manager::class); - $fileName = $backupData['file_name'] ?: date('Y-m-d_Hi'); - try { - $manager->makeBackup()->run('mysql', [ - new Destination($this->storageType, 'backup/db/' . $fileName) - ], 'gzip'); - - return $fileName; - - } catch (FileExistsException $e) { - flash()->error('Database tidak dapat dibackup dengan Nama File yang sama.'); - return false; - } - } - - public function restore($fileName) - { - try { - $manager = app()->make(Manager::class); - $manager->makeRestore()->run($this->storageType, 'backup/db/' . $fileName, 'mysql', 'gzip'); - return true; - - } catch (FileNotFoundException $e) { - flash()->error('Tidak dapat mengembalikan Database.'); - return false; - } - } - - public function delete($fileName) - { - if ($this->storage->has('backup/db/' . $fileName)) { - $this->storage->delete('backup/db/' . $fileName); - - return true; - } - - return false; - } - - public function proccessBackupFileUpload($req) - { - $file = $req->file('backup_file'); - - if ($this->storage->has('backup/db/' . $file->getClientOriginalName())) { - flash()->error('Upload file gagal, terdapat Nama File yang sama.'); - return false; - } - - $result = $this->storage->put('backup/db/' . $file->getClientOriginalName(), file_get_contents($file)); - - return $result; - } -} \ No newline at end of file diff --git a/app/Http/Controllers/BackupsController.php b/app/Http/Controllers/BackupsController.php index e8408bb..757f0f5 100755 --- a/app/Http/Controllers/BackupsController.php +++ b/app/Http/Controllers/BackupsController.php @@ -2,83 +2,98 @@ namespace App\Http\Controllers; -use App\Http\Requests\Backups\CreateRequest; -use App\Http\Requests\Backups\BackupUploadRequest; -use App\Http\Requests\Backups\DeleteRequest; -use App\Http\Controllers\Controller; -use App\Entities\Backups\BackupsRepository; - +use App\Http\Requests\BackupUploadRequest; +use BackupManager\Filesystems\Destination; +use BackupManager\Manager; use Illuminate\Http\Request; - -class BackupsController extends Controller { - - private $repo; - - public function __construct(BackupsRepository $repo) - { - $this->repo = $repo; - } - - public function index(Request $req) - { - $backups = $this->repo->getAllFiles(); - return view('backups.index',compact('backups')); - } - - public function restore($fileName) - { - return view('backups.restore', compact('fileName')); - } - - public function postRestore(Request $req, $fileName) - { - $result = $this->repo->restore($fileName); - - if ($result) - flash()->success('Database berhasil dikembalikan dengan file ' . $fileName); - - return redirect()->route('backups.index'); - } - - public function store(CreateRequest $req) - { - $fileName = $this->repo->create($req->except('_token')); - - if ($fileName) - flash()->success('Backup berhasil dilakukan, nama File : ' . $fileName); - - return redirect()->route('backups.index'); - } - - public function delete($fileName) - { - return view('backups.delete', compact('fileName')); - } - - public function destroy(Request $req, $fileName) - { - $result = $this->repo->delete($fileName); - - if ($result) - flash()->success('File ' . $fileName . ' berhasil dihapus.'); - else - flash()->error('File ' . $fileName . ' gagal dihapus.'); - - return redirect()->route('backups.index'); - } - - public function upload(BackupUploadRequest $req) - { - $result = $this->repo->proccessBackupFileUpload($req); - if ($result) - flash()->success('Upload file berhasil.'); - - return redirect()->route('backups.index'); - } - - public function download($fileName) - { - return response()->download(storage_path('app') . '/backup/db/'.$fileName); - } - +use League\Flysystem\FileExistsException; +use League\Flysystem\FileNotFoundException; + +class BackupsController extends Controller +{ + public function index(Request $request) + { + if (!file_exists(storage_path('app/backup/db'))) { + $backups = []; + } else { + $backups = \File::allFiles(storage_path('app/backup/db')); + + // Sort files by modified time DESC + usort($backups, function ($a, $b) { + return -1 * strcmp($a->getMTime(), $b->getMTime()); + }); + } + + return view('backups.index', compact('backups')); + } + + public function store(Request $request) + { + $this->validate($request, [ + 'file_name' => 'nullable|max:30|regex:/^[\w._-]+$/', + ]); + + try { + $manager = app()->make(Manager::class); + $fileName = $request->get('file_name') ?: date('Y-m-d_Hi'); + + $manager->makeBackup()->run('mysql', [ + new Destination('local', 'backup/db/'.$fileName), + ], 'gzip'); + + flash(trans('backup.created', ['filename' => $fileName.'.gz']), 'success'); + + return redirect()->route('backups.index'); + } catch (FileExistsException $e) { + flash(trans('backup.not_created', ['filename' => $fileName.'.gz']), 'danger'); + + return redirect()->route('backups.index'); + } + } + + public function destroy($fileName) + { + if (file_exists(storage_path('app/backup/db/').$fileName)) { + unlink(storage_path('app/backup/db/').$fileName); + } + + flash(trans('backup.deleted', ['filename' => $fileName]), 'warning'); + return redirect()->route('backups.index'); + } + + public function download($fileName) + { + return response()->download(storage_path('app/backup/db/').$fileName); + } + + public function restore($fileName) + { + try { + $manager = app()->make(Manager::class); + $manager->makeRestore()->run('local', 'backup/db/'.$fileName, 'mysql', 'gzip'); + } catch (FileNotFoundException $e) { + } + + flash(trans('backup.restored', ['filename' => $fileName]), 'success'); + return redirect()->route('backups.index'); + } + + public function upload(Request $request) + { + $data = $request->validate([ + 'backup_file' => 'required|mimetypes:application/x-gzip', + ], [ + 'backup_file.mimetypes' => 'Invalid file type, must be .gz file', + ]); + + $file = $data['backup_file']; + $fileName = $file->getClientOriginalName(); + + if (file_exists(storage_path('app/backup/db/').$fileName) == false) { + $file->storeAs('backup/db', $fileName); + } + + flash(trans('backup.uploaded', ['filename' => $fileName]), 'success'); + return redirect()->route('backups.index'); + } } diff --git a/app/Http/Requests/Backups/BackupUploadRequest.php b/app/Http/Requests/Backups/BackupUploadRequest.php deleted file mode 100644 index 7ef5115..0000000 --- a/app/Http/Requests/Backups/BackupUploadRequest.php +++ /dev/null @@ -1,52 +0,0 @@ -user()->can('manage_backups'); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules() - { - return [ - 'backup_file' => 'required|sql_zip' - ]; - } - - public function messages() - { - return [ - 'file.sql_zip' => 'Isian file harus dokumen berjenis .zip, .gz atau .sql', - ]; - } - - protected function getValidatorInstance() - { - $validator = parent::getValidatorInstance(); - - $validator->addImplicitExtension('sql_zip', function($attribute, $value, $parameters) { - if ($value) - return in_array($value->getClientOriginalExtension(), ['zip','gz','sql']); - - return false; - }); - - return $validator; - } - -} diff --git a/app/Http/Requests/Backups/CreateRequest.php b/app/Http/Requests/Backups/CreateRequest.php deleted file mode 100644 index 0393567..0000000 --- a/app/Http/Requests/Backups/CreateRequest.php +++ /dev/null @@ -1,31 +0,0 @@ -user()->can('manage_backups'); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules() - { - return [ - 'file_name' => 'nullable|max:20|alpha_dash', - ]; - } - -} diff --git a/app/Http/Requests/Backups/DeleteRequest.php b/app/Http/Requests/Backups/DeleteRequest.php deleted file mode 100644 index 65526c9..0000000 --- a/app/Http/Requests/Backups/DeleteRequest.php +++ /dev/null @@ -1,31 +0,0 @@ -user()->can('manage_backups'); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules() - { - return [ - 'file_name' => 'required' - ]; - } - -} diff --git a/resources/lang/en/backup.php b/resources/lang/en/backup.php new file mode 100644 index 0000000..1fe2618 --- /dev/null +++ b/resources/lang/en/backup.php @@ -0,0 +1,40 @@ + 'Database Backup Manager', + 'list' => 'Backup File List', + 'file_name' => 'File Name', + 'file_size' => 'File Size', + 'created_at' => 'Created at', + 'actions' => 'Actions', + 'empty' => 'No backup file available.', + + // Create backup file + 'create' => 'Create Backup File', + 'created' => 'Backup file :filename created.', + 'not_created' => 'Backup file named :filename already exists.', + + // Delete backup file + 'delete' => 'Delete', + 'delete_title' => 'Delete this backup file', + 'sure_to_delete_file' => 'Are you sure to delete this file ":filename"?', + 'cancel_delete' => 'Cancel Delete', + 'confirm_delete' => 'YES, please delete this file!', + 'deleted' => 'Backup file :filename has been deleted!', + + // Download backup file + 'download' => 'Download', + + // Restore backup + 'restore' => 'Restore', + 'restore_title' => 'Restore database from file', + 'sure_to_restore' => 'Are you sure to restore database with this backup file ":filename"?

Please make sure your current database has been backed up.', + 'cancel_restore' => 'Cancel Restore', + 'confirm_restore' => 'YES, Restore Database!', + 'restored' => 'Database restored with backup file :filename', + + // Upload backup fle + 'upload' => 'Upload Backup File', + 'uploaded' => 'Backup file :filename uploaded.', +]; diff --git a/resources/views/backups/delete.blade.php b/resources/views/backups/delete.blade.php deleted file mode 100755 index 3348efe..0000000 --- a/resources/views/backups/delete.blade.php +++ /dev/null @@ -1,21 +0,0 @@ -@extends('layouts.app') - -@section('content') -
-
-
-

- Apakah anda yakin akan menghapus file backup "{{ $fileName }}" ini? -

-
- -
-@endsection \ No newline at end of file diff --git a/resources/views/backups/forms.blade.php b/resources/views/backups/forms.blade.php new file mode 100644 index 0000000..79bc354 --- /dev/null +++ b/resources/views/backups/forms.blade.php @@ -0,0 +1,70 @@ +@if (request('action') == 'delete' && Request::has('file_name')) +
+
+

@lang('backup.delete')

+
+
+

@lang('backup.sure_to_delete_file', ['filename' => request('file_name')])

+
+ +
+@endif +@if (request('action') == 'restore' && Request::has('file_name')) +
+

@lang('backup.restore')

+
+

@lang('backup.sure_to_restore', ['filename' => request('file_name')])

+
+ +
+@endif +@if (request('action') == null) +
+
+
+ {{ csrf_field() }} +
+ + + {!! $errors->first('file_name', '
:message
') !!} +
+
+ +
+
+
+
+ {{ csrf_field() }} +
+ + + {!! $errors->first('backup_file', '
:message
') !!} +
+
+ +
+
+
+
+@endif diff --git a/resources/views/backups/index.blade.php b/resources/views/backups/index.blade.php old mode 100755 new mode 100644 index 7a9f9d2..f812c34 --- a/resources/views/backups/index.blade.php +++ b/resources/views/backups/index.blade.php @@ -1,64 +1,57 @@ @extends('layouts.app') -@section('title','Daftar Backup Database Sistem') +@section('title',trans('backup.index_title')) @section('content') -

- Daftar Backup Database Sistem -

+ +
-

Daftar File Backup

-
- - - - - - - - - - @forelse($backups as $key => $backup) - - - - - - - - @empty - - - - @endforelse - -
#Nama FileUkuranTanggal Jam{{ trans('app.action') }}
{{ $key + 1 }}{{ $backup->getFilename() }}{{ formatSizeUnits($backup->getSize()) }}{{ date('Y-m-d H:i:s', $backup->getMTime()) }} - {!! link_to_route('backups.download','Download',[$backup->getFilename()],['class'=>'btn btn-default btn-xs','target' => '_blank']) !!} - {!! link_to_route('backups.restore','Restore',[$backup->getFilename()],['class'=>'btn btn-warning btn-xs']) !!} - {!! link_to_route('backups.delete','x',[$backup->getFilename()],['class'=>'btn btn-danger btn-xs']) !!} -
Belum ada file backup
-
+ + + + + + + + + + @forelse($backups as $key => $backup) + + + + + + + + @empty + + + + @endforelse + +
@lang('app.table_no')@lang('backup.file_name')@lang('backup.file_size')@lang('backup.created_at')@lang('backup.actions')
{{ $key + 1 }}{{ $backup->getFilename() }}{{ formatSizeUnits($backup->getSize()) }}{{ date('Y-m-d H:i:s', $backup->getMTime()) }} + @lang('backup.restore') + @lang('backup.download') + @lang('backup.delete') +
@lang('backup.empty')
-
-
- {!! Form::open(['route' => 'backups.store','class' => '']) !!} - {!! FormField::text('file_name', ['label' => 'Buat Backup Database', 'placeholder' => date('Y-m-d_Hi')]) !!} - {!! Form::submit('Buat Backup', ['class' => 'btn btn-success']) !!} - {!! Form::close() !!} - -
- - {!! Form::open(['route' => 'backups.upload','class' => '', 'files' => true]) !!} - {!! FormField::file('backup_file', ['label' => 'Upload File Backup','placeholder'=>'Pilih File']) !!} - {!! Form::submit('Upload', ['class' => 'btn btn-info']) !!} - {!! Form::close() !!} - -
-
+ @include('backups.forms')
@endsection diff --git a/resources/views/backups/restore.blade.php b/resources/views/backups/restore.blade.php deleted file mode 100755 index b12a541..0000000 --- a/resources/views/backups/restore.blade.php +++ /dev/null @@ -1,22 +0,0 @@ -@extends('layouts.app') - -@section('content') -
-
-
-

- Apakah anda yakin akan mengembalikan seluruh data sesuai file ini "{{ $fileName }}"?
- Pastikan data saat ini sudah dibackup. -

-
- -
-@endsection \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 972acf5..c9d6e72 100644 --- a/routes/web.php +++ b/routes/web.php @@ -6,11 +6,20 @@ require __DIR__ . '/web/pages.php'; require __DIR__ . '/web/users.php'; require __DIR__ . '/web/references.php'; require __DIR__ . '/web/account.php'; -require __DIR__ . '/web/backup.php'; require __DIR__ . '/web/projects.php'; require __DIR__ . '/web/payments.php'; require __DIR__ . '/web/subscriptions.php'; require __DIR__ . '/web/reports.php'; require __DIR__ . '/web/invoices.php'; require __DIR__ . '/web/options-vue.php'; -require __DIR__ . '/web/calendar.php'; \ No newline at end of file +require __DIR__ . '/web/calendar.php'; + +Route::group(['middleware' => ['web','role:admin']], function () { + /* + * Backup Restore Database Routes + */ + Route::post('backups/upload', ['as'=>'backups.upload', 'uses'=>'BackupsController@upload']); + Route::post('backups/{fileName}/restore', ['as'=>'backups.restore', 'uses'=>'BackupsController@restore']); + Route::get('backups/{fileName}/dl', ['as'=>'backups.download', 'uses'=>'BackupsController@download']); + Route::resource('backups', 'BackupsController', ['except' => ['create', 'show', 'edit']]); +}); diff --git a/routes/web/backup.php b/routes/web/backup.php deleted file mode 100644 index 4fc5a90..0000000 --- a/routes/web/backup.php +++ /dev/null @@ -1,14 +0,0 @@ - ['web','role:admin']], function() { - /** - * Backups Routes - */ - Route::get('backups/{fileName}/restore', ['as'=>'backups.restore', 'uses'=>'BackupsController@restore']); - Route::post('backups/{fileName}/restore', ['as'=>'backups.restore', 'uses'=>'BackupsController@postRestore']); - Route::get('backups/{fileName}/dl', ['as'=>'backups.download', 'uses'=>'BackupsController@download']); - Route::post('backups/upload', ['as'=>'backups.upload', 'uses'=>'BackupsController@upload']); - Route::get('backups/{id}/delete', ['as'=>'backups.delete', 'uses'=>'BackupsController@delete']); - Route::resource('backups','BackupsController'); - -});