Merge branch 'next' into fix-postgres-init-scripts

This commit is contained in:
🏔️ Peak
2024-12-16 12:36:50 +01:00
committed by GitHub
220 changed files with 6558 additions and 3643 deletions

View File

@@ -2,6 +2,7 @@
namespace App\Livewire\Notifications;
use App\Models\DiscordNotificationSettings;
use App\Models\Team;
use App\Notifications\Test;
use Livewire\Attributes\Validate;
@@ -11,6 +12,8 @@ class Discord extends Component
{
public Team $team;
public DiscordNotificationSettings $settings;
#[Validate(['boolean'])]
public bool $discordEnabled = false;
@@ -18,27 +21,46 @@ class Discord extends Component
public ?string $discordWebhookUrl = null;
#[Validate(['boolean'])]
public bool $discordNotificationsTest = false;
public bool $deploymentSuccessDiscordNotifications = false;
#[Validate(['boolean'])]
public bool $discordNotificationsDeployments = false;
public bool $deploymentFailureDiscordNotifications = true;
#[Validate(['boolean'])]
public bool $discordNotificationsStatusChanges = false;
public bool $statusChangeDiscordNotifications = false;
#[Validate(['boolean'])]
public bool $discordNotificationsDatabaseBackups = false;
public bool $backupSuccessDiscordNotifications = false;
#[Validate(['boolean'])]
public bool $discordNotificationsScheduledTasks = false;
public bool $backupFailureDiscordNotifications = true;
#[Validate(['boolean'])]
public bool $discordNotificationsServerDiskUsage = false;
public bool $scheduledTaskSuccessDiscordNotifications = false;
#[Validate(['boolean'])]
public bool $scheduledTaskFailureDiscordNotifications = true;
#[Validate(['boolean'])]
public bool $dockerCleanupSuccessDiscordNotifications = false;
#[Validate(['boolean'])]
public bool $dockerCleanupFailureDiscordNotifications = true;
#[Validate(['boolean'])]
public bool $serverDiskUsageDiscordNotifications = true;
#[Validate(['boolean'])]
public bool $serverReachableDiscordNotifications = false;
#[Validate(['boolean'])]
public bool $serverUnreachableDiscordNotifications = true;
public function mount()
{
try {
$this->team = auth()->user()->currentTeam();
$this->settings = $this->team->discordNotificationSettings;
$this->syncData();
} catch (\Throwable $e) {
return handleError($e, $this);
@@ -49,25 +71,40 @@ class Discord extends Component
{
if ($toModel) {
$this->validate();
$this->team->discord_enabled = $this->discordEnabled;
$this->team->discord_webhook_url = $this->discordWebhookUrl;
$this->team->discord_notifications_test = $this->discordNotificationsTest;
$this->team->discord_notifications_deployments = $this->discordNotificationsDeployments;
$this->team->discord_notifications_status_changes = $this->discordNotificationsStatusChanges;
$this->team->discord_notifications_database_backups = $this->discordNotificationsDatabaseBackups;
$this->team->discord_notifications_scheduled_tasks = $this->discordNotificationsScheduledTasks;
$this->team->discord_notifications_server_disk_usage = $this->discordNotificationsServerDiskUsage;
$this->team->save();
$this->settings->discord_enabled = $this->discordEnabled;
$this->settings->discord_webhook_url = $this->discordWebhookUrl;
$this->settings->deployment_success_discord_notifications = $this->deploymentSuccessDiscordNotifications;
$this->settings->deployment_failure_discord_notifications = $this->deploymentFailureDiscordNotifications;
$this->settings->status_change_discord_notifications = $this->statusChangeDiscordNotifications;
$this->settings->backup_success_discord_notifications = $this->backupSuccessDiscordNotifications;
$this->settings->backup_failure_discord_notifications = $this->backupFailureDiscordNotifications;
$this->settings->scheduled_task_success_discord_notifications = $this->scheduledTaskSuccessDiscordNotifications;
$this->settings->scheduled_task_failure_discord_notifications = $this->scheduledTaskFailureDiscordNotifications;
$this->settings->docker_cleanup_success_discord_notifications = $this->dockerCleanupSuccessDiscordNotifications;
$this->settings->docker_cleanup_failure_discord_notifications = $this->dockerCleanupFailureDiscordNotifications;
$this->settings->server_disk_usage_discord_notifications = $this->serverDiskUsageDiscordNotifications;
$this->settings->server_reachable_discord_notifications = $this->serverReachableDiscordNotifications;
$this->settings->server_unreachable_discord_notifications = $this->serverUnreachableDiscordNotifications;
$this->settings->save();
refreshSession();
} else {
$this->discordEnabled = $this->team->discord_enabled;
$this->discordWebhookUrl = $this->team->discord_webhook_url;
$this->discordNotificationsTest = $this->team->discord_notifications_test;
$this->discordNotificationsDeployments = $this->team->discord_notifications_deployments;
$this->discordNotificationsStatusChanges = $this->team->discord_notifications_status_changes;
$this->discordNotificationsDatabaseBackups = $this->team->discord_notifications_database_backups;
$this->discordNotificationsScheduledTasks = $this->team->discord_notifications_scheduled_tasks;
$this->discordNotificationsServerDiskUsage = $this->team->discord_notifications_server_disk_usage;
$this->discordEnabled = $this->settings->discord_enabled;
$this->discordWebhookUrl = $this->settings->discord_webhook_url;
$this->deploymentSuccessDiscordNotifications = $this->settings->deployment_success_discord_notifications;
$this->deploymentFailureDiscordNotifications = $this->settings->deployment_failure_discord_notifications;
$this->statusChangeDiscordNotifications = $this->settings->status_change_discord_notifications;
$this->backupSuccessDiscordNotifications = $this->settings->backup_success_discord_notifications;
$this->backupFailureDiscordNotifications = $this->settings->backup_failure_discord_notifications;
$this->scheduledTaskSuccessDiscordNotifications = $this->settings->scheduled_task_success_discord_notifications;
$this->scheduledTaskFailureDiscordNotifications = $this->settings->scheduled_task_failure_discord_notifications;
$this->dockerCleanupSuccessDiscordNotifications = $this->settings->docker_cleanup_success_discord_notifications;
$this->dockerCleanupFailureDiscordNotifications = $this->settings->docker_cleanup_failure_discord_notifications;
$this->serverDiskUsageDiscordNotifications = $this->settings->server_disk_usage_discord_notifications;
$this->serverReachableDiscordNotifications = $this->settings->server_reachable_discord_notifications;
$this->serverUnreachableDiscordNotifications = $this->settings->server_unreachable_discord_notifications;
}
}
@@ -117,7 +154,7 @@ class Discord extends Component
public function sendTestNotification()
{
try {
$this->team->notify(new Test);
$this->team->notify(new Test(channel: 'discord'));
$this->dispatch('success', 'Test notification sent.');
} catch (\Throwable $e) {
return handleError($e, $this);

View File

@@ -2,6 +2,7 @@
namespace App\Livewire\Notifications;
use App\Models\EmailNotificationSettings;
use App\Models\Team;
use App\Notifications\Test;
use Illuminate\Support\Facades\RateLimiter;
@@ -11,17 +12,20 @@ use Livewire\Component;
class Email extends Component
{
protected $listeners = ['refresh' => '$refresh'];
#[Locked]
public Team $team;
#[Locked]
public EmailNotificationSettings $settings;
#[Locked]
public string $emails;
#[Validate(['boolean'])]
public bool $smtpEnabled = false;
#[Validate(['boolean'])]
public bool $useInstanceEmailSettings = false;
#[Validate(['nullable', 'email'])]
public ?string $smtpFromAddress = null;
@@ -34,11 +38,11 @@ class Email extends Component
#[Validate(['nullable', 'string'])]
public ?string $smtpHost = null;
#[Validate(['nullable', 'numeric'])]
#[Validate(['nullable', 'numeric', 'min:1', 'max:65535'])]
public ?int $smtpPort = null;
#[Validate(['nullable', 'string', 'in:tls,ssl,none'])]
public ?string $smtpEncryption = null;
public ?string $smtpEncryption = 'tls';
#[Validate(['nullable', 'string'])]
public ?string $smtpUsername = null;
@@ -50,29 +54,50 @@ class Email extends Component
public ?int $smtpTimeout = null;
#[Validate(['boolean'])]
public bool $smtpNotificationsTest = false;
#[Validate(['boolean'])]
public bool $smtpNotificationsDeployments = false;
#[Validate(['boolean'])]
public bool $smtpNotificationsStatusChanges = false;
#[Validate(['boolean'])]
public bool $smtpNotificationsDatabaseBackups = false;
#[Validate(['boolean'])]
public bool $smtpNotificationsScheduledTasks = false;
#[Validate(['boolean'])]
public bool $smtpNotificationsServerDiskUsage = false;
#[Validate(['boolean'])]
public bool $resendEnabled;
public bool $resendEnabled = false;
#[Validate(['nullable', 'string'])]
public ?string $resendApiKey = null;
#[Validate(['boolean'])]
public bool $useInstanceEmailSettings = false;
#[Validate(['boolean'])]
public bool $deploymentSuccessEmailNotifications = false;
#[Validate(['boolean'])]
public bool $deploymentFailureEmailNotifications = true;
#[Validate(['boolean'])]
public bool $statusChangeEmailNotifications = false;
#[Validate(['boolean'])]
public bool $backupSuccessEmailNotifications = false;
#[Validate(['boolean'])]
public bool $backupFailureEmailNotifications = true;
#[Validate(['boolean'])]
public bool $scheduledTaskSuccessEmailNotifications = false;
#[Validate(['boolean'])]
public bool $scheduledTaskFailureEmailNotifications = true;
#[Validate(['boolean'])]
public bool $dockerCleanupSuccessEmailNotifications = false;
#[Validate(['boolean'])]
public bool $dockerCleanupFailureEmailNotifications = true;
#[Validate(['boolean'])]
public bool $serverDiskUsageEmailNotifications = true;
#[Validate(['boolean'])]
public bool $serverReachableEmailNotifications = false;
#[Validate(['boolean'])]
public bool $serverUnreachableEmailNotifications = true;
#[Validate(['nullable', 'email'])]
public ?string $testEmailAddress = null;
@@ -81,7 +106,9 @@ class Email extends Component
try {
$this->team = auth()->user()->currentTeam();
$this->emails = auth()->user()->email;
$this->settings = $this->team->emailNotificationSettings;
$this->syncData();
$this->testEmailAddress = auth()->user()->email;
} catch (\Throwable $e) {
return handleError($e, $this);
}
@@ -91,47 +118,191 @@ class Email extends Component
{
if ($toModel) {
$this->validate();
$this->team->smtp_enabled = $this->smtpEnabled;
$this->team->smtp_from_address = $this->smtpFromAddress;
$this->team->smtp_from_name = $this->smtpFromName;
$this->team->smtp_host = $this->smtpHost;
$this->team->smtp_port = $this->smtpPort;
$this->team->smtp_encryption = $this->smtpEncryption;
$this->team->smtp_username = $this->smtpUsername;
$this->team->smtp_password = $this->smtpPassword;
$this->team->smtp_timeout = $this->smtpTimeout;
$this->team->smtp_recipients = $this->smtpRecipients;
$this->team->smtp_notifications_test = $this->smtpNotificationsTest;
$this->team->smtp_notifications_deployments = $this->smtpNotificationsDeployments;
$this->team->smtp_notifications_status_changes = $this->smtpNotificationsStatusChanges;
$this->team->smtp_notifications_database_backups = $this->smtpNotificationsDatabaseBackups;
$this->team->smtp_notifications_scheduled_tasks = $this->smtpNotificationsScheduledTasks;
$this->team->smtp_notifications_server_disk_usage = $this->smtpNotificationsServerDiskUsage;
$this->team->use_instance_email_settings = $this->useInstanceEmailSettings;
$this->team->resend_enabled = $this->resendEnabled;
$this->team->resend_api_key = $this->resendApiKey;
$this->team->save();
refreshSession();
$this->settings->smtp_enabled = $this->smtpEnabled;
$this->settings->smtp_from_address = $this->smtpFromAddress;
$this->settings->smtp_from_name = $this->smtpFromName;
$this->settings->smtp_recipients = $this->smtpRecipients;
$this->settings->smtp_host = $this->smtpHost;
$this->settings->smtp_port = $this->smtpPort;
$this->settings->smtp_encryption = $this->smtpEncryption;
$this->settings->smtp_username = $this->smtpUsername;
$this->settings->smtp_password = $this->smtpPassword;
$this->settings->smtp_timeout = $this->smtpTimeout;
$this->settings->resend_enabled = $this->resendEnabled;
$this->settings->resend_api_key = $this->resendApiKey;
$this->settings->use_instance_email_settings = $this->useInstanceEmailSettings;
$this->settings->deployment_success_email_notifications = $this->deploymentSuccessEmailNotifications;
$this->settings->deployment_failure_email_notifications = $this->deploymentFailureEmailNotifications;
$this->settings->status_change_email_notifications = $this->statusChangeEmailNotifications;
$this->settings->backup_success_email_notifications = $this->backupSuccessEmailNotifications;
$this->settings->backup_failure_email_notifications = $this->backupFailureEmailNotifications;
$this->settings->scheduled_task_success_email_notifications = $this->scheduledTaskSuccessEmailNotifications;
$this->settings->scheduled_task_failure_email_notifications = $this->scheduledTaskFailureEmailNotifications;
$this->settings->docker_cleanup_success_email_notifications = $this->dockerCleanupSuccessEmailNotifications;
$this->settings->docker_cleanup_failure_email_notifications = $this->dockerCleanupFailureEmailNotifications;
$this->settings->server_disk_usage_email_notifications = $this->serverDiskUsageEmailNotifications;
$this->settings->server_reachable_email_notifications = $this->serverReachableEmailNotifications;
$this->settings->server_unreachable_email_notifications = $this->serverUnreachableEmailNotifications;
$this->settings->save();
} else {
$this->smtpEnabled = $this->team->smtp_enabled;
$this->smtpFromAddress = $this->team->smtp_from_address;
$this->smtpFromName = $this->team->smtp_from_name;
$this->smtpHost = $this->team->smtp_host;
$this->smtpPort = $this->team->smtp_port;
$this->smtpEncryption = $this->team->smtp_encryption;
$this->smtpUsername = $this->team->smtp_username;
$this->smtpPassword = $this->team->smtp_password;
$this->smtpTimeout = $this->team->smtp_timeout;
$this->smtpRecipients = $this->team->smtp_recipients;
$this->smtpNotificationsTest = $this->team->smtp_notifications_test;
$this->smtpNotificationsDeployments = $this->team->smtp_notifications_deployments;
$this->smtpNotificationsStatusChanges = $this->team->smtp_notifications_status_changes;
$this->smtpNotificationsDatabaseBackups = $this->team->smtp_notifications_database_backups;
$this->smtpNotificationsScheduledTasks = $this->team->smtp_notifications_scheduled_tasks;
$this->smtpNotificationsServerDiskUsage = $this->team->smtp_notifications_server_disk_usage;
$this->useInstanceEmailSettings = $this->team->use_instance_email_settings;
$this->resendEnabled = $this->team->resend_enabled;
$this->resendApiKey = $this->team->resend_api_key;
$this->smtpEnabled = $this->settings->smtp_enabled;
$this->smtpFromAddress = $this->settings->smtp_from_address;
$this->smtpFromName = $this->settings->smtp_from_name;
$this->smtpRecipients = $this->settings->smtp_recipients;
$this->smtpHost = $this->settings->smtp_host;
$this->smtpPort = $this->settings->smtp_port;
$this->smtpEncryption = $this->settings->smtp_encryption;
$this->smtpUsername = $this->settings->smtp_username;
$this->smtpPassword = $this->settings->smtp_password;
$this->smtpTimeout = $this->settings->smtp_timeout;
$this->resendEnabled = $this->settings->resend_enabled;
$this->resendApiKey = $this->settings->resend_api_key;
$this->useInstanceEmailSettings = $this->settings->use_instance_email_settings;
$this->deploymentSuccessEmailNotifications = $this->settings->deployment_success_email_notifications;
$this->deploymentFailureEmailNotifications = $this->settings->deployment_failure_email_notifications;
$this->statusChangeEmailNotifications = $this->settings->status_change_email_notifications;
$this->backupSuccessEmailNotifications = $this->settings->backup_success_email_notifications;
$this->backupFailureEmailNotifications = $this->settings->backup_failure_email_notifications;
$this->scheduledTaskSuccessEmailNotifications = $this->settings->scheduled_task_success_email_notifications;
$this->scheduledTaskFailureEmailNotifications = $this->settings->scheduled_task_failure_email_notifications;
$this->dockerCleanupSuccessEmailNotifications = $this->settings->docker_cleanup_success_email_notifications;
$this->dockerCleanupFailureEmailNotifications = $this->settings->docker_cleanup_failure_email_notifications;
$this->serverDiskUsageEmailNotifications = $this->settings->server_disk_usage_email_notifications;
$this->serverReachableEmailNotifications = $this->settings->server_reachable_email_notifications;
$this->serverUnreachableEmailNotifications = $this->settings->server_unreachable_email_notifications;
}
}
public function submit()
{
try {
$this->resetErrorBag();
$this->saveModel();
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function saveModel()
{
$this->syncData(true);
$this->dispatch('success', 'Email notifications settings updated.');
}
public function instantSave(?string $type = null)
{
try {
$this->resetErrorBag();
if ($type === 'SMTP') {
$this->submitSmtp();
} elseif ($type === 'Resend') {
$this->submitResend();
} else {
$this->smtpEnabled = false;
$this->resendEnabled = false;
$this->saveModel();
return;
}
} catch (\Throwable $e) {
if ($type === 'SMTP') {
$this->smtpEnabled = false;
} elseif ($type === 'Resend') {
$this->resendEnabled = false;
}
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}
public function submitSmtp()
{
try {
$this->resetErrorBag();
$this->validate([
'smtpEnabled' => 'boolean',
'smtpFromAddress' => 'required|email',
'smtpFromName' => 'required|string',
'smtpHost' => 'required|string',
'smtpPort' => 'required|numeric',
'smtpEncryption' => 'required|string|in:tls,ssl,none',
'smtpUsername' => 'nullable|string',
'smtpPassword' => 'nullable|string',
'smtpTimeout' => 'nullable|numeric',
], [
'smtpFromAddress.required' => 'From Address is required.',
'smtpFromAddress.email' => 'Please enter a valid email address.',
'smtpFromName.required' => 'From Name is required.',
'smtpHost.required' => 'SMTP Host is required.',
'smtpPort.required' => 'SMTP Port is required.',
'smtpPort.numeric' => 'SMTP Port must be a number.',
'smtpEncryption.required' => 'Encryption type is required.',
]);
$this->settings->resend_enabled = false;
$this->settings->use_instance_email_settings = false;
$this->resendEnabled = false;
$this->useInstanceEmailSettings = false;
$this->settings->smtp_enabled = $this->smtpEnabled;
$this->settings->smtp_from_address = $this->smtpFromAddress;
$this->settings->smtp_from_name = $this->smtpFromName;
$this->settings->smtp_host = $this->smtpHost;
$this->settings->smtp_port = $this->smtpPort;
$this->settings->smtp_encryption = $this->smtpEncryption;
$this->settings->smtp_username = $this->smtpUsername;
$this->settings->smtp_password = $this->smtpPassword;
$this->settings->smtp_timeout = $this->smtpTimeout;
$this->settings->save();
$this->dispatch('success', 'SMTP settings updated.');
} catch (\Throwable $e) {
$this->smtpEnabled = false;
return handleError($e);
}
}
public function submitResend()
{
try {
$this->resetErrorBag();
$this->validate([
'resendEnabled' => 'boolean',
'resendApiKey' => 'required|string',
'smtpFromAddress' => 'required|email',
'smtpFromName' => 'required|string',
], [
'resendApiKey.required' => 'Resend API Key is required.',
'smtpFromAddress.required' => 'From Address is required.',
'smtpFromAddress.email' => 'Please enter a valid email address.',
'smtpFromName.required' => 'From Name is required.',
]);
$this->settings->smtp_enabled = false;
$this->settings->use_instance_email_settings = false;
$this->smtpEnabled = false;
$this->useInstanceEmailSettings = false;
$this->settings->resend_enabled = $this->resendEnabled;
$this->settings->resend_api_key = $this->resendApiKey;
$this->settings->smtp_from_address = $this->smtpFromAddress;
$this->settings->smtp_from_name = $this->smtpFromName;
$this->settings->save();
$this->dispatch('success', 'Resend settings updated.');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
@@ -149,7 +320,7 @@ class Email extends Component
'test-email:'.$this->team->id,
$perMinute = 0,
function () {
$this->team?->notify(new Test($this->testEmailAddress));
$this->team?->notify(new Test($this->testEmailAddress, 'email'));
$this->dispatch('success', 'Test Email sent.');
},
$decaySeconds = 10,
@@ -163,70 +334,6 @@ class Email extends Component
}
}
public function instantSaveInstance()
{
try {
$this->smtpEnabled = false;
$this->resendEnabled = false;
$this->saveModel();
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function instantSaveSmtpEnabled()
{
try {
$this->validate([
'smtpHost' => 'required',
'smtpPort' => 'required|numeric',
], [
'smtpHost.required' => 'SMTP Host is required.',
'smtpPort.required' => 'SMTP Port is required.',
]);
$this->resendEnabled = false;
$this->saveModel();
} catch (\Throwable $e) {
$this->smtpEnabled = false;
return handleError($e, $this);
}
}
public function instantSaveResend()
{
try {
$this->validate([
'resendApiKey' => 'required',
], [
'resendApiKey.required' => 'Resend API Key is required.',
]);
$this->smtpEnabled = false;
$this->saveModel();
} catch (\Throwable $e) {
$this->resendEnabled = false;
return handleError($e, $this);
}
}
public function saveModel()
{
$this->syncData(true);
refreshSession();
$this->dispatch('success', 'Settings saved.');
}
public function submit()
{
try {
$this->resetErrorBag();
$this->saveModel();
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function copyFromInstanceSettings()
{
$settings = instanceSettings();

View File

@@ -0,0 +1,184 @@
<?php
namespace App\Livewire\Notifications;
use App\Models\PushoverNotificationSettings;
use App\Models\Team;
use App\Notifications\Test;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Validate;
use Livewire\Component;
class Pushover extends Component
{
protected $listeners = ['refresh' => '$refresh'];
#[Locked]
public Team $team;
#[Locked]
public PushoverNotificationSettings $settings;
#[Validate(['boolean'])]
public bool $pushoverEnabled = false;
#[Validate(['nullable', 'string'])]
public ?string $pushoverUserKey = null;
#[Validate(['nullable', 'string'])]
public ?string $pushoverApiToken = null;
#[Validate(['boolean'])]
public bool $deploymentSuccessPushoverNotifications = false;
#[Validate(['boolean'])]
public bool $deploymentFailurePushoverNotifications = true;
#[Validate(['boolean'])]
public bool $statusChangePushoverNotifications = false;
#[Validate(['boolean'])]
public bool $backupSuccessPushoverNotifications = false;
#[Validate(['boolean'])]
public bool $backupFailurePushoverNotifications = true;
#[Validate(['boolean'])]
public bool $scheduledTaskSuccessPushoverNotifications = false;
#[Validate(['boolean'])]
public bool $scheduledTaskFailurePushoverNotifications = true;
#[Validate(['boolean'])]
public bool $dockerCleanupSuccessPushoverNotifications = false;
#[Validate(['boolean'])]
public bool $dockerCleanupFailurePushoverNotifications = true;
#[Validate(['boolean'])]
public bool $serverDiskUsagePushoverNotifications = true;
#[Validate(['boolean'])]
public bool $serverReachablePushoverNotifications = false;
#[Validate(['boolean'])]
public bool $serverUnreachablePushoverNotifications = true;
public function mount()
{
try {
$this->team = auth()->user()->currentTeam();
$this->settings = $this->team->pushoverNotificationSettings;
$this->syncData();
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function syncData(bool $toModel = false)
{
if ($toModel) {
$this->validate();
$this->settings->pushover_enabled = $this->pushoverEnabled;
$this->settings->pushover_user_key = $this->pushoverUserKey;
$this->settings->pushover_api_token = $this->pushoverApiToken;
$this->settings->deployment_success_pushover_notifications = $this->deploymentSuccessPushoverNotifications;
$this->settings->deployment_failure_pushover_notifications = $this->deploymentFailurePushoverNotifications;
$this->settings->status_change_pushover_notifications = $this->statusChangePushoverNotifications;
$this->settings->backup_success_pushover_notifications = $this->backupSuccessPushoverNotifications;
$this->settings->backup_failure_pushover_notifications = $this->backupFailurePushoverNotifications;
$this->settings->scheduled_task_success_pushover_notifications = $this->scheduledTaskSuccessPushoverNotifications;
$this->settings->scheduled_task_failure_pushover_notifications = $this->scheduledTaskFailurePushoverNotifications;
$this->settings->docker_cleanup_success_pushover_notifications = $this->dockerCleanupSuccessPushoverNotifications;
$this->settings->docker_cleanup_failure_pushover_notifications = $this->dockerCleanupFailurePushoverNotifications;
$this->settings->server_disk_usage_pushover_notifications = $this->serverDiskUsagePushoverNotifications;
$this->settings->server_reachable_pushover_notifications = $this->serverReachablePushoverNotifications;
$this->settings->server_unreachable_pushover_notifications = $this->serverUnreachablePushoverNotifications;
$this->settings->save();
refreshSession();
} else {
$this->pushoverEnabled = $this->settings->pushover_enabled;
$this->pushoverUserKey = $this->settings->pushover_user_key;
$this->pushoverApiToken = $this->settings->pushover_api_token;
$this->deploymentSuccessPushoverNotifications = $this->settings->deployment_success_pushover_notifications;
$this->deploymentFailurePushoverNotifications = $this->settings->deployment_failure_pushover_notifications;
$this->statusChangePushoverNotifications = $this->settings->status_change_pushover_notifications;
$this->backupSuccessPushoverNotifications = $this->settings->backup_success_pushover_notifications;
$this->backupFailurePushoverNotifications = $this->settings->backup_failure_pushover_notifications;
$this->scheduledTaskSuccessPushoverNotifications = $this->settings->scheduled_task_success_pushover_notifications;
$this->scheduledTaskFailurePushoverNotifications = $this->settings->scheduled_task_failure_pushover_notifications;
$this->dockerCleanupSuccessPushoverNotifications = $this->settings->docker_cleanup_success_pushover_notifications;
$this->dockerCleanupFailurePushoverNotifications = $this->settings->docker_cleanup_failure_pushover_notifications;
$this->serverDiskUsagePushoverNotifications = $this->settings->server_disk_usage_pushover_notifications;
$this->serverReachablePushoverNotifications = $this->settings->server_reachable_pushover_notifications;
$this->serverUnreachablePushoverNotifications = $this->settings->server_unreachable_pushover_notifications;
}
}
public function instantSavePushoverEnabled()
{
try {
$this->validate([
'pushoverUserKey' => 'required',
'pushoverApiToken' => 'required',
], [
'pushoverUserKey.required' => 'Pushover User Key is required.',
'pushoverApiToken.required' => 'Pushover API Token is required.',
]);
$this->saveModel();
} catch (\Throwable $e) {
$this->pushoverEnabled = false;
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}
public function instantSave()
{
try {
$this->syncData(true);
} catch (\Throwable $e) {
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}
public function submit()
{
try {
$this->resetErrorBag();
$this->syncData(true);
$this->saveModel();
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function saveModel()
{
$this->syncData(true);
refreshSession();
$this->dispatch('success', 'Settings saved.');
}
public function sendTestNotification()
{
try {
$this->team->notify(new Test(channel: 'pushover'));
$this->dispatch('success', 'Test notification sent.');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function render()
{
return view('livewire.notifications.pushover');
}
}

View File

@@ -2,15 +2,23 @@
namespace App\Livewire\Notifications;
use App\Models\SlackNotificationSettings;
use App\Models\Team;
use App\Notifications\Test;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Validate;
use Livewire\Component;
class Slack extends Component
{
protected $listeners = ['refresh' => '$refresh'];
#[Locked]
public Team $team;
#[Locked]
public SlackNotificationSettings $settings;
#[Validate(['boolean'])]
public bool $slackEnabled = false;
@@ -18,27 +26,46 @@ class Slack extends Component
public ?string $slackWebhookUrl = null;
#[Validate(['boolean'])]
public bool $slackNotificationsTest = false;
public bool $deploymentSuccessSlackNotifications = false;
#[Validate(['boolean'])]
public bool $slackNotificationsDeployments = false;
public bool $deploymentFailureSlackNotifications = true;
#[Validate(['boolean'])]
public bool $slackNotificationsStatusChanges = false;
public bool $statusChangeSlackNotifications = false;
#[Validate(['boolean'])]
public bool $slackNotificationsDatabaseBackups = false;
public bool $backupSuccessSlackNotifications = false;
#[Validate(['boolean'])]
public bool $slackNotificationsScheduledTasks = false;
public bool $backupFailureSlackNotifications = true;
#[Validate(['boolean'])]
public bool $slackNotificationsServerDiskUsage = false;
public bool $scheduledTaskSuccessSlackNotifications = false;
#[Validate(['boolean'])]
public bool $scheduledTaskFailureSlackNotifications = true;
#[Validate(['boolean'])]
public bool $dockerCleanupSuccessSlackNotifications = false;
#[Validate(['boolean'])]
public bool $dockerCleanupFailureSlackNotifications = true;
#[Validate(['boolean'])]
public bool $serverDiskUsageSlackNotifications = true;
#[Validate(['boolean'])]
public bool $serverReachableSlackNotifications = false;
#[Validate(['boolean'])]
public bool $serverUnreachableSlackNotifications = true;
public function mount()
{
try {
$this->team = auth()->user()->currentTeam();
$this->settings = $this->team->slackNotificationSettings;
$this->syncData();
} catch (\Throwable $e) {
return handleError($e, $this);
@@ -49,25 +76,40 @@ class Slack extends Component
{
if ($toModel) {
$this->validate();
$this->team->slack_enabled = $this->slackEnabled;
$this->team->slack_webhook_url = $this->slackWebhookUrl;
$this->team->slack_notifications_test = $this->slackNotificationsTest;
$this->team->slack_notifications_deployments = $this->slackNotificationsDeployments;
$this->team->slack_notifications_status_changes = $this->slackNotificationsStatusChanges;
$this->team->slack_notifications_database_backups = $this->slackNotificationsDatabaseBackups;
$this->team->slack_notifications_scheduled_tasks = $this->slackNotificationsScheduledTasks;
$this->team->slack_notifications_server_disk_usage = $this->slackNotificationsServerDiskUsage;
$this->team->save();
$this->settings->slack_enabled = $this->slackEnabled;
$this->settings->slack_webhook_url = $this->slackWebhookUrl;
$this->settings->deployment_success_slack_notifications = $this->deploymentSuccessSlackNotifications;
$this->settings->deployment_failure_slack_notifications = $this->deploymentFailureSlackNotifications;
$this->settings->status_change_slack_notifications = $this->statusChangeSlackNotifications;
$this->settings->backup_success_slack_notifications = $this->backupSuccessSlackNotifications;
$this->settings->backup_failure_slack_notifications = $this->backupFailureSlackNotifications;
$this->settings->scheduled_task_success_slack_notifications = $this->scheduledTaskSuccessSlackNotifications;
$this->settings->scheduled_task_failure_slack_notifications = $this->scheduledTaskFailureSlackNotifications;
$this->settings->docker_cleanup_success_slack_notifications = $this->dockerCleanupSuccessSlackNotifications;
$this->settings->docker_cleanup_failure_slack_notifications = $this->dockerCleanupFailureSlackNotifications;
$this->settings->server_disk_usage_slack_notifications = $this->serverDiskUsageSlackNotifications;
$this->settings->server_reachable_slack_notifications = $this->serverReachableSlackNotifications;
$this->settings->server_unreachable_slack_notifications = $this->serverUnreachableSlackNotifications;
$this->settings->save();
refreshSession();
} else {
$this->slackEnabled = $this->team->slack_enabled;
$this->slackWebhookUrl = $this->team->slack_webhook_url;
$this->slackNotificationsTest = $this->team->slack_notifications_test;
$this->slackNotificationsDeployments = $this->team->slack_notifications_deployments;
$this->slackNotificationsStatusChanges = $this->team->slack_notifications_status_changes;
$this->slackNotificationsDatabaseBackups = $this->team->slack_notifications_database_backups;
$this->slackNotificationsScheduledTasks = $this->team->slack_notifications_scheduled_tasks;
$this->slackNotificationsServerDiskUsage = $this->team->slack_notifications_server_disk_usage;
$this->slackEnabled = $this->settings->slack_enabled;
$this->slackWebhookUrl = $this->settings->slack_webhook_url;
$this->deploymentSuccessSlackNotifications = $this->settings->deployment_success_slack_notifications;
$this->deploymentFailureSlackNotifications = $this->settings->deployment_failure_slack_notifications;
$this->statusChangeSlackNotifications = $this->settings->status_change_slack_notifications;
$this->backupSuccessSlackNotifications = $this->settings->backup_success_slack_notifications;
$this->backupFailureSlackNotifications = $this->settings->backup_failure_slack_notifications;
$this->scheduledTaskSuccessSlackNotifications = $this->settings->scheduled_task_success_slack_notifications;
$this->scheduledTaskFailureSlackNotifications = $this->settings->scheduled_task_failure_slack_notifications;
$this->dockerCleanupSuccessSlackNotifications = $this->settings->docker_cleanup_success_slack_notifications;
$this->dockerCleanupFailureSlackNotifications = $this->settings->docker_cleanup_failure_slack_notifications;
$this->serverDiskUsageSlackNotifications = $this->settings->server_disk_usage_slack_notifications;
$this->serverReachableSlackNotifications = $this->settings->server_reachable_slack_notifications;
$this->serverUnreachableSlackNotifications = $this->settings->server_unreachable_slack_notifications;
}
}
@@ -84,6 +126,8 @@ class Slack extends Component
$this->slackEnabled = false;
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}
@@ -93,6 +137,8 @@ class Slack extends Component
$this->syncData(true);
} catch (\Throwable $e) {
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}
@@ -117,7 +163,7 @@ class Slack extends Component
public function sendTestNotification()
{
try {
$this->team->notify(new Test);
$this->team->notify(new Test(channel: 'slack'));
$this->dispatch('success', 'Test notification sent.');
} catch (\Throwable $e) {
return handleError($e, $this);

View File

@@ -3,14 +3,22 @@
namespace App\Livewire\Notifications;
use App\Models\Team;
use App\Models\TelegramNotificationSettings;
use App\Notifications\Test;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Validate;
use Livewire\Component;
class Telegram extends Component
{
protected $listeners = ['refresh' => '$refresh'];
#[Locked]
public Team $team;
#[Locked]
public TelegramNotificationSettings $settings;
#[Validate(['boolean'])]
public bool $telegramEnabled = false;
@@ -21,42 +29,82 @@ class Telegram extends Component
public ?string $telegramChatId = null;
#[Validate(['boolean'])]
public bool $telegramNotificationsTest = false;
public bool $deploymentSuccessTelegramNotifications = false;
#[Validate(['boolean'])]
public bool $telegramNotificationsDeployments = false;
public bool $deploymentFailureTelegramNotifications = true;
#[Validate(['boolean'])]
public bool $telegramNotificationsStatusChanges = false;
public bool $statusChangeTelegramNotifications = false;
#[Validate(['boolean'])]
public bool $telegramNotificationsDatabaseBackups = false;
public bool $backupSuccessTelegramNotifications = false;
#[Validate(['boolean'])]
public bool $telegramNotificationsScheduledTasks = false;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsTestMessageThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsDeploymentsMessageThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsStatusChangesMessageThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsDatabaseBackupsMessageThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsScheduledTasksThreadId = null;
public bool $backupFailureTelegramNotifications = true;
#[Validate(['boolean'])]
public bool $telegramNotificationsServerDiskUsage = false;
public bool $scheduledTaskSuccessTelegramNotifications = false;
#[Validate(['boolean'])]
public bool $scheduledTaskFailureTelegramNotifications = true;
#[Validate(['boolean'])]
public bool $dockerCleanupSuccessTelegramNotifications = false;
#[Validate(['boolean'])]
public bool $dockerCleanupFailureTelegramNotifications = true;
#[Validate(['boolean'])]
public bool $serverDiskUsageTelegramNotifications = true;
#[Validate(['boolean'])]
public bool $serverReachableTelegramNotifications = false;
#[Validate(['boolean'])]
public bool $serverUnreachableTelegramNotifications = true;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsDeploymentSuccessThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsDeploymentFailureThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsStatusChangeThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsBackupSuccessThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsBackupFailureThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsScheduledTaskSuccessThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsScheduledTaskFailureThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsDockerCleanupSuccessThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsDockerCleanupFailureThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsServerDiskUsageThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsServerReachableThreadId = null;
#[Validate(['nullable', 'string'])]
public ?string $telegramNotificationsServerUnreachableThreadId = null;
public function mount()
{
try {
$this->team = auth()->user()->currentTeam();
$this->settings = $this->team->telegramNotificationSettings;
$this->syncData();
} catch (\Throwable $e) {
return handleError($e, $this);
@@ -67,39 +115,68 @@ class Telegram extends Component
{
if ($toModel) {
$this->validate();
$this->team->telegram_enabled = $this->telegramEnabled;
$this->team->telegram_token = $this->telegramToken;
$this->team->telegram_chat_id = $this->telegramChatId;
$this->team->telegram_notifications_test = $this->telegramNotificationsTest;
$this->team->telegram_notifications_deployments = $this->telegramNotificationsDeployments;
$this->team->telegram_notifications_status_changes = $this->telegramNotificationsStatusChanges;
$this->team->telegram_notifications_database_backups = $this->telegramNotificationsDatabaseBackups;
$this->team->telegram_notifications_scheduled_tasks = $this->telegramNotificationsScheduledTasks;
$this->team->telegram_notifications_test_message_thread_id = $this->telegramNotificationsTestMessageThreadId;
$this->team->telegram_notifications_deployments_message_thread_id = $this->telegramNotificationsDeploymentsMessageThreadId;
$this->team->telegram_notifications_status_changes_message_thread_id = $this->telegramNotificationsStatusChangesMessageThreadId;
$this->team->telegram_notifications_database_backups_message_thread_id = $this->telegramNotificationsDatabaseBackupsMessageThreadId;
$this->team->telegram_notifications_scheduled_tasks_thread_id = $this->telegramNotificationsScheduledTasksThreadId;
$this->team->telegram_notifications_server_disk_usage = $this->telegramNotificationsServerDiskUsage;
$this->team->save();
refreshSession();
} else {
$this->telegramEnabled = $this->team->telegram_enabled;
$this->telegramToken = $this->team->telegram_token;
$this->telegramChatId = $this->team->telegram_chat_id;
$this->telegramNotificationsTest = $this->team->telegram_notifications_test;
$this->telegramNotificationsDeployments = $this->team->telegram_notifications_deployments;
$this->telegramNotificationsStatusChanges = $this->team->telegram_notifications_status_changes;
$this->telegramNotificationsDatabaseBackups = $this->team->telegram_notifications_database_backups;
$this->telegramNotificationsScheduledTasks = $this->team->telegram_notifications_scheduled_tasks;
$this->telegramNotificationsTestMessageThreadId = $this->team->telegram_notifications_test_message_thread_id;
$this->telegramNotificationsDeploymentsMessageThreadId = $this->team->telegram_notifications_deployments_message_thread_id;
$this->telegramNotificationsStatusChangesMessageThreadId = $this->team->telegram_notifications_status_changes_message_thread_id;
$this->telegramNotificationsDatabaseBackupsMessageThreadId = $this->team->telegram_notifications_database_backups_message_thread_id;
$this->telegramNotificationsScheduledTasksThreadId = $this->team->telegram_notifications_scheduled_tasks_thread_id;
$this->telegramNotificationsServerDiskUsage = $this->team->telegram_notifications_server_disk_usage;
}
$this->settings->telegram_enabled = $this->telegramEnabled;
$this->settings->telegram_token = $this->telegramToken;
$this->settings->telegram_chat_id = $this->telegramChatId;
$this->settings->deployment_success_telegram_notifications = $this->deploymentSuccessTelegramNotifications;
$this->settings->deployment_failure_telegram_notifications = $this->deploymentFailureTelegramNotifications;
$this->settings->status_change_telegram_notifications = $this->statusChangeTelegramNotifications;
$this->settings->backup_success_telegram_notifications = $this->backupSuccessTelegramNotifications;
$this->settings->backup_failure_telegram_notifications = $this->backupFailureTelegramNotifications;
$this->settings->scheduled_task_success_telegram_notifications = $this->scheduledTaskSuccessTelegramNotifications;
$this->settings->scheduled_task_failure_telegram_notifications = $this->scheduledTaskFailureTelegramNotifications;
$this->settings->docker_cleanup_success_telegram_notifications = $this->dockerCleanupSuccessTelegramNotifications;
$this->settings->docker_cleanup_failure_telegram_notifications = $this->dockerCleanupFailureTelegramNotifications;
$this->settings->server_disk_usage_telegram_notifications = $this->serverDiskUsageTelegramNotifications;
$this->settings->server_reachable_telegram_notifications = $this->serverReachableTelegramNotifications;
$this->settings->server_unreachable_telegram_notifications = $this->serverUnreachableTelegramNotifications;
$this->settings->telegram_notifications_deployment_success_thread_id = $this->telegramNotificationsDeploymentSuccessThreadId;
$this->settings->telegram_notifications_deployment_failure_thread_id = $this->telegramNotificationsDeploymentFailureThreadId;
$this->settings->telegram_notifications_status_change_thread_id = $this->telegramNotificationsStatusChangeThreadId;
$this->settings->telegram_notifications_backup_success_thread_id = $this->telegramNotificationsBackupSuccessThreadId;
$this->settings->telegram_notifications_backup_failure_thread_id = $this->telegramNotificationsBackupFailureThreadId;
$this->settings->telegram_notifications_scheduled_task_success_thread_id = $this->telegramNotificationsScheduledTaskSuccessThreadId;
$this->settings->telegram_notifications_scheduled_task_failure_thread_id = $this->telegramNotificationsScheduledTaskFailureThreadId;
$this->settings->telegram_notifications_docker_cleanup_success_thread_id = $this->telegramNotificationsDockerCleanupSuccessThreadId;
$this->settings->telegram_notifications_docker_cleanup_failure_thread_id = $this->telegramNotificationsDockerCleanupFailureThreadId;
$this->settings->telegram_notifications_server_disk_usage_thread_id = $this->telegramNotificationsServerDiskUsageThreadId;
$this->settings->telegram_notifications_server_reachable_thread_id = $this->telegramNotificationsServerReachableThreadId;
$this->settings->telegram_notifications_server_unreachable_thread_id = $this->telegramNotificationsServerUnreachableThreadId;
$this->settings->save();
} else {
$this->telegramEnabled = $this->settings->telegram_enabled;
$this->telegramToken = $this->settings->telegram_token;
$this->telegramChatId = $this->settings->telegram_chat_id;
$this->deploymentSuccessTelegramNotifications = $this->settings->deployment_success_telegram_notifications;
$this->deploymentFailureTelegramNotifications = $this->settings->deployment_failure_telegram_notifications;
$this->statusChangeTelegramNotifications = $this->settings->status_change_telegram_notifications;
$this->backupSuccessTelegramNotifications = $this->settings->backup_success_telegram_notifications;
$this->backupFailureTelegramNotifications = $this->settings->backup_failure_telegram_notifications;
$this->scheduledTaskSuccessTelegramNotifications = $this->settings->scheduled_task_success_telegram_notifications;
$this->scheduledTaskFailureTelegramNotifications = $this->settings->scheduled_task_failure_telegram_notifications;
$this->dockerCleanupSuccessTelegramNotifications = $this->settings->docker_cleanup_success_telegram_notifications;
$this->dockerCleanupFailureTelegramNotifications = $this->settings->docker_cleanup_failure_telegram_notifications;
$this->serverDiskUsageTelegramNotifications = $this->settings->server_disk_usage_telegram_notifications;
$this->serverReachableTelegramNotifications = $this->settings->server_reachable_telegram_notifications;
$this->serverUnreachableTelegramNotifications = $this->settings->server_unreachable_telegram_notifications;
$this->telegramNotificationsDeploymentSuccessThreadId = $this->settings->telegram_notifications_deployment_success_thread_id;
$this->telegramNotificationsDeploymentFailureThreadId = $this->settings->telegram_notifications_deployment_failure_thread_id;
$this->telegramNotificationsStatusChangeThreadId = $this->settings->telegram_notifications_status_change_thread_id;
$this->telegramNotificationsBackupSuccessThreadId = $this->settings->telegram_notifications_backup_success_thread_id;
$this->telegramNotificationsBackupFailureThreadId = $this->settings->telegram_notifications_backup_failure_thread_id;
$this->telegramNotificationsScheduledTaskSuccessThreadId = $this->settings->telegram_notifications_scheduled_task_success_thread_id;
$this->telegramNotificationsScheduledTaskFailureThreadId = $this->settings->telegram_notifications_scheduled_task_failure_thread_id;
$this->telegramNotificationsDockerCleanupSuccessThreadId = $this->settings->telegram_notifications_docker_cleanup_success_thread_id;
$this->telegramNotificationsDockerCleanupFailureThreadId = $this->settings->telegram_notifications_docker_cleanup_failure_thread_id;
$this->telegramNotificationsServerDiskUsageThreadId = $this->settings->telegram_notifications_server_disk_usage_thread_id;
$this->telegramNotificationsServerReachableThreadId = $this->settings->telegram_notifications_server_reachable_thread_id;
$this->telegramNotificationsServerUnreachableThreadId = $this->settings->telegram_notifications_server_unreachable_thread_id;
}
}
public function instantSave()
@@ -108,6 +185,8 @@ class Telegram extends Component
$this->syncData(true);
} catch (\Throwable $e) {
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}
@@ -137,6 +216,8 @@ class Telegram extends Component
$this->telegramEnabled = false;
return handleError($e, $this);
} finally {
$this->dispatch('refresh');
}
}
@@ -150,7 +231,7 @@ class Telegram extends Component
public function sendTestNotification()
{
try {
$this->team->notify(new Test);
$this->team->notify(new Test(channel: 'telegram'));
$this->dispatch('success', 'Test notification sent.');
} catch (\Throwable $e) {
return handleError($e, $this);

View File

@@ -327,7 +327,7 @@ class General extends Component
}
}
public function set_redirect()
public function setRedirect()
{
try {
$has_www = collect($this->application->fqdns)->filter(fn ($fqdn) => str($fqdn)->contains('www.'))->count();
@@ -360,10 +360,10 @@ class General extends Component
if ($warning) {
$this->dispatch('warning', __('warning.sslipdomain'));
}
$this->resetDefaultLabels();
// $this->resetDefaultLabels();
if ($this->application->isDirty('redirect')) {
$this->set_redirect();
$this->setRedirect();
}
$this->checkFqdns();

View File

@@ -9,11 +9,9 @@ class BackupNow extends Component
{
public $backup;
public function backup_now()
public function backupNow()
{
dispatch(new DatabaseBackupJob(
backup: $this->backup
));
DatabaseBackupJob::dispatch($this->backup);
$this->dispatch('success', 'Backup queued. It will be available in a few minutes.');
}
}

View File

@@ -46,125 +46,84 @@ class Index extends Component
return redirect()->route('dashboard');
}
$this->project = $project;
$this->environment = $environment;
$this->applications = $this->environment->applications->load(['tags']);
$this->environment = $environment->loadCount([
'applications',
'redis',
'postgresqls',
'mysqls',
'keydbs',
'dragonflies',
'clickhouses',
'mariadbs',
'mongodbs',
'services',
]);
// Eager load all relationships for applications including nested ones
$this->applications = $this->environment->applications()->with([
'tags',
'additional_servers.settings',
'additional_networks',
'destination.server.settings',
'settings',
])->get()->sortBy('name');
$this->applications = $this->applications->map(function ($application) {
if (data_get($application, 'environment.project.uuid')) {
$application->hrefLink = route('project.application.configuration', [
'project_uuid' => data_get($application, 'environment.project.uuid'),
'environment_name' => data_get($application, 'environment.name'),
'application_uuid' => data_get($application, 'uuid'),
]);
}
$application->hrefLink = route('project.application.configuration', [
'project_uuid' => $this->project->uuid,
'application_uuid' => $application->uuid,
'environment_name' => $this->environment->name,
]);
return $application;
});
$this->postgresqls = $this->environment->postgresqls->load(['tags'])->sortBy('name');
$this->postgresqls = $this->postgresqls->map(function ($postgresql) {
if (data_get($postgresql, 'environment.project.uuid')) {
$postgresql->hrefLink = route('project.database.configuration', [
'project_uuid' => data_get($postgresql, 'environment.project.uuid'),
'environment_name' => data_get($postgresql, 'environment.name'),
'database_uuid' => data_get($postgresql, 'uuid'),
]);
}
return $postgresql;
});
$this->redis = $this->environment->redis->load(['tags'])->sortBy('name');
$this->redis = $this->redis->map(function ($redis) {
if (data_get($redis, 'environment.project.uuid')) {
$redis->hrefLink = route('project.database.configuration', [
'project_uuid' => data_get($redis, 'environment.project.uuid'),
'environment_name' => data_get($redis, 'environment.name'),
'database_uuid' => data_get($redis, 'uuid'),
]);
}
// Load all database resources in a single query per type
$databaseTypes = [
'postgresqls' => 'postgresqls',
'redis' => 'redis',
'mongodbs' => 'mongodbs',
'mysqls' => 'mysqls',
'mariadbs' => 'mariadbs',
'keydbs' => 'keydbs',
'dragonflies' => 'dragonflies',
'clickhouses' => 'clickhouses',
];
return $redis;
});
$this->mongodbs = $this->environment->mongodbs->load(['tags'])->sortBy('name');
$this->mongodbs = $this->mongodbs->map(function ($mongodb) {
if (data_get($mongodb, 'environment.project.uuid')) {
$mongodb->hrefLink = route('project.database.configuration', [
'project_uuid' => data_get($mongodb, 'environment.project.uuid'),
'environment_name' => data_get($mongodb, 'environment.name'),
'database_uuid' => data_get($mongodb, 'uuid'),
]);
}
// Load all server-related data first to prevent duplicate queries
$serverData = $this->environment->applications()
->with(['destination.server.settings'])
->get()
->pluck('destination.server')
->filter()
->unique('id');
return $mongodb;
});
$this->mysqls = $this->environment->mysqls->load(['tags'])->sortBy('name');
$this->mysqls = $this->mysqls->map(function ($mysql) {
if (data_get($mysql, 'environment.project.uuid')) {
$mysql->hrefLink = route('project.database.configuration', [
'project_uuid' => data_get($mysql, 'environment.project.uuid'),
'environment_name' => data_get($mysql, 'environment.name'),
'database_uuid' => data_get($mysql, 'uuid'),
foreach ($databaseTypes as $property => $relation) {
$this->{$property} = $this->environment->{$relation}()->with([
'tags',
'destination.server.settings',
])->get()->sortBy('name');
$this->{$property} = $this->{$property}->map(function ($db) {
$db->hrefLink = route('project.database.configuration', [
'project_uuid' => $this->project->uuid,
'database_uuid' => $db->uuid,
'environment_name' => $this->environment->name,
]);
}
return $mysql;
});
$this->mariadbs = $this->environment->mariadbs->load(['tags'])->sortBy('name');
$this->mariadbs = $this->mariadbs->map(function ($mariadb) {
if (data_get($mariadb, 'environment.project.uuid')) {
$mariadb->hrefLink = route('project.database.configuration', [
'project_uuid' => data_get($mariadb, 'environment.project.uuid'),
'environment_name' => data_get($mariadb, 'environment.name'),
'database_uuid' => data_get($mariadb, 'uuid'),
]);
}
return $db;
});
}
return $mariadb;
});
$this->keydbs = $this->environment->keydbs->load(['tags'])->sortBy('name');
$this->keydbs = $this->keydbs->map(function ($keydb) {
if (data_get($keydb, 'environment.project.uuid')) {
$keydb->hrefLink = route('project.database.configuration', [
'project_uuid' => data_get($keydb, 'environment.project.uuid'),
'environment_name' => data_get($keydb, 'environment.name'),
'database_uuid' => data_get($keydb, 'uuid'),
]);
}
return $keydb;
});
$this->dragonflies = $this->environment->dragonflies->load(['tags'])->sortBy('name');
$this->dragonflies = $this->dragonflies->map(function ($dragonfly) {
if (data_get($dragonfly, 'environment.project.uuid')) {
$dragonfly->hrefLink = route('project.database.configuration', [
'project_uuid' => data_get($dragonfly, 'environment.project.uuid'),
'environment_name' => data_get($dragonfly, 'environment.name'),
'database_uuid' => data_get($dragonfly, 'uuid'),
]);
}
return $dragonfly;
});
$this->clickhouses = $this->environment->clickhouses->load(['tags'])->sortBy('name');
$this->clickhouses = $this->clickhouses->map(function ($clickhouse) {
if (data_get($clickhouse, 'environment.project.uuid')) {
$clickhouse->hrefLink = route('project.database.configuration', [
'project_uuid' => data_get($clickhouse, 'environment.project.uuid'),
'environment_name' => data_get($clickhouse, 'environment.name'),
'database_uuid' => data_get($clickhouse, 'uuid'),
]);
}
return $clickhouse;
});
$this->services = $this->environment->services->load(['tags'])->sortBy('name');
// Load services with their tags and server
$this->services = $this->environment->services()->with([
'tags',
'destination.server.settings',
])->get()->sortBy('name');
$this->services = $this->services->map(function ($service) {
if (data_get($service, 'environment.project.uuid')) {
$service->hrefLink = route('project.service.configuration', [
'project_uuid' => data_get($service, 'environment.project.uuid'),
'environment_name' => data_get($service, 'environment.name'),
'service_uuid' => data_get($service, 'uuid'),
]);
$service->status = $service->status();
}
$service->hrefLink = route('project.service.configuration', [
'project_uuid' => $this->project->uuid,
'service_uuid' => $service->uuid,
'environment_name' => $this->environment->name,
]);
return $service;
});

View File

@@ -27,7 +27,7 @@ class Navbar extends Component
public function mount()
{
if (str($this->service->status())->contains('running') && is_null($this->service->config_hash)) {
if (str($this->service->status)->contains('running') && is_null($this->service->config_hash)) {
$this->service->isConfigurationChanged(true);
$this->dispatch('configurationChanged');
}

View File

@@ -42,9 +42,11 @@ class ResourceOperations extends Component
$uuid = (string) new Cuid2;
$server = $new_destination->server;
if ($this->resource->getMorphClass() === \App\Models\Application::class) {
$name = 'clone-of-'.str($this->resource->name)->limit(20).'-'.$uuid;
$new_resource = $this->resource->replicate()->fill([
'uuid' => $uuid,
'name' => $this->resource->name.'-clone-'.$uuid,
'name' => $name,
'fqdn' => generateFqdn($server, $uuid),
'status' => 'exited',
'destination_id' => $new_destination->id,
@@ -64,8 +66,12 @@ class ResourceOperations extends Component
}
$persistentVolumes = $this->resource->persistentStorages()->get();
foreach ($persistentVolumes as $volume) {
$volumeName = str($volume->name)->replace($this->resource->uuid, $new_resource->uuid)->value();
if ($volumeName === $volume->name) {
$volumeName = $new_resource->uuid.'-'.str($volume->name)->afterLast('-');
}
$newPersistentVolume = $volume->replicate()->fill([
'name' => $new_resource->uuid.'-'.str($volume->name)->afterLast('-'),
'name' => $volumeName,
'resource_id' => $new_resource->id,
]);
$newPersistentVolume->save();

View File

@@ -23,9 +23,6 @@ class Index extends Component
#[Validate('nullable|string|max:255')]
public ?string $fqdn = null;
#[Validate('nullable|string|max:255')]
public ?string $resale_license = null;
#[Validate('required|integer|min:1025|max:65535')]
public int $public_port_min;
@@ -83,7 +80,6 @@ class Index extends Component
} else {
$this->settings = instanceSettings();
$this->fqdn = $this->settings->fqdn;
$this->resale_license = $this->settings->resale_license;
$this->public_port_min = $this->settings->public_port_min;
$this->public_port_max = $this->settings->public_port_max;
$this->custom_dns_servers = $this->settings->custom_dns_servers;
@@ -122,7 +118,6 @@ class Index extends Component
}
$this->settings->fqdn = $this->fqdn;
$this->settings->resale_license = $this->resale_license;
$this->settings->public_port_min = $this->public_port_min;
$this->settings->public_port_max = $this->public_port_max;
$this->settings->custom_dns_servers = $this->custom_dns_servers;

View File

@@ -3,6 +3,10 @@
namespace App\Livewire;
use App\Models\InstanceSettings;
use App\Models\Team;
use App\Notifications\Test;
use Illuminate\Support\Facades\RateLimiter;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Validate;
use Livewire\Component;
@@ -10,9 +14,21 @@ class SettingsEmail extends Component
{
public InstanceSettings $settings;
#[Locked]
public Team $team;
#[Validate(['boolean'])]
public bool $smtpEnabled = false;
#[Validate(['nullable', 'email'])]
public ?string $smtpFromAddress = null;
#[Validate(['nullable', 'string'])]
public ?string $smtpFromName = null;
#[Validate(['nullable', 'string'])]
public ?string $smtpRecipients = null;
#[Validate(['nullable', 'string'])]
public ?string $smtpHost = null;
@@ -20,29 +36,26 @@ class SettingsEmail extends Component
public ?int $smtpPort = null;
#[Validate(['nullable', 'string', 'in:tls,ssl,none'])]
public ?string $smtpEncryption = null;
public ?string $smtpEncryption = 'tls';
#[Validate(['nullable', 'string'])]
public ?string $smtpUsername = null;
#[Validate(['nullable'])]
#[Validate(['nullable', 'string'])]
public ?string $smtpPassword = null;
#[Validate(['nullable', 'numeric'])]
public ?int $smtpTimeout = null;
#[Validate(['nullable', 'email'])]
public ?string $smtpFromAddress = null;
#[Validate(['nullable', 'string'])]
public ?string $smtpFromName = null;
#[Validate(['boolean'])]
public bool $resendEnabled = false;
#[Validate(['nullable', 'string'])]
public ?string $resendApiKey = null;
#[Validate(['nullable', 'email'])]
public ?string $testEmailAddress = null;
public function mount()
{
if (isInstanceAdmin() === false) {
@@ -50,6 +63,8 @@ class SettingsEmail extends Component
}
$this->settings = instanceSettings();
$this->syncData();
$this->team = auth()->user()->currentTeam();
$this->testEmailAddress = auth()->user()->email;
}
public function syncData(bool $toModel = false)
@@ -90,7 +105,7 @@ class SettingsEmail extends Component
try {
$this->resetErrorBag();
$this->syncData(true);
$this->dispatch('success', 'Settings saved.');
$this->dispatch('success', 'Transactional email settings updated.');
} catch (\Throwable $e) {
return handleError($e, $this);
}
@@ -99,19 +114,129 @@ class SettingsEmail extends Component
public function instantSave(string $type)
{
try {
$this->resetErrorBag();
if ($type === 'SMTP') {
$this->resendEnabled = false;
} else {
$this->smtpEnabled = false;
}
$this->syncData(true);
if ($this->smtpEnabled || $this->resendEnabled) {
$this->dispatch('success', "{$type} enabled.");
} else {
$this->dispatch('success', "{$type} disabled.");
$this->submitSmtp();
} elseif ($type === 'Resend') {
$this->submitResend();
}
} catch (\Throwable $e) {
if ($type === 'SMTP') {
$this->smtpEnabled = false;
} elseif ($type === 'Resend') {
$this->resendEnabled = false;
}
return handleError($e, $this);
}
}
public function submitSmtp()
{
try {
$this->validate([
'smtpEnabled' => 'boolean',
'smtpFromAddress' => 'required|email',
'smtpFromName' => 'required|string',
'smtpHost' => 'required|string',
'smtpPort' => 'required|numeric',
'smtpEncryption' => 'required|string|in:tls,ssl,none',
'smtpUsername' => 'nullable|string',
'smtpPassword' => 'nullable|string',
'smtpTimeout' => 'nullable|numeric',
], [
'smtpFromAddress.required' => 'From Address is required.',
'smtpFromAddress.email' => 'Please enter a valid email address.',
'smtpFromName.required' => 'From Name is required.',
'smtpHost.required' => 'SMTP Host is required.',
'smtpPort.required' => 'SMTP Port is required.',
'smtpPort.numeric' => 'SMTP Port must be a number.',
'smtpEncryption.required' => 'Encryption type is required.',
]);
$this->resendEnabled = false;
$this->settings->resend_enabled = false;
$this->settings->smtp_enabled = $this->smtpEnabled;
$this->settings->smtp_host = $this->smtpHost;
$this->settings->smtp_port = $this->smtpPort;
$this->settings->smtp_encryption = $this->smtpEncryption;
$this->settings->smtp_username = $this->smtpUsername;
$this->settings->smtp_password = $this->smtpPassword;
$this->settings->smtp_timeout = $this->smtpTimeout;
$this->settings->smtp_from_address = $this->smtpFromAddress;
$this->settings->smtp_from_name = $this->smtpFromName;
$this->settings->save();
$this->dispatch('success', 'SMTP settings updated.');
} catch (\Throwable $e) {
$this->smtpEnabled = false;
return handleError($e);
}
}
public function submitResend()
{
try {
$this->validate([
'resendEnabled' => 'boolean',
'resendApiKey' => 'required|string',
'smtpFromAddress' => 'required|email',
'smtpFromName' => 'required|string',
], [
'resendApiKey.required' => 'Resend API Key is required.',
'smtpFromAddress.required' => 'From Address is required.',
'smtpFromAddress.email' => 'Please enter a valid email address.',
'smtpFromName.required' => 'From Name is required.',
]);
$this->smtpEnabled = false;
$this->settings->smtp_enabled = false;
$this->settings->resend_enabled = $this->resendEnabled;
$this->settings->resend_api_key = $this->resendApiKey;
$this->settings->smtp_from_address = $this->smtpFromAddress;
$this->settings->smtp_from_name = $this->smtpFromName;
$this->settings->save();
$this->dispatch('success', 'Resend settings updated.');
} catch (\Throwable $e) {
$this->resendEnabled = false;
return handleError($e);
}
}
public function sendTestEmail()
{
try {
$this->validate([
'testEmailAddress' => 'required|email',
], [
'testEmailAddress.required' => 'Test email address is required.',
'testEmailAddress.email' => 'Please enter a valid email address.',
]);
$executed = RateLimiter::attempt(
'test-email:'.$this->team->id,
$perMinute = 0,
function () {
$this->team?->notify(new Test($this->testEmailAddress, 'email'));
$this->dispatch('success', 'Test Email sent.');
},
$decaySeconds = 10,
);
if (! $executed) {
throw new \Exception('Too many messages sent!');
}
} catch (\Throwable $e) {
return handleError($e);
}
}
}

View File

@@ -17,6 +17,7 @@ class SettingsOauth extends Component
$carry["oauth_settings_map.$setting->provider.client_secret"] = 'nullable';
$carry["oauth_settings_map.$setting->provider.redirect_uri"] = 'nullable';
$carry["oauth_settings_map.$setting->provider.tenant"] = 'nullable';
$carry["oauth_settings_map.$setting->provider.base_url"] = 'nullable';
return $carry;
}, []);
@@ -34,16 +35,30 @@ class SettingsOauth extends Component
}, []);
}
private function updateOauthSettings()
private function updateOauthSettings(?string $provider = null)
{
foreach (array_values($this->oauth_settings_map) as &$setting) {
$setting->save();
if ($provider) {
$oauth = $this->oauth_settings_map[$provider];
if (! $oauth->couldBeEnabled()) {
$oauth->update(['enabled' => false]);
throw new \Exception('OAuth settings are not complete for '.$oauth->provider.'.<br/>Please fill in all required fields.');
}
$oauth->save();
$this->dispatch('success', 'OAuth settings for '.$oauth->provider.' updated successfully!');
} else {
foreach (array_values($this->oauth_settings_map) as &$setting) {
$setting->save();
}
}
}
public function instantSave()
public function instantSave(string $provider)
{
$this->updateOauthSettings();
try {
$this->updateOauthSettings($provider);
} catch (\Exception $e) {
return handleError($e, $this);
}
}
public function submit()

View File

@@ -1,70 +0,0 @@
<?php
namespace App\Livewire\Waitlist;
use App\Jobs\SendConfirmationForWaitlistJob;
use App\Models\User;
use App\Models\Waitlist;
use Illuminate\Support\Str;
use Livewire\Component;
class Index extends Component
{
public string $email;
public int $users = 0;
public int $waitingInLine = 0;
protected $rules = [
'email' => 'required|email',
];
public function render()
{
return view('livewire.waitlist.index')->layout('layouts.simple');
}
public function mount()
{
if (config('constants.waitlist.enabled') == false) {
return redirect()->route('register');
}
$this->waitingInLine = Waitlist::whereVerified(true)->count();
$this->users = User::count();
if (isDev()) {
$this->email = 'waitlist@example.com';
}
}
public function submit()
{
$this->validate();
try {
$already_registered = User::whereEmail($this->email)->first();
if ($already_registered) {
throw new \Exception('You are already on the waitlist or registered. <br>Please check your email to verify your email address or contact support.');
}
$found = Waitlist::where('email', $this->email)->first();
if ($found) {
if (! $found->verified) {
$this->dispatch('error', 'You are already on the waitlist. <br>Please check your email to verify your email address.');
return;
}
$this->dispatch('error', 'You are already on the waitlist. <br>You will be notified when your turn comes. <br>Thank you.');
return;
}
$waitlist = Waitlist::create([
'email' => Str::lower($this->email),
'type' => 'registration',
]);
$this->dispatch('success', 'Check your email to verify your email address.');
dispatch(new SendConfirmationForWaitlistJob($this->email, $waitlist->uuid));
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
}