Merge branch 'next' into add-no-encryption-option
This commit is contained in:
@@ -24,7 +24,7 @@ class StartClickhouse
|
||||
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||
|
||||
$this->commands = [
|
||||
"echo 'Starting {$database->name}.'",
|
||||
"echo 'Starting database.'",
|
||||
"mkdir -p $this->configuration_dir",
|
||||
];
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class StartDragonfly
|
||||
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||
|
||||
$this->commands = [
|
||||
"echo 'Starting {$database->name}.'",
|
||||
"echo 'Starting database.'",
|
||||
"mkdir -p $this->configuration_dir",
|
||||
];
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class StartKeydb
|
||||
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||
|
||||
$this->commands = [
|
||||
"echo 'Starting {$database->name}.'",
|
||||
"echo 'Starting database.'",
|
||||
"mkdir -p $this->configuration_dir",
|
||||
];
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class StartMariadb
|
||||
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||
|
||||
$this->commands = [
|
||||
"echo 'Starting {$database->name}.'",
|
||||
"echo 'Starting database.'",
|
||||
"mkdir -p $this->configuration_dir",
|
||||
];
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class StartMongodb
|
||||
}
|
||||
|
||||
$this->commands = [
|
||||
"echo 'Starting {$database->name}.'",
|
||||
"echo 'Starting database.'",
|
||||
"mkdir -p $this->configuration_dir",
|
||||
];
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class StartMysql
|
||||
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||
|
||||
$this->commands = [
|
||||
"echo 'Starting {$database->name}.'",
|
||||
"echo 'Starting database.'",
|
||||
"mkdir -p $this->configuration_dir",
|
||||
];
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class StartPostgresql
|
||||
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||
|
||||
$this->commands = [
|
||||
"echo 'Starting {$database->name}.'",
|
||||
"echo 'Starting database.'",
|
||||
"mkdir -p $this->configuration_dir",
|
||||
"mkdir -p $this->configuration_dir/docker-entrypoint-initdb.d/",
|
||||
];
|
||||
|
||||
@@ -25,7 +25,7 @@ class StartRedis
|
||||
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||
|
||||
$this->commands = [
|
||||
"echo 'Starting {$database->name}.'",
|
||||
"echo 'Starting database.'",
|
||||
"mkdir -p $this->configuration_dir",
|
||||
];
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ class GetContainersStatus
|
||||
})->first();
|
||||
if (! $foundTcpProxy) {
|
||||
StartDatabaseProxy::run($database);
|
||||
// $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$database->name}", $this->server));
|
||||
// $this->server->team?->notify(new ContainerRestarted("TCP Proxy for database", $this->server));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -51,7 +51,6 @@ class ServerCheck
|
||||
|
||||
$containerReplicates = null;
|
||||
$this->isSentinel = true;
|
||||
|
||||
} else {
|
||||
['containers' => $this->containers, 'containerReplicates' => $containerReplicates] = $this->server->getContainers();
|
||||
// ServerStorageCheckJob::dispatch($this->server);
|
||||
@@ -148,7 +147,6 @@ class ServerCheck
|
||||
} else {
|
||||
$labels = Arr::undot(data_get($container, 'Config.Labels'));
|
||||
}
|
||||
|
||||
}
|
||||
$managed = data_get($labels, 'coolify.managed');
|
||||
if (! $managed) {
|
||||
@@ -259,7 +257,7 @@ class ServerCheck
|
||||
})->first();
|
||||
if (! $foundTcpProxy) {
|
||||
StartDatabaseProxy::run($database);
|
||||
// $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$database->name}", $this->server));
|
||||
// $this->server->team?->notify(new ContainerRestarted("TCP Proxy for database", $this->server));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class CloudCleanupSubscriptions extends Command
|
||||
}
|
||||
// If the team has no subscription id and the invoice is paid, we need to reset the invoice paid status
|
||||
if (! (data_get($team, 'subscription.stripe_subscription_id'))) {
|
||||
$this->info("Resetting invoice paid status for team {$team->id} {$team->name}");
|
||||
$this->info("Resetting invoice paid status for team {$team->id}");
|
||||
|
||||
$team->subscription->update([
|
||||
'stripe_invoice_paid' => false,
|
||||
@@ -61,9 +61,9 @@ class CloudCleanupSubscriptions extends Command
|
||||
$this->info('Subscription id: '.data_get($team, 'subscription.stripe_subscription_id'));
|
||||
$confirm = $this->confirm('Do you want to cancel the subscription?', true);
|
||||
if (! $confirm) {
|
||||
$this->info("Skipping team {$team->id} {$team->name}");
|
||||
$this->info("Skipping team {$team->id}");
|
||||
} else {
|
||||
$this->info("Cancelling subscription for team {$team->id} {$team->name}");
|
||||
$this->info("Cancelling subscription for team {$team->id}");
|
||||
$team->subscription->update([
|
||||
'stripe_invoice_paid' => false,
|
||||
'stripe_trial_already_ended' => false,
|
||||
|
||||
@@ -187,7 +187,7 @@ class Emails extends Command
|
||||
'team_id' => 0,
|
||||
]);
|
||||
}
|
||||
$this->mail = (new BackupSuccess($backup, $db))->toMail();
|
||||
// $this->mail = (new BackupSuccess($backup->frequency, $db->name))->toMail();
|
||||
$this->sendEmail();
|
||||
break;
|
||||
// case 'invitation-link':
|
||||
|
||||
@@ -20,7 +20,10 @@ class ServicesGenerate extends Command
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$serviceTemplatesJson = collect(glob(base_path('templates/compose/*.yaml')))
|
||||
$serviceTemplatesJson = collect(array_merge(
|
||||
glob(base_path('templates/compose/*.yaml')),
|
||||
glob(base_path('templates/compose/*.yml'))
|
||||
))
|
||||
->mapWithKeys(function ($file): array {
|
||||
$file = basename($file);
|
||||
$parsed = $this->processFile($file);
|
||||
@@ -68,7 +71,7 @@ class ServicesGenerate extends Command
|
||||
'slogan' => $data->get('slogan', str($file)->headline()),
|
||||
'compose' => $compose,
|
||||
'tags' => $tags,
|
||||
'logo' => $data->get('logo', 'svgs/coolify.png'),
|
||||
'logo' => $data->get('logo', 'svgs/default.webp'),
|
||||
'minversion' => $data->get('minversion', '0.0.0'),
|
||||
];
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ class Kernel extends ConsoleKernel
|
||||
}
|
||||
|
||||
foreach ($servers as $server) {
|
||||
$serverTimezone = $server->settings->server_timezone;
|
||||
$serverTimezone = data_get($server->settings, 'server_timezone', $this->instanceTimezone);
|
||||
|
||||
// Sentinel check
|
||||
$lastSentinelUpdate = $server->sentinel_updated_at;
|
||||
@@ -141,8 +141,12 @@ class Kernel extends ConsoleKernel
|
||||
if (validate_timezone($serverTimezone) === false) {
|
||||
$serverTimezone = config('app.timezone');
|
||||
}
|
||||
$this->scheduleInstance->job(new ServerCheckJob($server))->timezone($serverTimezone)->everyMinute()->onOneServer();
|
||||
// $this->scheduleInstance->job(new \App\Jobs\ServerCheckNewJob($server))->everyMinute()->onOneServer();
|
||||
if (isCloud()) {
|
||||
$this->scheduleInstance->job(new ServerCheckJob($server))->timezone($serverTimezone)->everyFiveMinutes()->onOneServer();
|
||||
} else {
|
||||
$this->scheduleInstance->job(new ServerCheckJob($server))->timezone($serverTimezone)->everyMinute()->onOneServer();
|
||||
}
|
||||
// $this->scheduleInstance->job(new \App\Jobs\ServerCheckNewJob($server))->everyFiveMinutes()->onOneServer();
|
||||
|
||||
// Check storage usage every 10 minutes if Sentinel does not activated
|
||||
$this->scheduleInstance->job(new ServerStorageCheckJob($server))->everyTenMinutes()->onOneServer();
|
||||
|
||||
@@ -1591,16 +1591,32 @@ class ApplicationsController extends Controller
|
||||
}
|
||||
$domains = $request->domains;
|
||||
if ($request->has('domains') && $server->isProxyShouldRun()) {
|
||||
$errors = [];
|
||||
$uuid = $request->uuid;
|
||||
$fqdn = $request->domains;
|
||||
$fqdn = str($fqdn)->replaceEnd(',', '')->trim();
|
||||
$fqdn = str($fqdn)->replaceStart(',', '')->trim();
|
||||
$application->fqdn = $fqdn;
|
||||
if (! $application->settings->is_container_label_readonly_enabled) {
|
||||
$customLabels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->custom_labels = base64_encode($customLabels);
|
||||
$errors = [];
|
||||
$fqdn = str($fqdn)->trim()->explode(',')->map(function ($domain) use (&$errors) {
|
||||
$domain = trim($domain);
|
||||
if (filter_var($domain, FILTER_VALIDATE_URL) === false || !preg_match('/^https?:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}/', $domain)) {
|
||||
$errors[] = 'Invalid domain: '.$domain;
|
||||
}
|
||||
return $domain;
|
||||
});
|
||||
if (count($errors) > 0) {
|
||||
return response()->json([
|
||||
'message' => 'Validation failed.',
|
||||
'errors' => $errors,
|
||||
], 422);
|
||||
}
|
||||
if (checkIfDomainIsAlreadyUsed($fqdn, $teamId, $uuid)) {
|
||||
return response()->json([
|
||||
'message' => 'Validation failed.',
|
||||
'errors' => [
|
||||
'domains' => 'One of the domain is already used.',
|
||||
],
|
||||
], 422);
|
||||
}
|
||||
$request->offsetUnset('domains');
|
||||
}
|
||||
|
||||
$dockerComposeDomainsJson = collect();
|
||||
@@ -2811,3 +2827,30 @@ class ApplicationsController extends Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$fqdn = str($fqdn)->replaceStart(',', '')->trim();
|
||||
$errors = [];
|
||||
$fqdn = str($fqdn)->trim()->explode(',')->map(function ($domain) use (&$errors) {
|
||||
if (filter_var($domain, FILTER_VALIDATE_URL) === false) {
|
||||
$errors[] = 'Invalid domain: ' . $domain;
|
||||
}
|
||||
|
||||
return str($domain)->trim()->lower();
|
||||
});
|
||||
if (count($errors) > 0) {
|
||||
return response()->json([
|
||||
'message' => 'Validation failed.',
|
||||
'errors' => $errors,
|
||||
], 422);
|
||||
}
|
||||
if (checkIfDomainIsAlreadyUsed($fqdn, $teamId, $uuid)) {
|
||||
return response()->json([
|
||||
'message' => 'Validation failed.',
|
||||
'errors' => [
|
||||
'domains' => 'One of the domain is already used.',
|
||||
],
|
||||
], 422);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1557,7 +1557,8 @@ class DatabasesController extends Controller
|
||||
]
|
||||
)
|
||||
),
|
||||
]),
|
||||
]
|
||||
),
|
||||
new OA\Response(
|
||||
response: 401,
|
||||
ref: '#/components/responses/401',
|
||||
@@ -1632,9 +1633,11 @@ class DatabasesController extends Controller
|
||||
type: 'object',
|
||||
properties: [
|
||||
'message' => ['type' => 'string', 'example' => 'Database starting request queued.'],
|
||||
])
|
||||
]
|
||||
)
|
||||
),
|
||||
]),
|
||||
]
|
||||
),
|
||||
new OA\Response(
|
||||
response: 401,
|
||||
ref: '#/components/responses/401',
|
||||
@@ -1708,9 +1711,11 @@ class DatabasesController extends Controller
|
||||
type: 'object',
|
||||
properties: [
|
||||
'message' => ['type' => 'string', 'example' => 'Database stopping request queued.'],
|
||||
])
|
||||
]
|
||||
)
|
||||
),
|
||||
]),
|
||||
]
|
||||
),
|
||||
new OA\Response(
|
||||
response: 401,
|
||||
ref: '#/components/responses/401',
|
||||
@@ -1784,9 +1789,11 @@ class DatabasesController extends Controller
|
||||
type: 'object',
|
||||
properties: [
|
||||
'message' => ['type' => 'string', 'example' => 'Database restaring request queued.'],
|
||||
])
|
||||
]
|
||||
)
|
||||
),
|
||||
]),
|
||||
]
|
||||
),
|
||||
new OA\Response(
|
||||
response: 401,
|
||||
ref: '#/components/responses/401',
|
||||
|
||||
@@ -463,7 +463,7 @@ class Github extends Controller
|
||||
$private_key = data_get($data, 'pem');
|
||||
$webhook_secret = data_get($data, 'webhook_secret');
|
||||
$private_key = PrivateKey::create([
|
||||
'name' => $slug,
|
||||
'name' => "github-app-{$slug}",
|
||||
'private_key' => $private_key,
|
||||
'team_id' => $github_app->team_id,
|
||||
'is_git_related' => true,
|
||||
|
||||
@@ -140,6 +140,8 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
||||
|
||||
private ?string $buildTarget = null;
|
||||
|
||||
private bool $disableBuildCache = false;
|
||||
|
||||
private Collection $saved_outputs;
|
||||
|
||||
private ?string $full_healthcheck_url = null;
|
||||
@@ -178,7 +180,11 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
||||
$this->pull_request_id = $this->application_deployment_queue->pull_request_id;
|
||||
$this->commit = $this->application_deployment_queue->commit;
|
||||
$this->rollback = $this->application_deployment_queue->rollback;
|
||||
$this->disableBuildCache = $this->application->settings->disable_build_cache;
|
||||
$this->force_rebuild = $this->application_deployment_queue->force_rebuild;
|
||||
if ($this->disableBuildCache) {
|
||||
$this->force_rebuild = true;
|
||||
}
|
||||
$this->restart_only = $this->application_deployment_queue->restart_only;
|
||||
$this->restart_only = $this->restart_only && $this->application->build_pack !== 'dockerimage' && $this->application->build_pack !== 'dockerfile';
|
||||
$this->only_this_server = $this->application_deployment_queue->only_this_server;
|
||||
@@ -1976,6 +1982,9 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
||||
$this->build_args = $this->build_args->implode(' ');
|
||||
|
||||
$this->application_deployment_queue->addLogEntry('----------------------------------------');
|
||||
if ($this->disableBuildCache) {
|
||||
$this->application_deployment_queue->addLogEntry('Docker build cache is disabled. It will not be used during the build process.');
|
||||
}
|
||||
if ($this->application->build_pack === 'static') {
|
||||
$this->application_deployment_queue->addLogEntry('Static deployment. Copying static assets to the image.');
|
||||
} else {
|
||||
@@ -2400,7 +2409,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
||||
if (! $this->only_this_server) {
|
||||
$this->deploy_to_additional_destinations();
|
||||
}
|
||||
$this->application->environment->project->team?->notify(new DeploymentSuccess($this->application, $this->deployment_uuid, $this->preview));
|
||||
//$this->application->environment->project->team?->notify(new DeploymentSuccess($this->application, $this->deployment_uuid, $this->preview));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -306,7 +306,7 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
if ($this->backup->save_s3) {
|
||||
$this->upload_to_s3();
|
||||
}
|
||||
$this->team?->notify(new BackupSuccess($this->backup, $this->database, $database));
|
||||
//$this->team?->notify(new BackupSuccess($this->backup, $this->database, $database));
|
||||
$this->backup_log->update([
|
||||
'status' => 'success',
|
||||
'message' => $this->backup_output,
|
||||
|
||||
@@ -31,7 +31,12 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue
|
||||
return [(new WithoutOverlapping($this->server->uuid))->dontRelease()];
|
||||
}
|
||||
|
||||
public function __construct(public Server $server) {}
|
||||
public function __construct(public Server $server)
|
||||
{
|
||||
if (isDev()) {
|
||||
$this->handle();
|
||||
}
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
|
||||
@@ -172,13 +172,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
||||
|
||||
public function getProxyType()
|
||||
{
|
||||
// Set Default Proxy Type
|
||||
$this->selectProxy(ProxyTypes::TRAEFIK->value);
|
||||
// $proxyTypeSet = $this->createdServer->proxy->type;
|
||||
// if (!$proxyTypeSet) {
|
||||
// $this->currentState = 'select-proxy';
|
||||
// return;
|
||||
// }
|
||||
$this->getProjects();
|
||||
}
|
||||
|
||||
@@ -189,7 +183,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
||||
|
||||
return;
|
||||
}
|
||||
$this->createdPrivateKey = PrivateKey::find($this->selectedExistingPrivateKey);
|
||||
$this->createdPrivateKey = PrivateKey::where('team_id', currentTeam()->id)->where('id', $this->selectedExistingPrivateKey)->first();
|
||||
$this->privateKey = $this->createdPrivateKey->private_key;
|
||||
$this->currentState = 'create-server';
|
||||
}
|
||||
|
||||
@@ -73,8 +73,8 @@ class Email extends Component
|
||||
#[Validate(['nullable', 'string'])]
|
||||
public ?string $resendApiKey = null;
|
||||
|
||||
#[Validate(['required', 'email'])]
|
||||
public string $testEmailAddress = '';
|
||||
#[Validate(['nullable', 'email'])]
|
||||
public ?string $testEmailAddress = null;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
|
||||
@@ -25,6 +25,9 @@ class Advanced extends Component
|
||||
#[Validate(['boolean'])]
|
||||
public bool $isAutoDeployEnabled = true;
|
||||
|
||||
#[Validate(['boolean'])]
|
||||
public bool $disableBuildCache = false;
|
||||
|
||||
#[Validate(['boolean'])]
|
||||
public bool $isLogDrainEnabled = false;
|
||||
|
||||
@@ -95,6 +98,7 @@ class Advanced extends Component
|
||||
$this->application->settings->is_stripprefix_enabled = $this->isStripprefixEnabled;
|
||||
$this->application->settings->is_raw_compose_deployment_enabled = $this->isRawComposeDeploymentEnabled;
|
||||
$this->application->settings->connect_to_docker_network = $this->isConnectToDockerNetworkEnabled;
|
||||
$this->application->settings->disable_build_cache = $this->disableBuildCache;
|
||||
$this->application->settings->save();
|
||||
} else {
|
||||
$this->isForceHttpsEnabled = $this->application->isForceHttpsEnabled();
|
||||
@@ -116,6 +120,7 @@ class Advanced extends Component
|
||||
$this->customInternalName = $this->application->settings->custom_internal_name;
|
||||
$this->isRawComposeDeploymentEnabled = $this->application->settings->is_raw_compose_deployment_enabled;
|
||||
$this->isConnectToDockerNetworkEnabled = $this->application->settings->connect_to_docker_network;
|
||||
$this->disableBuildCache = $this->application->settings->disable_build_cache;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,24 +16,30 @@ class Configuration extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (! $project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']);
|
||||
if (! $environment) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$application = $environment->applications->where('uuid', request()->route('application_uuid'))->first();
|
||||
if (! $application) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$project = currentTeam()
|
||||
->projects()
|
||||
->select('id', 'uuid', 'team_id')
|
||||
->where('uuid', request()->route('project_uuid'))
|
||||
->firstOrFail();
|
||||
$environment = $project->environments()
|
||||
->select('id', 'name', 'project_id')
|
||||
->where('name', request()->route('environment_name'))
|
||||
->firstOrFail();
|
||||
$application = $environment->applications()
|
||||
->with(['destination'])
|
||||
->where('uuid', request()->route('application_uuid'))
|
||||
->firstOrFail();
|
||||
|
||||
$this->application = $application;
|
||||
$mainServer = $this->application->destination->server;
|
||||
$servers = Server::ownedByCurrentTeam()->get();
|
||||
$this->servers = $servers->filter(function ($server) use ($mainServer) {
|
||||
return $server->id != $mainServer->id;
|
||||
});
|
||||
if ($application->destination && $application->destination->server) {
|
||||
$mainServer = $application->destination->server;
|
||||
$this->servers = Server::ownedByCurrentTeam()
|
||||
->select('id', 'name')
|
||||
->where('id', '!=', $mainServer->id)
|
||||
->get();
|
||||
} else {
|
||||
$this->servers = collect();
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -168,18 +168,42 @@ class ExecuteContainerCommand extends Component
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Validate container name format
|
||||
if (! preg_match('/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/', $this->selected_container)) {
|
||||
throw new \InvalidArgumentException('Invalid container name format');
|
||||
}
|
||||
|
||||
// Verify container exists in our allowed list
|
||||
$container = collect($this->containers)->firstWhere('container.Names', $this->selected_container);
|
||||
if (is_null($container)) {
|
||||
throw new \RuntimeException('Container not found.');
|
||||
}
|
||||
$server = data_get($this->container, 'server');
|
||||
|
||||
// Verify server ownership and status
|
||||
$server = data_get($container, 'server');
|
||||
if (! $server || ! $server instanceof Server) {
|
||||
throw new \RuntimeException('Invalid server configuration.');
|
||||
}
|
||||
|
||||
if ($server->isForceDisabled()) {
|
||||
throw new \RuntimeException('Server is disabled.');
|
||||
}
|
||||
|
||||
// Additional ownership verification based on resource type
|
||||
$resourceServer = match ($this->type) {
|
||||
'application' => $this->resource->destination->server,
|
||||
'database' => $this->resource->destination->server,
|
||||
'service' => $this->resource->server,
|
||||
default => throw new \RuntimeException('Invalid resource type.')
|
||||
};
|
||||
|
||||
if ($server->id !== $resourceServer->id && ! $this->resource->additional_servers->contains('id', $server->id)) {
|
||||
throw new \RuntimeException('Server ownership verification failed.');
|
||||
}
|
||||
|
||||
$this->dispatch(
|
||||
'send-terminal-command',
|
||||
isset($container),
|
||||
true,
|
||||
data_get($container, 'container.Names'),
|
||||
data_get($container, 'server.uuid')
|
||||
);
|
||||
|
||||
@@ -29,11 +29,20 @@ class Terminal extends Component
|
||||
$server = Server::ownedByCurrentTeam()->whereUuid($serverUuid)->firstOrFail();
|
||||
|
||||
if ($isContainer) {
|
||||
// Validate container identifier format (alphanumeric, dashes, and underscores only)
|
||||
if (! preg_match('/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/', $identifier)) {
|
||||
throw new \InvalidArgumentException('Invalid container identifier format');
|
||||
}
|
||||
|
||||
// Verify container exists and belongs to the user's team
|
||||
$status = getContainerStatus($server, $identifier);
|
||||
if ($status !== 'running') {
|
||||
return;
|
||||
}
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, "docker exec -it {$identifier} sh -c 'PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && if [ -f ~/.profile ]; then . ~/.profile; fi && if [ -n \"\$SHELL\" ]; then exec \$SHELL; else sh; fi'");
|
||||
|
||||
// Escape the identifier for shell usage
|
||||
$escapedIdentifier = escapeshellarg($identifier);
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, "docker exec -it {$escapedIdentifier} sh -c 'PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && if [ -f ~/.profile ]; then . ~/.profile; fi && if [ -n \"\$SHELL\" ]; then exec \$SHELL; else sh; fi'");
|
||||
} else {
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && if [ -f ~/.profile ]; then . ~/.profile; fi && if [ -n "$SHELL" ]; then exec $SHELL; else sh; fi');
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ class Advanced extends Component
|
||||
#[Validate('boolean')]
|
||||
public bool $forceDockerCleanup = false;
|
||||
|
||||
#[Validate('string')]
|
||||
#[Validate(['string', 'required'])]
|
||||
public string $dockerCleanupFrequency = '*/10 * * * *';
|
||||
|
||||
#[Validate(['integer', 'min:1', 'max:99'])]
|
||||
@@ -78,7 +78,6 @@ class Advanced extends Component
|
||||
try {
|
||||
$this->syncData(true);
|
||||
$this->dispatch('success', 'Server updated.');
|
||||
// $this->dispatch('refreshServerShow');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -49,33 +49,73 @@ class LogDrains extends Component
|
||||
}
|
||||
}
|
||||
|
||||
public function syncData(bool $toModel = false)
|
||||
public function syncDataNewRelic(bool $toModel = false)
|
||||
{
|
||||
if ($toModel) {
|
||||
$this->server->settings->is_logdrain_newrelic_enabled = $this->isLogDrainNewRelicEnabled;
|
||||
$this->server->settings->logdrain_newrelic_license_key = $this->logDrainNewRelicLicenseKey;
|
||||
$this->server->settings->logdrain_newrelic_base_uri = $this->logDrainNewRelicBaseUri;
|
||||
} else {
|
||||
$this->isLogDrainNewRelicEnabled = $this->server->settings->is_logdrain_newrelic_enabled;
|
||||
$this->logDrainNewRelicLicenseKey = $this->server->settings->logdrain_newrelic_license_key;
|
||||
$this->logDrainNewRelicBaseUri = $this->server->settings->logdrain_newrelic_base_uri;
|
||||
}
|
||||
}
|
||||
|
||||
public function syncDataAxiom(bool $toModel = false)
|
||||
{
|
||||
if ($toModel) {
|
||||
$this->server->settings->is_logdrain_axiom_enabled = $this->isLogDrainAxiomEnabled;
|
||||
$this->server->settings->logdrain_axiom_dataset_name = $this->logDrainAxiomDatasetName;
|
||||
$this->server->settings->logdrain_axiom_api_key = $this->logDrainAxiomApiKey;
|
||||
} else {
|
||||
$this->isLogDrainAxiomEnabled = $this->server->settings->is_logdrain_axiom_enabled;
|
||||
$this->logDrainAxiomDatasetName = $this->server->settings->logdrain_axiom_dataset_name;
|
||||
$this->logDrainAxiomApiKey = $this->server->settings->logdrain_axiom_api_key;
|
||||
}
|
||||
}
|
||||
|
||||
public function syncDataCustom(bool $toModel = false)
|
||||
{
|
||||
if ($toModel) {
|
||||
$this->server->settings->is_logdrain_custom_enabled = $this->isLogDrainCustomEnabled;
|
||||
$this->server->settings->logdrain_custom_config = $this->logDrainCustomConfig;
|
||||
$this->server->settings->logdrain_custom_config_parser = $this->logDrainCustomConfigParser;
|
||||
} else {
|
||||
$this->isLogDrainCustomEnabled = $this->server->settings->is_logdrain_custom_enabled;
|
||||
$this->logDrainCustomConfig = $this->server->settings->logdrain_custom_config;
|
||||
$this->logDrainCustomConfigParser = $this->server->settings->logdrain_custom_config_parser;
|
||||
}
|
||||
}
|
||||
|
||||
public function syncData(bool $toModel = false, ?string $type = null)
|
||||
{
|
||||
if ($toModel) {
|
||||
$this->customValidation();
|
||||
$this->server->settings->is_logdrain_newrelic_enabled = $this->isLogDrainNewRelicEnabled;
|
||||
$this->server->settings->is_logdrain_axiom_enabled = $this->isLogDrainAxiomEnabled;
|
||||
$this->server->settings->is_logdrain_custom_enabled = $this->isLogDrainCustomEnabled;
|
||||
|
||||
$this->server->settings->logdrain_newrelic_license_key = $this->logDrainNewRelicLicenseKey;
|
||||
$this->server->settings->logdrain_newrelic_base_uri = $this->logDrainNewRelicBaseUri;
|
||||
$this->server->settings->logdrain_axiom_dataset_name = $this->logDrainAxiomDatasetName;
|
||||
$this->server->settings->logdrain_axiom_api_key = $this->logDrainAxiomApiKey;
|
||||
$this->server->settings->logdrain_custom_config = $this->logDrainCustomConfig;
|
||||
$this->server->settings->logdrain_custom_config_parser = $this->logDrainCustomConfigParser;
|
||||
|
||||
if ($type === 'newrelic') {
|
||||
$this->syncDataNewRelic($toModel);
|
||||
} elseif ($type === 'axiom') {
|
||||
$this->syncDataAxiom($toModel);
|
||||
} elseif ($type === 'custom') {
|
||||
$this->syncDataCustom($toModel);
|
||||
} else {
|
||||
$this->syncDataNewRelic($toModel);
|
||||
$this->syncDataAxiom($toModel);
|
||||
$this->syncDataCustom($toModel);
|
||||
}
|
||||
$this->server->settings->save();
|
||||
} else {
|
||||
$this->isLogDrainNewRelicEnabled = $this->server->settings->is_logdrain_newrelic_enabled;
|
||||
$this->isLogDrainAxiomEnabled = $this->server->settings->is_logdrain_axiom_enabled;
|
||||
$this->isLogDrainCustomEnabled = $this->server->settings->is_logdrain_custom_enabled;
|
||||
|
||||
$this->logDrainNewRelicLicenseKey = $this->server->settings->logdrain_newrelic_license_key;
|
||||
$this->logDrainNewRelicBaseUri = $this->server->settings->logdrain_newrelic_base_uri;
|
||||
$this->logDrainAxiomDatasetName = $this->server->settings->logdrain_axiom_dataset_name;
|
||||
$this->logDrainAxiomApiKey = $this->server->settings->logdrain_axiom_api_key;
|
||||
$this->logDrainCustomConfig = $this->server->settings->logdrain_custom_config;
|
||||
$this->logDrainCustomConfigParser = $this->server->settings->logdrain_custom_config_parser;
|
||||
if ($type === 'newrelic') {
|
||||
$this->syncDataNewRelic($toModel);
|
||||
} elseif ($type === 'axiom') {
|
||||
$this->syncDataAxiom($toModel);
|
||||
} elseif ($type === 'custom') {
|
||||
$this->syncDataCustom($toModel);
|
||||
} else {
|
||||
$this->syncDataNewRelic($toModel);
|
||||
$this->syncDataAxiom($toModel);
|
||||
$this->syncDataCustom($toModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +176,7 @@ class LogDrains extends Component
|
||||
public function submit(string $type)
|
||||
{
|
||||
try {
|
||||
$this->syncData(true);
|
||||
$this->syncData(true, $type);
|
||||
$this->dispatch('success', 'Settings saved.');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace App\Livewire\Server;
|
||||
use App\Actions\Server\StartSentinel;
|
||||
use App\Actions\Server\StopSentinel;
|
||||
use App\Models\Server;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
@@ -79,9 +79,6 @@ class Show extends Component
|
||||
#[Validate(['required'])]
|
||||
public string $serverTimezone;
|
||||
|
||||
#[Locked]
|
||||
public array $timezones;
|
||||
|
||||
public function getListeners()
|
||||
{
|
||||
$teamId = auth()->user()->currentTeam()->id;
|
||||
@@ -96,13 +93,21 @@ class Show extends Component
|
||||
{
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||
$this->timezones = collect(timezone_identifiers_list())->sort()->values()->toArray();
|
||||
$this->syncData();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
#[Computed]
|
||||
public function timezones(): array
|
||||
{
|
||||
return collect(timezone_identifiers_list())
|
||||
->sort()
|
||||
->values()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public function syncData(bool $toModel = false)
|
||||
{
|
||||
if ($toModel) {
|
||||
|
||||
@@ -7,7 +7,7 @@ use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
@@ -17,9 +17,6 @@ class Index extends Component
|
||||
|
||||
protected Server $server;
|
||||
|
||||
#[Locked]
|
||||
public $timezones;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $is_auto_update_enabled;
|
||||
|
||||
@@ -53,7 +50,7 @@ class Index extends Component
|
||||
#[Validate('string')]
|
||||
public string $auto_update_frequency;
|
||||
|
||||
#[Validate('string')]
|
||||
#[Validate('string|required')]
|
||||
public string $update_check_frequency;
|
||||
|
||||
#[Validate('required|string|timezone')]
|
||||
@@ -101,14 +98,29 @@ class Index extends Component
|
||||
$this->is_api_enabled = $this->settings->is_api_enabled;
|
||||
$this->auto_update_frequency = $this->settings->auto_update_frequency;
|
||||
$this->update_check_frequency = $this->settings->update_check_frequency;
|
||||
$this->timezones = collect(timezone_identifiers_list())->sort()->values()->toArray();
|
||||
$this->instance_timezone = $this->settings->instance_timezone;
|
||||
$this->disable_two_step_confirmation = $this->settings->disable_two_step_confirmation;
|
||||
}
|
||||
}
|
||||
|
||||
#[Computed]
|
||||
public function timezones(): array
|
||||
{
|
||||
return collect(timezone_identifiers_list())
|
||||
->sort()
|
||||
->values()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public function instantSave($isSave = true)
|
||||
{
|
||||
$this->validate();
|
||||
if ($this->settings->is_auto_update_enabled === true) {
|
||||
$this->validate([
|
||||
'auto_update_frequency' => ['required', 'string'],
|
||||
]);
|
||||
}
|
||||
|
||||
$this->settings->fqdn = $this->fqdn;
|
||||
$this->settings->resale_license = $this->resale_license;
|
||||
$this->settings->public_port_min = $this->public_port_min;
|
||||
|
||||
@@ -4,6 +4,11 @@ namespace App\Livewire\Source\Github;
|
||||
|
||||
use App\Jobs\GithubAppPermissionJob;
|
||||
use App\Models\GithubApp;
|
||||
use App\Models\PrivateKey;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Lcobucci\JWT\Configuration;
|
||||
use Lcobucci\JWT\Signer\Key\InMemory;
|
||||
use Lcobucci\JWT\Signer\Rsa\Sha256;
|
||||
use Livewire\Component;
|
||||
|
||||
class Change extends Component
|
||||
@@ -51,12 +56,20 @@ class Change extends Component
|
||||
'github_app.administration' => 'nullable|string',
|
||||
];
|
||||
|
||||
public function boot()
|
||||
{
|
||||
if ($this->github_app) {
|
||||
$this->github_app->makeVisible(['client_secret', 'webhook_secret']);
|
||||
}
|
||||
}
|
||||
|
||||
public function checkPermissions()
|
||||
{
|
||||
GithubAppPermissionJob::dispatchSync($this->github_app);
|
||||
$this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||
$this->dispatch('success', 'Github App permissions updated.');
|
||||
}
|
||||
|
||||
// public function check()
|
||||
// {
|
||||
|
||||
@@ -90,15 +103,16 @@ class Change extends Component
|
||||
|
||||
// ray($runners_by_repository);
|
||||
// }
|
||||
|
||||
public function mount()
|
||||
{
|
||||
try {
|
||||
$github_app_uuid = request()->github_app_uuid;
|
||||
$this->github_app = GithubApp::ownedByCurrentTeam()->whereUuid($github_app_uuid)->firstOrFail();
|
||||
$this->github_app->makeVisible(['client_secret', 'webhook_secret']);
|
||||
|
||||
$this->applications = $this->github_app->applications;
|
||||
$settings = instanceSettings();
|
||||
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||
|
||||
$this->name = str($this->github_app->name)->kebab();
|
||||
$this->fqdn = $settings->fqdn;
|
||||
@@ -142,6 +156,77 @@ class Change extends Component
|
||||
}
|
||||
}
|
||||
|
||||
public function getGithubAppNameUpdatePath()
|
||||
{
|
||||
if (str($this->github_app->organization)->isNotEmpty()) {
|
||||
return "{$this->github_app->html_url}/organizations/{$this->github_app->organization}/settings/apps/{$this->github_app->name}";
|
||||
}
|
||||
|
||||
return "{$this->github_app->html_url}/settings/apps/{$this->github_app->name}";
|
||||
}
|
||||
|
||||
private function generateGithubJwt($private_key, $app_id): string
|
||||
{
|
||||
$configuration = Configuration::forAsymmetricSigner(
|
||||
new Sha256,
|
||||
InMemory::plainText($private_key),
|
||||
InMemory::plainText($private_key)
|
||||
);
|
||||
|
||||
$now = time();
|
||||
|
||||
return $configuration->builder()
|
||||
->issuedBy((string) $app_id)
|
||||
->permittedFor('https://api.github.com')
|
||||
->identifiedBy((string) $now)
|
||||
->issuedAt(new \DateTimeImmutable("@{$now}"))
|
||||
->expiresAt(new \DateTimeImmutable('@'.($now + 600)))
|
||||
->getToken($configuration->signer(), $configuration->signingKey())
|
||||
->toString();
|
||||
}
|
||||
|
||||
public function updateGithubAppName()
|
||||
{
|
||||
try {
|
||||
$privateKey = PrivateKey::ownedByCurrentTeam()->find($this->github_app->private_key_id);
|
||||
|
||||
if (! $privateKey) {
|
||||
$this->dispatch('error', 'No private key found for this GitHub App.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$jwt = $this->generateGithubJwt($privateKey->private_key, $this->github_app->app_id);
|
||||
|
||||
$response = Http::withHeaders([
|
||||
'Accept' => 'application/vnd.github+json',
|
||||
'X-GitHub-Api-Version' => '2022-11-28',
|
||||
'Authorization' => "Bearer {$jwt}",
|
||||
])->get("{$this->github_app->api_url}/app");
|
||||
|
||||
if ($response->successful()) {
|
||||
$app_data = $response->json();
|
||||
$app_slug = $app_data['slug'] ?? null;
|
||||
|
||||
if ($app_slug) {
|
||||
$this->github_app->name = $app_slug;
|
||||
$this->name = str($app_slug)->kebab();
|
||||
$privateKey->name = "github-app-{$app_slug}";
|
||||
$privateKey->save();
|
||||
$this->github_app->save();
|
||||
$this->dispatch('success', 'GitHub App name and SSH key name synchronized successfully.');
|
||||
} else {
|
||||
$this->dispatch('info', 'Could not find App Name (slug) in GitHub response.');
|
||||
}
|
||||
} else {
|
||||
$error_message = $response->json()['message'] ?? 'Unknown error';
|
||||
$this->dispatch('error', "Failed to fetch GitHub App information: {$error_message}");
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Models;
|
||||
|
||||
use App\Enums\ApplicationDeploymentStatus;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Process\InvokedProcess;
|
||||
@@ -104,7 +105,7 @@ use Visus\Cuid2\Cuid2;
|
||||
|
||||
class Application extends BaseModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
use HasFactory, SoftDeletes;
|
||||
|
||||
private static $parserVersion = '4';
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
@@ -18,4 +19,18 @@ abstract class BaseModel extends Model
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function name(): Attribute
|
||||
{
|
||||
return new Attribute(
|
||||
get: fn () => sanitize_string($this->getRawOriginal('name')),
|
||||
);
|
||||
}
|
||||
|
||||
public function image(): Attribute
|
||||
{
|
||||
return new Attribute(
|
||||
get: fn () => sanitize_string($this->getRawOriginal('image')),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ use App\Notifications\Server\Reachable;
|
||||
use App\Notifications\Server\Unreachable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -48,7 +49,7 @@ use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class Server extends BaseModel
|
||||
{
|
||||
use SchemalessAttributesTrait, SoftDeletes;
|
||||
use HasFactory, SchemalessAttributesTrait, SoftDeletes;
|
||||
|
||||
public static $batch_counter = 0;
|
||||
|
||||
@@ -610,7 +611,8 @@ $schema://$host {
|
||||
}
|
||||
$memory = json_decode($memory, true);
|
||||
$parsedCollection = collect($memory)->map(function ($metric) {
|
||||
return [(int) $metric['time'], (float) $metric['usedPercent']];
|
||||
$usedPercent = $metric['usedPercent'] ?? 0.0;
|
||||
return [(int) $metric['time'], (float) $usedPercent];
|
||||
});
|
||||
|
||||
return $parsedCollection->toArray();
|
||||
@@ -1039,7 +1041,7 @@ $schema://$host {
|
||||
$this->unreachable_notification_sent = false;
|
||||
$this->save();
|
||||
$this->refresh();
|
||||
$this->team->notify(new Reachable($this));
|
||||
// $this->team->notify(new Reachable($this));
|
||||
}
|
||||
|
||||
public function sendUnreachableNotification()
|
||||
@@ -1047,7 +1049,7 @@ $schema://$host {
|
||||
$this->unreachable_notification_sent = true;
|
||||
$this->save();
|
||||
$this->refresh();
|
||||
$this->team->notify(new Unreachable($this));
|
||||
// $this->team->notify(new Unreachable($this));
|
||||
}
|
||||
|
||||
public function validateConnection(bool $justCheckingNewKey = false)
|
||||
|
||||
@@ -4,18 +4,12 @@ namespace App\Notifications\Application;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationPreview;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class DeploymentFailed extends Notification implements ShouldQueue
|
||||
class DeploymentFailed extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public Application $application;
|
||||
|
||||
public ?ApplicationPreview $preview = null;
|
||||
|
||||
@@ -4,18 +4,12 @@ namespace App\Notifications\Application;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationPreview;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class DeploymentSuccess extends Notification implements ShouldQueue
|
||||
class DeploymentSuccess extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public Application $application;
|
||||
|
||||
public ?ApplicationPreview $preview = null;
|
||||
|
||||
@@ -3,18 +3,12 @@
|
||||
namespace App\Notifications\Application;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class StatusChanged extends Notification implements ShouldQueue
|
||||
class StatusChanged extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public string $resource_name;
|
||||
|
||||
public string $project_uuid;
|
||||
|
||||
@@ -3,18 +3,12 @@
|
||||
namespace App\Notifications\Container;
|
||||
|
||||
use App\Models\Server;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class ContainerRestarted extends Notification implements ShouldQueue
|
||||
class ContainerRestarted extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public function __construct(public string $name, public Server $server, public ?string $url = null)
|
||||
{
|
||||
$this->onQueue('high');
|
||||
|
||||
@@ -3,18 +3,12 @@
|
||||
namespace App\Notifications\Container;
|
||||
|
||||
use App\Models\Server;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class ContainerStopped extends Notification implements ShouldQueue
|
||||
class ContainerStopped extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public function __construct(public string $name, public Server $server, public ?string $url = null)
|
||||
{
|
||||
$this->onQueue('high');
|
||||
|
||||
18
app/Notifications/CustomEmailNotification.php
Normal file
18
app/Notifications/CustomEmailNotification.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class CustomEmailNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $backoff = [10, 20, 30, 40, 50];
|
||||
|
||||
public $tries = 5;
|
||||
|
||||
public $maxExceptions = 5;
|
||||
}
|
||||
@@ -3,20 +3,12 @@
|
||||
namespace App\Notifications\Database;
|
||||
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class BackupFailed extends Notification implements ShouldQueue
|
||||
class BackupFailed extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $backoff = 10;
|
||||
|
||||
public $tries = 2;
|
||||
|
||||
public string $name;
|
||||
|
||||
public string $frequency;
|
||||
|
||||
@@ -3,20 +3,12 @@
|
||||
namespace App\Notifications\Database;
|
||||
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class BackupSuccess extends Notification implements ShouldQueue
|
||||
class BackupSuccess extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $backoff = 10;
|
||||
|
||||
public $tries = 3;
|
||||
|
||||
public string $name;
|
||||
|
||||
public string $frequency;
|
||||
@@ -24,6 +16,7 @@ class BackupSuccess extends Notification implements ShouldQueue
|
||||
public function __construct(ScheduledDatabaseBackup $backup, public $database, public $database_name)
|
||||
{
|
||||
$this->onQueue('high');
|
||||
|
||||
$this->name = $database->name;
|
||||
$this->frequency = $backup->frequency;
|
||||
}
|
||||
|
||||
@@ -3,20 +3,12 @@
|
||||
namespace App\Notifications\ScheduledTask;
|
||||
|
||||
use App\Models\ScheduledTask;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class TaskFailed extends Notification implements ShouldQueue
|
||||
class TaskFailed extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $backoff = 10;
|
||||
|
||||
public $tries = 2;
|
||||
|
||||
public ?string $url = null;
|
||||
|
||||
public function __construct(public ScheduledTask $task, public string $output)
|
||||
|
||||
@@ -5,17 +5,11 @@ namespace App\Notifications\Server;
|
||||
use App\Models\Server;
|
||||
use App\Notifications\Channels\DiscordChannel;
|
||||
use App\Notifications\Channels\TelegramChannel;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class DockerCleanup extends Notification implements ShouldQueue
|
||||
class DockerCleanup extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public function __construct(public Server $server, public string $message)
|
||||
{
|
||||
$this->onQueue('high');
|
||||
|
||||
@@ -6,18 +6,12 @@ use App\Models\Server;
|
||||
use App\Notifications\Channels\DiscordChannel;
|
||||
use App\Notifications\Channels\EmailChannel;
|
||||
use App\Notifications\Channels\TelegramChannel;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class ForceDisabled extends Notification implements ShouldQueue
|
||||
class ForceDisabled extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public function __construct(public Server $server)
|
||||
{
|
||||
$this->onQueue('high');
|
||||
|
||||
@@ -6,18 +6,12 @@ use App\Models\Server;
|
||||
use App\Notifications\Channels\DiscordChannel;
|
||||
use App\Notifications\Channels\EmailChannel;
|
||||
use App\Notifications\Channels\TelegramChannel;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class ForceEnabled extends Notification implements ShouldQueue
|
||||
class ForceEnabled extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public function __construct(public Server $server)
|
||||
{
|
||||
$this->onQueue('high');
|
||||
|
||||
@@ -3,18 +3,12 @@
|
||||
namespace App\Notifications\Server;
|
||||
|
||||
use App\Models\Server;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class HighDiskUsage extends Notification implements ShouldQueue
|
||||
class HighDiskUsage extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public function __construct(public Server $server, public int $disk_usage, public int $server_disk_usage_notification_threshold)
|
||||
{
|
||||
$this->onQueue('high');
|
||||
|
||||
@@ -6,18 +6,12 @@ use App\Models\Server;
|
||||
use App\Notifications\Channels\DiscordChannel;
|
||||
use App\Notifications\Channels\EmailChannel;
|
||||
use App\Notifications\Channels\TelegramChannel;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class Reachable extends Notification implements ShouldQueue
|
||||
class Reachable extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
protected bool $isRateLimited = false;
|
||||
|
||||
public function __construct(public Server $server)
|
||||
|
||||
@@ -6,18 +6,12 @@ use App\Models\Server;
|
||||
use App\Notifications\Channels\DiscordChannel;
|
||||
use App\Notifications\Channels\EmailChannel;
|
||||
use App\Notifications\Channels\TelegramChannel;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use App\Notifications\Dto\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class Unreachable extends Notification implements ShouldQueue
|
||||
class Unreachable extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
protected bool $isRateLimited = false;
|
||||
|
||||
public function __construct(public Server $server)
|
||||
|
||||
@@ -6,17 +6,11 @@ use App\Models\Team;
|
||||
use App\Models\TeamInvitation;
|
||||
use App\Models\User;
|
||||
use App\Notifications\Channels\TransactionalEmailChannel;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class InvitationLink extends Notification implements ShouldQueue
|
||||
class InvitationLink extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 5;
|
||||
|
||||
public function via(): array
|
||||
{
|
||||
return [TransactionalEmailChannel::class];
|
||||
|
||||
@@ -3,17 +3,11 @@
|
||||
namespace App\Notifications\TransactionalEmails;
|
||||
|
||||
use App\Notifications\Channels\EmailChannel;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use App\Notifications\CustomEmailNotification;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class Test extends Notification implements ShouldQueue
|
||||
class Test extends CustomEmailNotification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public $tries = 5;
|
||||
|
||||
public function __construct(public string $emails)
|
||||
{
|
||||
$this->onQueue('high');
|
||||
|
||||
Reference in New Issue
Block a user