Skip to content

Commit

Permalink
Add database notifications (#817)
Browse files Browse the repository at this point in the history
* add database notifications to all panels

* add successful param to Installed event

* add listener for Installed event

* create event for subuser creation

* add listener for SubUserAdded event

* always send Installed event

* create event for subuser removal

* add listener for SubUserRemoved event

* add prefix to server name

* remove view action from SubUserRemoved notification
  • Loading branch information
Boy132 authored Dec 12, 2024
1 parent eb81903 commit d092276
Show file tree
Hide file tree
Showing 16 changed files with 176 additions and 45 deletions.
2 changes: 1 addition & 1 deletion app/Events/Server/Installed.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
}
17 changes: 17 additions & 0 deletions app/Events/Server/SubUserAdded.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace App\Events\Server;

use App\Events\Event;
use App\Models\Subuser;
use Illuminate\Queue\SerializesModels;

class SubUserAdded extends Event
{
use SerializesModels;

/**
* Create a new event instance.
*/
public function __construct(public Subuser $subuser) {}
}
18 changes: 18 additions & 0 deletions app/Events/Server/SubUserRemoved.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace App\Events\Server;

use App\Events\Event;
use App\Models\Server;
use App\Models\User;
use Illuminate\Queue\SerializesModels;

class SubUserRemoved extends Event
{
use SerializesModels;

/**
* Create a new event instance.
*/
public function __construct(public Server $server, public User $user) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,11 @@ public function store(InstallationDataRequest $request, Server $server): JsonRes
{
$status = null;

// Make sure the type of failure is accurate
if (!$request->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
Expand All @@ -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);
}
Expand Down
29 changes: 29 additions & 0 deletions app/Listeners/Server/ServerInstalledListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace App\Listeners\Server;

use App\Events\Server\Installed;
use App\Filament\Server\Pages\Console;
use Filament\Notifications\Actions\Action;
use Filament\Notifications\Notification;

class ServerInstalledListener
{
public function handle(Installed $event): void
{
$event->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);
}
}
29 changes: 29 additions & 0 deletions app/Listeners/Server/SubUserAddedListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace App\Listeners\Server;

use App\Events\Server\SubUserAdded;
use App\Filament\Server\Pages\Console;
use Filament\Notifications\Actions\Action;
use Filament\Notifications\Notification;

class SubUserAddedListener
{
public function handle(SubUserAdded $event): void
{
$event->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);
}
}
17 changes: 17 additions & 0 deletions app/Listeners/Server/SubUserRemovedListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace App\Listeners\Server;

use App\Events\Server\SubUserRemoved;
use Filament\Notifications\Notification;

class SubUserRemovedListener
{
public function handle(SubUserRemoved $event): void
{
Notification::make()
->title('Removed from Server')
->body('You have been removed as a subuser from ' . $event->server->name . '.')
->sendToDatabase($event->user);
}
}
23 changes: 18 additions & 5 deletions app/Notifications/AddedToServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}

/**
Expand All @@ -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));
Expand Down
23 changes: 18 additions & 5 deletions app/Notifications/RemovedFromServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}

/**
Expand All @@ -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'));
Expand Down
23 changes: 16 additions & 7 deletions app/Notifications/ServerInstalled.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}
}

/**
Expand Down
1 change: 1 addition & 0 deletions app/Providers/Filament/AdminPanelProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions app/Providers/Filament/AppPanelProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions app/Providers/Filament/ServerPanelProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 2 additions & 6 deletions app/Services/Subusers/SubuserCreationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
});
Expand Down
7 changes: 2 additions & 5 deletions app/Services/Subusers/SubuserDeletionService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion tests/Feature/Webhooks/ProcessWebhooksTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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, [
Expand Down

0 comments on commit d092276

Please sign in to comment.