mirror of
https://github.com/pelican-dev/panel.git
synced 2026-05-04 18:00:48 +03:00
Compare commits
9 Commits
lance/2026
...
lance/1022
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea978f3485 | ||
|
|
c8dcff2ee9 | ||
|
|
0579fd6df5 | ||
|
|
789c4c7284 | ||
|
|
b1a39f1724 | ||
|
|
6a548c09a0 | ||
|
|
55bda569cc | ||
|
|
adf1249086 | ||
|
|
dbf77bf146 |
@@ -2,11 +2,18 @@
|
|||||||
|
|
||||||
namespace App\Extensions\Filesystem;
|
namespace App\Extensions\Filesystem;
|
||||||
|
|
||||||
|
use Aws\CommandInterface;
|
||||||
|
use Aws\Result;
|
||||||
use Aws\S3\S3ClientInterface;
|
use Aws\S3\S3ClientInterface;
|
||||||
|
use GuzzleHttp\Client as GuzzleClient;
|
||||||
use League\Flysystem\AwsS3V3\AwsS3V3Adapter;
|
use League\Flysystem\AwsS3V3\AwsS3V3Adapter;
|
||||||
|
use RuntimeException;
|
||||||
|
use SimpleXMLElement;
|
||||||
|
|
||||||
class S3Filesystem extends AwsS3V3Adapter
|
class S3Filesystem extends AwsS3V3Adapter
|
||||||
{
|
{
|
||||||
|
private ?GuzzleClient $guzzle = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<mixed> $options
|
* @param array<mixed> $options
|
||||||
*/
|
*/
|
||||||
@@ -26,6 +33,18 @@ class S3Filesystem extends AwsS3V3Adapter
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getGuzzleClient(): GuzzleClient
|
||||||
|
{
|
||||||
|
if ($this->guzzle === null) {
|
||||||
|
$this->guzzle = new GuzzleClient([
|
||||||
|
'timeout' => 30,
|
||||||
|
'connect_timeout' => 10,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->guzzle;
|
||||||
|
}
|
||||||
|
|
||||||
public function getClient(): S3ClientInterface
|
public function getClient(): S3ClientInterface
|
||||||
{
|
{
|
||||||
return $this->client;
|
return $this->client;
|
||||||
@@ -35,4 +54,78 @@ class S3Filesystem extends AwsS3V3Adapter
|
|||||||
{
|
{
|
||||||
return $this->bucket;
|
return $this->bucket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute an S3 command using a presigned URL for maximum compatibility
|
||||||
|
* with S3-compatible providers.
|
||||||
|
*
|
||||||
|
* @return Result<array<string, mixed>>
|
||||||
|
*/
|
||||||
|
public function executeS3Command(CommandInterface $command): Result
|
||||||
|
{
|
||||||
|
$presignedRequest = $this->client->createPresignedRequest($command, '+60 minutes');
|
||||||
|
|
||||||
|
$response = $this->getGuzzleClient()->send($presignedRequest);
|
||||||
|
|
||||||
|
$body = (string) $response->getBody();
|
||||||
|
$commandName = $command->getName();
|
||||||
|
|
||||||
|
// S3's CompleteMultipartUpload can return HTTP 200 with an <Error> body
|
||||||
|
if ($body !== '' && str_contains($body, '<Error>')) {
|
||||||
|
throw new RuntimeException("S3 returned an error for $commandName: $body");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Result($this->parseS3Response($commandName, $body));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the XML response body based on the S3 command type.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
private function parseS3Response(string $commandName, string $body): array
|
||||||
|
{
|
||||||
|
if ($body === '') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$xml = @simplexml_load_string($body);
|
||||||
|
if ($xml === false) {
|
||||||
|
throw new RuntimeException("Failed to parse S3 XML response for $commandName: $body");
|
||||||
|
}
|
||||||
|
|
||||||
|
return match ($commandName) {
|
||||||
|
'CreateMultipartUpload' => $this->parseCreateMultipartUpload($xml),
|
||||||
|
'ListParts' => $this->parseListParts($xml),
|
||||||
|
'CompleteMultipartUpload' => [],
|
||||||
|
default => [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{UploadId: string}
|
||||||
|
*/
|
||||||
|
private function parseCreateMultipartUpload(SimpleXMLElement $xml): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'UploadId' => (string) $xml->UploadId,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{Parts: array<int, array{ETag: string, PartNumber: int}>}
|
||||||
|
*/
|
||||||
|
private function parseListParts(SimpleXMLElement $xml): array
|
||||||
|
{
|
||||||
|
$parts = [];
|
||||||
|
|
||||||
|
foreach ($xml->Part as $part) {
|
||||||
|
$parts[] = [
|
||||||
|
'ETag' => (string) $part->ETag,
|
||||||
|
'PartNumber' => (int) $part->PartNumber,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['Parts' => $parts];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,11 +78,15 @@ class Console extends Page
|
|||||||
$feature = data_get($data, 'key');
|
$feature = data_get($data, 'key');
|
||||||
|
|
||||||
$feature = $this->featureService->get($feature);
|
$feature = $this->featureService->get($feature);
|
||||||
if (!$feature || $this->getMountedAction()) {
|
if (!$feature) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->mountAction($feature->getId());
|
|
||||||
sleep(2); // TODO find a better way
|
if ($this->getMountedAction()) {
|
||||||
|
$this->replaceMountedAction($feature->getId());
|
||||||
|
} else {
|
||||||
|
$this->mountAction($feature->getId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getWidgetData(): array
|
public function getWidgetData(): array
|
||||||
|
|||||||
@@ -209,16 +209,18 @@ class ListFiles extends ListRecords
|
|||||||
->required()
|
->required()
|
||||||
->live(),
|
->live(),
|
||||||
TextEntry::make('new_location')
|
TextEntry::make('new_location')
|
||||||
->state(fn (Get $get, File $file) => resolve_path(join_paths($this->path, $get('location') ?? '/', $file->name))),
|
->state(fn (Get $get, File $file) => resolve_path(join_paths($this->path, str_ends_with($get('location') ?? '/', '/') ? join_paths($get('location') ?? '/', $file->name) : $get('location') ?? '/'))),
|
||||||
])
|
])
|
||||||
->action(function ($data, File $file) {
|
->action(function ($data, File $file) {
|
||||||
$location = $data['location'];
|
$location = $data['location'];
|
||||||
$files = [['to' => join_paths($location, $file->name), 'from' => $file->name]];
|
$endsWithSlash = str_ends_with($location, '/');
|
||||||
|
$to = $endsWithSlash ? join_paths($location, $file->name) : $location;
|
||||||
|
$files = [['to' => $to, 'from' => $file->name]];
|
||||||
|
|
||||||
$this->getDaemonFileRepository()->renameFiles($this->path, $files);
|
$this->getDaemonFileRepository()->renameFiles($this->path, $files);
|
||||||
|
|
||||||
$oldLocation = join_paths($this->path, $file->name);
|
$oldLocation = join_paths($this->path, $file->name);
|
||||||
$newLocation = resolve_path(join_paths($this->path, $location, $file->name));
|
$newLocation = resolve_path(join_paths($this->path, $to));
|
||||||
|
|
||||||
Activity::event('server:file.rename')
|
Activity::event('server:file.rename')
|
||||||
->property('directory', $this->path)
|
->property('directory', $this->path)
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class BackupRemoteUploadController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute the CreateMultipartUpload request
|
// Execute the CreateMultipartUpload request
|
||||||
$result = $client->execute($client->getCommand('CreateMultipartUpload', $params));
|
$result = $adapter->executeS3Command($client->getCommand('CreateMultipartUpload', $params));
|
||||||
|
|
||||||
// Get the UploadId from the CreateMultipartUpload request, this is needed to create
|
// Get the UploadId from the CreateMultipartUpload request, this is needed to create
|
||||||
// the other presigned urls.
|
// the other presigned urls.
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ class BackupStatusController extends Controller
|
|||||||
|
|
||||||
$client = $adapter->getClient();
|
$client = $adapter->getClient();
|
||||||
if (!$successful) {
|
if (!$successful) {
|
||||||
$client->execute($client->getCommand('AbortMultipartUpload', $params));
|
$adapter->executeS3Command($client->getCommand('AbortMultipartUpload', $params));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ class BackupStatusController extends Controller
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (is_null($parts)) {
|
if (is_null($parts)) {
|
||||||
$params['MultipartUpload']['Parts'] = $client->execute($client->getCommand('ListParts', $params))['Parts'];
|
$params['MultipartUpload']['Parts'] = $adapter->executeS3Command($client->getCommand('ListParts', $params))['Parts'];
|
||||||
} else {
|
} else {
|
||||||
foreach ($parts as $part) {
|
foreach ($parts as $part) {
|
||||||
$params['MultipartUpload']['Parts'][] = [
|
$params['MultipartUpload']['Parts'][] = [
|
||||||
@@ -159,6 +159,6 @@ class BackupStatusController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$client->execute($client->getCommand('CompleteMultipartUpload', $params));
|
$adapter->executeS3Command($client->getCommand('CompleteMultipartUpload', $params));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class OAuthController extends Controller
|
|||||||
$email = $oauthUser->getEmail();
|
$email = $oauthUser->getEmail();
|
||||||
|
|
||||||
if (!$email) {
|
if (!$email) {
|
||||||
return $this->errorRedirect();
|
return $this->errorRedirect('No email was linked to your account on the OAuth provider.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = User::whereEmail($email)->first();
|
$user = User::whereEmail($email)->first();
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ class Node extends Model implements Validatable
|
|||||||
'disk_used' => 0,
|
'disk_used' => 0,
|
||||||
];
|
];
|
||||||
|
|
||||||
return cache()->remember("nodes.$this->id.statistics", now()->addSeconds(360), function () use ($default) {
|
return cache()->flexible("nodes.$this->id.statistics", [5, 30], function () use ($default) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
$data = Http::daemon($this)
|
$data = Http::daemon($this)
|
||||||
|
|||||||
@@ -23,14 +23,16 @@ class AccountCreated extends Notification implements ShouldQueue
|
|||||||
|
|
||||||
public function toMail(User $notifiable): MailMessage
|
public function toMail(User $notifiable): MailMessage
|
||||||
{
|
{
|
||||||
|
$locale = $notifiable->language ?? 'en';
|
||||||
|
|
||||||
$message = (new MailMessage())
|
$message = (new MailMessage())
|
||||||
->greeting('Hello ' . $notifiable->username . '!')
|
->greeting(trans('mail.greeting', ['name' => $notifiable->username], $locale))
|
||||||
->line('You are receiving this email because an account has been created for you on ' . config('app.name') . '.')
|
->line(trans('mail.account_created.body', ['app' => config('app.name')], $locale))
|
||||||
->line('Username: ' . $notifiable->username)
|
->line(trans('mail.account_created.username', ['username' => $notifiable->username], $locale))
|
||||||
->line('Email: ' . $notifiable->email);
|
->line(trans('mail.account_created.email', ['email' => $notifiable->email], $locale));
|
||||||
|
|
||||||
if (!is_null($this->token)) {
|
if (!is_null($this->token)) {
|
||||||
return $message->action('Setup Your Account', Filament::getPanel('app')->getResetPasswordUrl($this->token, $notifiable));
|
return $message->action(trans('mail.account_created.action', locale: $locale), Filament::getPanel('app')->getResetPasswordUrl($this->token, $notifiable));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $message;
|
return $message;
|
||||||
|
|||||||
@@ -24,10 +24,12 @@ class AddedToServer extends Notification implements ShouldQueue
|
|||||||
|
|
||||||
public function toMail(User $notifiable): MailMessage
|
public function toMail(User $notifiable): MailMessage
|
||||||
{
|
{
|
||||||
|
$locale = $notifiable->language ?? 'en';
|
||||||
|
|
||||||
return (new MailMessage())
|
return (new MailMessage())
|
||||||
->greeting('Hello ' . $notifiable->username . '!')
|
->greeting(trans('mail.greeting', ['name' => $notifiable->username], $locale))
|
||||||
->line('You have been added as a subuser for the following server, allowing you certain control over the server.')
|
->line(trans('mail.added_to_server.body', locale: $locale))
|
||||||
->line('Server Name: ' . $this->server->name)
|
->line(trans('mail.added_to_server.server_name', ['name' => $this->server->name], $locale))
|
||||||
->action('Visit Server', Console::getUrl(panel: 'server', tenant: $this->server));
|
->action(trans('mail.added_to_server.action', locale: $locale), Console::getUrl(panel: 'server', tenant: $this->server));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,11 @@ class MailTested extends Notification
|
|||||||
|
|
||||||
public function toMail(): MailMessage
|
public function toMail(): MailMessage
|
||||||
{
|
{
|
||||||
|
$locale = $this->user->language ?? 'en';
|
||||||
|
|
||||||
return (new MailMessage())
|
return (new MailMessage())
|
||||||
->subject('Panel Test Message')
|
->subject(trans('mail.mail_tested.subject', locale: $locale))
|
||||||
->greeting('Hello ' . $this->user->username . '!')
|
->greeting(trans('mail.greeting', ['name' => $this->user->username], $locale))
|
||||||
->line('This is a test of the Panel mail system. You\'re good to go!');
|
->line(trans('mail.mail_tested.body', locale: $locale));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,11 +23,13 @@ class RemovedFromServer extends Notification implements ShouldQueue
|
|||||||
|
|
||||||
public function toMail(User $notifiable): MailMessage
|
public function toMail(User $notifiable): MailMessage
|
||||||
{
|
{
|
||||||
|
$locale = $notifiable->language ?? 'en';
|
||||||
|
|
||||||
return (new MailMessage())
|
return (new MailMessage())
|
||||||
->error()
|
->error()
|
||||||
->greeting('Hello ' . $notifiable->username . '.')
|
->greeting(trans('mail.greeting', ['name' => $notifiable->username], $locale))
|
||||||
->line('You have been removed as a subuser for the following server.')
|
->line(trans('mail.removed_from_server.body', locale: $locale))
|
||||||
->line('Server Name: ' . $this->server->name)
|
->line(trans('mail.removed_from_server.server_name', ['name' => $this->server->name], $locale))
|
||||||
->action('Visit Panel', url(''));
|
->action(trans('mail.removed_from_server.action', locale: $locale), url(''));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,10 +24,12 @@ class ServerInstalled extends Notification implements ShouldQueue
|
|||||||
|
|
||||||
public function toMail(User $notifiable): MailMessage
|
public function toMail(User $notifiable): MailMessage
|
||||||
{
|
{
|
||||||
|
$locale = $notifiable->language ?? 'en';
|
||||||
|
|
||||||
return (new MailMessage())
|
return (new MailMessage())
|
||||||
->greeting('Hello ' . $notifiable->username . '.')
|
->greeting(trans('mail.greeting', ['name' => $notifiable->username], $locale))
|
||||||
->line('Your server has finished installing and is now ready for you to use.')
|
->line(trans('mail.server_installed.body', locale: $locale))
|
||||||
->line('Server Name: ' . $this->server->name)
|
->line(trans('mail.server_installed.server_name', ['name' => $this->server->name], $locale))
|
||||||
->action('Login and Begin Using', Console::getUrl(panel: 'server', tenant: $this->server));
|
->action(trans('mail.server_installed.action', locale: $locale), Console::getUrl(panel: 'server', tenant: $this->server));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ use Filament\Facades\Filament;
|
|||||||
use Illuminate\Contracts\Auth\Factory as AuthFactory;
|
use Illuminate\Contracts\Auth\Factory as AuthFactory;
|
||||||
use Illuminate\Database\ConnectionInterface;
|
use Illuminate\Database\ConnectionInterface;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Request;
|
use Illuminate\Support\Facades\Request;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
@@ -71,7 +70,7 @@ class ActivityLogService
|
|||||||
*/
|
*/
|
||||||
public function subject(...$subjects): self
|
public function subject(...$subjects): self
|
||||||
{
|
{
|
||||||
foreach (Arr::wrap($subjects) as $subject) {
|
foreach ($subjects as $subject) {
|
||||||
if (is_null($subject)) {
|
if (is_null($subject)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ use App\Extensions\Backups\BackupManager;
|
|||||||
use App\Extensions\Filesystem\S3Filesystem;
|
use App\Extensions\Filesystem\S3Filesystem;
|
||||||
use App\Models\Backup;
|
use App\Models\Backup;
|
||||||
use App\Repositories\Daemon\DaemonBackupRepository;
|
use App\Repositories\Daemon\DaemonBackupRepository;
|
||||||
use Aws\S3\S3Client;
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Database\ConnectionInterface;
|
use Illuminate\Database\ConnectionInterface;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
@@ -72,14 +71,12 @@ class DeleteBackupService
|
|||||||
|
|
||||||
/** @var S3Filesystem $adapter */
|
/** @var S3Filesystem $adapter */
|
||||||
$adapter = $this->manager->adapter(Backup::ADAPTER_AWS_S3);
|
$adapter = $this->manager->adapter(Backup::ADAPTER_AWS_S3);
|
||||||
|
|
||||||
/** @var S3Client $client */
|
|
||||||
$client = $adapter->getClient();
|
$client = $adapter->getClient();
|
||||||
|
|
||||||
$client->deleteObject([
|
$adapter->executeS3Command($client->getCommand('DeleteObject', [
|
||||||
'Bucket' => $adapter->getBucket(),
|
'Bucket' => $adapter->getBucket(),
|
||||||
'Key' => sprintf('%s/%s.tar.gz', $backup->server->uuid, $backup->uuid),
|
'Key' => sprintf('%s/%s.tar.gz', $backup->server->uuid, $backup->uuid),
|
||||||
]);
|
]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
lang/en/mail.php
Normal file
35
lang/en/mail.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'greeting' => 'Hello :name!',
|
||||||
|
|
||||||
|
'account_created' => [
|
||||||
|
'body' => 'You are receiving this email because an account has been created for you on :app.',
|
||||||
|
'username' => 'Username: :username',
|
||||||
|
'email' => 'Email: :email',
|
||||||
|
'action' => 'Setup Your Account',
|
||||||
|
],
|
||||||
|
|
||||||
|
'added_to_server' => [
|
||||||
|
'body' => 'You have been added as a subuser for the following server, allowing you certain control over the server.',
|
||||||
|
'server_name' => 'Server Name: :name',
|
||||||
|
'action' => 'Visit Server',
|
||||||
|
],
|
||||||
|
|
||||||
|
'removed_from_server' => [
|
||||||
|
'body' => 'You have been removed as a subuser for the following server.',
|
||||||
|
'server_name' => 'Server Name: :name',
|
||||||
|
'action' => 'Visit Panel',
|
||||||
|
],
|
||||||
|
|
||||||
|
'server_installed' => [
|
||||||
|
'body' => 'Your server has finished installing and is now ready for you to use.',
|
||||||
|
'server_name' => 'Server Name: :name',
|
||||||
|
'action' => 'Login and Begin Using',
|
||||||
|
],
|
||||||
|
|
||||||
|
'mail_tested' => [
|
||||||
|
'subject' => 'Panel Test Message',
|
||||||
|
'body' => 'This is a test of the Panel mail system. You\'re good to go!',
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -5,6 +5,10 @@
|
|||||||
|
|
||||||
RewriteEngine On
|
RewriteEngine On
|
||||||
|
|
||||||
|
# Handle X-Forwarded-Proto Header
|
||||||
|
RewriteCond %{HTTP:X-Forwarded-Proto} =https [NC]
|
||||||
|
RewriteRule .* - [E=HTTPS:on]
|
||||||
|
|
||||||
# Handle Authorization Header
|
# Handle Authorization Header
|
||||||
RewriteCond %{HTTP:Authorization} .
|
RewriteCond %{HTTP:Authorization} .
|
||||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ use App\Models\Backup;
|
|||||||
use App\Repositories\Daemon\DaemonBackupRepository;
|
use App\Repositories\Daemon\DaemonBackupRepository;
|
||||||
use App\Services\Backups\DeleteBackupService;
|
use App\Services\Backups\DeleteBackupService;
|
||||||
use App\Tests\Integration\IntegrationTestCase;
|
use App\Tests\Integration\IntegrationTestCase;
|
||||||
|
use Aws\CommandInterface;
|
||||||
use GuzzleHttp\Psr7\Response;
|
use GuzzleHttp\Psr7\Response;
|
||||||
use Illuminate\Http\Client\ConnectionException;
|
use Illuminate\Http\Client\ConnectionException;
|
||||||
|
use Mockery;
|
||||||
|
|
||||||
class DeleteBackupServiceTest extends IntegrationTestCase
|
class DeleteBackupServiceTest extends IntegrationTestCase
|
||||||
{
|
{
|
||||||
@@ -92,10 +94,12 @@ class DeleteBackupServiceTest extends IntegrationTestCase
|
|||||||
$manager->expects('adapter')->with(Backup::ADAPTER_AWS_S3)->andReturn($adapter);
|
$manager->expects('adapter')->with(Backup::ADAPTER_AWS_S3)->andReturn($adapter);
|
||||||
|
|
||||||
$adapter->expects('getBucket')->andReturn('foobar');
|
$adapter->expects('getBucket')->andReturn('foobar');
|
||||||
$adapter->expects('getClient->deleteObject')->with([
|
$mockCommand = Mockery::mock(CommandInterface::class);
|
||||||
|
$adapter->expects('getClient->getCommand')->with('DeleteObject', [
|
||||||
'Bucket' => 'foobar',
|
'Bucket' => 'foobar',
|
||||||
'Key' => sprintf('%s/%s.tar.gz', $server->uuid, $backup->uuid),
|
'Key' => sprintf('%s/%s.tar.gz', $server->uuid, $backup->uuid),
|
||||||
]);
|
])->andReturn($mockCommand);
|
||||||
|
$adapter->expects('executeS3Command')->with($mockCommand);
|
||||||
|
|
||||||
$this->app->make(DeleteBackupService::class)->handle($backup);
|
$this->app->make(DeleteBackupService::class)->handle($backup);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user