diff --git a/app/Events/Server/Installed.php b/app/Events/Server/Installed.php index a8420a858f..391a5b31e3 100644 --- a/app/Events/Server/Installed.php +++ b/app/Events/Server/Installed.php @@ -13,5 +13,5 @@ class Installed extends Event /** * Create a new event instance. */ - public function __construct(public Server $server) {} + public function __construct(public Server $server, public bool $successful, public bool $initialInstall) {} } diff --git a/app/Events/Server/SubUserAdded.php b/app/Events/Server/SubUserAdded.php new file mode 100644 index 0000000000..895542f4dd --- /dev/null +++ b/app/Events/Server/SubUserAdded.php @@ -0,0 +1,17 @@ +boolean('successful')) { - $status = ServerState::InstallFailed; + $successful = $request->boolean('successful'); - if ($request->boolean('reinstall')) { - $status = ServerState::ReinstallFailed; - } + // Make sure the type of failure is accurate + if (!$successful) { + $status = $request->boolean('reinstall') ? ServerState::ReinstallFailed : ServerState::InstallFailed; } // Keep the server suspended if it's already suspended @@ -55,16 +53,8 @@ public function store(InstallationDataRequest $request, Server $server): JsonRes $server->installed_at = now(); $server->save(); - // If the server successfully installed, fire installed event. - // This logic allows individually disabling install and reinstall notifications separately. $isInitialInstall = is_null($previouslyInstalledAt); - if ($isInitialInstall && config()->get('panel.email.send_install_notification', true)) { - event(new ServerInstalled($server)); - } - - if (!$isInitialInstall && config()->get('panel.email.send_reinstall_notification', true)) { - event(new ServerInstalled($server)); - } + event(new ServerInstalled($server, $successful, $isInitialInstall)); return new JsonResponse([], Response::HTTP_NO_CONTENT); } diff --git a/app/Listeners/Server/ServerInstalledListener.php b/app/Listeners/Server/ServerInstalledListener.php new file mode 100644 index 0000000000..7c015be492 --- /dev/null +++ b/app/Listeners/Server/ServerInstalledListener.php @@ -0,0 +1,29 @@ +server->loadMissing('user'); + + Notification::make() + ->status($event->successful ? 'success' : 'danger') + ->title('Server ' . ($event->initialInstall ? 'Installation' : 'Reinstallation') . ' ' . ($event->successful ? 'completed' : 'failed')) + ->body('Server Name: ' . $event->server->name) + ->actions([ + Action::make('view') + ->button() + ->label('Open Server') + ->markAsRead() + ->url(fn () => Console::getUrl(panel: 'server', tenant: $event->server)), + ]) + ->sendToDatabase($event->server->user); + } +} diff --git a/app/Listeners/Server/SubUserAddedListener.php b/app/Listeners/Server/SubUserAddedListener.php new file mode 100644 index 0000000000..737495316c --- /dev/null +++ b/app/Listeners/Server/SubUserAddedListener.php @@ -0,0 +1,29 @@ +subuser->loadMissing('server'); + $event->subuser->loadMissing('user'); + + Notification::make() + ->title('Added to Server') + ->body('You have been added as a subuser to ' . $event->subuser->server->name . '.') + ->actions([ + Action::make('view') + ->button() + ->label('Open Server') + ->markAsRead() + ->url(fn () => Console::getUrl(panel: 'server', tenant: $event->subuser->server)), + ]) + ->sendToDatabase($event->subuser->user); + } +} diff --git a/app/Listeners/Server/SubUserRemovedListener.php b/app/Listeners/Server/SubUserRemovedListener.php new file mode 100644 index 0000000000..8cc5a07fd0 --- /dev/null +++ b/app/Listeners/Server/SubUserRemovedListener.php @@ -0,0 +1,17 @@ +title('Removed from Server') + ->body('You have been removed as a subuser from ' . $event->server->name . '.') + ->sendToDatabase($event->user); + } +} diff --git a/app/Notifications/AddedToServer.php b/app/Notifications/AddedToServer.php index 647c338229..8e64bb5f13 100644 --- a/app/Notifications/AddedToServer.php +++ b/app/Notifications/AddedToServer.php @@ -2,7 +2,12 @@ namespace App\Notifications; +use App\Events\Server\SubUserAdded; +use App\Models\Server; +use App\Models\User; use Illuminate\Bus\Queueable; +use Illuminate\Container\Container; +use Illuminate\Contracts\Notifications\Dispatcher; use Illuminate\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; @@ -11,14 +16,22 @@ class AddedToServer extends Notification implements ShouldQueue { use Queueable; - public object $server; + public Server $server; + + public User $user; /** - * Create a new notification instance. + * Handle a direct call to this notification from the subuser added event. This is configured + * in the event service provider. */ - public function __construct(array $server) + public function handle(SubUserAdded $event): void { - $this->server = (object) $server; + $this->server = $event->subuser->server; + $this->user = $event->subuser->user; + + // Since we are calling this notification directly from an event listener we need to fire off the dispatcher + // to send the email now. Don't use send() or you'll end up firing off two different events. + Container::getInstance()->make(Dispatcher::class)->sendNow($this->user, $this); } /** @@ -35,7 +48,7 @@ public function via(): array public function toMail(): MailMessage { return (new MailMessage()) - ->greeting('Hello ' . $this->server->user . '!') + ->greeting('Hello ' . $this->user->username . '!') ->line('You have been added as a subuser for the following server, allowing you certain control over the server.') ->line('Server Name: ' . $this->server->name) ->action('Visit Server', url('/server/' . $this->server->uuid_short)); diff --git a/app/Notifications/RemovedFromServer.php b/app/Notifications/RemovedFromServer.php index 668d8f28a5..8d5722dff9 100644 --- a/app/Notifications/RemovedFromServer.php +++ b/app/Notifications/RemovedFromServer.php @@ -2,7 +2,12 @@ namespace App\Notifications; +use App\Events\Server\SubUserRemoved; +use App\Models\Server; +use App\Models\User; use Illuminate\Bus\Queueable; +use Illuminate\Container\Container; +use Illuminate\Contracts\Notifications\Dispatcher; use Illuminate\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; @@ -11,14 +16,22 @@ class RemovedFromServer extends Notification implements ShouldQueue { use Queueable; - public object $server; + public Server $server; + + public User $user; /** - * Create a new notification instance. + * Handle a direct call to this notification from the subuser removed event. This is configured + * in the event service provider. */ - public function __construct(array $server) + public function handle(SubUserRemoved $event): void { - $this->server = (object) $server; + $this->server = $event->server; + $this->user = $event->user; + + // Since we are calling this notification directly from an event listener we need to fire off the dispatcher + // to send the email now. Don't use send() or you'll end up firing off two different events. + Container::getInstance()->make(Dispatcher::class)->sendNow($this->user, $this); } /** @@ -36,7 +49,7 @@ public function toMail(): MailMessage { return (new MailMessage()) ->error() - ->greeting('Hello ' . $this->server->user . '.') + ->greeting('Hello ' . $this->user->username . '.') ->line('You have been removed as a subuser for the following server.') ->line('Server Name: ' . $this->server->name) ->action('Visit Panel', route('index')); diff --git a/app/Notifications/ServerInstalled.php b/app/Notifications/ServerInstalled.php index fa6500afab..b2ead05bd7 100644 --- a/app/Notifications/ServerInstalled.php +++ b/app/Notifications/ServerInstalled.php @@ -4,7 +4,6 @@ use App\Models\User; use Illuminate\Bus\Queueable; -use App\Events\Event; use App\Models\Server; use Illuminate\Container\Container; use App\Events\Server\Installed; @@ -27,14 +26,24 @@ class ServerInstalled extends Notification implements ShouldQueue */ public function handle(Installed $event): void { - $event->server->loadMissing('user'); + if ($event->initialInstall && !config()->get('panel.email.send_install_notification', true)) { + return; + } - $this->server = $event->server; - $this->user = $event->server->user; + if (!$event->initialInstall && !config()->get('panel.email.send_reinstall_notification', true)) { + return; + } - // Since we are calling this notification directly from an event listener we need to fire off the dispatcher - // to send the email now. Don't use send() or you'll end up firing off two different events. - Container::getInstance()->make(Dispatcher::class)->sendNow($this->user, $this); + if ($event->successful) { + $event->server->loadMissing('user'); + + $this->server = $event->server; + $this->user = $event->server->user; + + // Since we are calling this notification directly from an event listener we need to fire off the dispatcher + // to send the email now. Don't use send() or you'll end up firing off two different events. + Container::getInstance()->make(Dispatcher::class)->sendNow($this->user, $this); + } } /** diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 11e83ad529..98eb37bad4 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -55,6 +55,7 @@ public function panel(Panel $panel): Panel ->spa() ->discoverResources(in: app_path('Filament/Admin/Resources'), for: 'App\\Filament\\Admin\\Resources') ->discoverPages(in: app_path('Filament/Admin/Pages'), for: 'App\\Filament\\Admin\\Pages') + ->databaseNotifications() ->middleware([ EncryptCookies::class, AddQueuedCookiesToResponse::class, diff --git a/app/Providers/Filament/AppPanelProvider.php b/app/Providers/Filament/AppPanelProvider.php index 3bd0e805e2..18a05ed540 100644 --- a/app/Providers/Filament/AppPanelProvider.php +++ b/app/Providers/Filament/AppPanelProvider.php @@ -46,6 +46,7 @@ public function panel(Panel $panel): Panel ->visible(fn (): bool => auth()->user()->canAccessPanel(Filament::getPanel('admin'))), ]) ->discoverResources(in: app_path('Filament/App/Resources'), for: 'App\\Filament\\App\\Resources') + ->databaseNotifications() ->middleware([ EncryptCookies::class, AddQueuedCookiesToResponse::class, diff --git a/app/Providers/Filament/ServerPanelProvider.php b/app/Providers/Filament/ServerPanelProvider.php index 9682a64651..72988cd8ee 100644 --- a/app/Providers/Filament/ServerPanelProvider.php +++ b/app/Providers/Filament/ServerPanelProvider.php @@ -65,6 +65,7 @@ public function panel(Panel $panel): Panel ->discoverResources(in: app_path('Filament/Server/Resources'), for: 'App\\Filament\\Server\\Resources') ->discoverPages(in: app_path('Filament/Server/Pages'), for: 'App\\Filament\\Server\\Pages') ->discoverWidgets(in: app_path('Filament/Server/Widgets'), for: 'App\\Filament\\Server\\Widgets') + ->databaseNotifications() ->middleware([ EncryptCookies::class, AddQueuedCookiesToResponse::class, diff --git a/app/Services/Subusers/SubuserCreationService.php b/app/Services/Subusers/SubuserCreationService.php index 4566ac3660..e4c66d61a6 100644 --- a/app/Services/Subusers/SubuserCreationService.php +++ b/app/Services/Subusers/SubuserCreationService.php @@ -2,8 +2,8 @@ namespace App\Services\Subusers; +use App\Events\Server\SubUserAdded; use App\Models\User; -use App\Notifications\AddedToServer; use Illuminate\Support\Str; use App\Models\Server; use App\Models\Subuser; @@ -63,11 +63,7 @@ public function handle(Server $server, string $email, array $permissions): Subus 'permissions' => array_unique($permissions), ]); - $subuser->user->notify(new AddedToServer([ - 'user' => $subuser->user->name_first, - 'name' => $subuser->server->name, - 'uuid_short' => $subuser->server->uuid_short, - ])); + event(new SubUserAdded($subuser)); return $subuser; }); diff --git a/app/Services/Subusers/SubuserDeletionService.php b/app/Services/Subusers/SubuserDeletionService.php index d3d4158d2c..9ee67ac7d3 100644 --- a/app/Services/Subusers/SubuserDeletionService.php +++ b/app/Services/Subusers/SubuserDeletionService.php @@ -2,11 +2,11 @@ namespace App\Services\Subusers; +use App\Events\Server\SubUserRemoved; use App\Exceptions\Http\Connection\DaemonConnectionException; use App\Facades\Activity; use App\Models\Server; use App\Models\Subuser; -use App\Notifications\RemovedFromServer; use App\Repositories\Daemon\DaemonServerRepository; class SubuserDeletionService @@ -25,10 +25,7 @@ public function handle(Subuser $subuser, Server $server): void $log->transaction(function ($instance) use ($server, $subuser) { $subuser->delete(); - $subuser->user->notify(new RemovedFromServer([ - 'user' => $subuser->user->name_first, - 'name' => $subuser->server->name, - ])); + event(new SubUserRemoved($subuser->server, $subuser->user)); try { $this->serverRepository->setServer($server)->revokeUserJTI($subuser->user_id); diff --git a/tests/Feature/Webhooks/ProcessWebhooksTest.php b/tests/Feature/Webhooks/ProcessWebhooksTest.php index c15683d29f..3658236978 100644 --- a/tests/Feature/Webhooks/ProcessWebhooksTest.php +++ b/tests/Feature/Webhooks/ProcessWebhooksTest.php @@ -185,7 +185,7 @@ public function test_it_is_triggered_on_custom_events() $server = $this->createServer(); - event(new Installed($server)); + event(new Installed($server, true, true)); $this->assertDatabaseCount(Webhook::class, 1); $this->assertDatabaseHas(Webhook::class, [