Skip to content

Commit 7f610eb

Browse files
committed
Initial commit
0 parents  commit 7f610eb

19 files changed

+1318
-0
lines changed

.DS_Store

6 KB
Binary file not shown.

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto

README.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
2+
# 📦 Laravel Backup Package
3+
4+
A simple Laravel package to automatically **backup your database and storage directory**, with a Blade-based UI to view, download, and delete backups.
5+
6+
---
7+
8+
## 🚀 Features
9+
10+
- 🔄 Daily backup of database and storage (`storage/app/public`)
11+
- 🧼 Auto-delete backups older than configurable days (default 5 days)
12+
- 🧾 List, download, and delete backups via Blade UI
13+
- 👤 Access control using roles and middleware
14+
- 🛠 Configurable via `config/laravelBackup.php`
15+
16+
---
17+
18+
## 📥 Installation
19+
20+
Install the package via composer:
21+
22+
```bash
23+
composer require avcodewizard/laravel-backup
24+
```
25+
---
26+
27+
## ⚙️ Configuration
28+
29+
Edit the config file at: `config/laravelBackup.php`
30+
31+
```php
32+
return [
33+
'backup_path' => storage_path('backups'),
34+
'keep_days' => 5, // Automatically delete backups older than 5 days
35+
'backup_storage_directory' => false, // true or false
36+
'check_access' => false, // Enable/disable role-based access to UI
37+
'allowed_roles' => [], // Role Names Example: ['Admin', 'Super-Admin','Developer', 'Manager']
38+
];
39+
```
40+
- If you want's to backup storage directory
41+
```
42+
'backup_storage_directory' => true, // true or false
43+
```
44+
45+
---
46+
47+
## 🛡️ Access Control
48+
49+
To enable UI access control based on user roles:
50+
51+
1. Set `'check_access' => true`
52+
2. Add roles in `'allowed_roles' => ['Admin']`
53+
3. Ensure your `User` model has a `hasRole()` method (e.g., using [spatie/laravel-permission](https://github.com/spatie/laravel-permission))
54+
55+
Middleware used:
56+
`Avcodewizard\LaravelBackup\Http\Middleware\CheckLaravelBackupAccess`
57+
58+
---
59+
60+
## 🖥️ Web Interface
61+
62+
Access the UI at:
63+
64+
```
65+
/laravel-backup
66+
```
67+
68+
Example route setup (already included in the package):
69+
70+
```php
71+
Route::prefix('laravel-backup')
72+
->middleware(['web', \Avcodewizard\LaravelBackup\Http\Middleware\CheckLaravelBackupAccess::class])
73+
->group(function () {
74+
Route::get('/', [BackupController::class, 'index'])->name('laravel-backup.index');
75+
Route::get('/create', [BackupController::class, 'create'])->name('laravel-backup.create');
76+
Route::get('/download', [BackupController::class, 'download'])->name('laravel-backup.download');
77+
Route::delete('/delete', [BackupController::class, 'delete'])->name('laravel-backup.delete');
78+
});
79+
```
80+
81+
---
82+
83+
## 🛠 Usage
84+
85+
### Create Backup via Web
86+
87+
1. Go to `/laravel-backup`
88+
2. Click **Create Backup**
89+
- If use want to create backup from ui, make sure to run the queue worker:
90+
```bash
91+
php artisan queue:work
92+
```
93+
94+
95+
### Create Backup via Terminal
96+
97+
```bash
98+
php artisan backup:run
99+
```
100+
101+
---
102+
103+
## 🧹 Automatic Cleanup
104+
105+
Backups older than `keep_days` will be deleted automatically.
106+
107+
### Add to Scheduler
108+
109+
In `app/Console/Kernel.php`, add:
110+
111+
```php
112+
$schedule->command('backup:run')->daily();
113+
```
114+
115+
---
116+
117+
## 📂 Backup Storage
118+
119+
Backups are saved in:
120+
121+
```
122+
storage/backups/
123+
```
124+
125+
Each backup includes:
126+
127+
- `YYYY-MM-DD-HH-MM-SS_database.sql`
128+
- `YYYY-MM-DD-HH-MM-SS_storage.zip`
129+
130+
---
131+
132+
## 🧑‍💻 Developer Notes
133+
134+
### Publish Config & Views
135+
136+
```bash
137+
php artisan vendor:publish --tag=laravel-backup
138+
```
139+
140+
This will publish:
141+
142+
- `config/laravelBackup.php`
143+
- Blade views to `resources/views/vendor/laravel-backup/`
144+
145+
146+
### Middleware Logic
147+
148+
The package uses a configurable middleware to restrict access:
149+
150+
```php
151+
if (!config('laravelBackup.check_access')) return $next($request);
152+
153+
$user = Auth::user();
154+
if (!$user) {
155+
abort(403, 'Unauthorized - no user authenticated.');
156+
}
157+
158+
if (!method_exists($user, 'hasRole')) {
159+
abort(403, 'User Role Not Implemented!');
160+
}
161+
162+
if (!$user->hasAnyRole(config('laravelBackup.allowed_roles'))) {
163+
abort(403, 'Unauthorized - insufficient permission.');
164+
}
165+
166+
return $next($request);
167+
```
168+
169+
You can customize access logic using roles or your own permission methods.
170+
171+
---
172+
173+
## 📄 License
174+
175+
This package is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
176+
177+
© 2025 [Avcodewizard](https://github.com/avcodewizard)

composer.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "avcodewizard/laravel-backup",
3+
"description": "A Laravel package for database and storage backup with auto-cleanup.",
4+
"keywords": ["laravel", "backup", "database backup", "storage backup","auto-backup", "auto-cleanup"],
5+
"type": "library",
6+
"license": "MIT",
7+
"version": "1.0.0",
8+
"autoload": {
9+
"psr-4": {
10+
"Avcodewizard\\LaravelBackup\\": "src/"
11+
}
12+
},
13+
"authors": [
14+
{
15+
"name": "Ankit Verma",
16+
"email": "ankitc4087@gmail.com"
17+
}
18+
],
19+
"require": {
20+
"php": ">=8.0",
21+
"illuminate/support": ">=10.0"
22+
},
23+
"extra": {
24+
"laravel": {
25+
"providers": [
26+
"Avcodewizard\\LaravelBackup\\BackupServiceProvider"
27+
]
28+
}
29+
},
30+
"minimum-stability": "dev"
31+
}

config/laravelBackup.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
return [
4+
'backup_path' => storage_path('backups'),
5+
'keep_days' => 5,
6+
'database' => [
7+
'connection' => env('DB_CONNECTION', 'mysql'),
8+
],
9+
'backup_storage_directory' => false, // true or false
10+
'check_access' => false, // true or false
11+
'allowed_roles' => [], // Role Names Example: ['Admin', 'Super-Admin','Developer', 'Manager']
12+
];

resources/views/backup_list.blade.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Backup Files</title>
8+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
9+
</head>
10+
11+
<body>
12+
<div class="container mt-5">
13+
14+
@if (session('success') || session('error'))
15+
<div class="alert alert-{{ session('success') ? 'success' : 'danger' }} alert-dismissible fade show"
16+
role="alert">
17+
{{ session('success') ?? session('error') }}
18+
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
19+
</div>
20+
21+
<script>
22+
setTimeout(function() {
23+
document.querySelector('.alert').style.display = 'none';
24+
}, 7000);
25+
</script>
26+
@endif
27+
<div class="d-flex justify-content-between align-items-center">
28+
<h2 class="mb-4">Backup Files</h2>
29+
<a href="{{ route('laravel-backup.create') }}" class="btn btn-primary mb-3">Create Backup</a>
30+
31+
</div>
32+
<table class="table table-bordered">
33+
<thead>
34+
<tr>
35+
<th>Timestamp</th>
36+
<th>Database Backup</th>
37+
@if (config('laravelBackup.backup_storage_directory'))
38+
<th>Storage Backup</th>
39+
@endif
40+
<th>Actions</th>
41+
</tr>
42+
</thead>
43+
<tbody>
44+
@foreach ($backups as $backup)
45+
<tr>
46+
<td>{{ $backup['timestamp'] }}</td>
47+
<td>
48+
@if ($backup['database'])
49+
<a href="{{ route('laravel-backup.download', ['file' => $backup['database']]) }}"
50+
class="btn btn-sm btn-primary">
51+
Download DB
52+
</a>
53+
@else
54+
N/A
55+
@endif
56+
</td>
57+
@if (config('laravelBackup.backup_storage_directory'))
58+
<td>
59+
@if ($backup['storage'])
60+
<a href="{{ route('laravel-backup.download', ['file' => $backup['storage']]) }}"
61+
class="btn btn-sm btn-success">
62+
Download Storage
63+
</a>
64+
@else
65+
N/A
66+
@endif
67+
</td>
68+
@endif
69+
<td>
70+
<form action="{{ route('laravel-backup.delete', ['timestamp' => $backup['timestamp']]) }}"
71+
method="POST">
72+
@csrf
73+
@method('DELETE')
74+
<button type="submit" class="btn btn-sm btn-danger">Delete</button>
75+
</form>
76+
</td>
77+
</tr>
78+
@endforeach
79+
</tbody>
80+
</table>
81+
</div>
82+
</body>
83+
84+
</html>

routes/web.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
use Avcodewizard\LaravelBackup\Http\Controllers\BackupController;
4+
use Illuminate\Support\Facades\Route;
5+
6+
$middleware = ['web',\Avcodewizard\LaravelBackup\Http\Middleware\CheckLaravelBackupAccess::class];
7+
8+
Route::prefix('laravel-backup')
9+
->middleware($middleware)
10+
->name('laravel-backup.')
11+
->group(function () {
12+
Route::get('/', [BackupController::class, 'index'])->name('index');
13+
Route::get('/create', [BackupController::class, 'create'])->name('create');
14+
Route::get('/download', [BackupController::class, 'download'])->name('download');
15+
Route::delete('/delete', [BackupController::class, 'delete'])->name('delete');
16+
});

src/BackupServiceProvider.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Avcodewizard\LaravelBackup;
4+
5+
use Illuminate\Support\ServiceProvider;
6+
use Avcodewizard\LaravelBackup\Commands\BackupCommand;
7+
8+
class BackupServiceProvider extends ServiceProvider
9+
{
10+
public function register()
11+
{
12+
$this->mergeConfigFrom(__DIR__.'/../config/laravelBackup.php', 'laravelBackup');
13+
}
14+
15+
public function boot()
16+
{
17+
$this->loadRoutesFrom(__DIR__.'/../routes/web.php');
18+
$this->loadViewsFrom(__DIR__.'/../resources/views', 'laravel-backup');
19+
20+
// Publish config file
21+
$this->publishes([
22+
__DIR__.'/../config/laravelBackup.php' => config_path('laravelBackup.php'),
23+
], 'laravel-backup');
24+
25+
// Register command
26+
if ($this->app->runningInConsole()) {
27+
$this->commands([
28+
BackupCommand::class,
29+
]);
30+
}
31+
}
32+
33+
// composer json
34+
// "repositories": [
35+
// {
36+
// "type": "path",
37+
// "url": "packages/avcodewizard/laravel-backup"
38+
// }
39+
// ],
40+
}

0 commit comments

Comments
 (0)