diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php index ba683d88e..dc699124f 100644 --- a/.phpstorm.meta.php +++ b/.phpstorm.meta.php @@ -164,6 +164,9 @@ 'Livewire\EventBus' => \Livewire\EventBus::class, 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, + 'Lorisleiva\Actions\ActionManager' => \Lorisleiva\Actions\ActionManager::class, + 'Lorisleiva\Lody\LodyManager' => \Lorisleiva\Lody\LodyManager::class, + 'Lorisleiva\Lody\Psr4Resolver' => \Lorisleiva\Lody\Psr4Resolver::class, 'Maatwebsite\Excel\Cache\CacheManager' => \Maatwebsite\Excel\Cache\CacheManager::class, 'Maatwebsite\Excel\Files\Filesystem' => \Maatwebsite\Excel\Files\Filesystem::class, 'Maatwebsite\Excel\Files\TemporaryFileFactory' => \Maatwebsite\Excel\Files\TemporaryFileFactory::class, @@ -397,6 +400,9 @@ 'Livewire\EventBus' => \Livewire\EventBus::class, 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, + 'Lorisleiva\Actions\ActionManager' => \Lorisleiva\Actions\ActionManager::class, + 'Lorisleiva\Lody\LodyManager' => \Lorisleiva\Lody\LodyManager::class, + 'Lorisleiva\Lody\Psr4Resolver' => \Lorisleiva\Lody\Psr4Resolver::class, 'Maatwebsite\Excel\Cache\CacheManager' => \Maatwebsite\Excel\Cache\CacheManager::class, 'Maatwebsite\Excel\Files\Filesystem' => \Maatwebsite\Excel\Files\Filesystem::class, 'Maatwebsite\Excel\Files\TemporaryFileFactory' => \Maatwebsite\Excel\Files\TemporaryFileFactory::class, @@ -630,6 +636,9 @@ 'Livewire\EventBus' => \Livewire\EventBus::class, 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, + 'Lorisleiva\Actions\ActionManager' => \Lorisleiva\Actions\ActionManager::class, + 'Lorisleiva\Lody\LodyManager' => \Lorisleiva\Lody\LodyManager::class, + 'Lorisleiva\Lody\Psr4Resolver' => \Lorisleiva\Lody\Psr4Resolver::class, 'Maatwebsite\Excel\Cache\CacheManager' => \Maatwebsite\Excel\Cache\CacheManager::class, 'Maatwebsite\Excel\Files\Filesystem' => \Maatwebsite\Excel\Files\Filesystem::class, 'Maatwebsite\Excel\Files\TemporaryFileFactory' => \Maatwebsite\Excel\Files\TemporaryFileFactory::class, @@ -863,6 +872,9 @@ 'Livewire\EventBus' => \Livewire\EventBus::class, 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, + 'Lorisleiva\Actions\ActionManager' => \Lorisleiva\Actions\ActionManager::class, + 'Lorisleiva\Lody\LodyManager' => \Lorisleiva\Lody\LodyManager::class, + 'Lorisleiva\Lody\Psr4Resolver' => \Lorisleiva\Lody\Psr4Resolver::class, 'Maatwebsite\Excel\Cache\CacheManager' => \Maatwebsite\Excel\Cache\CacheManager::class, 'Maatwebsite\Excel\Files\Filesystem' => \Maatwebsite\Excel\Files\Filesystem::class, 'Maatwebsite\Excel\Files\TemporaryFileFactory' => \Maatwebsite\Excel\Files\TemporaryFileFactory::class, @@ -1096,6 +1108,9 @@ 'Livewire\EventBus' => \Livewire\EventBus::class, 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, + 'Lorisleiva\Actions\ActionManager' => \Lorisleiva\Actions\ActionManager::class, + 'Lorisleiva\Lody\LodyManager' => \Lorisleiva\Lody\LodyManager::class, + 'Lorisleiva\Lody\Psr4Resolver' => \Lorisleiva\Lody\Psr4Resolver::class, 'Maatwebsite\Excel\Cache\CacheManager' => \Maatwebsite\Excel\Cache\CacheManager::class, 'Maatwebsite\Excel\Files\Filesystem' => \Maatwebsite\Excel\Files\Filesystem::class, 'Maatwebsite\Excel\Files\TemporaryFileFactory' => \Maatwebsite\Excel\Files\TemporaryFileFactory::class, @@ -1329,6 +1344,9 @@ 'Livewire\EventBus' => \Livewire\EventBus::class, 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, + 'Lorisleiva\Actions\ActionManager' => \Lorisleiva\Actions\ActionManager::class, + 'Lorisleiva\Lody\LodyManager' => \Lorisleiva\Lody\LodyManager::class, + 'Lorisleiva\Lody\Psr4Resolver' => \Lorisleiva\Lody\Psr4Resolver::class, 'Maatwebsite\Excel\Cache\CacheManager' => \Maatwebsite\Excel\Cache\CacheManager::class, 'Maatwebsite\Excel\Files\Filesystem' => \Maatwebsite\Excel\Files\Filesystem::class, 'Maatwebsite\Excel\Files\TemporaryFileFactory' => \Maatwebsite\Excel\Files\TemporaryFileFactory::class, @@ -1562,6 +1580,9 @@ 'Livewire\EventBus' => \Livewire\EventBus::class, 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, + 'Lorisleiva\Actions\ActionManager' => \Lorisleiva\Actions\ActionManager::class, + 'Lorisleiva\Lody\LodyManager' => \Lorisleiva\Lody\LodyManager::class, + 'Lorisleiva\Lody\Psr4Resolver' => \Lorisleiva\Lody\Psr4Resolver::class, 'Maatwebsite\Excel\Cache\CacheManager' => \Maatwebsite\Excel\Cache\CacheManager::class, 'Maatwebsite\Excel\Files\Filesystem' => \Maatwebsite\Excel\Files\Filesystem::class, 'Maatwebsite\Excel\Files\TemporaryFileFactory' => \Maatwebsite\Excel\Files\TemporaryFileFactory::class, @@ -1795,6 +1816,9 @@ 'Livewire\EventBus' => \Livewire\EventBus::class, 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, + 'Lorisleiva\Actions\ActionManager' => \Lorisleiva\Actions\ActionManager::class, + 'Lorisleiva\Lody\LodyManager' => \Lorisleiva\Lody\LodyManager::class, + 'Lorisleiva\Lody\Psr4Resolver' => \Lorisleiva\Lody\Psr4Resolver::class, 'Maatwebsite\Excel\Cache\CacheManager' => \Maatwebsite\Excel\Cache\CacheManager::class, 'Maatwebsite\Excel\Files\Filesystem' => \Maatwebsite\Excel\Files\Filesystem::class, 'Maatwebsite\Excel\Files\TemporaryFileFactory' => \Maatwebsite\Excel\Files\TemporaryFileFactory::class, @@ -2028,6 +2052,9 @@ 'Livewire\EventBus' => \Livewire\EventBus::class, 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, + 'Lorisleiva\Actions\ActionManager' => \Lorisleiva\Actions\ActionManager::class, + 'Lorisleiva\Lody\LodyManager' => \Lorisleiva\Lody\LodyManager::class, + 'Lorisleiva\Lody\Psr4Resolver' => \Lorisleiva\Lody\Psr4Resolver::class, 'Maatwebsite\Excel\Cache\CacheManager' => \Maatwebsite\Excel\Cache\CacheManager::class, 'Maatwebsite\Excel\Files\Filesystem' => \Maatwebsite\Excel\Files\Filesystem::class, 'Maatwebsite\Excel\Files\TemporaryFileFactory' => \Maatwebsite\Excel\Files\TemporaryFileFactory::class, @@ -2261,6 +2288,9 @@ 'Livewire\EventBus' => \Livewire\EventBus::class, 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, + 'Lorisleiva\Actions\ActionManager' => \Lorisleiva\Actions\ActionManager::class, + 'Lorisleiva\Lody\LodyManager' => \Lorisleiva\Lody\LodyManager::class, + 'Lorisleiva\Lody\Psr4Resolver' => \Lorisleiva\Lody\Psr4Resolver::class, 'Maatwebsite\Excel\Cache\CacheManager' => \Maatwebsite\Excel\Cache\CacheManager::class, 'Maatwebsite\Excel\Files\Filesystem' => \Maatwebsite\Excel\Files\Filesystem::class, 'Maatwebsite\Excel\Files\TemporaryFileFactory' => \Maatwebsite\Excel\Files\TemporaryFileFactory::class, @@ -2494,6 +2524,9 @@ 'Livewire\EventBus' => \Livewire\EventBus::class, 'Livewire\LivewireManager' => \Livewire\LivewireManager::class, 'Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys' => \Livewire\Mechanisms\ExtendBlade\DeterministicBladeKeys::class, + 'Lorisleiva\Actions\ActionManager' => \Lorisleiva\Actions\ActionManager::class, + 'Lorisleiva\Lody\LodyManager' => \Lorisleiva\Lody\LodyManager::class, + 'Lorisleiva\Lody\Psr4Resolver' => \Lorisleiva\Lody\Psr4Resolver::class, 'Maatwebsite\Excel\Cache\CacheManager' => \Maatwebsite\Excel\Cache\CacheManager::class, 'Maatwebsite\Excel\Files\Filesystem' => \Maatwebsite\Excel\Files\Filesystem::class, 'Maatwebsite\Excel\Files\TemporaryFileFactory' => \Maatwebsite\Excel\Files\TemporaryFileFactory::class, diff --git a/_ide_helper.php b/_ide_helper.php index f12317437..5fc8dcff3 100644 --- a/_ide_helper.php +++ b/_ide_helper.php @@ -4342,7 +4342,7 @@ public static function macroCall($method, $parameters) */ public static function lock($name, $seconds = 0, $owner = null) { - /** @var \Illuminate\Cache\FileStore $instance */ + /** @var \Illuminate\Cache\DatabaseStore $instance */ return $instance->lock($name, $seconds, $owner); } /** @@ -4355,65 +4355,54 @@ public static function lock($name, $seconds = 0, $owner = null) */ public static function restoreLock($name, $owner) { - /** @var \Illuminate\Cache\FileStore $instance */ + /** @var \Illuminate\Cache\DatabaseStore $instance */ return $instance->restoreLock($name, $owner); } /** - * Remove all items from the cache. - * - * @return bool - * @static - */ - public static function flush() - { - /** @var \Illuminate\Cache\FileStore $instance */ - return $instance->flush(); - } - /** - * Get the full path for the given cache key. + * Remove an item from the cache if it is expired. * * @param string $key - * @return string + * @return bool * @static */ - public static function path($key) + public static function forgetIfExpired($key) { - /** @var \Illuminate\Cache\FileStore $instance */ - return $instance->path($key); + /** @var \Illuminate\Cache\DatabaseStore $instance */ + return $instance->forgetIfExpired($key); } /** - * Get the Filesystem instance. + * Remove all items from the cache. * - * @return \Illuminate\Filesystem\Filesystem + * @return bool * @static */ - public static function getFilesystem() + public static function flush() { - /** @var \Illuminate\Cache\FileStore $instance */ - return $instance->getFilesystem(); + /** @var \Illuminate\Cache\DatabaseStore $instance */ + return $instance->flush(); } /** - * Get the working directory of the cache. + * Get the underlying database connection. * - * @return string + * @return \Illuminate\Database\MySqlConnection * @static */ - public static function getDirectory() + public static function getConnection() { - /** @var \Illuminate\Cache\FileStore $instance */ - return $instance->getDirectory(); + /** @var \Illuminate\Cache\DatabaseStore $instance */ + return $instance->getConnection(); } /** - * Set the cache directory where locks should be stored. + * Specify the name of the connection that should be used to manage locks. * - * @param string|null $lockDirectory - * @return \Illuminate\Cache\FileStore + * @param \Illuminate\Database\ConnectionInterface $connection + * @return \Illuminate\Cache\DatabaseStore * @static */ - public static function setLockDirectory($lockDirectory) + public static function setLockConnection($connection) { - /** @var \Illuminate\Cache\FileStore $instance */ - return $instance->setLockDirectory($lockDirectory); + /** @var \Illuminate\Cache\DatabaseStore $instance */ + return $instance->setLockConnection($connection); } /** * Get the cache key prefix. @@ -4423,7 +4412,7 @@ public static function setLockDirectory($lockDirectory) */ public static function getPrefix() { - /** @var \Illuminate\Cache\FileStore $instance */ + /** @var \Illuminate\Cache\DatabaseStore $instance */ return $instance->getPrefix(); } @@ -19375,6 +19364,310 @@ public static function originalMethod() } +} + + namespace Lorisleiva\Actions\Facades { + /** + * + * + * @see ActionManager + */ + class Actions { + /** + * + * + * @param \Lorisleiva\Actions\class-string $jobDecoratorClass + * @static + */ + public static function useJobDecorator($jobDecoratorClass) + { + return \Lorisleiva\Actions\ActionManager::useJobDecorator($jobDecoratorClass); + } + /** + * + * + * @param \Lorisleiva\Actions\class-string $uniqueJobDecoratorClass + * @static + */ + public static function useUniqueJobDecorator($uniqueJobDecoratorClass) + { + return \Lorisleiva\Actions\ActionManager::useUniqueJobDecorator($uniqueJobDecoratorClass); + } + /** + * + * + * @static + */ + public static function setBacktraceLimit($backtraceLimit) + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->setBacktraceLimit($backtraceLimit); + } + /** + * + * + * @static + */ + public static function setDesignPatterns($designPatterns) + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->setDesignPatterns($designPatterns); + } + /** + * + * + * @static + */ + public static function getDesignPatterns() + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->getDesignPatterns(); + } + /** + * + * + * @static + */ + public static function registerDesignPattern($designPattern) + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->registerDesignPattern($designPattern); + } + /** + * + * + * @static + */ + public static function getDesignPatternsMatching($usedTraits) + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->getDesignPatternsMatching($usedTraits); + } + /** + * + * + * @static + */ + public static function extend($app, $abstract) + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->extend($app, $abstract); + } + /** + * + * + * @static + */ + public static function isExtending($abstract) + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->isExtending($abstract); + } + /** + * + * + * @static + */ + public static function shouldExtend($abstract) + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->shouldExtend($abstract); + } + /** + * + * + * @static + */ + public static function identifyAndDecorate($instance) + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->identifyAndDecorate($instance); + } + /** + * + * + * @static + */ + public static function identifyFromBacktrace($usedTraits, $frame = null) + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->identifyFromBacktrace($usedTraits, $frame); + } + /** + * + * + * @static + */ + public static function registerRoutes($paths = 'app/Actions') + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->registerRoutes($paths); + } + /** + * + * + * @static + */ + public static function registerCommands($paths = 'app/Actions') + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->registerCommands($paths); + } + /** + * + * + * @static + */ + public static function registerRoutesForAction($className) + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->registerRoutesForAction($className); + } + /** + * + * + * @static + */ + public static function registerCommandsForAction($className) + { + /** @var \Lorisleiva\Actions\ActionManager $instance */ + return $instance->registerCommandsForAction($className); + } + + } + +} + + namespace Lorisleiva\Lody { + /** + * + * + * @see LodyManager + */ + class Lody { + /** + * + * + * @static + */ + public static function classes($paths, $recursive = true) + { + /** @var \Lorisleiva\Lody\LodyManager $instance */ + return $instance->classes($paths, $recursive); + } + /** + * + * + * @static + */ + public static function classesFromFinder($finder) + { + /** @var \Lorisleiva\Lody\LodyManager $instance */ + return $instance->classesFromFinder($finder); + } + /** + * + * + * @static + */ + public static function files($paths, $recursive = true, $hidden = false) + { + /** @var \Lorisleiva\Lody\LodyManager $instance */ + return $instance->files($paths, $recursive, $hidden); + } + /** + * + * + * @static + */ + public static function filesFromFinder($finder) + { + /** @var \Lorisleiva\Lody\LodyManager $instance */ + return $instance->filesFromFinder($finder); + } + /** + * + * + * @static + */ + public static function resolvePathUsing($callback) + { + /** @var \Lorisleiva\Lody\LodyManager $instance */ + return $instance->resolvePathUsing($callback); + } + /** + * + * + * @static + */ + public static function resolvePath($path) + { + /** @var \Lorisleiva\Lody\LodyManager $instance */ + return $instance->resolvePath($path); + } + /** + * + * + * @static + */ + public static function resolveClassnameUsing($callback) + { + /** @var \Lorisleiva\Lody\LodyManager $instance */ + return $instance->resolveClassnameUsing($callback); + } + /** + * + * + * @static + */ + public static function resolveClassname($file) + { + /** @var \Lorisleiva\Lody\LodyManager $instance */ + return $instance->resolveClassname($file); + } + /** + * + * + * @static + */ + public static function setBasePath($basePath) + { + /** @var \Lorisleiva\Lody\LodyManager $instance */ + return $instance->setBasePath($basePath); + } + /** + * + * + * @static + */ + public static function getBasePath($path = '') + { + /** @var \Lorisleiva\Lody\LodyManager $instance */ + return $instance->getBasePath($path); + } + /** + * + * + * @static + */ + public static function setAutoloadPath($autoloadPath) + { + /** @var \Lorisleiva\Lody\LodyManager $instance */ + return $instance->setAutoloadPath($autoloadPath); + } + /** + * + * + * @static + */ + public static function getAutoloadPath() + { + /** @var \Lorisleiva\Lody\LodyManager $instance */ + return $instance->getAutoloadPath(); + } + + } + } namespace Maatwebsite\Excel\Facades { @@ -27448,6 +27741,8 @@ class Vite extends \Illuminate\Support\Facades\Vite {} class TimeZoneHelper extends \App\Helpers\TimeZoneHelper {} class EloquentSerialize extends \AnourValar\EloquentSerialize\Facades\EloquentSerializeFacade {} class Livewire extends \Livewire\Livewire {} + class Action extends \Lorisleiva\Actions\Facades\Actions {} + class Lody extends \Lorisleiva\Lody\Lody {} class Excel extends \Maatwebsite\Excel\Facades\Excel {} class Flare extends \Spatie\LaravelIgnition\Facades\Flare {} diff --git a/app/Actions/Notifications/SendDatabaseTestNotification.php b/app/Actions/Notifications/SendDatabaseTestNotification.php new file mode 100644 index 000000000..6611ad491 --- /dev/null +++ b/app/Actions/Notifications/SendDatabaseTestNotification.php @@ -0,0 +1,29 @@ +notify( + Notification::make() + ->title('Test database notification received!') + ->body('You say pong') + ->success() + ->toDatabase(), + ); + + Notification::make() + ->title('Test database notification sent.') + ->body('I say ping') + ->success() + ->send(); + } +} diff --git a/app/Actions/Notifications/SendMailTestNotification.php b/app/Actions/Notifications/SendMailTestNotification.php new file mode 100644 index 000000000..735a114c7 --- /dev/null +++ b/app/Actions/Notifications/SendMailTestNotification.php @@ -0,0 +1,35 @@ +title('You need to add mail recipients!') + ->warning() + ->send(); + + return; + } + + foreach ($recipients as $recipient) { + Mail::to($recipient) + ->send(new TestMail()); + } + + Notification::make() + ->title('Test mail notification sent.') + ->success() + ->send(); + } +} diff --git a/app/Actions/Notifications/SendTelegramTestNotification.php b/app/Actions/Notifications/SendTelegramTestNotification.php new file mode 100644 index 000000000..c7c64a815 --- /dev/null +++ b/app/Actions/Notifications/SendTelegramTestNotification.php @@ -0,0 +1,35 @@ +title('You need to add Telegram recipients!') + ->warning() + ->send(); + + return; + } + + foreach ($recipients as $recipient) { + FacadesNotification::route('telegram_chat_id', $recipient['telegram_chat_id']) + ->notify(new TestNotification); + } + + Notification::make() + ->title('Test Telegram notification sent.') + ->success() + ->send(); + } +} diff --git a/app/Actions/Notifications/SendWebhookTestNotification.php b/app/Actions/Notifications/SendWebhookTestNotification.php new file mode 100644 index 000000000..eff22684d --- /dev/null +++ b/app/Actions/Notifications/SendWebhookTestNotification.php @@ -0,0 +1,37 @@ +title('You need to add webhook urls!') + ->warning() + ->send(); + + return; + } + + foreach ($urls as $url) { + WebhookCall::create() + ->url($url['url']) + ->payload(['message' => '👋 Testing the Webhook notification channel.']) + ->doNotSign() + ->dispatch(); + } + + Notification::make() + ->title('Test webhook notification sent.') + ->success() + ->send(); + } +} diff --git a/app/Filament/Pages/Settings/NotificationPage.php b/app/Filament/Pages/Settings/NotificationPage.php index 49dfaeaad..a79d61165 100755 --- a/app/Filament/Pages/Settings/NotificationPage.php +++ b/app/Filament/Pages/Settings/NotificationPage.php @@ -2,18 +2,15 @@ namespace App\Filament\Pages\Settings; -use App\Forms\Components\TestDatabaseNotification; -use App\Forms\Components\TestMailNotification; -use App\Forms\Components\TestTelegramNotification; -use App\Mail\Test; -use App\Notifications\Telegram\TestNotification as TelegramTestNotification; +use App\Actions\Notifications\SendDatabaseTestNotification; +use App\Actions\Notifications\SendMailTestNotification; +use App\Actions\Notifications\SendTelegramTestNotification; +use App\Actions\Notifications\SendWebhookTestNotification; use App\Settings\NotificationSettings; use Filament\Forms; use Filament\Forms\Form; -use Filament\Notifications\Notification; use Filament\Pages\SettingsPage; -use Illuminate\Support\Facades\Mail; -use Illuminate\Support\Facades\Notification as FacadesNotification; +use Illuminate\Support\Facades\Auth; class NotificationPage extends SettingsPage { @@ -60,7 +57,7 @@ public function form(Form $form): Form Forms\Components\Toggle::make('database_enabled') ->label('Enable database notifications') ->reactive() - ->columnSpan(2), + ->columnSpanFull(), Forms\Components\Grid::make([ 'default' => 1, ]) @@ -70,12 +67,16 @@ public function form(Form $form): Form ->schema([ Forms\Components\Toggle::make('database_on_speedtest_run') ->label('Notify on every speedtest run') - ->columnSpan(2), + ->columnSpanFull(), Forms\Components\Toggle::make('database_on_threshold_failure') ->label('Notify on threshold failures') - ->columnSpan(2), + ->columnSpanFull(), ]), - TestDatabaseNotification::make('test channel'), + Forms\Components\Actions::make([ + Forms\Components\Actions\Action::make('test database') + ->label('Test database channel') + ->action(fn () => SendDatabaseTestNotification::run(user: Auth::user())), + ]), ]), ]) ->compact() @@ -89,34 +90,36 @@ public function form(Form $form): Form Forms\Components\Toggle::make('mail_enabled') ->label('Enable mail notifications') ->reactive() - ->columnSpan(2), + ->columnSpanFull(), Forms\Components\Grid::make([ 'default' => 1, ]) + ->hidden(fn (Forms\Get $get) => $get('mail_enabled') !== true) ->schema([ Forms\Components\Fieldset::make('Triggers') ->schema([ Forms\Components\Toggle::make('mail_on_speedtest_run') ->label('Notify on every speedtest run') - ->columnSpan(2), + ->columnSpanFull(), Forms\Components\Toggle::make('mail_on_threshold_failure') ->label('Notify on threshold failures') - ->columnSpan(2), + ->columnSpanFull(), ]), - ]) - ->hidden(fn (Forms\Get $get) => $get('mail_enabled') !== true), - - Forms\Components\Repeater::make('mail_recipients') - ->label('Recipients') - ->schema([ - Forms\Components\TextInput::make('email_address') - ->email() - ->required(), - ]) - ->hidden(fn (Forms\Get $get) => $get('mail_enabled') !== true) - ->columnSpan(['md' => 2]), - TestMailNotification::make('test channel') - ->hidden(fn (Forms\Get $get) => $get('mail_enabled') !== true), + Forms\Components\Repeater::make('mail_recipients') + ->label('Recipients') + ->schema([ + Forms\Components\TextInput::make('email_address') + ->email() + ->required(), + ]) + ->columnSpanFull(), + Forms\Components\Actions::make([ + Forms\Components\Actions\Action::make('test mail') + ->label('Test mail channel') + ->action(fn (Forms\Get $get) => SendMailTestNotification::run(recipients: $get('mail_recipients'))) + ->hidden(fn (Forms\Get $get) => ! count($get('mail_recipients'))), + ]), + ]), ]) ->compact() ->columns([ @@ -129,33 +132,80 @@ public function form(Form $form): Form Forms\Components\Toggle::make('telegram_enabled') ->label('Enable telegram notifications') ->reactive() - ->columnSpan(2), + ->columnSpanFull(), Forms\Components\Grid::make([ - 'default' => 1, ]) + 'default' => 1, + ]) ->hidden(fn (Forms\Get $get) => $get('telegram_enabled') !== true) ->schema([ Forms\Components\Fieldset::make('Triggers') ->schema([ Forms\Components\Toggle::make('telegram_on_speedtest_run') ->label('Notify on every speedtest run') - ->columnSpan(2), + ->columnSpanFull(), Forms\Components\Toggle::make('telegram_on_threshold_failure') ->label('Notify on threshold failures') - ->columnSpan(2), + ->columnSpanFull(), ]), + Forms\Components\Repeater::make('telegram_recipients') + ->label('Recipients') + ->schema([ + Forms\Components\TextInput::make('telegram_chat_id') + ->label('Telegram Chat ID') + ->maxLength(50) + ->required(), + ]) + ->columnSpanFull(), + Forms\Components\Actions::make([ + Forms\Components\Actions\Action::make('test telegram') + ->label('Test Telegram channel') + ->action(fn (Forms\Get $get) => SendTelegramTestNotification::run(recipients: $get('telegram_recipients'))) + ->hidden(fn (Forms\Get $get) => ! count($get('telegram_recipients')) || blank(config('telegram.bot'))), + ]), ]), - Forms\Components\Repeater::make('telegram_recipients') - ->label('Recipients') + ]) + ->compact() + ->columns([ + 'default' => 1, + 'md' => 2, + ]), + + Forms\Components\Section::make('Webhook') + ->schema([ + Forms\Components\Toggle::make('webhook_enabled') + ->label('Enable webhook notifications') + ->reactive() + ->columnSpanFull(), + Forms\Components\Grid::make([ + 'default' => 1, + ]) + ->hidden(fn (Forms\Get $get) => $get('webhook_enabled') !== true) ->schema([ - Forms\Components\TextInput::make('telegram_chat_id') - ->maxLength(50) - ->required() - ->columnSpan(['md' => 2]), - ]) - ->hidden(fn (Forms\Get $get) => $get('telegram_enabled') !== true) - ->columnSpan(['md' => 2]), - TestTelegramNotification::make('test channel') - ->hidden(fn (Forms\Get $get) => $get('telegram_enabled') !== true), + Forms\Components\Fieldset::make('Triggers') + ->schema([ + Forms\Components\Toggle::make('webhook_on_speedtest_run') + ->label('Notify on every speedtest run') + ->columnSpan(2), + Forms\Components\Toggle::make('webhook_on_threshold_failure') + ->label('Notify on threshold failures') + ->columnSpan(2), + ]), + Forms\Components\Repeater::make('webhook_urls') + ->label('Recipients') + ->schema([ + Forms\Components\TextInput::make('url') + ->maxLength(2000) + ->required() + ->url(), + ]) + ->columnSpanFull(), + Forms\Components\Actions::make([ + Forms\Components\Actions\Action::make('test webhook') + ->label('Test webhook channel') + ->action(fn (Forms\Get $get) => SendWebhookTestNotification::run(urls: $get('webhook_urls'))) + ->hidden(fn (Forms\Get $get) => ! count($get('webhook_urls'))), + ]), + ]), ]) ->compact() ->columns([ @@ -177,85 +227,4 @@ public function form(Form $form): Form ]), ]); } - - public function sendTestDatabaseNotification(): void - { - $recipient = auth()->user(); - - $recipient->notify( - Notification::make() - ->title('Test database notification received!') - ->body('You say pong') - ->success() - ->toDatabase(), - ); - - Notification::make() - ->title('Test database notification sent.') - ->body('I say ping') - ->success() - ->send(); - } - - public function sendTestMailNotification(): void - { - $notificationSettings = new (NotificationSettings::class); - - if (blank($notificationSettings->mail_recipients)) { - Notification::make() - ->title('You need to add mail recipients.') - ->body('Make sure to click "Save changes" before testing mail notifications.') - ->warning() - ->send(); - - return; - } - - foreach ($notificationSettings->mail_recipients as $recipient) { - Mail::to($recipient) - ->send(new Test()); - } - - Notification::make() - ->title('Test mail notification sent.') - ->success() - ->send(); - } - - public function sendTestTelegramNotification(): void - { - $notificationSettings = new (NotificationSettings::class); - - $bot = config('telegram.bot'); - - if (blank($bot)) { - Notification::make() - ->title('No Telegram bot provided.') - ->body('You need to add "TELEGRAM_BOT_TOKEN" in your .env file or add it as environment variable') - ->danger() - ->send(); - - return; - } - - if (blank($notificationSettings->telegram_recipients)) { - Notification::make() - ->title('You need to add Telegram recipients.') - ->body('Make sure to click "Save changes" before testing Telegram notifications.') - ->warning() - ->send(); - - return; - } - - foreach ($notificationSettings->telegram_recipients as $recipient) { - FacadesNotification::route('telegram_chat_id', $recipient['telegram_chat_id']) - ->notify(new TelegramTestNotification); - } - - Notification::make() - ->title('Test Telegram notification sent.') - ->success() - ->send(); - } } diff --git a/app/Forms/Components/TestDatabaseNotification.php b/app/Forms/Components/TestDatabaseNotification.php deleted file mode 100644 index 017e4c8e0..000000000 --- a/app/Forms/Components/TestDatabaseNotification.php +++ /dev/null @@ -1,10 +0,0 @@ -notificationSettings->webhook_enabled) { + if ($this->notificationSettings->webhook_on_speedtest_run && count($this->notificationSettings->webhook_urls)) { + foreach ($this->notificationSettings->webhook_urls as $url) { + WebhookCall::create() + ->url($url['url']) + ->payload([ + 'result_id' => $event->result->id, + 'site_name' => $this->generalSettings->site_name, + 'ping' => $event->result->ping, + 'download' => $event->result->downloadBits, + 'upload' => $event->result->uploadBits, + ]) + ->doNotSign() + ->dispatch(); + } + } + } } } diff --git a/app/Listeners/Threshold/AbsoluteListener.php b/app/Listeners/Threshold/AbsoluteListener.php index b5a4c3012..05180e44d 100644 --- a/app/Listeners/Threshold/AbsoluteListener.php +++ b/app/Listeners/Threshold/AbsoluteListener.php @@ -10,8 +10,10 @@ use App\Telegram\TelegramNotification; use Filament\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; +use Spatie\WebhookServer\WebhookCall; class AbsoluteListener implements ShouldQueue { @@ -60,6 +62,11 @@ public function handle(ResultCreated $event): void if ($this->notificationSettings->telegram_enabled == true && $this->notificationSettings->telegram_on_threshold_failure == true) { $this->telegramChannel($event); } + + // Webhook notification channel + if ($this->notificationSettings->webhook_enabled == true && $this->notificationSettings->webhook_on_threshold_failure == true) { + $this->webhookChannel($event); + } } /** @@ -211,4 +218,71 @@ protected function telegramChannel(ResultCreated $event): void } } } + + /** + * Handle webhook notifications. + * + * TODO: refactor + */ + protected function webhookChannel(ResultCreated $event): void + { + $failedThresholds = []; + + if (! count($this->notificationSettings->webhook_urls) > 0) { + Log::info('Skipping sending webhook notification, no urls.'); + } + + // Download threshold + if ($this->thresholdSettings->absolute_download > 0) { + if (absoluteDownloadThresholdFailed($this->thresholdSettings->absolute_download, $event->result->download)) { + array_push($failedThresholds, [ + 'name' => 'Download', + 'threshold' => $this->thresholdSettings->absolute_download, + 'value' => toBits(convertSize($event->result->download), 2), + ]); + } + } + + // Upload threshold + if ($this->thresholdSettings->absolute_upload > 0) { + if (absoluteUploadThresholdFailed($this->thresholdSettings->absolute_upload, $event->result->upload)) { + array_push($failedThresholds, [ + 'name' => 'Upload', + 'threshold' => $this->thresholdSettings->absolute_upload, + 'value' => toBits(convertSize($event->result->upload), 2), + ]); + } + } + + // Ping threshold + if ($this->thresholdSettings->absolute_ping > 0) { + if (absolutePingThresholdFailed($this->thresholdSettings->absolute_ping, $event->result->ping)) { + array_push($failedThresholds, [ + 'name' => 'Ping', + 'threshold' => $this->thresholdSettings->absolute_ping, + 'value' => round($event->result->ping, 2), + ]); + } + } + + if (count($failedThresholds)) { + foreach ($this->notificationSettings->webhook_urls as $url) { + Http::post($url['url'], [ + 'result_id' => $event->result->id, + 'site_name' => $this->generalSettings->site_name, + 'metrics' => $failedThresholds, + ]); + + WebhookCall::create() + ->url($url['url']) + ->payload([ + 'result_id' => $event->result->id, + 'site_name' => $this->generalSettings->site_name, + 'metrics' => $failedThresholds, + ]) + ->doNotSign() + ->dispatch(); + } + } + } } diff --git a/app/Models/Result.php b/app/Models/Result.php index 9500cf9e0..684c7d815 100644 --- a/app/Models/Result.php +++ b/app/Models/Result.php @@ -102,9 +102,9 @@ public function getJitterData(): array $data = json_decode($this->data, true); return [ - 'download' => $data['download']['latency']['jitter'] ?? null, - 'upload' => $data['upload']['latency']['jitter'] ?? null, - 'ping' => $data['ping']['jitter'] ?? null, + 'download' => Arr::get($data, 'download.latency.jitter'), + 'upload' => Arr::get($data, 'upload.latency.jitter'), + 'ping' => Arr::get($data, 'ping.jitter'), ]; } diff --git a/app/Settings/NotificationSettings.php b/app/Settings/NotificationSettings.php index 182794dc8..f23dfdbf6 100644 --- a/app/Settings/NotificationSettings.php +++ b/app/Settings/NotificationSettings.php @@ -28,6 +28,14 @@ class NotificationSettings extends Settings public ?array $telegram_recipients; + public bool $webhook_enabled; + + public bool $webhook_on_speedtest_run; + + public bool $webhook_on_threshold_failure; + + public ?array $webhook_urls; + public static function group(): string { return 'notification'; diff --git a/composer.json b/composer.json index 327f6d5ba..b96595195 100644 --- a/composer.json +++ b/composer.json @@ -23,9 +23,12 @@ "laravel/sanctum": "^3.3.3", "laravel/tinker": "^2.9.0", "livewire/livewire": "^3.4.4", + "lorisleiva/laravel-actions": "^2.7", "maatwebsite/excel": "^3.1.52", "maennchen/zipstream-php": "^2.4", - "spatie/laravel-settings": "^2.8.3" + "spatie/laravel-settings": "^2.8.3", + "spatie/laravel-webhook-server": "^3.8", + "timokoerber/laravel-one-time-operations": "^1.4" }, "require-dev": { "barryvdh/laravel-ide-helper": "^2.13", diff --git a/composer.lock b/composer.lock index 25a024710..121ee5c93 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c1fc419fdb039a495ad46edcf52b3d33", + "content-hash": "f44490fddff7bd37173e0cd526bfa6f5", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -3879,6 +3879,153 @@ ], "time": "2024-01-28T19:07:11+00:00" }, + { + "name": "lorisleiva/laravel-actions", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/lorisleiva/laravel-actions.git", + "reference": "5d2e2a670ad758496021943a8d6dea4014e213d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lorisleiva/laravel-actions/zipball/5d2e2a670ad758496021943a8d6dea4014e213d6", + "reference": "5d2e2a670ad758496021943a8d6dea4014e213d6", + "shasum": "" + }, + "require": { + "illuminate/contracts": "9.0 - 9.34 || ^9.36 || ^10.0", + "lorisleiva/lody": "^0.4", + "php": "^8.0" + }, + "require-dev": { + "orchestra/testbench": "^8.5", + "pestphp/pest": "^1.23", + "phpunit/phpunit": "^9.6" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Lorisleiva\\Actions\\ActionServiceProvider" + ], + "aliases": { + "Action": "Lorisleiva\\Actions\\Facades\\Actions" + } + } + }, + "autoload": { + "psr-4": { + "Lorisleiva\\Actions\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Loris Leiva", + "email": "loris.leiva@gmail.com", + "homepage": "https://lorisleiva.com", + "role": "Developer" + } + ], + "description": "Laravel components that take care of one specific task", + "homepage": "https://github.com/lorisleiva/laravel-actions", + "keywords": [ + "action", + "command", + "component", + "controller", + "job", + "laravel", + "object" + ], + "support": { + "issues": "https://github.com/lorisleiva/laravel-actions/issues", + "source": "https://github.com/lorisleiva/laravel-actions/tree/v2.7.3" + }, + "funding": [ + { + "url": "https://github.com/sponsors/lorisleiva", + "type": "github" + } + ], + "time": "2024-01-09T16:57:43+00:00" + }, + { + "name": "lorisleiva/lody", + "version": "v0.4.0", + "source": { + "type": "git", + "url": "https://github.com/lorisleiva/lody.git", + "reference": "1a43e8e423f3b2b64119542bc44a2071208fae16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lorisleiva/lody/zipball/1a43e8e423f3b2b64119542bc44a2071208fae16", + "reference": "1a43e8e423f3b2b64119542bc44a2071208fae16", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^8.0|^9.0|^10.0", + "php": "^8.0" + }, + "require-dev": { + "orchestra/testbench": "^8.0", + "pestphp/pest": "^1.20.0", + "phpunit/phpunit": "^9.5.10" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Lorisleiva\\Lody\\LodyServiceProvider" + ], + "aliases": { + "Lody": "Lorisleiva\\Lody\\Lody" + } + } + }, + "autoload": { + "psr-4": { + "Lorisleiva\\Lody\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Loris Leiva", + "email": "loris.leiva@gmail.com", + "homepage": "https://lorisleiva.com", + "role": "Developer" + } + ], + "description": "Load files and classes as lazy collections in Laravel.", + "homepage": "https://github.com/lorisleiva/lody", + "keywords": [ + "classes", + "collection", + "files", + "laravel", + "load" + ], + "support": { + "issues": "https://github.com/lorisleiva/lody/issues", + "source": "https://github.com/lorisleiva/lody/tree/v0.4.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/lorisleiva", + "type": "github" + } + ], + "time": "2023-02-05T15:03:45+00:00" + }, { "name": "maatwebsite/excel", "version": "3.1.52", @@ -6637,6 +6784,80 @@ ], "time": "2023-03-30T12:47:39+00:00" }, + { + "name": "spatie/laravel-webhook-server", + "version": "3.8.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-webhook-server.git", + "reference": "bdcd23abd78805705a5ac29a66fddefea3fd32a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-webhook-server/zipball/bdcd23abd78805705a5ac29a66fddefea3fd32a0", + "reference": "bdcd23abd78805705a5ac29a66fddefea3fd32a0", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/guzzle": "^6.3|^7.3", + "illuminate/bus": "^8.50|^9.0|^10.0", + "illuminate/queue": "^8.50|^9.0|^10.0", + "illuminate/support": "^8.50|^9.0|^10.0", + "php": "^8.0", + "spatie/laravel-package-tools": "^1.11" + }, + "require-dev": { + "mockery/mockery": "^1.4.3", + "orchestra/testbench": "^6.19|^7.0", + "pestphp/pest": "^1.22", + "pestphp/pest-plugin-laravel": "^1.3", + "spatie/test-time": "^1.2.2" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\WebhookServer\\WebhookServerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\WebhookServer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Send webhooks in Laravel apps", + "homepage": "https://github.com/spatie/laravel-webhook-server", + "keywords": [ + "laravel-webhook-server", + "server", + "spatie", + "webhook" + ], + "support": { + "source": "https://github.com/spatie/laravel-webhook-server/tree/3.8.0" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + } + ], + "time": "2023-11-27T11:46:04+00:00" + }, { "name": "spatie/temporary-directory", "version": "2.2.1", @@ -9144,6 +9365,70 @@ }, "time": "2023-12-08T13:03:43+00:00" }, + { + "name": "timokoerber/laravel-one-time-operations", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/TimoKoerber/laravel-one-time-operations.git", + "reference": "148fd0a05ddd4fbc2c8b65846cfb4a4cc788e37c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/TimoKoerber/laravel-one-time-operations/zipball/148fd0a05ddd4fbc2c8b65846cfb4a4cc788e37c", + "reference": "148fd0a05ddd4fbc2c8b65846cfb4a4cc788e37c", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^9.0|^10.0", + "illuminate/support": "^9.0|^10.0", + "php": "^8.0" + }, + "require-dev": { + "orchestra/testbench": "7", + "phpunit/phpunit": "^9.4" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "TimoKoerber\\LaravelOneTimeOperations\\Providers\\OneTimeOperationsServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "TimoKoerber\\LaravelOneTimeOperations\\": "src/", + "TimoKoerber\\LaravelOneTimeOperations\\Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "timo.koerber", + "email": "koerber.timo@gmail.com", + "homepage": "https://www.timokoerber.com", + "role": "Developer" + } + ], + "description": "Run operations once after deployment - just like you do it with migrations!", + "homepage": "https://github.com/timokoerber/laravel-one-time-operations", + "keywords": [ + "deployment", + "jobs", + "laravel", + "migrations", + "operations" + ], + "support": { + "issues": "https://github.com/TimoKoerber/laravel-one-time-operations/issues", + "source": "https://github.com/TimoKoerber/laravel-one-time-operations/tree/1.4.0" + }, + "time": "2023-12-16T18:30:50+00:00" + }, { "name": "vlucas/phpdotenv", "version": "v5.6.0", @@ -12232,5 +12517,8 @@ "php": "^8.1" }, "platform-dev": [], + "platform-overrides": { + "php": "8.2" + }, "plugin-api-version": "2.6.0" } diff --git a/config/speedtest.php b/config/speedtest.php index b657c42ee..ffbaab19a 100644 --- a/config/speedtest.php +++ b/config/speedtest.php @@ -6,9 +6,9 @@ /** * Build information */ - 'build_date' => Carbon::parse('2024-02-04'), + 'build_date' => Carbon::parse('2024-02-06'), - 'build_version' => 'v0.14.7', + 'build_version' => 'v0.15.0', /** * General diff --git a/config/webhook-server.php b/config/webhook-server.php new file mode 100644 index 000000000..4e8b53819 --- /dev/null +++ b/config/webhook-server.php @@ -0,0 +1,83 @@ + 'default', + + /* + * The default queue connection that should be used to send webhook requests. + */ + 'connection' => null, + + /* + * The default http verb to use. + */ + 'http_verb' => 'post', + + /* + * Proxies to use for request. + * + * See https://docs.guzzlephp.org/en/stable/request-options.html#proxy + */ + 'proxy' => null, + + /* + * This class is responsible for calculating the signature that will be added to + * the headers of the webhook request. A webhook client can use the signature + * to verify the request hasn't been tampered with. + */ + 'signer' => \Spatie\WebhookServer\Signer\DefaultSigner::class, + + /* + * This is the name of the header where the signature will be added. + */ + 'signature_header_name' => 'Signature', + + /* + * These are the headers that will be added to all webhook requests. + */ + 'headers' => [ + 'Content-Type' => 'application/json', + ], + + /* + * If a call to a webhook takes longer that this amount of seconds + * the attempt will be considered failed. + */ + 'timeout_in_seconds' => env('WEBHOOK_TIMEOUT_IN_SECONDS', 3), + + /* + * The amount of times the webhook should be called before we give up. + */ + 'tries' => env('WEBHOOK_TRIES', 3), + + /* + * This class determines how many seconds there should be between attempts. + */ + 'backoff_strategy' => \Spatie\WebhookServer\BackoffStrategy\ExponentialBackoffStrategy::class, + + /* + * This class is used to dispatch webhooks on to the queue. + */ + 'webhook_job' => \Spatie\WebhookServer\CallWebhookJob::class, + + /* + * By default we will verify that the ssl certificate of the destination + * of the webhook is valid. + */ + 'verify_ssl' => env('WEBHOOK_VERIFY_SSL', true), + + /* + * When set to true, an exception will be thrown when the last attempt fails + */ + 'throw_exception_on_failure' => env('WEBHOOK_THROW_EXCEPTION_ON_FAILURE', false), + + /* + * When using Laravel Horizon you can specify tags that should be used on the + * underlying job that performs the webhook request. + */ + 'tags' => [], +]; diff --git a/database/migrations/2023_09_11_144858_create_webhook_notification_settings.php b/database/migrations/2023_09_11_144858_create_webhook_notification_settings.php new file mode 100644 index 000000000..23d51c5dc --- /dev/null +++ b/database/migrations/2023_09_11_144858_create_webhook_notification_settings.php @@ -0,0 +1,17 @@ +migrator->add('notification.webhook_enabled', false); + $this->migrator->add('notification.webhook_on_speedtest_run', false); + $this->migrator->add('notification.webhook_on_threshold_failure', false); + $this->migrator->add('notification.webhook_urls', null); + } +}; diff --git a/package-lock.json b/package-lock.json index 56a4ca238..3c41134dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -870,9 +870,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001582", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001582.tgz", - "integrity": "sha512-vsJG3V5vgfduaQGVxL53uSX/HUzxyr2eA8xCo36OLal7sRcSZbibJtLeh0qja4sFOr/QQGt4opB4tOy+eOgAxg==", + "version": "1.0.30001584", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001584.tgz", + "integrity": "sha512-LOz7CCQ9M1G7OjJOF9/mzmqmj3jE/7VOmrfw6Mgs0E8cjOsbRXQJHsPBfmBOXDskXKrHLyyW3n7kpDW/4BsfpQ==", "dev": true, "funding": [ { @@ -890,16 +890,10 @@ ] }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -912,6 +906,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -1000,9 +997,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.654", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.654.tgz", - "integrity": "sha512-hjfFa+Vj4WGLRVTlCQa+IivBkpcp+boGxMQfusOC/me5Y5NfU4wX7wyw+K9p8Cw4tl0BVIZGH2n7y/jMc3w4pg==", + "version": "1.4.659", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.659.tgz", + "integrity": "sha512-sRJ3nV3HowrYpBtPF9bASQV7OW49IgZC01Xiq43WfSE3RTCkK0/JidoCmR73Hyc1mN+l/H4Yqx0eNiomvExFZg==", "dev": true }, "node_modules/emoji-regex": { @@ -1050,9 +1047,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -1087,9 +1084,9 @@ } }, "node_modules/fastq": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", - "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -1556,9 +1553,9 @@ } }, "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "version": "8.4.34", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.34.tgz", + "integrity": "sha512-4eLTO36woPSocqZ1zIrFD2K1v6wH7pY1uBh0JIM2KKfrVtGvPFiAku6aNOP0W1Wr9qwnaCsF0Z+CrVnryB2A8Q==", "dev": true, "funding": [ { diff --git a/resources/views/forms/components/test-database-notification.blade.php b/resources/views/forms/components/test-database-notification.blade.php deleted file mode 100644 index bd04861e9..000000000 --- a/resources/views/forms/components/test-database-notification.blade.php +++ /dev/null @@ -1,5 +0,0 @@ -
- - Test database channel - -
diff --git a/resources/views/forms/components/test-mail-notification.blade.php b/resources/views/forms/components/test-mail-notification.blade.php deleted file mode 100644 index dba69b249..000000000 --- a/resources/views/forms/components/test-mail-notification.blade.php +++ /dev/null @@ -1,5 +0,0 @@ -
- - Test mail channel - -
diff --git a/resources/views/forms/components/test-telegram-notification.blade.php b/resources/views/forms/components/test-telegram-notification.blade.php deleted file mode 100644 index e6778ab3a..000000000 --- a/resources/views/forms/components/test-telegram-notification.blade.php +++ /dev/null @@ -1,5 +0,0 @@ -
- - Test telegram channel - -
diff --git a/vite.config.js b/vite.config.js index 7a41e6b9d..e65af2a5f 100644 --- a/vite.config.js +++ b/vite.config.js @@ -10,9 +10,4 @@ export default defineConfig({ ], }), ], - server: { - hmr: { - host: 'localhost', - }, - }, });