diff --git a/app/Console/Commands/NotifyDemo.php b/app/Console/Commands/NotifyDemo.php new file mode 100644 index 000000000..1d5906bd0 --- /dev/null +++ b/app/Console/Commands/NotifyDemo.php @@ -0,0 +1,75 @@ +argument('channel'); + + if (blank($channel)) { + $this->showHelp(); + return; + } + + ray($channel); + } + + private function showHelp() + { + style('coolify')->color('#9333EA'); + style('title-box')->apply('mt-1 px-2 py-1 bg-coolify'); + + render(<<<'HTML' +
+
+ Coolify +
+

+ Demo Notify => Send a demo notification to a given channel. +

+

+ php artisan app:demo-notify {channel} +

+
+
Channels:
+ +
+
+ HTML); + + ask(<<<'HTML' +
+ In which manner you wish a coolified notification? +
+ HTML, ['email', 'slack', 'discord', 'telegram']); + } +} diff --git a/app/Http/Livewire/Notifications/DiscordSettings.php b/app/Http/Livewire/Notifications/DiscordSettings.php new file mode 100644 index 000000000..fe689d4b2 --- /dev/null +++ b/app/Http/Livewire/Notifications/DiscordSettings.php @@ -0,0 +1,43 @@ + 'nullable|url', + 'model.extra_attributes.discord_active' => 'nullable|boolean', + ]; + protected $validationAttributes = [ + 'model.extra_attributes.discord_webhook' => 'Discord Webhook', + ]; + public function mount($model) + { + // + } + public function submit() + { + $this->resetErrorBag(); + $this->validate(); + $this->model->save(); + if ( is_a($this->model, Team::class)) { + session(['currentTeam' => $this->model]); + } + } + public function sentTestMessage() + { + Notification::send($this->model, new DemoNotification); + } + public function render() + { + return view('livewire.notifications.discord-settings'); + } +} diff --git a/app/Http/Livewire/Notifications/EmailSettings.php b/app/Http/Livewire/Notifications/EmailSettings.php new file mode 100644 index 000000000..caeeca2b8 --- /dev/null +++ b/app/Http/Livewire/Notifications/EmailSettings.php @@ -0,0 +1,53 @@ + 'nullable|boolean', + 'model.extra_attributes.recipients' => 'nullable', + 'model.extra_attributes.smtp_host' => 'nullable', + 'model.extra_attributes.smtp_port' => 'nullable', + 'model.extra_attributes.smtp_encryption' => 'nullable', + 'model.extra_attributes.smtp_username' => 'nullable', + 'model.extra_attributes.smtp_password' => 'nullable', + 'model.extra_attributes.smtp_timeout' => 'nullable', + ]; + protected $validationAttributes = [ + 'model.extra_attributes.recipients' => 'Recipients', + 'model.extra_attributes.smtp_host' => 'Host', + 'model.extra_attributes.smtp_port' => 'Port', + 'model.extra_attributes.smtp_encryption' => 'Encryption', + 'model.extra_attributes.smtp_username' => 'Username', + 'model.extra_attributes.smtp_password' => 'Password', + 'model.extra_attributes.smtp_timeout' => 'Timeout', + ]; + public function mount($model) + { + // + } + public function submit() + { + $this->resetErrorBag(); + $this->validate(); + $this->model->save(); + if ( is_a($this->model, Team::class)) { + session(['currentTeam' => $this->model]); + } + } + public function sendTestNotification() + { + + } + public function render() + { + return view('livewire.notifications.email-settings'); + } +} diff --git a/app/Http/Livewire/Settings/DiscordNotifications.php b/app/Http/Livewire/Settings/DiscordNotifications.php deleted file mode 100644 index 4227c2276..000000000 --- a/app/Http/Livewire/Settings/DiscordNotifications.php +++ /dev/null @@ -1,38 +0,0 @@ - 'nullable|url', - ]; - protected $validationAttributes = [ - 'settings.extra_attributes.discord_webhook' => 'Discord Webhook', - ]; - public function mount($settings) - { - // - } - public function submit() - { - $this->resetErrorBag(); - $this->validate(); - $this->settings->save(); - } - public function sentTestMessage() - { - Notification::send(auth()->user(), new TestMessage); - } - public function render() - { - return view('livewire.settings.discord-notifications'); - } -} diff --git a/app/Http/Livewire/Settings/EmailNotifications.php b/app/Http/Livewire/Settings/EmailNotifications.php deleted file mode 100644 index b1bca81c8..000000000 --- a/app/Http/Livewire/Settings/EmailNotifications.php +++ /dev/null @@ -1,49 +0,0 @@ - 'nullable', - 'settings.extra_attributes.smtp_port' => 'nullable', - 'settings.extra_attributes.smtp_encryption' => 'nullable', - 'settings.extra_attributes.smtp_username' => 'nullable', - 'settings.extra_attributes.smtp_password' => 'nullable', - 'settings.extra_attributes.smtp_timeout' => 'nullable', - ]; - protected $validationAttributes = [ - 'settings.extra_attributes.smtp_host' => 'Host', - 'settings.extra_attributes.smtp_port' => 'Port', - 'settings.extra_attributes.smtp_encryption' => 'Encryption', - 'settings.extra_attributes.smtp_username' => 'Username', - 'settings.extra_attributes.smtp_password' => 'Password', - 'settings.extra_attributes.smtp_timeout' => 'Timeout', - ]; - public function mount($settings) - { - ray($settings); - // - } - public function submit() - { - $this->resetErrorBag(); - $this->validate(); - $this->settings->save(); - } - public function sentTestMessage() - { - - } - public function render() - { - return view('livewire.settings.email-notifications'); - } -} diff --git a/app/Mail/ExampleMail.php b/app/Mail/ExampleMail.php deleted file mode 100644 index 0167b26e1..000000000 --- a/app/Mail/ExampleMail.php +++ /dev/null @@ -1,53 +0,0 @@ - - */ - public function attachments(): array - { - return []; - } -} diff --git a/app/Models/InstanceSettings.php b/app/Models/InstanceSettings.php index 445d07477..c2394a008 100644 --- a/app/Models/InstanceSettings.php +++ b/app/Models/InstanceSettings.php @@ -2,21 +2,10 @@ namespace App\Models; -use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; -use Spatie\SchemalessAttributes\Casts\SchemalessAttributes; class InstanceSettings extends Model { - public $casts = [ - 'extra_attributes' => SchemalessAttributes::class, - ]; - - public function scopeWithExtraAttributes(): Builder - { - return $this->extra_attributes->modelScope(); - } - public static function get() { return InstanceSettings::findOrFail(0); diff --git a/app/Models/Team.php b/app/Models/Team.php index aaadcbb5a..fd5a0f06e 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -2,28 +2,59 @@ namespace App\Models; -class Team extends BaseModel +use App\Notifications\Channels\SendsCoolifyEmail; +use App\Notifications\Channels\SendsDiscord; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Notifications\Notifiable; +use Spatie\SchemalessAttributes\Casts\SchemalessAttributes; + +class Team extends BaseModel implements SendsDiscord, SendsCoolifyEmail { + use Notifiable; + protected $casts = [ + 'extra_attributes' => SchemalessAttributes::class, 'personal_team' => 'boolean', ]; protected $fillable = [ 'id', 'name', - 'personal_team' + 'personal_team', + 'extra_attributes', ]; + + public function routeNotificationForDiscord() + { + return $this->extra_attributes->get('discord_webhook'); + } + + public function routeNotificationForCoolifyEmail() + { + $recipients = $this->extra_attributes->get('recipients', ''); + + return explode(PHP_EOL, $recipients); + } + + public function scopeWithExtraAttributes(): Builder + { + return $this->extra_attributes->modelScope(); + } + public function projects() { return $this->hasMany(Project::class); } + public function servers() { return $this->hasMany(Server::class); } + public function applications() { return $this->hasManyThrough(Application::class, Project::class); } + public function privateKeys() { return $this->hasMany(PrivateKey::class); diff --git a/app/Notifications/Channels/CoolifyEmailChannel.php b/app/Notifications/Channels/CoolifyEmailChannel.php new file mode 100644 index 000000000..a32b58381 --- /dev/null +++ b/app/Notifications/Channels/CoolifyEmailChannel.php @@ -0,0 +1,41 @@ +bootConfigs($notifiable); + $bcc = $notifiable->routeNotificationForCoolifyEmail(); + $mailMessage = $notification->toMail($notifiable); + + Mail::send([], [], fn(Message $message) => $message + ->from('ask@me.com', 'My Coolify Instance') + ->bcc($bcc) + ->subject($mailMessage->subject) + ->html((string) $mailMessage->render()) + ); + } + + private function bootConfigs($notifiable): void + { + config()->set('mail.mailers.smtp', [ + "transport" => "smtp", + "host" => $notifiable->extra_attributes?->get('smtp_host'), + "port" => $notifiable->extra_attributes?->get('smtp_port'), + "encryption" => $notifiable->extra_attributes?->get('smtp_encryption'), + "username" => $notifiable->extra_attributes?->get('smtp_username'), + "password" => $notifiable->extra_attributes?->get('smtp_password'), + "timeout" => $notifiable->extra_attributes?->get('smtp_timeout'), + "local_domain" => null, + ]); + } +} diff --git a/app/Notifications/Channels/DiscordChannel.php b/app/Notifications/Channels/DiscordChannel.php index 77709ec0b..06c8c0130 100644 --- a/app/Notifications/Channels/DiscordChannel.php +++ b/app/Notifications/Channels/DiscordChannel.php @@ -3,7 +3,6 @@ namespace App\Notifications\Channels; use App\Jobs\SendMessageToDiscordJob; -use App\Models\InstanceSettings; use Illuminate\Notifications\Notification; class DiscordChannel @@ -11,14 +10,11 @@ class DiscordChannel /** * Send the given notification. */ - public function send(object $notifiable, Notification $notification): void + public function send(SendsDiscord $notifiable, Notification $notification): void { $message = $notification->toDiscord($notifiable); - $webhookUrl = data_get( - InstanceSettings::get(), - 'extra_attributes.discord_webhook' - ); + $webhookUrl = $notifiable->routeNotificationForDiscord(); dispatch(new SendMessageToDiscordJob($message, $webhookUrl)); } diff --git a/app/Notifications/Channels/SendsCoolifyEmail.php b/app/Notifications/Channels/SendsCoolifyEmail.php new file mode 100644 index 000000000..e1698a1fe --- /dev/null +++ b/app/Notifications/Channels/SendsCoolifyEmail.php @@ -0,0 +1,8 @@ +extra_attributes?->get('smtp_active') && $channels[] = CoolifyEmailChannel::class; + $notifiable->extra_attributes?->get('discord_active') && $channels[] = DiscordChannel::class; + return $channels; } /** @@ -35,33 +39,16 @@ public function via(object $notifiable): array */ public function toMail(object $notifiable): MailMessage { - $smtp = [ - "transport" => "smtp", - "host" => "mailpit", - "port" => 1025, - "encryption" => 'tls', - "username" => null, - "password" => null, - "timeout" => null, - "local_domain" => null, - ]; - config()->set('mail.mailers.smtp', $smtp); - - \Illuminate\Support\Facades\Mail::mailer('smtp') - ->to('ask@me.com') - ->send(new \App\Mail\ExampleMail); - - - return (new MailMessage) + ->subject('Coolify demo notification') ->line('Welcome to Coolify!') + ->error() ->action('Go to dashboard', url('/')) ->line('We need your attention for disk usage.'); } public function toDiscord(object $notifiable): string { - ray('1111'); return 'Welcome to Coolify! We need your attention for disk usage. [Go to dashboard]('.url('/').')'; } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 3129c24ce..be599237a 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -3,13 +3,11 @@ namespace App\Providers; use App\Jobs\CoolifyTask; -use Illuminate\Mail\MailManager; use Illuminate\Queue\Events\JobProcessed; use Illuminate\Support\Facades\Process; use Illuminate\Support\Facades\Queue; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; -use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport; class AppServiceProvider extends ServiceProvider { @@ -28,10 +26,6 @@ public function register(): void */ public function boot(): void { - if (! $this->app->environment('production')) { - \Illuminate\Support\Facades\Mail::alwaysTo('noone@example.com'); - } - Queue::after(function (JobProcessed $event) { // @TODO: Remove `coolify-builder` container after the remoteProcess job is finishged and remoteProcess->type == `deployment`. if ($event->job->resolveName() === CoolifyTask::class) { diff --git a/database/migrations/2023_03_20_112811_create_teams_table.php b/database/migrations/2023_03_20_112811_create_teams_table.php index 77e7b840f..4396c8db7 100644 --- a/database/migrations/2023_03_20_112811_create_teams_table.php +++ b/database/migrations/2023_03_20_112811_create_teams_table.php @@ -16,6 +16,7 @@ public function up(): void $table->string('uuid')->unique(); $table->string('name'); $table->boolean('personal_team')->default(false); + $table->schemalessAttributes('extra_attributes'); $table->timestamps(); }); } diff --git a/database/migrations/2023_03_20_112813_create_instance_settings_table.php b/database/migrations/2023_03_20_112813_create_instance_settings_table.php index 2d1826d30..a09288e21 100644 --- a/database/migrations/2023_03_20_112813_create_instance_settings_table.php +++ b/database/migrations/2023_03_20_112813_create_instance_settings_table.php @@ -20,16 +20,11 @@ public function up(): void $table->integer('public_port_min')->default(9000); $table->integer('public_port_max')->default(9100); // $table->string('custom_dns_servers')->default('1.1.1.1,8.8.8.8'); - $table->boolean('do_not_track')->default(false); - $table->boolean('is_auto_update_enabled')->default(true); // $table->boolean('is_dns_check_enabled')->default(true); $table->boolean('is_registration_enabled')->default(true); $table->boolean('is_https_forced')->default(true); - - $table->schemalessAttributes('extra_attributes'); - $table->timestamps(); }); } diff --git a/resources/views/livewire/notifications/discord-settings.blade.php b/resources/views/livewire/notifications/discord-settings.blade.php new file mode 100644 index 000000000..730293f2d --- /dev/null +++ b/resources/views/livewire/notifications/discord-settings.blade.php @@ -0,0 +1,23 @@ +
+
Discord
+
+
+
+ +
+
+ +
+
+ + Submit + + + Send test message + +
+
+
diff --git a/resources/views/livewire/notifications/email-settings.blade.php b/resources/views/livewire/notifications/email-settings.blade.php new file mode 100644 index 000000000..a87b10abb --- /dev/null +++ b/resources/views/livewire/notifications/email-settings.blade.php @@ -0,0 +1,43 @@ +
+
E-mail - SMTP
+
+
+
+ +
+
+
+ +
+
+
+
+ + + +
+
+ + + +
+
+ +
+
+
+ + Submit + + + Send test message + +
+
+
diff --git a/resources/views/livewire/settings/discord-notifications.blade.php b/resources/views/livewire/settings/discord-notifications.blade.php deleted file mode 100644 index d13e26e27..000000000 --- a/resources/views/livewire/settings/discord-notifications.blade.php +++ /dev/null @@ -1,15 +0,0 @@ -
-
-
- -
-
- - Submit - - - Send test message - -
-
-
diff --git a/resources/views/livewire/settings/email-notifications.blade.php b/resources/views/livewire/settings/email-notifications.blade.php deleted file mode 100644 index 4f3af4156..000000000 --- a/resources/views/livewire/settings/email-notifications.blade.php +++ /dev/null @@ -1,27 +0,0 @@ -
-
-
-
- - - -
-
- - - -
-
-
- - Submit - -
-
- - - Send test message - -
-
-
diff --git a/resources/views/settings.blade.php b/resources/views/settings.blade.php index dbd8588f1..847b84673 100644 --- a/resources/views/settings.blade.php +++ b/resources/views/settings.blade.php @@ -4,11 +4,4 @@

General

-
- -

Notifications

- - - -
diff --git a/resources/views/team.blade.php b/resources/views/team.blade.php index 135c131d8..0cc1cf511 100644 --- a/resources/views/team.blade.php +++ b/resources/views/team.blade.php @@ -3,6 +3,10 @@

Current Team

Name: {{ session('currentTeam.name') }}

- +
+

Notifications

+ + +
diff --git a/routes/console.php b/routes/console.php index 2de1715be..e05f4c9a1 100644 --- a/routes/console.php +++ b/routes/console.php @@ -1,9 +1,7 @@ "smtp", - "host" => "mailpit", - "port" => 1025, - "encryption" => 'tls', - "username" => null, - "password" => null, - "timeout" => null, - "local_domain" => null, - ]; - config()->set('mail.mailers.smtp', $smtp); - - // For testing custom SMTP Mailer - \Illuminate\Support\Facades\Mail::mailer('smtp') - ->to('ask@me.com') - ->send(new \App\Mail\ExampleMail); - - // For sending a notification -// \Illuminate\Support\Facades\Notification::send( -// \App\Models\User::find(1), -// new \App\Notifications\TestMessage -// ); - + $this->comment(Inspiring::quote()); })->purpose('Display an inspiring quote');