mirror of
https://github.com/PhyreApps/PhyrePanel.git
synced 2024-11-22 07:30:25 +00:00
Compare commits
26 commits
716a9ba1f1
...
023560c09d
Author | SHA1 | Date | |
---|---|---|---|
|
023560c09d | ||
|
726f151d8a | ||
|
6184a6dcc3 | ||
|
77f6e11350 | ||
|
8db638d4f5 | ||
|
8fece790aa | ||
|
4cc2fbb40d | ||
|
70b51841eb | ||
|
2327b7d1ad | ||
|
971a7b3b19 | ||
|
4129a0875a | ||
|
c0678b17fa | ||
|
aecf11c084 | ||
|
a1359933e0 | ||
|
ee4587f81d | ||
|
35d8bf58a5 | ||
|
28a9f2392d | ||
|
093ac611b7 | ||
|
489ae3ee08 | ||
|
d738974329 | ||
|
fc6aac0f53 | ||
|
33adbec9e4 | ||
|
13b5e89f81 | ||
|
98efa1b42c | ||
|
e1d7d50a1f | ||
|
f8f0460bb9 |
29 changed files with 295 additions and 157 deletions
3
.github/workflows/app-code-coverage.yml
vendored
3
.github/workflows/app-code-coverage.yml
vendored
|
@ -10,7 +10,7 @@ jobs:
|
|||
matrix:
|
||||
os: [ubuntu-22.04]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: hetzner-${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
|
@ -65,6 +65,7 @@ jobs:
|
|||
|
||||
cd /usr/local/phyre/web/
|
||||
sudo chmod -R 777 vendor
|
||||
apt install composer -y
|
||||
composer test:coverage
|
||||
|
||||
- name: Code Cov
|
||||
|
|
2
.github/workflows/app-unit-test.yml
vendored
2
.github/workflows/app-unit-test.yml
vendored
|
@ -11,7 +11,7 @@ jobs:
|
|||
#os: [ubuntu-24.04, ubuntu-22.04, ubuntu-20.04]
|
||||
os: [ubuntu-22.04]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: hetzner-${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
|
|
|
@ -98,7 +98,7 @@ RUN cp .env.example .env \
|
|||
&& sed -i "s/^DB_USERNAME=.*/DB_USERNAME=$PANEL_DB_USER/" .env \
|
||||
&& sed -i "s/^DB_PASSWORD=.*/DB_PASSWORD=$PANEL_DB_PASSWORD/" .env \
|
||||
&& sed -i "s/^DB_CONNECTION=.*/DB_CONNECTION=mysql/" .env \
|
||||
&& sed -i "s/^MYSQl_ROOT_USERNAME=.*/MYSQl_ROOT_USERNAME=$MYSQL_ROOT_USERNAME/" .env \
|
||||
&& sed -i "s/^MYSQL_ROOT_USERNAME=.*/MYSQL_ROOT_USERNAME=$MYSQL_ROOT_USERNAME/" .env \
|
||||
&& sed -i "s/^MYSQL_ROOT_PASSWORD=.*/MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD/" .env
|
||||
|
||||
# Generate application key and migrate database
|
||||
|
|
|
@ -130,7 +130,7 @@ sed -i "s/^DB_USERNAME=.*/DB_USERNAME=$PANEL_DB_USER/" .env
|
|||
sed -i "s/^DB_PASSWORD=.*/DB_PASSWORD=$PANEL_DB_PASSWORD/" .env
|
||||
sed -i "s/^DB_CONNECTION=.*/DB_CONNECTION=mysql/" .env
|
||||
|
||||
sed -i "s/^MYSQl_ROOT_USERNAME=.*/MYSQl_ROOT_USERNAME=$MYSQL_ROOT_USERNAME/" .env
|
||||
sed -i "s/^MYSQL_ROOT_USERNAME=.*/MYSQL_ROOT_USERNAME=$MYSQL_ROOT_USERNAME/" .env
|
||||
sed -i "s/^MYSQL_ROOT_PASSWORD=.*/MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD/" .env
|
||||
|
||||
phyre-php artisan key:generate
|
||||
|
|
|
@ -54,7 +54,7 @@ sed -i "s/^DB_USERNAME=.*/DB_USERNAME=$PHYRE_PANEL_DB_USER/" .env
|
|||
sed -i "s/^DB_PASSWORD=.*/DB_PASSWORD=$PHYRE_PANEL_DB_PASSWORD/" .env
|
||||
sed -i "s/^DB_CONNECTION=.*/DB_CONNECTION=mysql/" .env
|
||||
|
||||
sed -i "s/^MYSQl_ROOT_USERNAME=.*/MYSQl_ROOT_USERNAME=$MYSQL_PHYRE_ROOT_USERNAME/" .env
|
||||
sed -i "s/^MYSQL_ROOT_USERNAME=.*/MYSQL_ROOT_USERNAME=$MYSQL_PHYRE_ROOT_USERNAME/" .env
|
||||
sed -i "s/^MYSQL_ROOT_PASSWORD=.*/MYSQL_ROOT_PASSWORD=$MYSQL_PHYRE_ROOT_PASSWORD/" .env
|
||||
|
||||
phyre-php artisan key:generate
|
||||
|
|
|
@ -135,7 +135,7 @@ sed -i "s/^DB_USERNAME=.*/DB_USERNAME=$PHYRE_PANEL_DB_USER/" .env
|
|||
sed -i "s/^DB_PASSWORD=.*/DB_PASSWORD=$PHYRE_PANEL_DB_PASSWORD/" .env
|
||||
sed -i "s/^DB_CONNECTION=.*/DB_CONNECTION=mysql/" .env
|
||||
|
||||
sed -i "s/^MYSQl_ROOT_USERNAME=.*/MYSQl_ROOT_USERNAME=$MYSQL_PHYRE_ROOT_USERNAME/" .env
|
||||
sed -i "s/^MYSQL_ROOT_USERNAME=.*/MYSQL_ROOT_USERNAME=$MYSQL_PHYRE_ROOT_USERNAME/" .env
|
||||
sed -i "s/^MYSQL_ROOT_PASSWORD=.*/MYSQL_ROOT_PASSWORD=$MYSQL_PHYRE_ROOT_PASSWORD/" .env
|
||||
|
||||
phyre-php artisan key:generate
|
||||
|
|
|
@ -54,7 +54,7 @@ sed -i "s/^DB_USERNAME=.*/DB_USERNAME=$PHYRE_PANEL_DB_USER/" .env
|
|||
sed -i "s/^DB_PASSWORD=.*/DB_PASSWORD=$PHYRE_PANEL_DB_PASSWORD/" .env
|
||||
sed -i "s/^DB_CONNECTION=.*/DB_CONNECTION=mysql/" .env
|
||||
|
||||
sed -i "s/^MYSQl_ROOT_USERNAME=.*/MYSQl_ROOT_USERNAME=$MYSQL_PHYRE_ROOT_USERNAME/" .env
|
||||
sed -i "s/^MYSQL_ROOT_USERNAME=.*/MYSQL_ROOT_USERNAME=$MYSQL_PHYRE_ROOT_USERNAME/" .env
|
||||
sed -i "s/^MYSQL_ROOT_PASSWORD=.*/MYSQL_ROOT_PASSWORD=$MYSQL_PHYRE_ROOT_PASSWORD/" .env
|
||||
|
||||
phyre-php artisan key:generate
|
||||
|
|
|
@ -137,7 +137,7 @@ sed -i "s/^DB_USERNAME=.*/DB_USERNAME=$PHYRE_PANEL_DB_USER/" .env
|
|||
sed -i "s/^DB_PASSWORD=.*/DB_PASSWORD=$PHYRE_PANEL_DB_PASSWORD/" .env
|
||||
sed -i "s/^DB_CONNECTION=.*/DB_CONNECTION=mysql/" .env
|
||||
|
||||
sed -i "s/^MYSQl_ROOT_USERNAME=.*/MYSQl_ROOT_USERNAME=$MYSQL_PHYRE_ROOT_USERNAME/" .env
|
||||
sed -i "s/^MYSQL_ROOT_USERNAME=.*/MYSQL_ROOT_USERNAME=$MYSQL_PHYRE_ROOT_USERNAME/" .env
|
||||
sed -i "s/^MYSQL_ROOT_PASSWORD=.*/MYSQL_ROOT_PASSWORD=$MYSQL_PHYRE_ROOT_PASSWORD/" .env
|
||||
|
||||
phyre-php artisan key:generate
|
||||
|
|
|
@ -17,7 +17,7 @@ DB_PASSWORD=
|
|||
|
||||
MYSQL_HOST=127.0.0.1
|
||||
MYSQL_PORT=3306
|
||||
MYSQl_ROOT_USERNAME=root
|
||||
MYSQL_ROOT_USERNAME=root
|
||||
MYSQL_ROOT_PASSWORD=root
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
|
|
47
web/app/BackupStorage.php
Normal file
47
web/app/BackupStorage.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use App\Models\Domain;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class BackupStorage
|
||||
{
|
||||
public static function getPath()
|
||||
{
|
||||
$rootPath = '/var/lib/phyre/backups/system';
|
||||
$customBackupPath = setting('general.backup_path');
|
||||
if (!empty($customBackupPath)) {
|
||||
$rootPath = $customBackupPath;
|
||||
}
|
||||
return $rootPath;
|
||||
}
|
||||
|
||||
public static function getInstance($path = false)
|
||||
{
|
||||
$rootPath = self::getPath();
|
||||
if ($path) {
|
||||
$rootPath = $path;
|
||||
}
|
||||
|
||||
$storageBuild = Storage::build([
|
||||
'driver' => 'local',
|
||||
'throw' => false,
|
||||
'root' => $rootPath,
|
||||
]);
|
||||
$storageBuild->buildTemporaryUrlsUsing(function ($path, $expiration, $options) use($rootPath) {
|
||||
return URL::temporarySignedRoute(
|
||||
'backup.download',
|
||||
$expiration,
|
||||
array_merge($options, [
|
||||
'path' => $path,
|
||||
'root_path' => $rootPath,
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
return $storageBuild;
|
||||
}
|
||||
}
|
|
@ -4,11 +4,16 @@ namespace App\Console\Commands;
|
|||
|
||||
use App\Models\Backup;
|
||||
use App\Models\HostingSubscription;
|
||||
use App\Models\HostingSubscriptionBackup;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
|
||||
|
||||
class CreateDailyFullHostingSubscriptionsBackup extends Command
|
||||
{
|
||||
/**
|
||||
|
@ -30,7 +35,27 @@ class CreateDailyFullHostingSubscriptionsBackup extends Command
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
// Find Hosting Subscriptions
|
||||
$findHostingSubscriptions = HostingSubscription::all();
|
||||
if ($findHostingSubscriptions->count() > 0) {
|
||||
foreach ($findHostingSubscriptions as $hostingSubscription) {
|
||||
|
||||
$findBackup = HostingSubscriptionBackup::where('hosting_subscription_id', $hostingSubscription->id)
|
||||
->where('backup_type', 'full')
|
||||
->where('created_at', '>=', Carbon::now()->subHours(24))
|
||||
->first();
|
||||
if (! $findBackup) {
|
||||
$backup = new HostingSubscriptionBackup();
|
||||
$backup->hosting_subscription_id = $hostingSubscription->id;
|
||||
$backup->backup_type = 'full';
|
||||
$backup->save();
|
||||
|
||||
} else {
|
||||
$this->error('Backup already exists for ' . $hostingSubscription->domain);
|
||||
$this->error('Created before: ' . $findBackup->created_at->diffForHumans());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,28 +37,6 @@ class RunHostingSubscriptionsBackupChecks extends Command
|
|||
$backup->delete();
|
||||
}
|
||||
|
||||
// // Find Hosting Subscriptions
|
||||
// $findHostingSubscriptions = HostingSubscription::all();
|
||||
// if ($findHostingSubscriptions->count() > 0) {
|
||||
// foreach ($findHostingSubscriptions as $hostingSubscription) {
|
||||
//
|
||||
// $findBackup = HostingSubscriptionBackup::where('hosting_subscription_id', $hostingSubscription->id)
|
||||
// ->where('backup_type', 'full')
|
||||
// ->where('created_at', '>=', Carbon::now()->subHours(24))
|
||||
// ->first();
|
||||
// if (! $findBackup) {
|
||||
// $backup = new HostingSubscriptionBackup();
|
||||
// $backup->hosting_subscription_id = $hostingSubscription->id;
|
||||
// $backup->backup_type = 'full';
|
||||
// $backup->save();
|
||||
// } else {
|
||||
// $this->error('Backup already exists for ' . $hostingSubscription->domain);
|
||||
// $this->error('Created before: ' . $findBackup->created_at->diffForHumans());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// Check for pending backups
|
||||
$getPendingBackups = HostingSubscriptionBackup::where('status', 'pending')
|
||||
->get();
|
||||
|
|
|
@ -10,7 +10,9 @@ use Filament\Forms\Components\Tabs;
|
|||
use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Get;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Outerweb\FilamentSettings\Filament\Pages\Settings as BaseSettings;
|
||||
use Symfony\Component\Console\Input\Input;
|
||||
|
||||
class Settings extends BaseSettings
|
||||
{
|
||||
|
@ -29,6 +31,7 @@ class Settings extends BaseSettings
|
|||
|
||||
public function schema(): array|Closure
|
||||
{
|
||||
|
||||
return [
|
||||
Tabs::make('Settings')
|
||||
->schema([
|
||||
|
@ -57,6 +60,12 @@ class Settings extends BaseSettings
|
|||
Textarea::make('general.domain_suspend_page_html'),
|
||||
Textarea::make('general.domain_created_page_html'),
|
||||
]),
|
||||
|
||||
Tabs\Tab::make('Backups')
|
||||
->schema([
|
||||
TextInput::make('general.backup_path')
|
||||
->default(Storage::path('backups'))
|
||||
]),
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\BackupStorage;
|
||||
use App\Filament\Enums\BackupStatus;
|
||||
use App\Filament\Enums\BackupType;
|
||||
use App\Filament\Resources\BackupResource\Pages;
|
||||
|
@ -101,10 +102,15 @@ class BackupResource extends Resource
|
|||
->actions([
|
||||
Tables\Actions\Action::make('download')
|
||||
->icon('heroicon-o-arrow-down-tray')
|
||||
->hidden(function (Backup $backup) {
|
||||
return $backup->status !== BackupStatus::Completed;
|
||||
})
|
||||
->action(function (Backup $backup) {
|
||||
$url = Storage::disk('backups')
|
||||
->temporaryUrl($backup->filepath, Carbon::now()->addMinutes(5));
|
||||
return redirect($url);
|
||||
|
||||
$backupStorage = BackupStorage::getInstance($backup->root_path);
|
||||
$tempUrl = $backupStorage->temporaryUrl($backup->file_name, Carbon::now()->addMinutes(5));
|
||||
|
||||
return redirect($tempUrl);
|
||||
}),
|
||||
Tables\Actions\ViewAction::make(),
|
||||
])
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace app\Filament\Resources\BackupResource\Widgets;
|
||||
|
||||
use App\BackupStorage;
|
||||
use App\Filament\Resources\BackupResource\Pages\ListBackups;
|
||||
use App\Filament\Resources\Shop\OrderResource\Pages\ListOrders;
|
||||
use App\Models\Backup;
|
||||
|
@ -31,7 +32,7 @@ class BackupStats extends BaseWidget
|
|||
}
|
||||
}
|
||||
$usedSpace = 0;
|
||||
$backupPath = storage_path('backups');
|
||||
$backupPath = BackupStorage::getPath();
|
||||
if (is_dir($backupPath)) {
|
||||
$usedSpace = $this->getDirectorySize($backupPath);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace app\Filament\Resources\HostingSubscriptionResource\Pages;
|
||||
|
||||
use App\BackupStorage;
|
||||
use App\Filament\Enums\BackupStatus;
|
||||
use App\Filament\Enums\HostingSubscriptionBackupType;
|
||||
use App\Filament\Resources\Blog\PostResource;
|
||||
use App\Filament\Resources\HostingSubscriptionResource;
|
||||
|
@ -18,6 +20,7 @@ use Filament\Resources\Pages\ManageRelatedRecords;
|
|||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Contracts\Support\Htmlable;
|
||||
use Illuminate\Support\Carbon;
|
||||
use JaOcero\RadioDeck\Forms\Components\RadioDeck;
|
||||
|
||||
class ManageHostingSubscriptionBackups extends ManageRelatedRecords
|
||||
|
@ -126,6 +129,18 @@ class ManageHostingSubscriptionBackups extends ManageRelatedRecords
|
|||
//
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\Action::make('download')
|
||||
->icon('heroicon-o-arrow-down-tray')
|
||||
->hidden(function (HostingSubscriptionBackup $backup) {
|
||||
return $backup->status !== BackupStatus::Completed;
|
||||
})
|
||||
->action(function (HostingSubscriptionBackup $backup) {
|
||||
|
||||
$backupStorage = BackupStorage::getInstance($backup->root_path);
|
||||
$tempUrl = $backupStorage->temporaryUrl($backup->file_name, Carbon::now()->addMinutes(5));
|
||||
|
||||
return redirect($tempUrl);
|
||||
}),
|
||||
Tables\Actions\ViewAction::make(),
|
||||
// Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\DeleteAction::make(),
|
||||
|
|
|
@ -4,6 +4,15 @@ namespace App;
|
|||
|
||||
class Helpers
|
||||
{
|
||||
public static function extractZip($tarFile, $extractPath)
|
||||
{
|
||||
shell_exec('mkdir -p ' . $extractPath);
|
||||
|
||||
$exec = shell_exec('unzip -o ' . $tarFile . ' -d ' . $extractPath);
|
||||
|
||||
return $exec;
|
||||
}
|
||||
|
||||
public static function extractTar($tarFile, $extractPath)
|
||||
{
|
||||
shell_exec('mkdir -p ' . $extractPath);
|
||||
|
|
|
@ -3,6 +3,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\BackupStorage;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
|
@ -19,7 +20,9 @@ class BackupDownloadController extends Controller
|
|||
return response('Invalid URL provided');
|
||||
}
|
||||
|
||||
return Storage::disk('backups')->download($request->get('path'));
|
||||
$backupStorage = BackupStorage::getInstance($request->get('root_path'));
|
||||
return $backupStorage->download($request->get('path'));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,12 +46,16 @@ class MasterDomain
|
|||
|
||||
$apacheBaseConfig = $apacheVirtualHostBuilder->buildConfig();
|
||||
|
||||
shell_exec('mkdir -p /var/www/logs/apache2');
|
||||
shell_exec('touch /var/www/logs/apache2/bytes.log');
|
||||
shell_exec('touch /var/www/logs/apache2/access.log');
|
||||
shell_exec('touch /var/www/logs/apache2/error.log');
|
||||
|
||||
if (!empty($apacheBaseConfig)) {
|
||||
file_put_contents('/etc/apache2/sites-available/'.$this->domain.'.conf', $apacheBaseConfig);
|
||||
shell_exec('ln -s /etc/apache2/sites-available/'.$this->domain.'-default.conf /etc/apache2/sites-enabled/'.$this->domain.'-default.conf');
|
||||
}
|
||||
|
||||
|
||||
// install SSL
|
||||
$findDomainSSLCertificate = null;
|
||||
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\BackupStorage;
|
||||
use App\Filament\Enums\BackupStatus;
|
||||
use App\Helpers;
|
||||
use App\ShellApi;
|
||||
use Dotenv\Dotenv;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Jackiedo\DotenvEditor\Facades\DotenvEditor;
|
||||
|
@ -87,7 +89,6 @@ class Backup extends Model
|
|||
public function checkBackup()
|
||||
{
|
||||
if ($this->status == BackupStatus::Processing) {
|
||||
|
||||
$backupDoneFile = $this->path.'/backup.done';
|
||||
if (file_exists($backupDoneFile)) {
|
||||
|
||||
|
@ -96,7 +97,7 @@ class Backup extends Model
|
|||
mkdir($tempValidatePath);
|
||||
}
|
||||
|
||||
shell_exec('cd '.$tempValidatePath.' && unzip -o '.Storage::disk('backups')->path($this->filepath));
|
||||
shell_exec('cd '.$tempValidatePath.' && unzip -o '.$this->file_path);
|
||||
|
||||
$validateDatabaseFile = $tempValidatePath.'/database.sql';
|
||||
$validateEnvFile = $tempValidatePath.'/.env';
|
||||
|
@ -110,6 +111,7 @@ class Backup extends Model
|
|||
}
|
||||
if (count($errorsBag) > 0) {
|
||||
$this->status = 'failed';
|
||||
$this->backup_log = 'Backup failed. Database or env file missing.';
|
||||
$this->save();
|
||||
return [
|
||||
'status' => 'failed',
|
||||
|
@ -125,6 +127,7 @@ class Backup extends Model
|
|||
|
||||
if (count($errorsBag) > 0) {
|
||||
$this->status = 'failed';
|
||||
$this->backup_log = 'Backup failed. Database or env file content mismatch.';
|
||||
$this->save();
|
||||
return [
|
||||
'status' => 'failed',
|
||||
|
@ -134,13 +137,17 @@ class Backup extends Model
|
|||
}
|
||||
|
||||
ShellApi::safeDelete($this->path,[
|
||||
Storage::path('backups')
|
||||
$this->root_path
|
||||
]);
|
||||
ShellApi::safeDelete($this->temp_path,[
|
||||
$this->root_path
|
||||
]);
|
||||
|
||||
$this->size = filesize(Storage::disk('backups')->path($this->filepath));
|
||||
$this->size = filesize($this->file_path);
|
||||
$this->status = 'completed';
|
||||
$this->completed = true;
|
||||
$this->completed_at = now();
|
||||
$this->backup_log = 'Backup completed';
|
||||
$this->save();
|
||||
|
||||
return [
|
||||
|
@ -152,7 +159,9 @@ class Backup extends Model
|
|||
$checkProcess = shell_exec('ps -p ' . $this->process_id . ' | grep ' . $this->process_id);
|
||||
if (Str::contains($checkProcess, $this->process_id)) {
|
||||
|
||||
|
||||
$this->size = Helpers::checkPathSize($this->path);
|
||||
$this->backup_log = file_get_contents($this->path.'/backup.log');
|
||||
$this->save();
|
||||
|
||||
return [
|
||||
|
@ -160,6 +169,7 @@ class Backup extends Model
|
|||
'message' => 'Backup is still processing'
|
||||
];
|
||||
} else {
|
||||
$this->backup_log = 'Backup failed. Process not found';
|
||||
$this->status = 'failed';
|
||||
$this->save();
|
||||
return [
|
||||
|
@ -179,20 +189,11 @@ class Backup extends Model
|
|||
];
|
||||
}
|
||||
|
||||
$storagePath = Storage::path('backups');
|
||||
if (! is_dir($storagePath)) {
|
||||
mkdir($storagePath);
|
||||
}
|
||||
$storagePath = BackupStorage::getPath();
|
||||
$backupPath = $storagePath.'/'.$this->id;
|
||||
if (!is_dir(dirname($backupPath))) {
|
||||
mkdir(dirname($backupPath));
|
||||
}
|
||||
if (! is_dir($backupPath)) {
|
||||
mkdir($backupPath);
|
||||
}
|
||||
$backupTempPath = $backupPath.'/temp';
|
||||
if (! is_dir($backupTempPath)) {
|
||||
mkdir($backupTempPath);
|
||||
shell_exec('mkdir -p '.$backupTempPath);
|
||||
}
|
||||
|
||||
$backupFilename = 'phyre-backup-'.date('Ymd-His').'.zip';
|
||||
|
@ -211,7 +212,13 @@ class Backup extends Model
|
|||
$shellFileContent .= 'echo "Backup Phyre Panel files"'. PHP_EOL;
|
||||
|
||||
// Export Phyre Panel database
|
||||
$shellFileContent .= 'mysqldump -u "'.env('MYSQl_ROOT_USERNAME').'" -p"'.env('MYSQL_ROOT_PASSWORD').'" "'.env('DB_DATABASE').'" > '.$databaseBackupPath . PHP_EOL;
|
||||
$mysqlAuthConf = '/root/.phyre-mysql.cnf';
|
||||
$mysqlAuthContent = '[client]' . PHP_EOL;
|
||||
$mysqlAuthContent .= 'user="' . env('MYSQL_ROOT_USERNAME') .'"'. PHP_EOL;
|
||||
$mysqlAuthContent .= 'password="' . env('MYSQL_ROOT_PASSWORD') . '"' . PHP_EOL;
|
||||
file_put_contents($mysqlAuthConf, $mysqlAuthContent);
|
||||
|
||||
$shellFileContent .= 'mysqldump --defaults-extra-file='.$mysqlAuthConf.' "'.env('DB_DATABASE').'" > '.$databaseBackupPath . PHP_EOL;
|
||||
|
||||
// Export Phyre Panel ENV
|
||||
$getEnv = Dotenv::createArrayBacked(base_path())->load();
|
||||
|
@ -226,11 +233,14 @@ class Backup extends Model
|
|||
$findHostingSubscription = HostingSubscription::all();
|
||||
if ($findHostingSubscription->count() > 0) {
|
||||
foreach ($findHostingSubscription as $hostingSubscription) {
|
||||
$hostingSubscriptionPath = $backupTempPath .'/hosting_subscriptions/'.$hostingSubscription->system_username;
|
||||
$hostingSubscriptionsMainPath = $backupTempPath .'/hosting_subscriptions';
|
||||
$hostingSubscriptionPath = $hostingSubscriptionsMainPath .'/'. $hostingSubscription->system_username;
|
||||
$shellFileContent .= PHP_EOL;
|
||||
$shellFileContent .= 'echo "Backup up hosting subscription: ' . $hostingSubscription->system_username .'" '. PHP_EOL;
|
||||
$shellFileContent .= 'mkdir -p '.$hostingSubscriptionPath.PHP_EOL;
|
||||
$shellFileContent .= 'cp -r /home/'.$hostingSubscription->system_username.'/* .[^.]* ' . $hostingSubscriptionPath .PHP_EOL;
|
||||
|
||||
// cp -r (copy recursively, also copy hidden files)
|
||||
$shellFileContent .= 'cp -r /home/'.$hostingSubscription->system_username.'/ ' . $hostingSubscriptionsMainPath .PHP_EOL;
|
||||
|
||||
$shellFileContent .= 'mkdir -p '.$hostingSubscriptionPath.'/databases'.PHP_EOL;
|
||||
|
||||
|
@ -246,7 +256,7 @@ class Backup extends Model
|
|||
$databaseName = $database->database_name_prefix . $database->database_name;
|
||||
$shellFileContent .= 'echo "Backup up database: ' . $databaseName . '" ' . PHP_EOL;
|
||||
$databaseBackupPath = $hostingSubscriptionPath . '/databases/' . $databaseName . '.sql';
|
||||
$shellFileContent .= 'mysqldump -u "' . env('MYSQl_ROOT_USERNAME') . '" -p"' . env('MYSQL_ROOT_PASSWORD') . '" "' . $databaseName . '" > ' . $databaseBackupPath . PHP_EOL;
|
||||
$shellFileContent .= 'mysqldump --defaults-extra-file='.$mysqlAuthConf.' "' . $databaseName . '" > ' . $databaseBackupPath . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,7 +264,8 @@ class Backup extends Model
|
|||
}
|
||||
}
|
||||
|
||||
$shellFileContent .= 'cd '.$backupTempPath .' && zip -r '.$backupFilePath.' ./* .[^.]* '. PHP_EOL;
|
||||
// With find, we can search for all files,directories (including hidden) in the current directory and zip them
|
||||
$shellFileContent .= 'cd '.$backupTempPath .' && find . -exec zip -r '.$backupFilePath.' {} \;'. PHP_EOL;
|
||||
|
||||
$shellFileContent .= 'rm -rf '.$backupTempPath.PHP_EOL;
|
||||
$shellFileContent .= 'echo "Backup complete"' . PHP_EOL;
|
||||
|
@ -269,11 +280,16 @@ class Backup extends Model
|
|||
if ($processId > 0 && is_numeric($processId)) {
|
||||
|
||||
$this->path = $backupPath;
|
||||
$this->filepath = $backupFilename;
|
||||
$this->root_path = $storagePath;
|
||||
$this->temp_path = $backupTempPath;
|
||||
$this->file_path = $backupFilePath;
|
||||
$this->file_name = $backupFilename;
|
||||
|
||||
$this->status = 'processing';
|
||||
$this->queued = true;
|
||||
$this->queued_at = now();
|
||||
$this->process_id = $processId;
|
||||
|
||||
$this->save();
|
||||
|
||||
return [
|
||||
|
|
|
@ -62,7 +62,7 @@ class Database extends Model
|
|||
$universalDatabaseExecutor = new UniversalDatabaseExecutor(
|
||||
env('MYSQL_HOST'),
|
||||
env('MYSQL_PORT'),
|
||||
env('MYSQl_ROOT_USERNAME'),
|
||||
env('MYSQL_ROOT_USERNAME'),
|
||||
env('MYSQL_ROOT_PASSWORD'),
|
||||
);
|
||||
$createDatabase = $universalDatabaseExecutor->createDatabase($databaseName);
|
||||
|
|
|
@ -58,7 +58,7 @@ class DatabaseUser extends Model
|
|||
$universalDatabaseExecutor = new UniversalDatabaseExecutor(
|
||||
env('MYSQL_HOST'),
|
||||
env('MYSQL_PORT'),
|
||||
env('MYSQl_ROOT_USERNAME'),
|
||||
env('MYSQL_ROOT_USERNAME'),
|
||||
env('MYSQL_ROOT_PASSWORD'),
|
||||
$findDatabase->database_name_prefix . $findDatabase->database_name
|
||||
);
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\BackupStorage;
|
||||
use App\Filament\Enums\BackupStatus;
|
||||
use App\Helpers;
|
||||
use App\ShellApi;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
@ -33,16 +35,16 @@ class HostingSubscriptionBackup extends Model
|
|||
'status' => BackupStatus::class,
|
||||
];
|
||||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::addGlobalScope('customer', function (Builder $query) {
|
||||
if (auth()->check() && auth()->guard()->name == 'web_customer') {
|
||||
$query->whereHas('hostingSubscription', function ($query) {
|
||||
$query->where('customer_id', auth()->user()->id);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// protected static function booted(): void
|
||||
// {
|
||||
// static::addGlobalScope('customer', function (Builder $query) {
|
||||
// if (auth()->check() && auth()->guard()->name == 'web_customer') {
|
||||
// $query->whereHas('hostingSubscription', function ($query) {
|
||||
// $query->where('customer_id', auth()->user()->id);
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
@ -57,9 +59,9 @@ class HostingSubscriptionBackup extends Model
|
|||
});
|
||||
|
||||
static::deleting(function ($model) {
|
||||
if (is_file($model->filepath)) {
|
||||
shell_exec('rm -rf ' . $model->filepath);
|
||||
}
|
||||
// if (is_file($model->filepath)) {
|
||||
// shell_exec('rm -rf ' . $model->filepath);
|
||||
// }
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -67,6 +69,7 @@ class HostingSubscriptionBackup extends Model
|
|||
{
|
||||
$cronJobCommand = 'phyre-php /usr/local/phyre/web/artisan phyre:run-hosting-subscriptions-backup-checks';
|
||||
$findCronJob = CronJob::where('command', $cronJobCommand)->first();
|
||||
|
||||
if (! $findCronJob) {
|
||||
$cronJob = new CronJob();
|
||||
$cronJob->schedule = '*/5 * * * *';
|
||||
|
@ -93,6 +96,7 @@ class HostingSubscriptionBackup extends Model
|
|||
$findHostingSubscription = HostingSubscription::select(['id'])
|
||||
->where('id', $this->hosting_subscription_id)
|
||||
->first();
|
||||
|
||||
if (! $findHostingSubscription) {
|
||||
$this->delete();
|
||||
return [
|
||||
|
@ -103,16 +107,23 @@ class HostingSubscriptionBackup extends Model
|
|||
|
||||
if ($this->status == BackupStatus::Processing) {
|
||||
|
||||
$backupDoneFile = $this->path.'/backup-'.$this->id.'.done';
|
||||
if (file_exists($backupDoneFile)) {
|
||||
$backupDoneFile = $this->path.'/backup.done';
|
||||
$backupZipFile = $this->file_path;
|
||||
|
||||
$this->size = Helpers::checkPathSize($this->path);
|
||||
if (file_exists($backupDoneFile) && file_exists($backupZipFile)) {
|
||||
|
||||
$this->size = filesize($this->file_path);
|
||||
$this->status = 'completed';
|
||||
$this->completed = true;
|
||||
$this->completed_at = now();
|
||||
$this->save();
|
||||
|
||||
shell_exec('rm -rf ' . $backupDoneFile);
|
||||
ShellApi::safeDelete($this->path,[
|
||||
$this->root_path
|
||||
]);
|
||||
ShellApi::safeDelete($this->temp_path,[
|
||||
$this->root_path
|
||||
]);
|
||||
|
||||
return [
|
||||
'status' => 'completed',
|
||||
|
@ -123,7 +134,7 @@ class HostingSubscriptionBackup extends Model
|
|||
$checkProcess = shell_exec('ps -p ' . $this->process_id . ' | grep ' . $this->process_id);
|
||||
if (Str::contains($checkProcess, $this->process_id)) {
|
||||
|
||||
$this->size = Helpers::checkPathSize($this->path);
|
||||
$this->size = Helpers::checkPathSize($this->temp_path);
|
||||
$this->save();
|
||||
|
||||
return [
|
||||
|
@ -170,32 +181,37 @@ class HostingSubscriptionBackup extends Model
|
|||
];
|
||||
}
|
||||
|
||||
$storagePath = storage_path('backups');
|
||||
$backupPath = $storagePath.'/hosting_subscriptions/'.$this->backup_type.'/'.$this->id;
|
||||
$backupStorageRootPath = '/var/lib/phyre/backups/hosting_subscriptions';
|
||||
$backupPath = $backupStorageRootPath . '/' . $findHostingSubscription->customer_id;
|
||||
|
||||
$backupTempPath = $backupPath.'/temp';
|
||||
shell_exec('mkdir -p ' . $backupTempPath);
|
||||
|
||||
$backupFileName = Str::slug($findHostingSubscription->system_username .'-'. date('Ymd-His')) . '.zip';
|
||||
$backupFilePath = $backupStorageRootPath.'/'.$backupFileName;
|
||||
|
||||
$backupFileName = Str::slug($findHostingSubscription->system_username .'-'. date('Ymd-His')) . '.tar.gz';
|
||||
$backupFilePath = $backupPath.'/'.$backupFileName;
|
||||
|
||||
$backupLogFileName = 'backup.log';
|
||||
$backupLogFilePath = $backupPath.'/'.$backupLogFileName;
|
||||
|
||||
$backupTargetPath = $findMainDomain->domain_root . '/backups';
|
||||
$backupTargetFilePath = $backupTargetPath.'/'.$backupFileName;
|
||||
$backupLogFilePath = $backupPath.'/backup.log';
|
||||
|
||||
$backupTempScript = '/tmp/backup-script-'.$this->id.'.sh';
|
||||
$shellFileContent = '';
|
||||
$shellFileContent .= 'mkdir -p '. $backupTargetPath.PHP_EOL;
|
||||
$shellFileContent .= 'echo "Backup up domain: '.$findHostingSubscription->domain .'"'. PHP_EOL;
|
||||
$shellFileContent .= 'echo "Backup up user: '.$findHostingSubscription->system_username .'"'. PHP_EOL;
|
||||
$shellFileContent .= 'echo "Backup filename: '.$backupFileName.'"' . PHP_EOL;
|
||||
|
||||
if ($this->backup_type == 'full') {
|
||||
$shellFileContent .= 'cp -r /home/' . $findHostingSubscription->system_username . ' ' . $backupTempPath . PHP_EOL;
|
||||
$shellFileContent .= 'rsync -azP '. $backupTempPath . '/' . $findHostingSubscription->system_username . '/ ' . $backupTempPath . PHP_EOL;
|
||||
$shellFileContent .= 'rm -rf '. $backupTempPath . '/' . $findHostingSubscription->system_username . '/' . PHP_EOL;
|
||||
}
|
||||
|
||||
if ($this->backup_type == 'full' || $this->backup_type == 'database') {
|
||||
|
||||
// Export Phyre Panel database
|
||||
$mysqlAuthConf = '/root/.phyre-mysql.cnf';
|
||||
$mysqlAuthContent = '[client]' . PHP_EOL;
|
||||
$mysqlAuthContent .= 'user="' . env('MYSQL_ROOT_USERNAME') .'"'. PHP_EOL;
|
||||
$mysqlAuthContent .= 'password="' . env('MYSQL_ROOT_PASSWORD') . '"' . PHP_EOL;
|
||||
file_put_contents($mysqlAuthConf, $mysqlAuthContent);
|
||||
|
||||
$getDatabases = Database::where('hosting_subscription_id', $findHostingSubscription->id)
|
||||
->where(function ($query) {
|
||||
$query->where('is_remote_database_server', '0')
|
||||
|
@ -205,30 +221,23 @@ class HostingSubscriptionBackup extends Model
|
|||
|
||||
if ($getDatabases->count() > 0) {
|
||||
foreach ($getDatabases as $database) {
|
||||
// $findDatabaseUser = DatabaseUser::where('database_id', $database->id)
|
||||
// ->first();
|
||||
// if (!$findDatabaseUser) {
|
||||
// continue;
|
||||
// }
|
||||
$databaseName = $database->database_name_prefix . $database->database_name;
|
||||
// $databaseUser = $findDatabaseUser->username_prefix . $findDatabaseUser->username;
|
||||
// $databaseUserPassword = $findDatabaseUser->password;
|
||||
|
||||
$shellFileContent .= 'echo "Backup up database: ' . $databaseName .'" '. PHP_EOL;
|
||||
// $shellFileContent .= 'echo "Backup up database user: ' . $databaseUser .'" '. PHP_EOL;
|
||||
$databaseBackupPath = $backupTempPath . '/' . $databaseName . '.sql';
|
||||
$shellFileContent .= 'mysqldump -u "'.env('MYSQl_ROOT_USERNAME').'" -p"'.env('MYSQL_ROOT_PASSWORD').'" "'.$databaseName.'" > '.$databaseBackupPath . PHP_EOL;
|
||||
$shellFileContent .= 'mkdir -p '.$backupTempPath . '/databases' . PHP_EOL;
|
||||
$databaseBackupPath = $backupTempPath . '/databases/' . $databaseName . '.sql';
|
||||
$shellFileContent .= 'mysqldump --defaults-extra-file='.$mysqlAuthConf.' "'.$databaseName.'" > '.$databaseBackupPath . PHP_EOL;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$shellFileContent .= 'cd '.$backupTempPath .' && tar -czvf '.$backupFilePath.' ./* '. PHP_EOL;
|
||||
// With find, we can search for all files,directories (including hidden) in the current directory and zip them
|
||||
$shellFileContent .= 'cd '.$backupTempPath .' && find . -exec zip -r '.$backupFilePath.' {} \;'. PHP_EOL;
|
||||
|
||||
$shellFileContent .= 'rm -rf '.$backupTempPath.PHP_EOL;
|
||||
$shellFileContent .= 'echo "Backup complete"' . PHP_EOL;
|
||||
$shellFileContent .= 'touch ' . $backupTargetPath. '/backup-'.$this->id.'.done' . PHP_EOL;
|
||||
$shellFileContent .= 'mv '.$backupFilePath.' '. $backupTargetFilePath.PHP_EOL;
|
||||
$shellFileContent .= 'touch ' . $backupPath. '/backup.done' . PHP_EOL;
|
||||
$shellFileContent .= 'rm -rf ' . $backupTempScript . PHP_EOL;
|
||||
|
||||
file_put_contents($backupTempScript, $shellFileContent);
|
||||
|
@ -238,8 +247,12 @@ class HostingSubscriptionBackup extends Model
|
|||
|
||||
if ($processId > 0 && is_numeric($processId)) {
|
||||
|
||||
$this->path = $findMainDomain->domain_root . '/backups';
|
||||
$this->filepath = $backupTargetFilePath;
|
||||
$this->path = $backupPath;
|
||||
$this->root_path = $backupStorageRootPath;
|
||||
$this->temp_path = $backupTempPath;
|
||||
$this->file_path = $backupFilePath;
|
||||
$this->file_name = $backupFileName;
|
||||
|
||||
$this->status = 'processing';
|
||||
$this->queued = true;
|
||||
$this->queued_at = now();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\BackupStorage;
|
||||
use App\Events\ModelDomainCreated;
|
||||
use App\Events\ModelDomainDeleting;
|
||||
use App\Events\ModelHostingSubscriptionCreated;
|
||||
|
@ -16,7 +17,9 @@ use App\Models\HostingSubscription;
|
|||
use App\Policies\CustomerPolicy;
|
||||
use BladeUI\Icons\Factory;
|
||||
use Filament\Facades\Filament;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
@ -32,15 +35,6 @@ class AppServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function register(): void
|
||||
{
|
||||
// This allows us to generate a temporary url for backups downloading
|
||||
Storage::disk('backups')->buildTemporaryUrlsUsing(function ($path, $expiration, $options) {
|
||||
return URL::temporarySignedRoute(
|
||||
'backup.download',
|
||||
$expiration,
|
||||
array_merge($options, ['path' => $path])
|
||||
);
|
||||
});
|
||||
|
||||
// Register Phyre Icons set
|
||||
$this->callAfterResolving(Factory::class, function (Factory $factory) {
|
||||
$factory->add('phyre', [
|
||||
|
@ -72,16 +66,5 @@ class AppServiceProvider extends ServiceProvider
|
|||
|
||||
Gate::define('delete-customer', [CustomerPolicy::class, 'delete']);
|
||||
|
||||
if (is_file(storage_path('installed'))) {
|
||||
$getDomains = Domain::all();
|
||||
if ($getDomains->count() > 0) {
|
||||
foreach ($getDomains as $domain) {
|
||||
$this->app['config']["filesystems.disks.backups_" . Str::slug($domain->domain)] = [
|
||||
'driver' => 'local',
|
||||
'root' => $domain->domain_root . '/backups',
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,12 +44,6 @@ return [
|
|||
'throw' => false,
|
||||
],
|
||||
|
||||
'backups' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/backups'),
|
||||
'throw' => false,
|
||||
],
|
||||
|
||||
's3' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
|
|
|
@ -16,8 +16,14 @@ return new class extends Migration
|
|||
|
||||
$table->string('backup_type')->nullable();
|
||||
$table->string('status')->nullable();
|
||||
$table->string('backup_log')->nullable();
|
||||
|
||||
$table->string('path')->nullable();
|
||||
$table->string('filepath')->nullable();
|
||||
$table->string('root_path')->nullable();
|
||||
$table->string('temp_path')->nullable();
|
||||
$table->string('file_path')->nullable();
|
||||
$table->string('file_name')->nullable();
|
||||
|
||||
$table->string('size')->nullable();
|
||||
$table->string('disk')->nullable();
|
||||
$table->string('process_id')->nullable();
|
||||
|
|
|
@ -17,8 +17,14 @@ return new class extends Migration
|
|||
$table->bigInteger('hosting_subscription_id')->nullable();
|
||||
$table->string('backup_type')->nullable();
|
||||
$table->string('status')->nullable();
|
||||
$table->string('backup_log')->nullable();
|
||||
|
||||
$table->string('path')->nullable();
|
||||
$table->string('filepath')->nullable();
|
||||
$table->string('root_path')->nullable();
|
||||
$table->string('temp_path')->nullable();
|
||||
$table->string('file_path')->nullable();
|
||||
$table->string('file_name')->nullable();
|
||||
|
||||
$table->string('size')->nullable();
|
||||
$table->string('disk')->nullable();
|
||||
$table->string('process_id')->nullable();
|
||||
|
|
|
@ -28,20 +28,25 @@ class BackupTest extends ActionTestCase
|
|||
$this->assertNotEmpty($findLastBackup->created_at);
|
||||
$this->assertSame($findLastBackup->backup_type, 'full');
|
||||
|
||||
|
||||
$backupFinished = false;
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
$findLastBackup = Backup::orderBy('id', 'desc')->first();
|
||||
$findLastBackup->checkBackup();
|
||||
|
||||
Artisan::call('phyre:run-backup-checks');
|
||||
|
||||
$findLastBackup = Backup::where('id', $findLastBackup->id)->first();
|
||||
if ($findLastBackup->status == BackupStatus::Completed) {
|
||||
$backupFinished = true;
|
||||
break;
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
|
||||
$this->assertTrue($backupFinished);
|
||||
$this->assertSame($findLastBackup->status, BackupStatus::Completed);
|
||||
$this->assertNotEmpty($findLastBackup->filepath);
|
||||
$this->assertTrue(file_exists(Storage::disk('backups')->path($findLastBackup->filepath)));
|
||||
$this->assertNotEmpty($findLastBackup->file_path);
|
||||
$this->assertTrue(file_exists($findLastBackup->file_path));
|
||||
|
||||
$backup = new Backup();
|
||||
$checkCronJob = $backup->checkCronJob();
|
||||
|
@ -81,24 +86,36 @@ class BackupTest extends ActionTestCase
|
|||
$findBackup = false;
|
||||
$backupCompleted = false;
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
|
||||
Artisan::call('phyre:run-backup-checks');
|
||||
|
||||
$findBackup = Backup::where('id', $backupId)->first();
|
||||
$findBackup->checkBackup();
|
||||
if ($findBackup->status == BackupStatus::Completed) {
|
||||
$backupCompleted = true;
|
||||
break;
|
||||
}
|
||||
if ($findBackup->status == BackupStatus::Failed) {
|
||||
$this->fail('Backup failed: '.$findBackup->backup_log);
|
||||
break;
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
if (!$backupCompleted) {
|
||||
$findBackup = Backup::where('id', $backupId)->first();
|
||||
$this->fail('Backup not completed: '.$findBackup->backup_log);
|
||||
}
|
||||
|
||||
$this->assertTrue($backupCompleted);
|
||||
$this->assertNotEmpty($findBackup->filepath);
|
||||
$this->assertTrue(file_exists(Storage::disk('backups')->path($findBackup->filepath)));
|
||||
$this->assertNotEmpty($findBackup->file_path);
|
||||
$this->assertTrue(file_exists($findBackup->file_path));
|
||||
|
||||
$getFilesize = filesize(Storage::disk('backups')->path($findBackup->filepath));
|
||||
$getFilesize = filesize($findBackup->file_path);
|
||||
$this->assertGreaterThan(0, $getFilesize);
|
||||
$this->assertSame($getFilesize, $findBackup->size);
|
||||
$this->assertSame($getFilesize, intval($findBackup->size));
|
||||
|
||||
Helpers::extractTar(Storage::disk('backups')->path($findBackup->filepath), $findBackup->path . '/unit-test');
|
||||
Helpers::extractZip($findBackup->file_path, $findBackup->path . '/unit-test');
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ class HostingSubscriptionBackupTest extends ActionTestCase
|
|||
|
||||
$chs = $this->_createHostingSubscription();
|
||||
|
||||
Artisan::call('phyre:run-hosting-subscriptions-backup');
|
||||
Artisan::call('phyre:create-daily-full-hosting-subscriptions-backup');
|
||||
|
||||
$findLastBackup = HostingSubscriptionBackup::where('hosting_subscription_id', $chs['hostingSubscriptionId'])
|
||||
->first();
|
||||
|
@ -39,20 +39,23 @@ class HostingSubscriptionBackupTest extends ActionTestCase
|
|||
$this->assertSame($findLastBackup->backup_type, 'full');
|
||||
|
||||
$backupFinished = false;
|
||||
for ($i = 0; $i < 50; $i++) {
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
|
||||
Artisan::call('phyre:run-hosting-subscriptions-backup-checks');
|
||||
|
||||
$findLastBackup = HostingSubscriptionBackup::where('id', $findLastBackup->id)->first();
|
||||
$findLastBackup->checkBackup();
|
||||
if ($findLastBackup->status == BackupStatus::Completed) {
|
||||
$backupFinished = true;
|
||||
break;
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
$this->assertTrue($backupFinished);
|
||||
$this->assertSame($findLastBackup->status, BackupStatus::Completed);
|
||||
$this->assertNotEmpty($findLastBackup->filepath);
|
||||
$this->assertTrue(file_exists($findLastBackup->filepath));
|
||||
$this->assertNotEmpty($findLastBackup->file_path);
|
||||
$this->assertTrue(file_exists($findLastBackup->file_path));
|
||||
|
||||
$backup = new HostingSubscriptionBackup();
|
||||
$checkCronJob = $backup->checkCronJob();
|
||||
|
@ -69,10 +72,12 @@ class HostingSubscriptionBackupTest extends ActionTestCase
|
|||
|
||||
$findBackup = false;
|
||||
$backupCompleted = false;
|
||||
for ($i = 0; $i < 50; $i++) {
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
|
||||
Artisan::call('phyre:run-hosting-subscriptions-backup-checks');
|
||||
|
||||
$findBackup = HostingSubscriptionBackup::where('id', $backupId)->first();
|
||||
if ($findBackup) {
|
||||
$status = $findBackup->checkBackup();
|
||||
if ($findBackup->status == BackupStatus::Completed) {
|
||||
$backupCompleted = true;
|
||||
break;
|
||||
|
@ -82,19 +87,19 @@ class HostingSubscriptionBackupTest extends ActionTestCase
|
|||
}
|
||||
|
||||
$this->assertTrue($backupCompleted);
|
||||
$this->assertNotEmpty($findBackup->filepath);
|
||||
$this->assertTrue(file_exists($findBackup->filepath));
|
||||
$this->assertNotEmpty($findBackup->file_path);
|
||||
$this->assertTrue(file_exists($findBackup->file_path));
|
||||
|
||||
$getFilesize = filesize($findBackup->filepath);
|
||||
$getFilesize = filesize($findBackup->file_path);
|
||||
$this->assertGreaterThan(0, $getFilesize);
|
||||
$this->assertSame(Helpers::checkPathSize($findBackup->path), $findBackup->size);
|
||||
$this->assertSame($getFilesize, intval($findBackup->size));
|
||||
|
||||
Helpers::extractTar($findBackup->filepath, $findBackup->path . '/unit-test');
|
||||
Helpers::extractZip($findBackup->file_path, $findBackup->path . '/unit-test');
|
||||
//
|
||||
// dd($chs);
|
||||
$findDatabase = Database::where('id', $chs['databaseId'])->first();
|
||||
|
||||
$extractedDatabase = $findBackup->path . '/unit-test/' . $findDatabase->database_name_prefix . $findDatabase->database_name . '.sql';
|
||||
$extractedDatabase = $findBackup->path . '/unit-test/databases/' . $findDatabase->database_name_prefix . $findDatabase->database_name . '.sql';
|
||||
|
||||
$this->assertTrue(file_exists($extractedDatabase));
|
||||
$extractedDatabaseContent = file_get_contents($extractedDatabase);
|
||||
$this->assertNotEmpty($extractedDatabaseContent);
|
||||
|
|
Loading…
Reference in a new issue