Starts Notifications feature. Missing to send email with runtime configs.
This commit is contained in:
parent
cd5655bd3f
commit
13fda50aac
6
.gitignore
vendored
6
.gitignore
vendored
@ -20,10 +20,8 @@ yarn-error.log
|
||||
/.npm
|
||||
/.bash_history
|
||||
/_data
|
||||
|
||||
# Temp while developing Proxy deployment
|
||||
resources/recipes
|
||||
|
||||
_testing_hosts/
|
||||
_volumes/
|
||||
.lesshst
|
||||
psysh_history
|
||||
.psql_history
|
||||
|
38
app/Http/Livewire/Settings/DiscordNotifications.php
Normal file
38
app/Http/Livewire/Settings/DiscordNotifications.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Settings;
|
||||
|
||||
use App\Models\InstanceSettings as ModelsInstanceSettings;
|
||||
use App\Notifications\TestMessage;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Livewire\Component;
|
||||
|
||||
class DiscordNotifications extends Component
|
||||
{
|
||||
public ModelsInstanceSettings $settings;
|
||||
|
||||
protected $rules = [
|
||||
'settings.extra_attributes.discord_webhook' => '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()
|
||||
{
|
||||
// @TODO figure out how to do it in runtime
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.settings.discord-notifications');
|
||||
}
|
||||
}
|
49
app/Http/Livewire/Settings/EmailNotifications.php
Normal file
49
app/Http/Livewire/Settings/EmailNotifications.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Settings;
|
||||
|
||||
use App\Models\InstanceSettings as ModelsInstanceSettings;
|
||||
use App\Notifications\TestMessage;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Livewire\Component;
|
||||
|
||||
class EmailNotifications extends Component
|
||||
{
|
||||
public ModelsInstanceSettings $settings;
|
||||
|
||||
protected $rules = [
|
||||
'settings.extra_attributes.smtp_host' => '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()
|
||||
{
|
||||
Notification::send(auth()->user(), new TestMessage);
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.settings.email-notifications');
|
||||
}
|
||||
}
|
45
app/Jobs/SendMessageToDiscordJob.php
Normal file
45
app/Jobs/SendMessageToDiscordJob.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class SendMessageToDiscordJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* The number of times the job may be attempted.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $tries = 5;
|
||||
|
||||
/**
|
||||
* The maximum number of unhandled exceptions to allow before failing.
|
||||
*/
|
||||
public int $maxExceptions = 3;
|
||||
|
||||
public function __construct(
|
||||
public string $text,
|
||||
public string $webhookUrl
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
$payload = [
|
||||
'content' => $this->text,
|
||||
];
|
||||
|
||||
Http::post($this->webhookUrl, $payload);
|
||||
}
|
||||
}
|
@ -2,10 +2,21 @@
|
||||
|
||||
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);
|
||||
|
25
app/Notifications/Channels/DiscordChannel.php
Normal file
25
app/Notifications/Channels/DiscordChannel.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications\Channels;
|
||||
|
||||
use App\Jobs\SendMessageToDiscordJob;
|
||||
use App\Models\InstanceSettings;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class DiscordChannel
|
||||
{
|
||||
/**
|
||||
* Send the given notification.
|
||||
*/
|
||||
public function send(object $notifiable, Notification $notification): void
|
||||
{
|
||||
$message = $notification->toDiscord($notifiable);
|
||||
|
||||
$webhookUrl = data_get(
|
||||
InstanceSettings::get(),
|
||||
'extra_attributes.discord_webhook'
|
||||
);
|
||||
|
||||
dispatch(new SendMessageToDiscordJob($message, $webhookUrl));
|
||||
}
|
||||
}
|
60
app/Notifications/TestMessage.php
Normal file
60
app/Notifications/TestMessage.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Notifications\Channels\DiscordChannel;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class TestMessage extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function via(object $notifiable): array
|
||||
{
|
||||
return ['mail', DiscordChannel::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*/
|
||||
public function toMail(object $notifiable): MailMessage
|
||||
{
|
||||
return (new MailMessage)
|
||||
->line('Welcome to Coolify!')
|
||||
->action('Go to dashboard', url('/'))
|
||||
->line('We need your attention for disk usage.');
|
||||
}
|
||||
|
||||
public function toDiscord(object $notifiable): string
|
||||
{
|
||||
return 'Welcome to Coolify! We need your attention for disk usage. [Go to dashboard]('.url('/').')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(object $notifiable): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
@ -3,11 +3,13 @@
|
||||
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
|
||||
{
|
||||
@ -26,6 +28,10 @@ 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) {
|
||||
|
@ -27,6 +27,9 @@ public function up(): void
|
||||
// $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();
|
||||
});
|
||||
}
|
||||
|
@ -64,3 +64,10 @@ services:
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- "./_data/coolify/proxy/testing-host-2:/data/coolify/proxy"
|
||||
mailpit:
|
||||
image: 'axllent/mailpit:latest'
|
||||
ports:
|
||||
- '${FORWARD_MAILPIT_PORT:-1025}:1025'
|
||||
- '${FORWARD_MAILPIT_DASHBOARD_PORT:-8025}:8025'
|
||||
networks:
|
||||
- coolify
|
||||
|
@ -5,26 +5,26 @@
|
||||
'confirmAction' => null,
|
||||
])
|
||||
@if ($type === 'submit')
|
||||
<button {{ $attributes }} type="submit" @if ($disabled !== null) disabled @endif wire:target="submit"
|
||||
wire:loading.delay.shorter.class="loading"
|
||||
@isset($confirm)
|
||||
x-on:click="toggleConfirmModal('{{ $confirm }}', '{{ explode('(', $confirmAction)[0] }}')"
|
||||
@endisset
|
||||
@isset($confirmAction)
|
||||
x-on:{{ explode('(', $confirmAction)[0] }}.window="$wire.{{ explode('(', $confirmAction)[0] }}"
|
||||
@endisset>
|
||||
<button {{ $attributes }} type="submit" @disabled($disabled) wire:target="submit"
|
||||
wire:loading.delay.shorter.class="loading"
|
||||
@isset($confirm)
|
||||
x-on:click="toggleConfirmModal('{{ $confirm }}', '{{ explode('(', $confirmAction)[0] }}')"
|
||||
@endisset
|
||||
@isset($confirmAction)
|
||||
x-on:{{ explode('(', $confirmAction)[0] }}.window="$wire.{{ explode('(', $confirmAction)[0] }}"
|
||||
@endisset>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
@elseif($type === 'button')
|
||||
<button {{ $attributes }} @if ($disabled !== null) disabled @endif type="button"
|
||||
wire:target="{{ explode('(', $attributes->whereStartsWith('wire:click')->first())[0] }}"
|
||||
wire:loading.delay.shorter.class="loading"
|
||||
@isset($confirm)
|
||||
x-on:click="toggleConfirmModal('{{ $confirm }}', '{{ explode('(', $confirmAction)[0] }}')"
|
||||
@endisset
|
||||
@isset($confirmAction)
|
||||
x-on:{{ explode('(', $confirmAction)[0] }}.window="$wire.{{ explode('(', $confirmAction)[0] }}"
|
||||
@endisset>
|
||||
<button {{ $attributes }} @disabled($disabled) type="button"
|
||||
wire:target="{{ explode('(', $attributes->whereStartsWith('wire:click')->first())[0] }}"
|
||||
wire:loading.delay.shorter.class="loading"
|
||||
@isset($confirm)
|
||||
x-on:click="toggleConfirmModal('{{ $confirm }}', '{{ explode('(', $confirmAction)[0] }}')"
|
||||
@endisset
|
||||
@isset($confirmAction)
|
||||
x-on:{{ explode('(', $confirmAction)[0] }}.window="$wire.{{ explode('(', $confirmAction)[0] }}"
|
||||
@endisset>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
@endif
|
||||
|
@ -0,0 +1,15 @@
|
||||
<div class="">
|
||||
<form wire:submit.prevent='submit' class="flex flex-col">
|
||||
<div class="flex flex-col gap-2 xl:flex-row w-96">
|
||||
<x-inputs.input id="settings.extra_attributes.discord_webhook" label="Discord Webhook" />
|
||||
</div>
|
||||
<div>
|
||||
<x-inputs.button class="w-16 mt-4" type="submit">
|
||||
Submit
|
||||
</x-inputs.button>
|
||||
<x-inputs.button class="mt-4 btn btn-xs no-animation normal-case text-white btn-primary" wire:click="sentTestMessage">
|
||||
Send test message
|
||||
</x-inputs.button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
@ -0,0 +1,24 @@
|
||||
<div class="mt-10">
|
||||
<form wire:submit.prevent='submit' class="flex flex-col">
|
||||
<div class="flex flex-col gap-2 xl:flex-row">
|
||||
<div class="flex flex-col w-96">
|
||||
<x-inputs.input id="settings.extra_attributes.smtp_host" label="Host" />
|
||||
<x-inputs.input id="settings.extra_attributes.smtp_port" label="Port" />
|
||||
<x-inputs.input id="settings.extra_attributes.smtp_encryption" label="Encryption" />
|
||||
</div>
|
||||
<div class="flex flex-col w-96">
|
||||
<x-inputs.input id="settings.extra_attributes.smtp_username" label="Username" />
|
||||
<x-inputs.input id="settings.extra_attributes.smtp_password" label="Password" />
|
||||
<x-inputs.input id="settings.extra_attributes.smtp_timeout" label="Timeout" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<x-inputs.button class="w-16 mt-4" type="submit">
|
||||
Submit
|
||||
</x-inputs.button>
|
||||
<x-inputs.button class="mt-4 btn btn-xs no-animation normal-case text-white btn-primary" wire:click="sentTestMessage">
|
||||
Send test message
|
||||
</x-inputs.button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
@ -1,4 +1,12 @@
|
||||
<x-layout>
|
||||
<h1>Settings</h1>
|
||||
|
||||
<h3>General</h3>
|
||||
<livewire:settings.form :settings="$settings" />
|
||||
|
||||
<div class="my-12"></div>
|
||||
|
||||
<h3>Notifications</h3>
|
||||
<livewire:settings.discord-notifications :settings="$settings" />
|
||||
<livewire:settings.email-notifications :settings="$settings" />
|
||||
</x-layout>
|
||||
|
@ -1,7 +1,8 @@
|
||||
<x-layout>
|
||||
<div>
|
||||
<h3>Current Team</h3>
|
||||
<p>Name: {{ session('currentTeam')->name }}</p>
|
||||
<livewire:switch-team>
|
||||
<p>Name: {{ session('currentTeam.name') }}</p>
|
||||
<livewire:switch-team/>
|
||||
|
||||
</div>
|
||||
</x-layout>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use Illuminate\Foundation\Inspiring;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Symfony\Component\Mailer\Mailer;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -14,19 +15,27 @@
|
||||
|
|
||||
*/
|
||||
|
||||
// Artisan::command('inspire', function () {
|
||||
Artisan::command('inspire', function () {
|
||||
|
||||
// $activity = Spatie\Activitylog\Models\Activity::latest()->first();
|
||||
$smtp = [
|
||||
"transport" => "smtp",
|
||||
"host" => "mailpit",
|
||||
"port" => 1025,
|
||||
"encryption" => 'tls',
|
||||
"username" => null,
|
||||
"password" => null,
|
||||
"timeout" => null,
|
||||
"local_domain" => null,
|
||||
];
|
||||
config()->set('mail.mailers.smtp', $smtp);
|
||||
|
||||
// $this->info(
|
||||
// collect(
|
||||
// json_decode(data_get($activity, 'description'), associative: true, flags: JSON_THROW_ON_ERROR)
|
||||
// )
|
||||
// ->sortBy('order')
|
||||
// ->map(fn($i) => $i['output'])
|
||||
// ->implode("\n")
|
||||
// );
|
||||
// \Illuminate\Support\Facades\Mail::mailer('smtp')
|
||||
// ->to('ask@me.com')
|
||||
// ->send(new \App\Mail\TestMail);
|
||||
|
||||
\Illuminate\Support\Facades\Notification::send(
|
||||
\App\Models\User::find(1),
|
||||
new \App\Notifications\TestMessage
|
||||
);
|
||||
|
||||
|
||||
// })->purpose('Display an inspiring quote');
|
||||
})->purpose('Display an inspiring quote');
|
||||
|
Loading…
Reference in New Issue
Block a user