Revert "rector: arrrrr"

This reverts commit 16c0cd10d8.
This commit is contained in:
Andras Bacsai
2025-01-07 15:31:43 +01:00
parent da07b4fdcf
commit 1fe4dd722b
349 changed files with 3689 additions and 4184 deletions

View File

@@ -3,7 +3,6 @@
namespace App\Models;
use App\Enums\ApplicationDeploymentStatus;
use Exception;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
@@ -148,15 +147,17 @@ class Application extends BaseModel
if ($application->isDirty('status')) {
$payload['last_online_at'] = now();
}
if ($application->isDirty('custom_nginx_configuration') && $application->custom_nginx_configuration === '') {
$payload['custom_nginx_configuration'] = null;
if ($application->isDirty('custom_nginx_configuration')) {
if ($application->custom_nginx_configuration === '') {
$payload['custom_nginx_configuration'] = null;
}
}
if ($payload !== []) {
if (count($payload) > 0) {
$application->forceFill($payload);
}
});
static::created(function ($application) {
ApplicationSetting::query()->create([
ApplicationSetting::create([
'application_id' => $application->id,
]);
$application->compose_parsing_version = self::$parserVersion;
@@ -181,12 +182,12 @@ class Application extends BaseModel
public static function ownedByCurrentTeamAPI(int $teamId)
{
return \App\Models\Application::query()->whereRelation('environment.project.team', 'id', $teamId)->orderBy('name');
return Application::whereRelation('environment.project.team', 'id', $teamId)->orderBy('name');
}
public static function ownedByCurrentTeam()
{
return \App\Models\Application::query()->whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name');
return Application::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name');
}
public function getContainersToStop(bool $previewDeployments = false): array
@@ -206,11 +207,11 @@ class Application extends BaseModel
}
$startTime = time();
while ($processes !== []) {
while (count($processes) > 0) {
$finishedProcesses = array_filter($processes, function ($process) {
return ! $process->running();
});
foreach (array_keys($finishedProcesses) as $containerName) {
foreach ($finishedProcesses as $containerName => $process) {
unset($processes[$containerName]);
$this->removeContainer($containerName, $server);
}
@@ -251,17 +252,17 @@ class Application extends BaseModel
}
}
public function delete_volumes(?Collection $collection)
public function delete_volumes(?Collection $persistentStorages)
{
if ($this->build_pack === 'dockercompose') {
$server = data_get($this, 'destination.server');
instant_remote_process(["cd {$this->dirOnServer()} && docker compose down -v"], $server, false);
} else {
if ($collection->count() === 0) {
if ($persistentStorages->count() === 0) {
return;
}
$server = data_get($this, 'destination.server');
foreach ($collection as $storage) {
foreach ($persistentStorages as $storage) {
instant_remote_process(["docker volume rm -f $storage->name"], $server, false);
}
}
@@ -288,12 +289,20 @@ class Application extends BaseModel
public function is_public_repository(): bool
{
return (bool) data_get($this, 'source.is_public');
if (data_get($this, 'source.is_public')) {
return true;
}
return false;
}
public function is_github_based(): bool
{
return (bool) data_get($this, 'source');
if (data_get($this, 'source')) {
return true;
}
return false;
}
public function isForceHttpsEnabled()
@@ -477,12 +486,13 @@ class Application extends BaseModel
set: function ($value) {
if (is_null($value) || $value === '') {
return '/Dockerfile';
}
if ($value !== '/') {
return Str::start(Str::replaceEnd('/', '', $value), '/');
}
} else {
if ($value !== '/') {
return Str::start(Str::replaceEnd('/', '', $value), '/');
}
return Str::start($value, '/');
return Str::start($value, '/');
}
}
);
}
@@ -493,12 +503,13 @@ class Application extends BaseModel
set: function ($value) {
if (is_null($value) || $value === '') {
return '/docker-compose.yaml';
}
if ($value !== '/') {
return Str::start(Str::replaceEnd('/', '', $value), '/');
}
} else {
if ($value !== '/') {
return Str::start(Str::replaceEnd('/', '', $value), '/');
}
return Str::start($value, '/');
return Str::start($value, '/');
}
}
);
}
@@ -569,18 +580,33 @@ class Application extends BaseModel
{
return Attribute::make(
set: function ($value) {
if (str($value)->contains('(')) {
$status = str($value)->before('(')->trim()->value();
$health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy';
} elseif (str($value)->contains(':')) {
$status = str($value)->before(':')->trim()->value();
$health = str($value)->after(':')->trim()->value() ?? 'unhealthy';
} else {
$status = $value;
$health = 'unhealthy';
}
if ($this->additional_servers->count() === 0) {
if (str($value)->contains('(')) {
$status = str($value)->before('(')->trim()->value();
$health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy';
} elseif (str($value)->contains(':')) {
$status = str($value)->before(':')->trim()->value();
$health = str($value)->after(':')->trim()->value() ?? 'unhealthy';
} else {
$status = $value;
$health = 'unhealthy';
}
return "$status:$health";
return "$status:$health";
} else {
if (str($value)->contains('(')) {
$status = str($value)->before('(')->trim()->value();
$health = str($value)->after('(')->before(')')->trim()->value() ?? 'unhealthy';
} elseif (str($value)->contains(':')) {
$status = str($value)->before(':')->trim()->value();
$health = str($value)->after(':')->trim()->value() ?? 'unhealthy';
} else {
$status = $value;
$health = 'unhealthy';
}
return "$status:$health";
}
},
get: function ($value) {
if ($this->additional_servers->count() === 0) {
@@ -597,24 +623,25 @@ class Application extends BaseModel
}
return "$status:$health";
}
$complex_status = null;
$complex_health = null;
$complex_status = $main_server_status = str($value)->before(':')->value();
$complex_health = $main_server_health = str($value)->after(':')->value() ?? 'unhealthy';
$additional_servers_status = $this->additional_servers->pluck('pivot.status');
foreach ($additional_servers_status as $status) {
$server_status = str($status)->before(':')->value();
$server_health = str($status)->after(':')->value() ?? 'unhealthy';
if ($main_server_status !== $server_status) {
$complex_status = 'degraded';
} else {
$complex_status = null;
$complex_health = null;
$complex_status = $main_server_status = str($value)->before(':')->value();
$complex_health = $main_server_health = str($value)->after(':')->value() ?? 'unhealthy';
$additional_servers_status = $this->additional_servers->pluck('pivot.status');
foreach ($additional_servers_status as $status) {
$server_status = str($status)->before(':')->value();
$server_health = str($status)->after(':')->value() ?? 'unhealthy';
if ($main_server_status !== $server_status) {
$complex_status = 'degraded';
}
if ($main_server_health !== $server_health) {
$complex_health = 'unhealthy';
}
}
if ($main_server_health !== $server_health) {
$complex_health = 'unhealthy';
}
}
return "$complex_status:$complex_health";
return "$complex_status:$complex_health";
}
},
);
}
@@ -763,24 +790,27 @@ class Application extends BaseModel
public function isDeploymentInprogress()
{
$deployments = ApplicationDeploymentQueue::query()->where('application_id', $this->id)->whereIn('status', [ApplicationDeploymentStatus::IN_PROGRESS, ApplicationDeploymentStatus::QUEUED])->count();
$deployments = ApplicationDeploymentQueue::where('application_id', $this->id)->whereIn('status', [ApplicationDeploymentStatus::IN_PROGRESS, ApplicationDeploymentStatus::QUEUED])->count();
if ($deployments > 0) {
return true;
}
return $deployments > 0;
return false;
}
public function get_last_successful_deployment()
{
return ApplicationDeploymentQueue::query()->where('application_id', $this->id)->where('status', ApplicationDeploymentStatus::FINISHED)->where('pull_request_id', 0)->orderBy('created_at', 'desc')->first();
return ApplicationDeploymentQueue::where('application_id', $this->id)->where('status', ApplicationDeploymentStatus::FINISHED)->where('pull_request_id', 0)->orderBy('created_at', 'desc')->first();
}
public function get_last_days_deployments()
{
return ApplicationDeploymentQueue::query()->where('application_id', $this->id)->where('created_at', '>=', now()->subDays(7))->orderBy('created_at', 'desc')->get();
return ApplicationDeploymentQueue::where('application_id', $this->id)->where('created_at', '>=', now()->subDays(7))->orderBy('created_at', 'desc')->get();
}
public function deployments(int $skip = 0, int $take = 10)
{
$deployments = ApplicationDeploymentQueue::query()->where('application_id', $this->id)->orderBy('created_at', 'desc');
$deployments = ApplicationDeploymentQueue::where('application_id', $this->id)->orderBy('created_at', 'desc');
$count = $deployments->count();
$deployments = $deployments->skip($skip)->take($take)->get();
@@ -792,17 +822,25 @@ class Application extends BaseModel
public function get_deployment(string $deployment_uuid)
{
return Activity::query()->where('subject_id', $this->id)->where('properties->type_uuid', '=', $deployment_uuid)->first();
return Activity::where('subject_id', $this->id)->where('properties->type_uuid', '=', $deployment_uuid)->first();
}
public function isDeployable(): bool
{
return (bool) $this->settings->is_auto_deploy_enabled;
if ($this->settings->is_auto_deploy_enabled) {
return true;
}
return false;
}
public function isPRDeployable(): bool
{
return (bool) $this->settings->is_preview_deployments_enabled;
if ($this->settings->is_preview_deployments_enabled) {
return true;
}
return false;
}
public function deploymentType()
@@ -812,17 +850,21 @@ class Application extends BaseModel
}
if (data_get($this, 'private_key_id')) {
return 'deploy_key';
}
if (data_get($this, 'source')) {
} elseif (data_get($this, 'source')) {
return 'source';
} else {
return 'other';
}
return 'other';
throw new \Exception('No deployment type found');
}
public function could_set_build_commands(): bool
{
return $this->build_pack === 'nixpacks';
if ($this->build_pack === 'nixpacks') {
return true;
}
return false;
}
public function git_based(): bool
@@ -830,13 +872,20 @@ class Application extends BaseModel
if ($this->dockerfile) {
return false;
}
if ($this->build_pack === 'dockerimage') {
return false;
}
return $this->build_pack !== 'dockerimage';
return true;
}
public function isHealthcheckDisabled(): bool
{
return data_get($this, 'health_check_enabled') === false;
if (data_get($this, 'health_check_enabled') === false) {
return true;
}
return false;
}
public function workdir()
@@ -869,13 +918,14 @@ class Application extends BaseModel
}
if ($oldConfigHash === $newConfigHash) {
return false;
}
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
return true;
}
}
public function customRepository()
@@ -907,7 +957,7 @@ class Application extends BaseModel
$git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git submodule update --init --recursive";
}
if ($this->settings->is_git_lfs_enabled) {
return "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git lfs pull";
$git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git lfs pull";
}
return $git_clone_command;
@@ -923,7 +973,7 @@ class Application extends BaseModel
'is_accessible' => true,
'error' => null,
];
} catch (RuntimeException $ex) {
} catch (\RuntimeException $ex) {
return [
'is_accessible' => false,
'error' => $ex->getMessage(),
@@ -1027,8 +1077,6 @@ class Application extends BaseModel
'fullRepoUrl' => $fullRepoUrl,
];
}
return null;
}
public function generateGitImportCommands(string $deployment_uuid, int $pull_request_id = 0, ?string $git_type = null, bool $exec_in_docker = true, bool $only_checkout = false, ?string $custom_base_dir = null, ?string $commit = null)
@@ -1050,7 +1098,7 @@ class Application extends BaseModel
$source_html_url_host = $url['host'];
$source_html_url_scheme = $url['scheme'];
if ($this->source->getMorphClass() === GithubApp::class) {
if ($this->source->getMorphClass() === \App\Models\GithubApp::class) {
if ($this->source->is_public) {
$fullRepoUrl = "{$this->source->html_url}/{$customRepository}";
$git_clone_command = "{$git_clone_command} {$this->source->html_url}/{$customRepository} {$baseDir}";
@@ -1207,16 +1255,14 @@ class Application extends BaseModel
'fullRepoUrl' => $fullRepoUrl,
];
}
return null;
}
public function oldRawParser()
{
try {
$yaml = Yaml::parse($this->docker_compose_raw);
} catch (Exception $e) {
throw new Exception($e->getMessage(), $e->getCode(), $e);
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
$services = data_get($yaml, 'services');
@@ -1224,27 +1270,24 @@ class Application extends BaseModel
$services = collect($services)->map(function ($service) use ($commands) {
$serviceVolumes = collect(data_get($service, 'volumes', []));
if ($serviceVolumes->count() > 0) {
foreach ($serviceVolumes as $serviceVolume) {
foreach ($serviceVolumes as $volume) {
$workdir = $this->workdir();
$type = null;
$source = null;
if (is_string($serviceVolume)) {
$source = str($serviceVolume)->before(':');
if (is_string($volume)) {
$source = str($volume)->before(':');
if ($source->startsWith('./') || $source->startsWith('/') || $source->startsWith('~')) {
$type = str('bind');
}
} elseif (is_array($serviceVolume)) {
$type = data_get_str($serviceVolume, 'type');
$source = data_get_str($serviceVolume, 'source');
} elseif (is_array($volume)) {
$type = data_get_str($volume, 'type');
$source = data_get_str($volume, 'source');
}
if ($type?->value() === 'bind') {
if ($source->value() === '/var/run/docker.sock') {
continue;
}
if ($source->value() === '/tmp') {
continue;
}
if ($source->value() === '/tmp/') {
if ($source->value() === '/tmp' || $source->value() === '/tmp/') {
continue;
}
if ($source->startsWith('.')) {
@@ -1279,28 +1322,27 @@ class Application extends BaseModel
{
if ((int) $this->compose_parsing_version >= 3) {
return newParser($this, $pull_request_id, $preview_id);
}
if ($this->docker_compose_raw) {
} elseif ($this->docker_compose_raw) {
return parseDockerComposeFile(resource: $this, isNew: false, pull_request_id: $pull_request_id, preview_id: $preview_id);
} else {
return collect([]);
}
return collect([]);
}
public function loadComposeFile($isInit = false)
{
$initialDockerComposeLocation = $this->docker_compose_location;
if ($isInit && $this->docker_compose_raw) {
return null;
return;
}
$cuid2 = new Cuid2;
['commands' => $cloneCommand] = $this->generateGitImportCommands(deployment_uuid: $cuid2, only_checkout: true, exec_in_docker: false, custom_base_dir: '.');
$uuid = new Cuid2;
['commands' => $cloneCommand] = $this->generateGitImportCommands(deployment_uuid: $uuid, only_checkout: true, exec_in_docker: false, custom_base_dir: '.');
$workdir = rtrim($this->base_directory, '/');
$composeFile = $this->docker_compose_location;
$fileList = collect([".$workdir$composeFile"]);
$gitRemoteStatus = $this->getGitRemoteStatus(deployment_uuid: $cuid2);
$gitRemoteStatus = $this->getGitRemoteStatus(deployment_uuid: $uuid);
if (! $gitRemoteStatus['is_accessible']) {
throw new RuntimeException("Failed to read Git source:\n\n{$gitRemoteStatus['error']}");
throw new \RuntimeException("Failed to read Git source:\n\n{$gitRemoteStatus['error']}");
}
$getGitVersion = instant_remote_process(['git --version'], $this->destination->server, false);
$gitVersion = str($getGitVersion)->explode(' ')->last();
@@ -1311,7 +1353,7 @@ class Application extends BaseModel
$paths = collect();
$currentPath = '';
foreach ($parts as $part) {
$currentPath .= ($currentPath !== '' && $currentPath !== '0' ? '/' : '').$part;
$currentPath .= ($currentPath ? '/' : '').$part;
if (str($currentPath)->isNotEmpty()) {
$paths->push($currentPath);
}
@@ -1320,9 +1362,9 @@ class Application extends BaseModel
return $paths;
})->flatten()->unique()->values();
$commands = collect([
"rm -rf /tmp/{$cuid2}",
"mkdir -p /tmp/{$cuid2}",
"cd /tmp/{$cuid2}",
"rm -rf /tmp/{$uuid}",
"mkdir -p /tmp/{$uuid}",
"cd /tmp/{$uuid}",
$cloneCommand,
'git sparse-checkout init',
"git sparse-checkout set {$fileList->implode(' ')}",
@@ -1331,9 +1373,9 @@ class Application extends BaseModel
]);
} else {
$commands = collect([
"rm -rf /tmp/{$cuid2}",
"mkdir -p /tmp/{$cuid2}",
"cd /tmp/{$cuid2}",
"rm -rf /tmp/{$uuid}",
"mkdir -p /tmp/{$uuid}",
"cd /tmp/{$uuid}",
$cloneCommand,
'git sparse-checkout init --cone',
"git sparse-checkout set {$fileList->implode(' ')}",
@@ -1343,22 +1385,22 @@ class Application extends BaseModel
}
try {
$composeFileContent = instant_remote_process($commands, $this->destination->server);
} catch (Exception $e) {
} catch (\Exception $e) {
if (str($e->getMessage())->contains('No such file')) {
throw new RuntimeException("Docker Compose file not found at: $workdir$composeFile<br><br>Check if you used the right extension (.yaml or .yml) in the compose file name.", $e->getCode(), $e);
throw new \RuntimeException("Docker Compose file not found at: $workdir$composeFile<br><br>Check if you used the right extension (.yaml or .yml) in the compose file name.");
}
if (str($e->getMessage())->contains('fatal: repository') && str($e->getMessage())->contains('does not exist')) {
if ($this->deploymentType() === 'deploy_key') {
throw new RuntimeException('Your deploy key does not have access to the repository. Please check your deploy key and try again.', $e->getCode(), $e);
throw new \RuntimeException('Your deploy key does not have access to the repository. Please check your deploy key and try again.');
}
throw new RuntimeException('Repository does not exist. Please check your repository URL and try again.', $e->getCode(), $e);
throw new \RuntimeException('Repository does not exist. Please check your repository URL and try again.');
}
throw new RuntimeException($e->getMessage(), $e->getCode(), $e);
throw new \RuntimeException($e->getMessage());
} finally {
$this->docker_compose_location = $initialDockerComposeLocation;
$this->save();
$commands = collect([
"rm -rf /tmp/{$cuid2}",
"rm -rf /tmp/{$uuid}",
]);
instant_remote_process($commands, $this->destination->server, false);
}
@@ -1374,7 +1416,11 @@ class Application extends BaseModel
$json = $json->filter(function ($value, $key) use ($diff) {
return ! in_array($key, $diff);
});
$this->docker_compose_domains = $json ? json_encode($json) : null;
if ($json) {
$this->docker_compose_domains = json_encode($json);
} else {
$this->docker_compose_domains = null;
}
$this->save();
}
@@ -1382,15 +1428,16 @@ class Application extends BaseModel
'parsedServices' => $parsedServices,
'initialDockerComposeLocation' => $this->docker_compose_location,
];
} else {
throw new \RuntimeException("Docker Compose file not found at: $workdir$composeFile<br><br>Check if you used the right extension (.yaml or .yml) in the compose file name.");
}
throw new RuntimeException("Docker Compose file not found at: $workdir$composeFile<br><br>Check if you used the right extension (.yaml or .yml) in the compose file name.");
}
public function parseContainerLabels(?ApplicationPreview $applicationPreview = null)
public function parseContainerLabels(?ApplicationPreview $preview = null)
{
$customLabels = data_get($this, 'custom_labels');
if (! $customLabels) {
return null;
return;
}
if (base64_encode(base64_decode($customLabels, true)) !== $customLabels) {
$this->custom_labels = str($customLabels)->replace(',', "\n");
@@ -1398,7 +1445,7 @@ class Application extends BaseModel
}
$customLabels = base64_decode($this->custom_labels);
if (mb_detect_encoding($customLabels, 'ASCII', true) === false) {
$customLabels = str(implode('|coolify|', generateLabelsApplication($this, $applicationPreview)))->replace('|coolify|', "\n");
$customLabels = str(implode('|coolify|', generateLabelsApplication($this, $preview)))->replace('|coolify|', "\n");
}
$this->custom_labels = base64_encode($customLabels);
$this->save();
@@ -1472,7 +1519,7 @@ class Application extends BaseModel
if (isset($healthcheckCommand) && str_contains($trimmedLine, '\\')) {
$healthcheckCommand .= ' '.trim($trimmedLine, '\\ ');
}
if (isset($healthcheckCommand) && ! str_contains($trimmedLine, '\\') && ($healthcheckCommand !== '' && $healthcheckCommand !== '0')) {
if (isset($healthcheckCommand) && ! str_contains($trimmedLine, '\\') && ! empty($healthcheckCommand)) {
$healthcheckCommand .= ' '.$trimmedLine;
break;
}
@@ -1522,8 +1569,8 @@ class Application extends BaseModel
$template = $this->preview_url_template;
$host = $url->getHost();
$schema = $url->getScheme();
$cuid2 = new Cuid2;
$preview_fqdn = str_replace('{{random}}', $cuid2, $template);
$random = new Cuid2;
$preview_fqdn = str_replace('{{random}}', $random, $template);
$preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn);
$preview_fqdn = str_replace('{{pr_id}}', $pull_request_id, $preview_fqdn);
$preview_fqdn = "$schema://$preview_fqdn";
@@ -1536,7 +1583,7 @@ class Application extends BaseModel
public static function getDomainsByUuid(string $uuid): array
{
$application = self::query()->where('uuid', $uuid)->first();
$application = self::where('uuid', $uuid)->first();
if ($application) {
return $application->fqdns;
@@ -1558,7 +1605,7 @@ class Application extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -1567,8 +1614,6 @@ class Application extends BaseModel
return $parsedCollection->toArray();
}
return null;
}
public function getMemoryMetrics(int $mins = 5)
@@ -1584,7 +1629,7 @@ class Application extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -1593,14 +1638,12 @@ class Application extends BaseModel
return $parsedCollection->toArray();
}
return null;
}
public function generateConfig($is_json = false)
{
$config = collect([]);
if (($this->build_pack = 'nixpacks') !== '') {
if ($this->build_pack = 'nixpacks') {
$config = collect([
'build_pack' => 'nixpacks',
'docker_registry_image_name' => $this->docker_registry_image_name,
@@ -1634,7 +1677,7 @@ class Application extends BaseModel
'config' => 'required|json',
]);
if ($validator->fails()) {
throw new Exception('Invalid JSON format');
throw new \Exception('Invalid JSON format');
}
$config = json_decode($config, true);
@@ -1646,7 +1689,7 @@ class Application extends BaseModel
'config.settings.is_static' => 'required|boolean',
]);
if ($deepValidator->fails()) {
throw new Exception('Invalid data');
throw new \Exception('Invalid data');
}
$config = $deepValidator->validated()['config'];
@@ -1655,8 +1698,8 @@ class Application extends BaseModel
data_forget($config, 'settings');
$this->update($config);
$this->settings()->update($settings);
} catch (Exception $e) {
throw new Exception('Failed to update application settings', $e->getCode(), $e);
} catch (\Exception $e) {
throw new \Exception('Failed to update application settings');
}
}
}

View File

@@ -43,14 +43,14 @@ class ApplicationDeploymentQueue extends Model
public function application(): Attribute
{
return Attribute::make(
get: fn () => Application::query()->find($this->application_id),
get: fn () => Application::find($this->application_id),
);
}
public function server(): Attribute
{
return Attribute::make(
get: fn () => Server::query()->find($this->server_id),
get: fn () => Server::find($this->server_id),
);
}

View File

@@ -37,7 +37,7 @@ class ApplicationPreview extends BaseModel
public static function findPreviewByApplicationAndPullId(int $application_id, int $pull_request_id)
{
return self::query()->where('application_id', $application_id)->where('pull_request_id', $pull_request_id)->firstOrFail();
return self::where('application_id', $application_id)->where('pull_request_id', $pull_request_id)->firstOrFail();
}
public function isRunning()

View File

@@ -30,6 +30,23 @@ class DiscordNotificationSettings extends Model
'server_unreachable_discord_notifications',
];
protected $casts = [
'discord_enabled' => 'boolean',
'discord_webhook_url' => 'encrypted',
'deployment_success_discord_notifications' => 'boolean',
'deployment_failure_discord_notifications' => 'boolean',
'status_change_discord_notifications' => 'boolean',
'backup_success_discord_notifications' => 'boolean',
'backup_failure_discord_notifications' => 'boolean',
'scheduled_task_success_discord_notifications' => 'boolean',
'scheduled_task_failure_discord_notifications' => 'boolean',
'docker_cleanup_discord_notifications' => 'boolean',
'server_disk_usage_discord_notifications' => 'boolean',
'server_reachable_discord_notifications' => 'boolean',
'server_unreachable_discord_notifications' => 'boolean',
];
public function team()
{
return $this->belongsTo(Team::class);
@@ -39,24 +56,4 @@ class DiscordNotificationSettings extends Model
{
return $this->discord_enabled;
}
protected function casts(): array
{
return [
'discord_enabled' => 'boolean',
'discord_webhook_url' => 'encrypted',
'deployment_success_discord_notifications' => 'boolean',
'deployment_failure_discord_notifications' => 'boolean',
'status_change_discord_notifications' => 'boolean',
'backup_success_discord_notifications' => 'boolean',
'backup_failure_discord_notifications' => 'boolean',
'scheduled_task_success_discord_notifications' => 'boolean',
'scheduled_task_failure_discord_notifications' => 'boolean',
'docker_cleanup_discord_notifications' => 'boolean',
'server_disk_usage_discord_notifications' => 'boolean',
'server_reachable_discord_notifications' => 'boolean',
'server_unreachable_discord_notifications' => 'boolean',
];
}
}

View File

@@ -37,6 +37,32 @@ class EmailNotificationSettings extends Model
'server_disk_usage_email_notifications',
];
protected $casts = [
'smtp_enabled' => 'boolean',
'smtp_from_address' => 'encrypted',
'smtp_from_name' => 'encrypted',
'smtp_recipients' => 'encrypted',
'smtp_host' => 'encrypted',
'smtp_port' => 'integer',
'smtp_username' => 'encrypted',
'smtp_password' => 'encrypted',
'smtp_timeout' => 'integer',
'resend_enabled' => 'boolean',
'resend_api_key' => 'encrypted',
'use_instance_email_settings' => 'boolean',
'deployment_success_email_notifications' => 'boolean',
'deployment_failure_email_notifications' => 'boolean',
'status_change_email_notifications' => 'boolean',
'backup_success_email_notifications' => 'boolean',
'backup_failure_email_notifications' => 'boolean',
'scheduled_task_success_email_notifications' => 'boolean',
'scheduled_task_failure_email_notifications' => 'boolean',
'server_disk_usage_email_notifications' => 'boolean',
];
public function team()
{
return $this->belongsTo(Team::class);
@@ -50,33 +76,4 @@ class EmailNotificationSettings extends Model
return $this->smtp_enabled || $this->resend_enabled || $this->use_instance_email_settings;
}
protected function casts(): array
{
return [
'smtp_enabled' => 'boolean',
'smtp_from_address' => 'encrypted',
'smtp_from_name' => 'encrypted',
'smtp_recipients' => 'encrypted',
'smtp_host' => 'encrypted',
'smtp_port' => 'integer',
'smtp_username' => 'encrypted',
'smtp_password' => 'encrypted',
'smtp_timeout' => 'integer',
'resend_enabled' => 'boolean',
'resend_api_key' => 'encrypted',
'use_instance_email_settings' => 'boolean',
'deployment_success_email_notifications' => 'boolean',
'deployment_failure_email_notifications' => 'boolean',
'status_change_email_notifications' => 'boolean',
'backup_success_email_notifications' => 'boolean',
'backup_failure_email_notifications' => 'boolean',
'scheduled_task_success_email_notifications' => 'boolean',
'scheduled_task_failure_email_notifications' => 'boolean',
'server_disk_usage_email_notifications' => 'boolean',
];
}
}

View File

@@ -55,30 +55,30 @@ class EnvironmentVariable extends Model
}
});
static::created(function (EnvironmentVariable $environmentVariable) {
if ($environmentVariable->resourceable_type === Application::class && ! $environmentVariable->is_preview) {
$found = ModelsEnvironmentVariable::where('key', $environmentVariable->key)
static::created(function (EnvironmentVariable $environment_variable) {
if ($environment_variable->resourceable_type === Application::class && ! $environment_variable->is_preview) {
$found = ModelsEnvironmentVariable::where('key', $environment_variable->key)
->where('resourceable_type', Application::class)
->where('resourceable_id', $environmentVariable->resourceable_id)
->where('resourceable_id', $environment_variable->resourceable_id)
->where('is_preview', true)
->first();
if (! $found) {
$application = Application::query()->find($environmentVariable->resourceable_id);
$application = Application::find($environment_variable->resourceable_id);
if ($application && $application->build_pack !== 'dockerfile') {
ModelsEnvironmentVariable::create([
'key' => $environmentVariable->key,
'value' => $environmentVariable->value,
'is_build_time' => $environmentVariable->is_build_time,
'is_multiline' => $environmentVariable->is_multiline ?? false,
'key' => $environment_variable->key,
'value' => $environment_variable->value,
'is_build_time' => $environment_variable->is_build_time,
'is_multiline' => $environment_variable->is_multiline ?? false,
'resourceable_type' => Application::class,
'resourceable_id' => $environmentVariable->resourceable_id,
'resourceable_id' => $environment_variable->resourceable_id,
'is_preview' => true,
]);
}
}
}
$environmentVariable->update([
$environment_variable->update([
'version' => config('constants.coolify.version'),
]);
});
@@ -143,15 +143,18 @@ class EnvironmentVariable extends Model
return Attribute::make(
get: function () {
$type = str($this->value)->after('{{')->before('.')->value;
if (str($this->value)->startsWith('{{'.$type) && str($this->value)->endsWith('}}')) {
return true;
}
return str($this->value)->startsWith('{{'.$type) && str($this->value)->endsWith('}}');
return false;
}
);
}
private function get_real_environment_variables(?string $environment_variable = null, $resource = null)
{
if (is_null($resource)) {
if ((is_null($environment_variable) && $environment_variable === '') || is_null($resource)) {
return null;
}
$environment_variable = trim($environment_variable);
@@ -159,12 +162,12 @@ class EnvironmentVariable extends Model
if ($sharedEnvsFound->isEmpty()) {
return $environment_variable;
}
foreach ($sharedEnvsFound as $sharedEnvFound) {
$type = str($sharedEnvFound)->match('/(.*?)\./');
foreach ($sharedEnvsFound as $sharedEnv) {
$type = str($sharedEnv)->match('/(.*?)\./');
if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
continue;
}
$variable = str($sharedEnvFound)->match('/\.(.*)/');
$variable = str($sharedEnv)->match('/\.(.*)/');
if ($type->value() === 'environment') {
$id = $resource->environment->id;
} elseif ($type->value() === 'project') {
@@ -175,9 +178,9 @@ class EnvironmentVariable extends Model
if (is_null($id)) {
continue;
}
$environment_variable_found = SharedEnvironmentVariable::query()->where('type', $type)->where('key', $variable)->where('team_id', $resource->team()->id)->where("{$type}_id", $id)->first();
$environment_variable_found = SharedEnvironmentVariable::where('type', $type)->where('key', $variable)->where('team_id', $resource->team()->id)->where("{$type}_id", $id)->first();
if ($environment_variable_found) {
$environment_variable = str($environment_variable)->replace("{{{$sharedEnvFound}}}", $environment_variable_found->value);
$environment_variable = str($environment_variable)->replace("{{{$sharedEnv}}}", $environment_variable_found->value);
}
}

View File

@@ -2,7 +2,6 @@
namespace App\Models;
use Exception;
use Illuminate\Database\Eloquent\Casts\Attribute;
class GithubApp extends BaseModel
@@ -11,6 +10,11 @@ class GithubApp extends BaseModel
protected $appends = ['type'];
protected $casts = [
'is_public' => 'boolean',
'type' => 'string',
];
protected $hidden = [
'client_secret',
'webhook_secret',
@@ -18,12 +22,12 @@ class GithubApp extends BaseModel
protected static function booted(): void
{
static::deleting(function (GithubApp $githubApp) {
$applications_count = Application::query()->where('source_id', $githubApp->id)->count();
static::deleting(function (GithubApp $github_app) {
$applications_count = Application::where('source_id', $github_app->id)->count();
if ($applications_count > 0) {
throw new Exception('You cannot delete this GitHub App because it is in use by '.$applications_count.' application(s). Delete them first.');
throw new \Exception('You cannot delete this GitHub App because it is in use by '.$applications_count.' application(s). Delete them first.');
}
$githubApp->privateKey()->delete();
$github_app->privateKey()->delete();
});
}
@@ -67,12 +71,4 @@ class GithubApp extends BaseModel
},
);
}
protected function casts(): array
{
return [
'is_public' => 'boolean',
'type' => 'string',
];
}
}

View File

@@ -15,11 +15,32 @@ class InstanceSettings extends Model implements SendsEmail
protected $guarded = [];
protected $casts = [
'smtp_enabled' => 'boolean',
'smtp_from_address' => 'encrypted',
'smtp_from_name' => 'encrypted',
'smtp_recipients' => 'encrypted',
'smtp_host' => 'encrypted',
'smtp_port' => 'integer',
'smtp_username' => 'encrypted',
'smtp_password' => 'encrypted',
'smtp_timeout' => 'integer',
'resend_enabled' => 'boolean',
'resend_api_key' => 'encrypted',
'allowed_ip_ranges' => 'array',
'is_auto_update_enabled' => 'boolean',
'auto_update_frequency' => 'string',
'update_check_frequency' => 'string',
'sentinel_token' => 'encrypted',
];
protected static function booted(): void
{
static::updated(function ($settings) {
if ($settings->isDirty('helper_version')) {
Server::query()->chunkById(100, function ($servers) {
Server::chunkById(100, function ($servers) {
foreach ($servers as $server) {
PullHelperImageJob::dispatch($server);
}
@@ -68,7 +89,7 @@ class InstanceSettings extends Model implements SendsEmail
public static function get()
{
return \App\Models\InstanceSettings::query()->findOrFail(0);
return InstanceSettings::findOrFail(0);
}
public function getRecipients($notification)
@@ -103,27 +124,4 @@ class InstanceSettings extends Model implements SendsEmail
// }
// );
// }
protected function casts(): array
{
return [
'smtp_enabled' => 'boolean',
'smtp_from_address' => 'encrypted',
'smtp_from_name' => 'encrypted',
'smtp_recipients' => 'encrypted',
'smtp_host' => 'encrypted',
'smtp_port' => 'integer',
'smtp_username' => 'encrypted',
'smtp_password' => 'encrypted',
'smtp_timeout' => 'integer',
'resend_enabled' => 'boolean',
'resend_api_key' => 'encrypted',
'allowed_ip_ranges' => 'array',
'is_auto_update_enabled' => 'boolean',
'auto_update_frequency' => 'string',
'update_check_frequency' => 'string',
'sentinel_token' => 'encrypted',
];
}
}

View File

@@ -3,8 +3,6 @@
namespace App\Models;
use App\Events\FileStorageChanged;
use App\Jobs\ServerStorageSaveJob;
use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class LocalFileVolume extends BaseModel
@@ -15,9 +13,9 @@ class LocalFileVolume extends BaseModel
protected static function booted()
{
static::created(function (LocalFileVolume $localFileVolume) {
$localFileVolume->load(['service']);
dispatch(new ServerStorageSaveJob($localFileVolume));
static::created(function (LocalFileVolume $fileVolume) {
$fileVolume->load(['service']);
dispatch(new \App\Jobs\ServerStorageSaveJob($fileVolume));
});
}
@@ -37,7 +35,7 @@ class LocalFileVolume extends BaseModel
$workdir = $this->resource->workdir();
$server = $this->resource->destination->server;
}
collect([]);
$commands = collect([]);
$path = data_get_str($this, 'fs_path');
if ($path->startsWith('.')) {
$path = $path->after('.');
@@ -82,8 +80,6 @@ class LocalFileVolume extends BaseModel
if ($commands->count() > 0) {
return instant_remote_process($commands, $server);
}
return null;
}
public function saveStorageOnServer()
@@ -122,13 +118,12 @@ class LocalFileVolume extends BaseModel
$this->content = $content;
$this->save();
FileStorageChanged::dispatch(data_get($server, 'team_id'));
throw new Exception('The following file is a file on the server, but you are trying to mark it as a directory. Please delete the file on the server or mark it as directory.');
}
if ($isDir === 'OK' && ! $this->is_directory) {
throw new \Exception('The following file is a file on the server, but you are trying to mark it as a directory. Please delete the file on the server or mark it as directory.');
} elseif ($isDir === 'OK' && ! $this->is_directory) {
if ($path === '/' || $path === '.' || $path === '..' || $path === '' || str($path)->isEmpty() || is_null($path)) {
$this->is_directory = true;
$this->save();
throw new Exception('The following file is a directory on the server, but you are trying to mark it as a file. <br><br>Please delete the directory on the server or mark it as directory.');
throw new \Exception('The following file is a directory on the server, but you are trying to mark it as a file. <br><br>Please delete the directory on the server or mark it as directory.');
}
instant_remote_process([
"rm -fr $path",

View File

@@ -49,9 +49,9 @@ class LocalPersistentVolume extends Model
set: function (?string $value) {
if ($value) {
return str($value)->trim()->start('/')->value;
} else {
return $value;
}
return $value;
}
);
}

View File

@@ -16,8 +16,8 @@ class OauthSetting extends Model
protected function clientSecret(): Attribute
{
return Attribute::make(
get: fn (?string $value) => $value === null || $value === '' || $value === '0' ? null : Crypt::decryptString($value),
set: fn (?string $value) => $value === null || $value === '' || $value === '0' ? null : Crypt::encryptString($value),
get: fn (?string $value) => empty($value) ? null : Crypt::decryptString($value),
set: fn (?string $value) => empty($value) ? null : Crypt::encryptString($value),
);
}

View File

@@ -3,12 +3,10 @@
namespace App\Models;
use DanHarrin\LivewireRateLimiting\WithRateLimiting;
use Exception;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\ValidationException;
use OpenApi\Attributes as OA;
use phpseclib3\Crypt\PublicKeyLoader;
use Throwable;
#[OA\Schema(
description: 'Private Key model',
@@ -38,6 +36,10 @@ class PrivateKey extends BaseModel
'fingerprint',
];
protected $casts = [
'private_key' => 'encrypted',
];
protected static function booted()
{
static::saving(function ($key) {
@@ -80,7 +82,7 @@ class PrivateKey extends BaseModel
PublicKeyLoader::load($privateKey);
return true;
} catch (Throwable $e) {
} catch (\Throwable $e) {
return false;
}
}
@@ -109,8 +111,8 @@ class PrivateKey extends BaseModel
'private_key' => $keyPair['private'],
'public_key' => $keyPair['public'],
];
} catch (Throwable $e) {
throw new Exception("Failed to generate new {$type} key: ".$e->getMessage(), $e->getCode(), $e);
} catch (\Throwable $e) {
throw new \Exception("Failed to generate new {$type} key: ".$e->getMessage());
}
}
@@ -120,7 +122,7 @@ class PrivateKey extends BaseModel
$key = PublicKeyLoader::load($privateKey);
return $key->getPublicKey()->toString('OpenSSH', ['comment' => '']);
} catch (Throwable $e) {
} catch (\Throwable $e) {
return null;
}
}
@@ -185,17 +187,10 @@ class PrivateKey extends BaseModel
public function isInUse()
{
if ($this->servers()->exists()) {
return true;
}
if ($this->applications()->exists()) {
return true;
}
if ($this->githubApps()->exists()) {
return true;
}
return (bool) $this->gitlabApps()->exists();
return $this->servers()->exists()
|| $this->applications()->exists()
|| $this->githubApps()->exists()
|| $this->gitlabApps()->exists();
}
public function safeDelete()
@@ -216,22 +211,22 @@ class PrivateKey extends BaseModel
$publicKey = $key->getPublicKey();
return $publicKey->getFingerprint('sha256');
} catch (Throwable $e) {
} catch (\Throwable $e) {
return null;
}
}
private static function fingerprintExists($fingerprint, $excludeId = null)
{
$builder = self::query()
$query = self::query()
->where('fingerprint', $fingerprint)
->where('id', '!=', $excludeId);
if (currentTeam()) {
$builder->where('team_id', currentTeam()->id);
$query->where('team_id', currentTeam()->id);
}
return $builder->exists();
return $query->exists();
}
public static function cleanupUnusedKeys()
@@ -240,11 +235,4 @@ class PrivateKey extends BaseModel
$privateKey->safeDelete();
});
}
protected function casts(): array
{
return [
'private_key' => 'encrypted',
];
}
}

View File

@@ -33,10 +33,10 @@ class Project extends BaseModel
protected static function booted()
{
static::created(function ($project) {
ProjectSetting::query()->create([
ProjectSetting::create([
'project_id' => $project->id,
]);
Environment::query()->create([
Environment::create([
'name' => 'production',
'project_id' => $project->id,
'uuid' => (string) new Cuid2,

View File

@@ -31,6 +31,24 @@ class PushoverNotificationSettings extends Model
'server_unreachable_pushover_notifications',
];
protected $casts = [
'pushover_enabled' => 'boolean',
'pushover_user_key' => 'encrypted',
'pushover_api_token' => 'encrypted',
'deployment_success_pushover_notifications' => 'boolean',
'deployment_failure_pushover_notifications' => 'boolean',
'status_change_pushover_notifications' => 'boolean',
'backup_success_pushover_notifications' => 'boolean',
'backup_failure_pushover_notifications' => 'boolean',
'scheduled_task_success_pushover_notifications' => 'boolean',
'scheduled_task_failure_pushover_notifications' => 'boolean',
'docker_cleanup_pushover_notifications' => 'boolean',
'server_disk_usage_pushover_notifications' => 'boolean',
'server_reachable_pushover_notifications' => 'boolean',
'server_unreachable_pushover_notifications' => 'boolean',
];
public function team()
{
return $this->belongsTo(Team::class);
@@ -40,25 +58,4 @@ class PushoverNotificationSettings extends Model
{
return $this->pushover_enabled;
}
protected function casts(): array
{
return [
'pushover_enabled' => 'boolean',
'pushover_user_key' => 'encrypted',
'pushover_api_token' => 'encrypted',
'deployment_success_pushover_notifications' => 'boolean',
'deployment_failure_pushover_notifications' => 'boolean',
'status_change_pushover_notifications' => 'boolean',
'backup_success_pushover_notifications' => 'boolean',
'backup_failure_pushover_notifications' => 'boolean',
'scheduled_task_success_pushover_notifications' => 'boolean',
'scheduled_task_failure_pushover_notifications' => 'boolean',
'docker_cleanup_pushover_notifications' => 'boolean',
'server_disk_usage_pushover_notifications' => 'boolean',
'server_reachable_pushover_notifications' => 'boolean',
'server_unreachable_pushover_notifications' => 'boolean',
];
}
}

View File

@@ -5,7 +5,6 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Storage;
use Throwable;
class S3Storage extends BaseModel
{
@@ -13,6 +12,12 @@ class S3Storage extends BaseModel
protected $guarded = [];
protected $casts = [
'is_usable' => 'boolean',
'key' => 'encrypted',
'secret' => 'encrypted',
];
public static function ownedByCurrentTeam(array $select = ['*'])
{
$selectArray = collect($select)->concat(['id']);
@@ -52,12 +57,12 @@ class S3Storage extends BaseModel
Storage::disk('custom-s3')->files();
$this->unusable_email_sent = false;
$this->is_usable = true;
} catch (Throwable $e) {
} catch (\Throwable $e) {
$this->is_usable = false;
if ($this->unusable_email_sent === false && is_transactional_emails_enabled()) {
$mailMessage = new MailMessage;
$mailMessage->subject('Coolify: S3 Storage Connection Error');
$mailMessage->view('emails.s3-connection-error', ['name' => $this->name, 'reason' => $e->getMessage(), 'url' => route('storage.show', ['storage_uuid' => $this->uuid])]);
$mail = new MailMessage;
$mail->subject('Coolify: S3 Storage Connection Error');
$mail->view('emails.s3-connection-error', ['name' => $this->name, 'reason' => $e->getMessage(), 'url' => route('storage.show', ['storage_uuid' => $this->uuid])]);
$users = collect([]);
$members = $this->team->members()->get();
foreach ($members as $user) {
@@ -66,7 +71,7 @@ class S3Storage extends BaseModel
}
}
foreach ($users as $user) {
send_user_an_email($mailMessage, $user->email);
send_user_an_email($mail, $user->email);
}
$this->unusable_email_sent = true;
}
@@ -78,13 +83,4 @@ class S3Storage extends BaseModel
}
}
}
protected function casts(): array
{
return [
'is_usable' => 'boolean',
'key' => 'encrypted',
'secret' => 'encrypted',
];
}
}

View File

@@ -10,7 +10,6 @@ use App\Events\ServerReachabilityChanged;
use App\Jobs\CheckAndStartSentinelJob;
use App\Notifications\Server\Reachable;
use App\Notifications\Server\Unreachable;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -20,13 +19,11 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Stringable;
use Log;
use OpenApi\Attributes as OA;
use Spatie\SchemalessAttributes\Casts\SchemalessAttributes;
use Spatie\SchemalessAttributes\SchemalessAttributesTrait;
use Spatie\Url\Url;
use Symfony\Component\Yaml\Yaml;
use Throwable;
#[OA\Schema(
description: 'Server model',
@@ -75,37 +72,39 @@ class Server extends BaseModel
}
});
static::created(function ($server) {
ServerSetting::query()->create([
ServerSetting::create([
'server_id' => $server->id,
]);
if ($server->id === 0) {
if ($server->isSwarm()) {
SwarmDocker::query()->create([
SwarmDocker::create([
'id' => 0,
'name' => 'coolify',
'network' => 'coolify-overlay',
'server_id' => $server->id,
]);
} else {
StandaloneDocker::query()->create([
StandaloneDocker::create([
'id' => 0,
'name' => 'coolify',
'network' => 'coolify',
'server_id' => $server->id,
]);
}
} elseif ($server->isSwarm()) {
SwarmDocker::query()->create([
'name' => 'coolify-overlay',
'network' => 'coolify-overlay',
'server_id' => $server->id,
]);
} else {
StandaloneDocker::query()->create([
'name' => 'coolify',
'network' => 'coolify',
'server_id' => $server->id,
]);
if ($server->isSwarm()) {
SwarmDocker::create([
'name' => 'coolify-overlay',
'network' => 'coolify-overlay',
'server_id' => $server->id,
]);
} else {
StandaloneDocker::create([
'name' => 'coolify',
'network' => 'coolify',
'server_id' => $server->id,
]);
}
}
if (! isset($server->proxy->redirect_enabled)) {
$server->proxy->redirect_enabled = true;
@@ -125,6 +124,17 @@ class Server extends BaseModel
});
}
protected $casts = [
'proxy' => SchemalessAttributes::class,
'logdrain_axiom_api_key' => 'encrypted',
'logdrain_newrelic_license_key' => 'encrypted',
'delete_unused_volumes' => 'boolean',
'delete_unused_networks' => 'boolean',
'unreachable_notification_sent' => 'boolean',
'is_build_server' => 'boolean',
'force_disabled' => 'boolean',
];
protected $schemalessAttributes = [
'proxy',
];
@@ -192,8 +202,10 @@ class Server extends BaseModel
$proxy_type = $this->proxyType();
$redirect_enabled = $this->proxy->redirect_enabled ?? true;
$redirect_url = $this->proxy->redirect_url;
if (isDev() && $proxy_type === ProxyTypes::CADDY->value) {
$dynamic_conf_path = '/data/coolify/proxy/caddy/dynamic';
if (isDev()) {
if ($proxy_type === ProxyTypes::CADDY->value) {
$dynamic_conf_path = '/data/coolify/proxy/caddy/dynamic';
}
}
if ($proxy_type === ProxyTypes::TRAEFIK->value) {
$default_redirect_file = "$dynamic_conf_path/default_redirect_503.yaml";
@@ -211,11 +223,15 @@ class Server extends BaseModel
instant_remote_process(["rm -f $default_redirect_file"], $this);
} else {
if ($proxy_type === ProxyTypes::CADDY->value) {
$conf = filled($redirect_url) ? ":80, :443 {
if (filled($redirect_url)) {
$conf = ":80, :443 {
redir $redirect_url
}" : ':80, :443 {
}";
} else {
$conf = ':80, :443 {
respond 503
}';
}
} elseif ($proxy_type === ProxyTypes::TRAEFIK->value) {
$dynamic_conf = [
'http' => [
@@ -458,9 +474,17 @@ $schema://$host {
if ($proxyType === ProxyTypes::TRAEFIK->value) {
// Do nothing
} elseif ($proxyType === ProxyTypes::CADDY->value) {
$proxy_path = isDev() ? '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/proxy/caddy' : $proxy_path.'/caddy';
if (isDev()) {
$proxy_path = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/proxy/caddy';
} else {
$proxy_path = $proxy_path.'/caddy';
}
} elseif ($proxyType === ProxyTypes::NGINX->value) {
$proxy_path = isDev() ? '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/proxy/nginx' : $proxy_path.'/nginx';
if (isDev()) {
$proxy_path = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/proxy/nginx';
} else {
$proxy_path = $proxy_path.'/nginx';
}
}
return $proxy_path;
@@ -521,7 +545,7 @@ $schema://$host {
{
$wait = $this->settings->sentinel_push_interval_seconds * 3;
if ($wait < 120) {
return 120;
$wait = 120;
}
return $wait;
@@ -563,7 +587,7 @@ $schema://$host {
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$cpu = json_decode($cpu, true);
@@ -571,8 +595,6 @@ $schema://$host {
return [(int) $metric['time'], (float) $metric['percent']];
});
}
return null;
}
public function getMemoryMetrics(int $mins = 5)
@@ -586,7 +608,7 @@ $schema://$host {
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$memory = json_decode($memory, true);
$parsedCollection = collect($memory)->map(function ($metric) {
@@ -597,8 +619,6 @@ $schema://$host {
return $parsedCollection->toArray();
}
return null;
}
public function getDiskUsage(): ?string
@@ -641,11 +661,11 @@ $schema://$host {
$containerReplicates = instant_remote_process(["docker service ls --format '{{json .}}'"], $this, false);
if ($containerReplicates) {
$containerReplicates = format_docker_command_output_to_json($containerReplicates);
foreach ($containerReplicates as $containerReplicate) {
$name = data_get($containerReplicate, 'Name');
$containers = $containers->map(function ($container) use ($name, $containerReplicate) {
foreach ($containerReplicates as $containerReplica) {
$name = data_get($containerReplica, 'Name');
$containers = $containers->map(function ($container) use ($name, $containerReplica) {
if (data_get($container, 'Spec.Name') === $name) {
$replicas = data_get($containerReplicate, 'Replicas');
$replicas = data_get($containerReplica, 'Replicas');
$running = str($replicas)->explode('/')[0];
$total = str($replicas)->explode('/')[1];
if ($running === $total) {
@@ -717,9 +737,9 @@ $schema://$host {
$containers = $containers->filter();
return collect($containers);
} else {
return collect([]);
}
return collect([]);
}
public function hasDefinedResources()
@@ -727,8 +747,11 @@ $schema://$host {
$applications = $this->applications()->count() > 0;
$databases = $this->databases()->count() > 0;
$services = $this->services()->count() > 0;
if ($applications || $databases || $services) {
return true;
}
return $applications || $databases || $services;
return false;
}
public function databases()
@@ -758,7 +781,7 @@ $schema://$host {
$additionalApplicationIds = collect($additionalApplicationIds)->map(function ($item) {
return $item->application_id;
});
Application::query()->whereIn('id', $additionalApplicationIds)->get()->each(function ($application) use ($applications) {
Application::whereIn('id', $additionalApplicationIds)->get()->each(function ($application) use ($applications) {
$applications->push($application);
});
@@ -776,7 +799,7 @@ $schema://$host {
{
return $this->previews()->filter(function ($preview) {
$applicationId = data_get($preview, 'application_id');
$application = Application::query()->find($applicationId);
$application = Application::find($applicationId);
if (! $application) {
return false;
}
@@ -878,7 +901,11 @@ $schema://$host {
public function isProxyShouldRun()
{
// TODO: Do we need "|| $this->proxy->force_stop" here?
return $this->proxyType() !== ProxyTypes::NONE->value && ! $this->isBuildServer();
if ($this->proxyType() === ProxyTypes::NONE->value || $this->isBuildServer()) {
return false;
}
return true;
}
public function skipServer()
@@ -886,8 +913,11 @@ $schema://$host {
if ($this->ip === '1.2.3.4') {
return true;
}
if ($this->settings->force_disabled === true) {
return true;
}
return $this->settings->force_disabled === true;
return false;
}
public function isFunctional()
@@ -911,8 +941,8 @@ $schema://$host {
$os_release = instant_remote_process(['cat /etc/os-release'], $this);
$releaseLines = collect(explode("\n", $os_release));
$collectedData = collect([]);
foreach ($releaseLines as $releaseLine) {
$item = str($releaseLine)->trim();
foreach ($releaseLines as $line) {
$item = str($line)->trim();
$collectedData->put($item->before('=')->value(), $item->after('=')->lower()->replace('"', '')->value());
}
$ID = data_get($collectedData, 'ID');
@@ -926,10 +956,10 @@ $schema://$host {
if ($supported->count() === 1) {
// ray('supported');
return str($supported->first());
} else {
// ray('not supported');
return false;
}
// ray('not supported');
return false;
}
public function isSwarm()
@@ -952,8 +982,11 @@ $schema://$host {
if ($this->status() === false) {
return false;
}
if ($this->isFunctional() === false) {
return false;
}
return $this->isFunctional() !== false;
return true;
}
public function status(): bool
@@ -993,19 +1026,19 @@ $schema://$host {
$unreachableNotificationSent = (bool) $this->unreachable_notification_sent;
$isReachable = (bool) $this->settings->is_reachable;
Log::debug('Server reachability check', [
\Log::debug('Server reachability check', [
'server_id' => $this->id,
'is_reachable' => $isReachable,
'notification_sent' => $unreachableNotificationSent,
'unreachable_count' => $this->unreachable_count,
]);
if ($isReachable) {
if ($isReachable === true) {
$this->unreachable_count = 0;
$this->save();
if ($unreachableNotificationSent) {
Log::debug('Server is now reachable, sending notification', [
if ($unreachableNotificationSent === true) {
\Log::debug('Server is now reachable, sending notification', [
'server_id' => $this->id,
]);
$this->sendReachableNotification();
@@ -1015,7 +1048,7 @@ $schema://$host {
}
$this->increment('unreachable_count');
Log::debug('Incremented unreachable count', [
\Log::debug('Incremented unreachable count', [
'server_id' => $this->id,
'new_count' => $this->unreachable_count,
]);
@@ -1023,7 +1056,7 @@ $schema://$host {
if ($this->unreachable_count === 1) {
$this->settings->is_reachable = true;
$this->settings->save();
Log::debug('First unreachable attempt, marking as reachable', [
\Log::debug('First unreachable attempt, marking as reachable', [
'server_id' => $this->id,
]);
@@ -1034,7 +1067,7 @@ $schema://$host {
$failedChecks = 0;
for ($i = 0; $i < 3; $i++) {
$status = $this->serverStatus();
Log::debug('Additional reachability check', [
\Log::debug('Additional reachability check', [
'server_id' => $this->id,
'attempt' => $i + 1,
'status' => $status,
@@ -1046,7 +1079,7 @@ $schema://$host {
}
if ($failedChecks === 3 && ! $unreachableNotificationSent) {
Log::debug('Server confirmed unreachable after 3 attempts, sending notification', [
\Log::debug('Server confirmed unreachable after 3 attempts, sending notification', [
'server_id' => $this->id,
]);
$this->sendUnreachableNotification();
@@ -1086,7 +1119,7 @@ $schema://$host {
}
return ['uptime' => true, 'error' => null];
} catch (Throwable $e) {
} catch (\Throwable $e) {
if ($justCheckingNewKey) {
return ['uptime' => false, 'error' => 'This key is not valid for this server.'];
}
@@ -1112,18 +1145,18 @@ $schema://$host {
$this->settings->is_usable = false;
$this->settings->save();
if ($throwError) {
throw new Exception('Server is not usable. Docker Engine is not installed.');
throw new \Exception('Server is not usable. Docker Engine is not installed.');
}
return false;
}
try {
instant_remote_process(['docker version'], $this);
} catch (Throwable $e) {
} catch (\Throwable $e) {
$this->settings->is_usable = false;
$this->settings->save();
if ($throwError) {
throw new Exception('Server is not usable. Docker Engine is not running.', $e->getCode(), $e);
throw new \Exception('Server is not usable. Docker Engine is not running.');
}
return false;
@@ -1142,7 +1175,7 @@ $schema://$host {
$this->settings->is_usable = false;
$this->settings->save();
if ($throwError) {
throw new Exception('Server is not usable. Docker Compose is not installed.');
throw new \Exception('Server is not usable. Docker Compose is not installed.');
}
return false;
@@ -1158,7 +1191,9 @@ $schema://$host {
$swarmStatus = instant_remote_process(['docker info|grep -i swarm'], $this, false);
$swarmStatus = str($swarmStatus)->trim()->after(':')->trim();
if ($swarmStatus === 'inactive') {
throw new Exception('Docker Swarm is not initiated. Please join the server to a swarm before continuing.');
throw new \Exception('Docker Swarm is not initiated. Please join the server to a swarm before continuing.');
return false;
}
$this->settings->is_usable = true;
$this->settings->save();
@@ -1190,13 +1225,13 @@ $schema://$host {
public function validateCoolifyNetwork($isSwarm = false, $isBuildServer = false)
{
if ($isBuildServer) {
return null;
return;
}
if ($isSwarm) {
return instant_remote_process(['docker network create --attachable --driver overlay coolify-overlay >/dev/null 2>&1 || true'], $this, false);
} else {
return instant_remote_process(['docker network create coolify --attachable >/dev/null 2>&1 || true'], $this, false);
}
return instant_remote_process(['docker network create coolify --attachable >/dev/null 2>&1 || true'], $this, false);
}
public function isNonRoot()
@@ -1225,7 +1260,7 @@ $schema://$host {
public function updateWithPrivateKey(array $data, ?PrivateKey $privateKey = null)
{
$this->update($data);
if ($privateKey instanceof PrivateKey) {
if ($privateKey) {
$this->privateKey()->associate($privateKey);
$this->save();
}
@@ -1255,11 +1290,9 @@ $schema://$host {
} else {
StartSentinel::run($this, true);
}
} catch (Throwable $e) {
} catch (\Throwable $e) {
return handleError($e);
}
return null;
}
public function url()
@@ -1289,21 +1322,7 @@ $schema://$host {
}
}
} else {
throw new Exception('Invalid proxy type.');
throw new \Exception('Invalid proxy type.');
}
}
protected function casts(): array
{
return [
'proxy' => SchemalessAttributes::class,
'logdrain_axiom_api_key' => 'encrypted',
'logdrain_newrelic_license_key' => 'encrypted',
'delete_unused_volumes' => 'boolean',
'delete_unused_networks' => 'boolean',
'unreachable_notification_sent' => 'boolean',
'is_build_server' => 'boolean',
'force_disabled' => 'boolean',
];
}
}

View File

@@ -6,7 +6,6 @@ use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;
use OpenApi\Attributes as OA;
use Throwable;
#[OA\Schema(
description: 'Server Settings model',
@@ -54,6 +53,14 @@ class ServerSetting extends Model
{
protected $guarded = [];
protected $casts = [
'force_docker_cleanup' => 'boolean',
'docker_cleanup_threshold' => 'integer',
'sentinel_token' => 'encrypted',
'is_reachable' => 'boolean',
'is_usable' => 'boolean',
];
protected static function booted()
{
static::creating(function ($setting) {
@@ -64,7 +71,7 @@ class ServerSetting extends Model
if (str($setting->sentinel_custom_url)->isEmpty()) {
$setting->generateSentinelUrl(save: false, ignoreEvent: true);
}
} catch (Throwable $e) {
} catch (\Throwable $e) {
Log::error('Error creating server setting: '.$e->getMessage());
}
});
@@ -141,15 +148,4 @@ class ServerSetting extends Model
}
);
}
protected function casts(): array
{
return [
'force_docker_cleanup' => 'boolean',
'docker_cleanup_threshold' => 'integer',
'sentinel_token' => 'encrypted',
'is_reachable' => 'boolean',
'is_usable' => 'boolean',
];
}
}

View File

@@ -84,13 +84,14 @@ class Service extends BaseModel
}
if ($oldConfigHash === $newConfigHash) {
return false;
}
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
return true;
}
}
protected function serverStatus(): Attribute
@@ -134,7 +135,7 @@ class Service extends BaseModel
public static function ownedByCurrentTeam()
{
return \App\Models\Service::query()->whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name');
return Service::whereRelation('environment.project.team', 'id', currentTeam()->id)->orderBy('name');
}
public function getContainersToStop(): array
@@ -160,7 +161,7 @@ class Service extends BaseModel
}
$startTime = time();
while ($processes !== []) {
while (count($processes) > 0) {
$finishedProcesses = array_filter($processes, function ($process) {
return ! $process->running();
});
@@ -230,7 +231,11 @@ class Service extends BaseModel
continue;
}
if ($status->startsWith('running')) {
$complexStatus = $complexStatus === 'exited' ? 'degraded' : 'running';
if ($complexStatus === 'exited') {
$complexStatus = 'degraded';
} else {
$complexStatus = 'running';
}
} elseif ($status->startsWith('restarting')) {
$complexStatus = 'degraded';
} elseif ($status->startsWith('exited')) {
@@ -255,7 +260,11 @@ class Service extends BaseModel
continue;
}
if ($status->startsWith('running')) {
$complexStatus = $complexStatus === 'exited' ? 'degraded' : 'running';
if ($complexStatus === 'exited') {
$complexStatus = 'degraded';
} else {
$complexStatus = 'running';
}
} elseif ($status->startsWith('restarting')) {
$complexStatus = 'degraded';
} elseif ($status->startsWith('exited')) {
@@ -1278,10 +1287,12 @@ class Service extends BaseModel
$real_value = $env->real_value;
if ($env->version === '4.0.0-beta.239') {
$real_value = $env->real_value;
} elseif ($env->is_literal || $env->is_multiline) {
$real_value = '\''.$real_value.'\'';
} else {
$real_value = escapeEnvVariables($env->real_value);
if ($env->is_literal || $env->is_multiline) {
$real_value = '\''.$real_value.'\'';
} else {
$real_value = escapeEnvVariables($env->real_value);
}
}
$commands[] = "echo \"{$env->key}={$real_value}\" >> .env";
}
@@ -1296,12 +1307,11 @@ class Service extends BaseModel
{
if ((int) $this->compose_parsing_version >= 3) {
return newParser($this);
}
if ($this->docker_compose_raw) {
} elseif ($this->docker_compose_raw) {
return parseDockerComposeFile($this, $isNew);
} else {
return collect([]);
}
return collect([]);
}
public function networks()

View File

@@ -34,12 +34,12 @@ class ServiceApplication extends BaseModel
public static function ownedByCurrentTeamAPI(int $teamId)
{
return \App\Models\ServiceApplication::query()->whereRelation('service.environment.project.team', 'id', $teamId)->orderBy('name');
return ServiceApplication::whereRelation('service.environment.project.team', 'id', $teamId)->orderBy('name');
}
public static function ownedByCurrentTeam()
{
return \App\Models\ServiceApplication::query()->whereRelation('service.environment.project.team', 'id', currentTeam()->id)->orderBy('name');
return ServiceApplication::whereRelation('service.environment.project.team', 'id', currentTeam()->id)->orderBy('name');
}
public function isRunning()

View File

@@ -26,12 +26,12 @@ class ServiceDatabase extends BaseModel
public static function ownedByCurrentTeamAPI(int $teamId)
{
return \App\Models\ServiceDatabase::query()->whereRelation('service.environment.project.team', 'id', $teamId)->orderBy('name');
return ServiceDatabase::whereRelation('service.environment.project.team', 'id', $teamId)->orderBy('name');
}
public static function ownedByCurrentTeam()
{
return \App\Models\ServiceDatabase::query()->whereRelation('service.environment.project.team', 'id', currentTeam()->id)->orderBy('name');
return ServiceDatabase::whereRelation('service.environment.project.team', 'id', currentTeam()->id)->orderBy('name');
}
public function restart()
@@ -133,19 +133,10 @@ class ServiceDatabase extends BaseModel
public function isBackupSolutionAvailable()
{
if (str($this->databaseType())->contains('mysql')) {
return true;
}
if (str($this->databaseType())->contains('postgres')) {
return true;
}
if (str($this->databaseType())->contains('postgis')) {
return true;
}
if (str($this->databaseType())->contains('mariadb')) {
return true;
}
return (bool) str($this->databaseType())->contains('mongodb');
return str($this->databaseType())->contains('mysql') ||
str($this->databaseType())->contains('postgres') ||
str($this->databaseType())->contains('postgis') ||
str($this->databaseType())->contains('mariadb') ||
str($this->databaseType())->contains('mongodb');
}
}

View File

@@ -8,11 +8,8 @@ class SharedEnvironmentVariable extends Model
{
protected $guarded = [];
protected function casts(): array
{
return [
'key' => 'string',
'value' => 'encrypted',
];
}
protected $casts = [
'key' => 'string',
'value' => 'encrypted',
];
}

View File

@@ -30,6 +30,23 @@ class SlackNotificationSettings extends Model
'server_unreachable_slack_notifications',
];
protected $casts = [
'slack_enabled' => 'boolean',
'slack_webhook_url' => 'encrypted',
'deployment_success_slack_notifications' => 'boolean',
'deployment_failure_slack_notifications' => 'boolean',
'status_change_slack_notifications' => 'boolean',
'backup_success_slack_notifications' => 'boolean',
'backup_failure_slack_notifications' => 'boolean',
'scheduled_task_success_slack_notifications' => 'boolean',
'scheduled_task_failure_slack_notifications' => 'boolean',
'docker_cleanup_slack_notifications' => 'boolean',
'server_disk_usage_slack_notifications' => 'boolean',
'server_reachable_slack_notifications' => 'boolean',
'server_unreachable_slack_notifications' => 'boolean',
];
public function team()
{
return $this->belongsTo(Team::class);
@@ -39,24 +56,4 @@ class SlackNotificationSettings extends Model
{
return $this->slack_enabled;
}
protected function casts(): array
{
return [
'slack_enabled' => 'boolean',
'slack_webhook_url' => 'encrypted',
'deployment_success_slack_notifications' => 'boolean',
'deployment_failure_slack_notifications' => 'boolean',
'status_change_slack_notifications' => 'boolean',
'backup_success_slack_notifications' => 'boolean',
'backup_failure_slack_notifications' => 'boolean',
'scheduled_task_success_slack_notifications' => 'boolean',
'scheduled_task_failure_slack_notifications' => 'boolean',
'docker_cleanup_slack_notifications' => 'boolean',
'server_disk_usage_slack_notifications' => 'boolean',
'server_reachable_slack_notifications' => 'boolean',
'server_unreachable_slack_notifications' => 'boolean',
];
}
}

View File

@@ -2,7 +2,6 @@
namespace App\Models;
use Exception;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -16,10 +15,14 @@ class StandaloneClickhouse extends BaseModel
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
protected $casts = [
'clickhouse_password' => 'encrypted',
];
protected static function booted()
{
static::created(function ($database) {
LocalPersistentVolume::query()->create([
LocalPersistentVolume::create([
'name' => 'clickhouse-data-'.$database->uuid,
'mount_path' => '/bitnami/clickhouse',
'host_path' => null,
@@ -66,13 +69,14 @@ class StandaloneClickhouse extends BaseModel
}
if ($oldConfigHash === $newConfigHash) {
return false;
}
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
return true;
}
}
public function isRunning()
@@ -105,8 +109,8 @@ class StandaloneClickhouse extends BaseModel
return;
}
$server = data_get($this, 'destination.server');
foreach ($persistentStorages as $persistentStorage) {
instant_remote_process(["docker volume rm -f $persistentStorage->name"], $server, false);
foreach ($persistentStorages as $storage) {
instant_remote_process(["docker volume rm -f $storage->name"], $server, false);
}
}
@@ -279,7 +283,7 @@ class StandaloneClickhouse extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -301,7 +305,7 @@ class StandaloneClickhouse extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -315,11 +319,4 @@ class StandaloneClickhouse extends BaseModel
{
return false;
}
protected function casts(): array
{
return [
'clickhouse_password' => 'encrypted',
];
}
}

View File

@@ -74,10 +74,6 @@ class StandaloneDocker extends BaseModel
public function attachedTo()
{
if ($this->applications?->count() > 0) {
return true;
}
return $this->databases()->count() > 0;
return $this->applications?->count() > 0 || $this->databases()->count() > 0;
}
}

View File

@@ -2,7 +2,6 @@
namespace App\Models;
use Exception;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -16,10 +15,14 @@ class StandaloneDragonfly extends BaseModel
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
protected $casts = [
'dragonfly_password' => 'encrypted',
];
protected static function booted()
{
static::created(function ($database) {
LocalPersistentVolume::query()->create([
LocalPersistentVolume::create([
'name' => 'dragonfly-data-'.$database->uuid,
'mount_path' => '/data',
'host_path' => null,
@@ -66,13 +69,14 @@ class StandaloneDragonfly extends BaseModel
}
if ($oldConfigHash === $newConfigHash) {
return false;
}
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
return true;
}
}
public function isRunning()
@@ -105,8 +109,8 @@ class StandaloneDragonfly extends BaseModel
return;
}
$server = data_get($this, 'destination.server');
foreach ($persistentStorages as $persistentStorage) {
instant_remote_process(["docker volume rm -f $persistentStorage->name"], $server, false);
foreach ($persistentStorages as $storage) {
instant_remote_process(["docker volume rm -f $storage->name"], $server, false);
}
}
@@ -273,7 +277,7 @@ class StandaloneDragonfly extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -295,7 +299,7 @@ class StandaloneDragonfly extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -315,11 +319,4 @@ class StandaloneDragonfly extends BaseModel
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
protected function casts(): array
{
return [
'dragonfly_password' => 'encrypted',
];
}
}

View File

@@ -2,7 +2,6 @@
namespace App\Models;
use Exception;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -16,10 +15,14 @@ class StandaloneKeydb extends BaseModel
protected $appends = ['internal_db_url', 'external_db_url', 'server_status'];
protected $casts = [
'keydb_password' => 'encrypted',
];
protected static function booted()
{
static::created(function ($database) {
LocalPersistentVolume::query()->create([
LocalPersistentVolume::create([
'name' => 'keydb-data-'.$database->uuid,
'mount_path' => '/data',
'host_path' => null,
@@ -66,13 +69,14 @@ class StandaloneKeydb extends BaseModel
}
if ($oldConfigHash === $newConfigHash) {
return false;
}
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
return true;
}
}
public function isRunning()
@@ -105,8 +109,8 @@ class StandaloneKeydb extends BaseModel
return;
}
$server = data_get($this, 'destination.server');
foreach ($persistentStorages as $persistentStorage) {
instant_remote_process(["docker volume rm -f $persistentStorage->name"], $server, false);
foreach ($persistentStorages as $storage) {
instant_remote_process(["docker volume rm -f $storage->name"], $server, false);
}
}
@@ -273,7 +277,7 @@ class StandaloneKeydb extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -295,7 +299,7 @@ class StandaloneKeydb extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -315,11 +319,4 @@ class StandaloneKeydb extends BaseModel
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
protected function casts(): array
{
return [
'keydb_password' => 'encrypted',
];
}
}

View File

@@ -2,7 +2,6 @@
namespace App\Models;
use Exception;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -16,10 +15,14 @@ class StandaloneMariadb extends BaseModel
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
protected $casts = [
'mariadb_password' => 'encrypted',
];
protected static function booted()
{
static::created(function ($database) {
LocalPersistentVolume::query()->create([
LocalPersistentVolume::create([
'name' => 'mariadb-data-'.$database->uuid,
'mount_path' => '/var/lib/mysql',
'host_path' => null,
@@ -66,13 +69,14 @@ class StandaloneMariadb extends BaseModel
}
if ($oldConfigHash === $newConfigHash) {
return false;
}
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
return true;
}
}
public function isRunning()
@@ -105,8 +109,8 @@ class StandaloneMariadb extends BaseModel
return;
}
$server = data_get($this, 'destination.server');
foreach ($persistentStorages as $persistentStorage) {
instant_remote_process(["docker volume rm -f $persistentStorage->name"], $server, false);
foreach ($persistentStorages as $storage) {
instant_remote_process(["docker volume rm -f $storage->name"], $server, false);
}
}
@@ -279,7 +283,7 @@ class StandaloneMariadb extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -301,7 +305,7 @@ class StandaloneMariadb extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -315,11 +319,4 @@ class StandaloneMariadb extends BaseModel
{
return true;
}
protected function casts(): array
{
return [
'mariadb_password' => 'encrypted',
];
}
}

View File

@@ -2,12 +2,10 @@
namespace App\Models;
use Exception;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Throwable;
class StandaloneMongodb extends BaseModel
{
@@ -20,7 +18,7 @@ class StandaloneMongodb extends BaseModel
protected static function booted()
{
static::created(function ($database) {
LocalPersistentVolume::query()->create([
LocalPersistentVolume::create([
'name' => 'mongodb-configdb-'.$database->uuid,
'mount_path' => '/data/configdb',
'host_path' => null,
@@ -28,7 +26,7 @@ class StandaloneMongodb extends BaseModel
'resource_type' => $database->getMorphClass(),
'is_readonly' => true,
]);
LocalPersistentVolume::query()->create([
LocalPersistentVolume::create([
'name' => 'mongodb-db-'.$database->uuid,
'mount_path' => '/data/db',
'host_path' => null,
@@ -75,13 +73,14 @@ class StandaloneMongodb extends BaseModel
}
if ($oldConfigHash === $newConfigHash) {
return false;
}
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
return true;
}
}
public function isRunning()
@@ -114,8 +113,8 @@ class StandaloneMongodb extends BaseModel
return;
}
$server = data_get($this, 'destination.server');
foreach ($persistentStorages as $persistentStorage) {
instant_remote_process(["docker volume rm -f $persistentStorage->name"], $server, false);
foreach ($persistentStorages as $storage) {
instant_remote_process(["docker volume rm -f $storage->name"], $server, false);
}
}
@@ -197,7 +196,7 @@ class StandaloneMongodb extends BaseModel
get: function ($value) {
try {
return decrypt($value);
} catch (Throwable $th) {
} catch (\Throwable $th) {
$this->mongo_initdb_root_password = encrypt($value);
$this->save();
@@ -298,7 +297,7 @@ class StandaloneMongodb extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -320,7 +319,7 @@ class StandaloneMongodb extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {

View File

@@ -2,7 +2,6 @@
namespace App\Models;
use Exception;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -16,10 +15,15 @@ class StandaloneMysql extends BaseModel
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
protected $casts = [
'mysql_password' => 'encrypted',
'mysql_root_password' => 'encrypted',
];
protected static function booted()
{
static::created(function ($database) {
LocalPersistentVolume::query()->create([
LocalPersistentVolume::create([
'name' => 'mysql-data-'.$database->uuid,
'mount_path' => '/var/lib/mysql',
'host_path' => null,
@@ -66,13 +70,14 @@ class StandaloneMysql extends BaseModel
}
if ($oldConfigHash === $newConfigHash) {
return false;
}
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
return true;
}
}
public function isRunning()
@@ -105,8 +110,8 @@ class StandaloneMysql extends BaseModel
return;
}
$server = data_get($this, 'destination.server');
foreach ($persistentStorages as $persistentStorage) {
instant_remote_process(["docker volume rm -f $persistentStorage->name"], $server, false);
foreach ($persistentStorages as $storage) {
instant_remote_process(["docker volume rm -f $storage->name"], $server, false);
}
}
@@ -273,7 +278,7 @@ class StandaloneMysql extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -295,7 +300,7 @@ class StandaloneMysql extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -315,12 +320,4 @@ class StandaloneMysql extends BaseModel
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
protected function casts(): array
{
return [
'mysql_password' => 'encrypted',
'mysql_root_password' => 'encrypted',
];
}
}

View File

@@ -2,7 +2,6 @@
namespace App\Models;
use Exception;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -16,10 +15,15 @@ class StandalonePostgresql extends BaseModel
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
protected $casts = [
'init_scripts' => 'array',
'postgres_password' => 'encrypted',
];
protected static function booted()
{
static::created(function ($database) {
LocalPersistentVolume::query()->create([
LocalPersistentVolume::create([
'name' => 'postgres-data-'.$database->uuid,
'mount_path' => '/var/lib/postgresql/data',
'host_path' => null,
@@ -70,8 +74,8 @@ class StandalonePostgresql extends BaseModel
return;
}
$server = data_get($this, 'destination.server');
foreach ($persistentStorages as $persistentStorage) {
instant_remote_process(["docker volume rm -f $persistentStorage->name"], $server, false);
foreach ($persistentStorages as $storage) {
instant_remote_process(["docker volume rm -f $storage->name"], $server, false);
}
}
@@ -91,13 +95,14 @@ class StandalonePostgresql extends BaseModel
}
if ($oldConfigHash === $newConfigHash) {
return false;
}
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
return true;
}
}
public function isRunning()
@@ -278,7 +283,7 @@ class StandalonePostgresql extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -300,7 +305,7 @@ class StandalonePostgresql extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -315,12 +320,4 @@ class StandalonePostgresql extends BaseModel
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
protected function casts(): array
{
return [
'init_scripts' => 'array',
'postgres_password' => 'encrypted',
];
}
}

View File

@@ -2,7 +2,6 @@
namespace App\Models;
use Exception;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -19,7 +18,7 @@ class StandaloneRedis extends BaseModel
protected static function booted()
{
static::created(function ($database) {
LocalPersistentVolume::query()->create([
LocalPersistentVolume::create([
'name' => 'redis-data-'.$database->uuid,
'mount_path' => '/data',
'host_path' => null,
@@ -66,13 +65,14 @@ class StandaloneRedis extends BaseModel
}
if ($oldConfigHash === $newConfigHash) {
return false;
}
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
} else {
if ($save) {
$this->config_hash = $newConfigHash;
$this->save();
}
return true;
return true;
}
}
public function isRunning()
@@ -105,8 +105,8 @@ class StandaloneRedis extends BaseModel
return;
}
$server = data_get($this, 'destination.server');
foreach ($persistentStorages as $persistentStorage) {
instant_remote_process(["docker volume rm -f $persistentStorage->name"], $server, false);
foreach ($persistentStorages as $storage) {
instant_remote_process(["docker volume rm -f $storage->name"], $server, false);
}
}
@@ -288,7 +288,7 @@ class StandaloneRedis extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {
@@ -310,7 +310,7 @@ class StandaloneRedis extends BaseModel
if ($error === 'Unauthorized') {
$error = 'Unauthorized, please check your metrics token or restart Sentinel to set a new token.';
}
throw new Exception($error);
throw new \Exception($error);
}
$metrics = json_decode($metrics, true);
$parsedCollection = collect($metrics)->map(function ($metric) {

View File

@@ -19,7 +19,7 @@ class Subscription extends Model
if (! $this->stripe_plan_id) {
return 'zero';
}
$subscription = \App\Models\Subscription::query()->where('id', $this->id)->first();
$subscription = Subscription::where('id', $this->id)->first();
if (! $subscription) {
return null;
}

View File

@@ -77,10 +77,6 @@ class SwarmDocker extends BaseModel
public function attachedTo()
{
if ($this->applications?->count() > 0) {
return true;
}
return $this->databases()->count() > 0;
return $this->applications?->count() > 0 || $this->databases()->count() > 0;
}
}

View File

@@ -8,7 +8,6 @@ use App\Notifications\Channels\SendsEmail;
use App\Notifications\Channels\SendsPushover;
use App\Notifications\Channels\SendsSlack;
use App\Traits\HasNotificationSettings;
use Exception;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
@@ -41,6 +40,10 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen
protected $guarded = [];
protected $casts = [
'personal_team' => 'boolean',
];
protected static function booted()
{
static::created(function ($team) {
@@ -53,7 +56,7 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen
static::saving(function ($team) {
if (auth()->user()?->isMember()) {
throw new Exception('You are not allowed to update this team.');
throw new \Exception('You are not allowed to update this team.');
}
});
@@ -92,7 +95,11 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen
public function serverOverflow()
{
return $this->serverLimit() < $this->servers->count();
if ($this->serverLimit() < $this->servers->count()) {
return true;
}
return false;
}
public static function serverLimit()
@@ -100,7 +107,7 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen
if (currentTeam()->id === 0 && isDev()) {
return 9999999;
}
$team = \App\Models\Team::query()->find(currentTeam()->id);
$team = Team::find(currentTeam()->id);
if (! $team) {
return 0;
}
@@ -162,20 +169,12 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen
if (isCloud()) {
return true;
}
if ($this->getNotificationSettings('email')?->isEnabled()) {
return true;
}
if ($this->getNotificationSettings('discord')?->isEnabled()) {
return true;
}
if ($this->getNotificationSettings('slack')?->isEnabled()) {
return true;
}
if ($this->getNotificationSettings('telegram')?->isEnabled()) {
return true;
}
return (bool) $this->getNotificationSettings('pushover')?->isEnabled();
return $this->getNotificationSettings('email')?->isEnabled() ||
$this->getNotificationSettings('discord')?->isEnabled() ||
$this->getNotificationSettings('slack')?->isEnabled() ||
$this->getNotificationSettings('telegram')?->isEnabled() ||
$this->getNotificationSettings('pushover')?->isEnabled();
}
public function subscriptionEnded()
@@ -223,7 +222,11 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen
public function isEmpty()
{
return $this->projects()->count() === 0 && $this->servers()->count() === 0 && $this->privateKeys()->count() === 0 && $this->sources()->count() === 0;
if ($this->projects()->count() === 0 && $this->servers()->count() === 0 && $this->privateKeys()->count() === 0 && $this->sources()->count() === 0) {
return true;
}
return false;
}
public function projects()
@@ -279,11 +282,4 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen
{
return $this->hasOne(PushoverNotificationSettings::class);
}
protected function casts(): array
{
return [
'personal_team' => 'boolean',
];
}
}

View File

@@ -31,9 +31,10 @@ class TeamInvitation extends Model
$diff = $createdAt->diffInDays(now());
if ($diff <= config('constants.invitation.link.expiration_days')) {
return true;
}
$this->delete();
} else {
$this->delete();
return false;
return false;
}
}
}

View File

@@ -43,6 +43,36 @@ class TelegramNotificationSettings extends Model
'telegram_notifications_server_unreachable_thread_id',
];
protected $casts = [
'telegram_enabled' => 'boolean',
'telegram_token' => 'encrypted',
'telegram_chat_id' => 'encrypted',
'deployment_success_telegram_notifications' => 'boolean',
'deployment_failure_telegram_notifications' => 'boolean',
'status_change_telegram_notifications' => 'boolean',
'backup_success_telegram_notifications' => 'boolean',
'backup_failure_telegram_notifications' => 'boolean',
'scheduled_task_success_telegram_notifications' => 'boolean',
'scheduled_task_failure_telegram_notifications' => 'boolean',
'docker_cleanup_telegram_notifications' => 'boolean',
'server_disk_usage_telegram_notifications' => 'boolean',
'server_reachable_telegram_notifications' => 'boolean',
'server_unreachable_telegram_notifications' => 'boolean',
'telegram_notifications_deployment_success_thread_id' => 'encrypted',
'telegram_notifications_deployment_failure_thread_id' => 'encrypted',
'telegram_notifications_status_change_thread_id' => 'encrypted',
'telegram_notifications_backup_success_thread_id' => 'encrypted',
'telegram_notifications_backup_failure_thread_id' => 'encrypted',
'telegram_notifications_scheduled_task_success_thread_id' => 'encrypted',
'telegram_notifications_scheduled_task_failure_thread_id' => 'encrypted',
'telegram_notifications_docker_cleanup_thread_id' => 'encrypted',
'telegram_notifications_server_disk_usage_thread_id' => 'encrypted',
'telegram_notifications_server_reachable_thread_id' => 'encrypted',
'telegram_notifications_server_unreachable_thread_id' => 'encrypted',
];
public function team()
{
return $this->belongsTo(Team::class);
@@ -52,37 +82,4 @@ class TelegramNotificationSettings extends Model
{
return $this->telegram_enabled;
}
protected function casts(): array
{
return [
'telegram_enabled' => 'boolean',
'telegram_token' => 'encrypted',
'telegram_chat_id' => 'encrypted',
'deployment_success_telegram_notifications' => 'boolean',
'deployment_failure_telegram_notifications' => 'boolean',
'status_change_telegram_notifications' => 'boolean',
'backup_success_telegram_notifications' => 'boolean',
'backup_failure_telegram_notifications' => 'boolean',
'scheduled_task_success_telegram_notifications' => 'boolean',
'scheduled_task_failure_telegram_notifications' => 'boolean',
'docker_cleanup_telegram_notifications' => 'boolean',
'server_disk_usage_telegram_notifications' => 'boolean',
'server_reachable_telegram_notifications' => 'boolean',
'server_unreachable_telegram_notifications' => 'boolean',
'telegram_notifications_deployment_success_thread_id' => 'encrypted',
'telegram_notifications_deployment_failure_thread_id' => 'encrypted',
'telegram_notifications_status_change_thread_id' => 'encrypted',
'telegram_notifications_backup_success_thread_id' => 'encrypted',
'telegram_notifications_backup_failure_thread_id' => 'encrypted',
'telegram_notifications_scheduled_task_success_thread_id' => 'encrypted',
'telegram_notifications_scheduled_task_failure_thread_id' => 'encrypted',
'telegram_notifications_docker_cleanup_thread_id' => 'encrypted',
'telegram_notifications_server_disk_usage_thread_id' => 'encrypted',
'telegram_notifications_server_reachable_thread_id' => 'encrypted',
'telegram_notifications_server_unreachable_thread_id' => 'encrypted',
];
}
}

View File

@@ -48,6 +48,12 @@ class User extends Authenticatable implements SendsEmail
'two_factor_secret',
];
protected $casts = [
'email_verified_at' => 'datetime',
'force_password_reset' => 'boolean',
'show_boarding' => 'boolean',
];
protected static function boot()
{
parent::boot();
@@ -61,7 +67,7 @@ class User extends Authenticatable implements SendsEmail
$team['id'] = 0;
$team['name'] = 'Root Team';
}
$new_team = Team::query()->create($team);
$new_team = Team::create($team);
$user->teams()->attach($new_team, ['role' => 'owner']);
});
}
@@ -77,7 +83,7 @@ class User extends Authenticatable implements SendsEmail
$team['id'] = 0;
$team['name'] = 'Root Team';
}
$new_team = Team::query()->create($team);
$new_team = Team::create($team);
$this->teams()->attach($new_team, ['role' => 'owner']);
return $new_team;
@@ -92,7 +98,7 @@ class User extends Authenticatable implements SendsEmail
hash('crc32b', $tokenEntropy)
);
$personalAccessToken = $this->tokens()->create([
$token = $this->tokens()->create([
'name' => $name,
'token' => hash('sha256', $plainTextToken),
'abilities' => $abilities,
@@ -100,7 +106,7 @@ class User extends Authenticatable implements SendsEmail
'team_id' => session('currentTeam')->id,
]);
return new NewAccessToken($personalAccessToken, $personalAccessToken->getKey().'|'.$plainTextToken);
return new NewAccessToken($token, $token->getKey().'|'.$plainTextToken);
}
public function teams()
@@ -115,7 +121,7 @@ class User extends Authenticatable implements SendsEmail
public function sendVerificationEmail()
{
$mailMessage = new MailMessage;
$mail = new MailMessage;
$url = Url::temporarySignedRoute(
'verify.verify',
Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
@@ -124,11 +130,11 @@ class User extends Authenticatable implements SendsEmail
'hash' => sha1($this->getEmailForVerification()),
]
);
$mailMessage->view('emails.email-verification', [
$mail->view('emails.email-verification', [
'url' => $url,
]);
$mailMessage->subject('Coolify: Verify your email.');
send_user_an_email($mailMessage, $this->email);
$mail->subject('Coolify: Verify your email.');
send_user_an_email($mail, $this->email);
}
public function sendPasswordResetNotification($token): void
@@ -138,11 +144,7 @@ class User extends Authenticatable implements SendsEmail
public function isAdmin()
{
if ($this->role() === 'admin') {
return true;
}
return $this->role() === 'owner';
return $this->role() === 'admin' || $this->role() === 'owner';
}
public function isOwner()
@@ -179,7 +181,11 @@ class User extends Authenticatable implements SendsEmail
{
$found_root_team = Auth::user()->teams->filter(function ($team) {
if ($team->id == 0) {
return (bool) Auth::user()->isAdmin();
if (! Auth::user()->isAdmin()) {
return false;
}
return true;
}
return false;
@@ -195,7 +201,7 @@ class User extends Authenticatable implements SendsEmail
return Auth::user()->teams[0];
}
return Team::query()->find(session('currentTeam')->id);
return Team::find(session('currentTeam')->id);
});
}
@@ -215,13 +221,4 @@ class User extends Authenticatable implements SendsEmail
return data_get($user, 'pivot.role');
}
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'force_password_reset' => 'boolean',
'show_boarding' => 'boolean',
];
}
}

View File

@@ -8,11 +8,8 @@ class Webhook extends Model
{
protected $guarded = [];
protected function casts(): array
{
return [
'type' => 'string',
'payload' => 'encrypted',
];
}
protected $casts = [
'type' => 'string',
'payload' => 'encrypted',
];
}