mirror of
https://github.com/vitodeploy/vito.git
synced 2025-07-04 15:32:35 +00:00
Add phpstan level 7(#544)
This commit is contained in:
@ -23,6 +23,7 @@
|
||||
*/
|
||||
class Backup extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\BackupFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -46,13 +47,18 @@ public static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::deleting(function (Backup $backup) {
|
||||
$backup->files()->each(function (BackupFile $file) {
|
||||
static::deleting(function ($backup): void {
|
||||
/** @var Backup $backup */
|
||||
$backup->files()->each(function ($file): void {
|
||||
/** @var BackupFile $file */
|
||||
$file->delete();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
BackupStatus::RUNNING => 'success',
|
||||
BackupStatus::FAILED => 'danger',
|
||||
@ -62,31 +68,46 @@ public static function boot(): void
|
||||
public function isCustomInterval(): bool
|
||||
{
|
||||
$intervals = array_keys(config('core.cronjob_intervals'));
|
||||
$intervals = array_filter($intervals, fn ($interval) => $interval !== 'custom');
|
||||
$intervals = array_filter($intervals, fn ($interval): bool => $interval !== 'custom');
|
||||
|
||||
return ! in_array($this->interval, $intervals);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, covariant $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<StorageProvider, covariant $this>
|
||||
*/
|
||||
public function storage(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(StorageProvider::class, 'storage_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Database, covariant $this>
|
||||
*/
|
||||
public function database(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Database::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<BackupFile, covariant $this>
|
||||
*/
|
||||
public function files(): HasMany
|
||||
{
|
||||
return $this->hasMany(BackupFile::class, 'backup_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne<BackupFile, covariant $this>
|
||||
*/
|
||||
public function lastFile(): HasOne
|
||||
{
|
||||
return $this->hasOne(BackupFile::class, 'backup_id')->latest();
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
class BackupFile extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\BackupFileFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -38,15 +39,16 @@ class BackupFile extends AbstractModel
|
||||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::created(function (BackupFile $backupFile) {
|
||||
static::created(function (BackupFile $backupFile): void {
|
||||
$keep = $backupFile->backup->keep_backups;
|
||||
if ($backupFile->backup->files()->count() > $keep) {
|
||||
/* @var BackupFile $lastFileToKeep */
|
||||
/** @var ?BackupFile $lastFileToKeep */
|
||||
$lastFileToKeep = $backupFile->backup->files()->orderByDesc('id')->skip($keep)->first();
|
||||
if ($lastFileToKeep) {
|
||||
$files = $backupFile->backup->files()
|
||||
->where('id', '<=', $lastFileToKeep->id)
|
||||
->get();
|
||||
/** @var BackupFile $file */
|
||||
foreach ($files as $file) {
|
||||
app(ManageBackupFile::class)->delete($file);
|
||||
}
|
||||
@ -55,6 +57,9 @@ protected static function booted(): void
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
BackupFileStatus::CREATED => 'success',
|
||||
BackupFileStatus::CREATING => 'warning',
|
||||
@ -78,6 +83,9 @@ public function isLocal(): bool
|
||||
return $this->backup->storage->provider === StorageProviderAlias::LOCAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Backup, covariant $this>
|
||||
*/
|
||||
public function backup(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Backup::class);
|
||||
@ -96,7 +104,7 @@ public function path(): string
|
||||
return match ($storage->provider) {
|
||||
StorageProviderAlias::DROPBOX => '/'.$databaseName.'/'.$this->name.'.zip',
|
||||
StorageProviderAlias::S3, StorageProviderAlias::FTP, StorageProviderAlias::LOCAL => implode('/', [
|
||||
rtrim($storage->credentials['path'], '/'),
|
||||
rtrim((string) $storage->credentials['path'], '/'),
|
||||
$databaseName,
|
||||
$this->name.'.zip',
|
||||
]),
|
||||
|
@ -16,12 +16,13 @@
|
||||
* @property string $command
|
||||
* @property Carbon $created_at
|
||||
* @property Carbon $updated_at
|
||||
* @property Collection<CommandExecution> $executions
|
||||
* @property Collection<int, CommandExecution> $executions
|
||||
* @property ?CommandExecution $lastExecution
|
||||
* @property Site $site
|
||||
*/
|
||||
class Command extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\CommandFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -38,32 +39,42 @@ public static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::deleting(function (Command $command) {
|
||||
static::deleting(function (Command $command): void {
|
||||
$command->executions()->delete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Site, covariant $this>
|
||||
*/
|
||||
public function site(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Site::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
public function getVariables(): array
|
||||
{
|
||||
$variables = [];
|
||||
preg_match_all('/\${(.*?)}/', $this->command, $matches);
|
||||
foreach ($matches[1] as $match) {
|
||||
$variables[] = $match;
|
||||
}
|
||||
$variables = $matches[1];
|
||||
|
||||
return array_unique($variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<CommandExecution, covariant $this>
|
||||
*/
|
||||
public function executions(): HasMany
|
||||
{
|
||||
return $this->hasMany(CommandExecution::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne<CommandExecution, covariant $this>
|
||||
*/
|
||||
public function lastExecution(): HasOne
|
||||
{
|
||||
return $this->hasOne(CommandExecution::class)->latest();
|
||||
|
@ -13,7 +13,7 @@
|
||||
* @property int $server_id
|
||||
* @property int $user_id
|
||||
* @property ?int $server_log_id
|
||||
* @property array $variables
|
||||
* @property array<mixed> $variables
|
||||
* @property string $status
|
||||
* @property Carbon $created_at
|
||||
* @property Carbon $updated_at
|
||||
@ -24,6 +24,7 @@
|
||||
*/
|
||||
class CommandExecution extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\CommandExecutionFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -43,12 +44,18 @@ class CommandExecution extends AbstractModel
|
||||
'variables' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
CommandExecutionStatus::EXECUTING => 'warning',
|
||||
CommandExecutionStatus::COMPLETED => 'success',
|
||||
CommandExecutionStatus::FAILED => 'danger',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Command, covariant $this>
|
||||
*/
|
||||
public function command(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Command::class);
|
||||
@ -58,7 +65,7 @@ public function getContent(): string
|
||||
{
|
||||
$content = $this->command->command;
|
||||
foreach ($this->variables as $variable => $value) {
|
||||
if (is_string($value) && ! empty($value)) {
|
||||
if (is_string($value) && ($value !== '' && $value !== '0')) {
|
||||
$content = str_replace('${'.$variable.'}', $value, $content);
|
||||
}
|
||||
}
|
||||
@ -66,16 +73,25 @@ public function getContent(): string
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<ServerLog, covariant $this>
|
||||
*/
|
||||
public function serverLog(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ServerLog::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, covariant $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, covariant $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
class CronJob extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\CronJobFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -34,6 +35,9 @@ class CronJob extends AbstractModel
|
||||
'hidden' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
CronjobStatus::CREATING => 'warning',
|
||||
CronjobStatus::READY => 'success',
|
||||
@ -43,6 +47,9 @@ class CronJob extends AbstractModel
|
||||
CronjobStatus::DISABLED => 'gray',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, covariant $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
@ -59,6 +66,7 @@ public static function crontab(Server $server, string $user): string
|
||||
CronjobStatus::ENABLING,
|
||||
])
|
||||
->get();
|
||||
/** @var CronJob $cronJob */
|
||||
foreach ($cronJobs as $key => $cronJob) {
|
||||
$data .= $cronJob->frequency.' '.$cronJob->command;
|
||||
if ($key != count($cronJobs) - 1) {
|
||||
@ -78,11 +86,8 @@ public function frequencyLabel(): string
|
||||
'0 0 * * 0' => 'Weekly',
|
||||
'0 0 1 * *' => 'Monthly',
|
||||
];
|
||||
if (isset($labels[$this->frequency])) {
|
||||
return $labels[$this->frequency];
|
||||
}
|
||||
|
||||
return $this->frequency;
|
||||
return $labels[$this->frequency] ?? $this->frequency;
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
|
@ -21,7 +21,9 @@
|
||||
*/
|
||||
class Database extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\DatabaseFactory> */
|
||||
use HasFactory;
|
||||
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
@ -40,8 +42,9 @@ public static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::deleting(function (Database $database) {
|
||||
$database->server->databaseUsers()->each(function (DatabaseUser $user) use ($database) {
|
||||
static::deleting(function (Database $database): void {
|
||||
$database->server->databaseUsers()->each(function ($user) use ($database): void {
|
||||
/** @var DatabaseUser $user */
|
||||
$databases = $user->databases;
|
||||
if ($databases && in_array($database->name, $databases)) {
|
||||
unset($databases[array_search($database->name, $databases)]);
|
||||
@ -52,6 +55,9 @@ public static function boot(): void
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
DatabaseStatus::READY => 'success',
|
||||
DatabaseStatus::CREATING => 'warning',
|
||||
@ -59,11 +65,17 @@ public static function boot(): void
|
||||
DatabaseStatus::FAILED => 'danger',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, covariant $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Backup, covariant $this>
|
||||
*/
|
||||
public function backups(): HasMany
|
||||
{
|
||||
return $this->hasMany(Backup::class)->where('type', 'database');
|
||||
|
@ -10,13 +10,14 @@
|
||||
* @property int $server_id
|
||||
* @property string $username
|
||||
* @property string $password
|
||||
* @property array $databases
|
||||
* @property array<string> $databases
|
||||
* @property string $host
|
||||
* @property string $status
|
||||
* @property Server $server
|
||||
*/
|
||||
class DatabaseUser extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\DatabaseUserFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -38,11 +39,17 @@ class DatabaseUser extends AbstractModel
|
||||
'password',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, covariant $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
DatabaseUserStatus::READY => 'success',
|
||||
DatabaseUserStatus::CREATING => 'warning',
|
||||
|
@ -12,14 +12,15 @@
|
||||
* @property int $log_id
|
||||
* @property string $commit_id
|
||||
* @property string $commit_id_short
|
||||
* @property array $commit_data
|
||||
* @property array<string, mixed> $commit_data
|
||||
* @property string $status
|
||||
* @property Site $site
|
||||
* @property DeploymentScript $deploymentScript
|
||||
* @property ServerLog $log
|
||||
* @property ?ServerLog $log
|
||||
*/
|
||||
class Deployment extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\DeploymentFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -38,22 +39,34 @@ class Deployment extends AbstractModel
|
||||
'commit_data' => 'json',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
DeploymentStatus::DEPLOYING => 'warning',
|
||||
DeploymentStatus::FINISHED => 'success',
|
||||
DeploymentStatus::FAILED => 'danger',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Site, covariant $this>
|
||||
*/
|
||||
public function site(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Site::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<DeploymentScript, covariant $this>
|
||||
*/
|
||||
public function deploymentScript(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DeploymentScript::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<ServerLog, covariant $this>
|
||||
*/
|
||||
public function log(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ServerLog::class, 'log_id');
|
||||
|
@ -13,13 +13,14 @@
|
||||
*/
|
||||
class DeploymentScript extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\DeploymentScriptFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::saving(function ($deploymentScript) {
|
||||
static::saving(function ($deploymentScript): void {
|
||||
$deploymentScript->content = str_replace("\r\n", "\n", $deploymentScript->content);
|
||||
});
|
||||
}
|
||||
@ -34,6 +35,9 @@ protected static function boot(): void
|
||||
'site_id' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Site, covariant $this>
|
||||
*/
|
||||
public function site(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Site::class);
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
class File extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\FileFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -53,7 +54,7 @@ protected static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::deleting(function (File $file) {
|
||||
static::deleting(function (File $file): bool {
|
||||
if ($file->name === '.' || $file->name === '..') {
|
||||
return false;
|
||||
}
|
||||
@ -64,11 +65,17 @@ protected static function boot(): void
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, covariant $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, covariant $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
class FirewallRule extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\FirewallRuleFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -47,9 +48,13 @@ public function getStatusColor(): string
|
||||
FirewallRuleStatus::DELETING => 'warning',
|
||||
FirewallRuleStatus::READY => 'success',
|
||||
FirewallRuleStatus::FAILED => 'danger',
|
||||
default => 'secondary',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, covariant $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
|
@ -10,15 +10,16 @@
|
||||
* @property int $site_id
|
||||
* @property int $source_control_id
|
||||
* @property string $secret
|
||||
* @property array $events
|
||||
* @property array $actions
|
||||
* @property array<string> $events
|
||||
* @property array<string, mixed> $actions
|
||||
* @property string $hook_id
|
||||
* @property array $hook_response
|
||||
* @property array<string, mixed> $hook_response
|
||||
* @property Site $site
|
||||
* @property SourceControl $sourceControl
|
||||
*/
|
||||
class GitHook extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\GitHookFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -39,11 +40,17 @@ class GitHook extends AbstractModel
|
||||
'hook_response' => 'json',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Site, covariant $this>
|
||||
*/
|
||||
public function site(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Site::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<SourceControl, covariant $this>
|
||||
*/
|
||||
public function sourceControl(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(SourceControl::class);
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
class LoadBalancerServer extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\LoadBalancerServerFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -32,6 +33,9 @@ class LoadBalancerServer extends AbstractModel
|
||||
'backup' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Site, covariant $this>
|
||||
*/
|
||||
public function loadBalancer(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Site::class, 'load_balancer_id');
|
||||
@ -39,6 +43,9 @@ public function loadBalancer(): BelongsTo
|
||||
|
||||
public function server(): ?Server
|
||||
{
|
||||
return $this->loadBalancer->project->servers()->where('local_ip', $this->ip)->first();
|
||||
/** @var ?Server $server */
|
||||
$server = $this->loadBalancer->project->servers()->where('local_ip', $this->ip)->first();
|
||||
|
||||
return $server;
|
||||
}
|
||||
}
|
||||
|
@ -10,13 +10,13 @@
|
||||
/**
|
||||
* @property int $id
|
||||
* @property int $server_id
|
||||
* @property float $load
|
||||
* @property float $memory_total
|
||||
* @property float $memory_used
|
||||
* @property float $memory_free
|
||||
* @property float $disk_total
|
||||
* @property float $disk_used
|
||||
* @property float $disk_free
|
||||
* @property ?float $load
|
||||
* @property ?float $memory_total
|
||||
* @property ?float $memory_used
|
||||
* @property ?float $memory_free
|
||||
* @property ?float $disk_total
|
||||
* @property ?float $disk_used
|
||||
* @property ?float $disk_free
|
||||
* @property-read float|int $memory_total_in_bytes
|
||||
* @property-read float|int $memory_used_in_bytes
|
||||
* @property-read float|int $memory_free_in_bytes
|
||||
@ -29,6 +29,7 @@
|
||||
*/
|
||||
class Metric extends Model
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\MetricFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -53,6 +54,9 @@ class Metric extends Model
|
||||
'disk_free' => 'float',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, covariant $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
@ -60,31 +64,31 @@ public function server(): BelongsTo
|
||||
|
||||
public function getMemoryTotalInBytesAttribute(): float|int
|
||||
{
|
||||
return $this->memory_total * 1024;
|
||||
return ($this->memory_total ?? 0) * 1024;
|
||||
}
|
||||
|
||||
public function getMemoryUsedInBytesAttribute(): float|int
|
||||
{
|
||||
return $this->memory_used * 1024;
|
||||
return ($this->memory_used ?? 0) * 1024;
|
||||
}
|
||||
|
||||
public function getMemoryFreeInBytesAttribute(): float|int
|
||||
{
|
||||
return $this->memory_free * 1024;
|
||||
return ($this->memory_free ?? 0) * 1024;
|
||||
}
|
||||
|
||||
public function getDiskTotalInBytesAttribute(): float|int
|
||||
{
|
||||
return $this->disk_total * (1024 * 1024);
|
||||
return ($this->disk_total ?? 0) * (1024 * 1024);
|
||||
}
|
||||
|
||||
public function getDiskUsedInBytesAttribute(): float|int
|
||||
{
|
||||
return $this->disk_used * (1024 * 1024);
|
||||
return ($this->disk_used ?? 0) * (1024 * 1024);
|
||||
}
|
||||
|
||||
public function getDiskFreeInBytesAttribute(): float|int
|
||||
{
|
||||
return $this->disk_free * (1024 * 1024);
|
||||
return ($this->disk_free ?? 0) * (1024 * 1024);
|
||||
}
|
||||
}
|
||||
|
@ -10,15 +10,17 @@
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string provider
|
||||
* @property array data
|
||||
* @property string label
|
||||
* @property bool connected
|
||||
* @property string $provider
|
||||
* @property array<string, mixed> $data
|
||||
* @property string $label
|
||||
* @property bool $connected
|
||||
* @property int $project_id
|
||||
*/
|
||||
class NotificationChannel extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\NotificationChannelFactory> */
|
||||
use HasFactory;
|
||||
|
||||
use Notifiable;
|
||||
|
||||
protected $fillable = [
|
||||
@ -41,7 +43,10 @@ public function provider(): \App\NotificationChannels\NotificationChannel
|
||||
{
|
||||
$class = config('core.notification_channels_providers_class')[$this->provider];
|
||||
|
||||
return new $class($this);
|
||||
/** @var \App\NotificationChannels\NotificationChannel $provider */
|
||||
$provider = new $class($this);
|
||||
|
||||
return $provider;
|
||||
}
|
||||
|
||||
public static function notifyAll(NotificationInterface $notification): void
|
||||
@ -52,16 +57,24 @@ public static function notifyAll(NotificationInterface $notification): void
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Project, covariant $this>
|
||||
*/
|
||||
public function project(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Project::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<NotificationChannel>
|
||||
*/
|
||||
public static function getByProjectId(int $projectId): Builder
|
||||
{
|
||||
return self::query()
|
||||
->where(function (Builder $query) use ($projectId) {
|
||||
$query->where('project_id', $projectId)->orWhereNull('project_id');
|
||||
});
|
||||
/** @var Builder<NotificationChannel> $query */
|
||||
$query = NotificationChannel::query();
|
||||
|
||||
return $query->where(function (Builder $query) use ($projectId): void {
|
||||
$query->where('project_id', $projectId)->orWhereNull('project_id');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
* @property int $tokenable_id
|
||||
* @property string $name
|
||||
* @property string $token
|
||||
* @property array $abilities
|
||||
* @property array<string> $abilities
|
||||
* @property Carbon $last_used_at
|
||||
* @property Carbon $created_at
|
||||
* @property Carbon $updated_at
|
||||
|
@ -18,14 +18,16 @@
|
||||
* @property Carbon $created_at
|
||||
* @property Carbon $updated_at
|
||||
* @property User $user
|
||||
* @property Collection<Server> $servers
|
||||
* @property Collection<User> $users
|
||||
* @property Collection<NotificationChannel> $notificationChannels
|
||||
* @property Collection<SourceControl> $sourceControls
|
||||
* @property Collection<int, Server> $servers
|
||||
* @property Collection<int, User> $users
|
||||
* @property Collection<int, NotificationChannel> $notificationChannels
|
||||
* @property Collection<int, SourceControl> $sourceControls
|
||||
*/
|
||||
class Project extends Model
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\ProjectFactory> */
|
||||
use HasFactory;
|
||||
|
||||
use HasTimezoneTimestamps;
|
||||
|
||||
protected $fillable = [
|
||||
@ -37,38 +39,57 @@ public static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::deleting(function (Project $project) {
|
||||
$project->servers()->each(function (Server $server) {
|
||||
static::deleting(function (Project $project): void {
|
||||
$project->servers()->each(function ($server): void {
|
||||
/** @var Server $server */
|
||||
$server->delete();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, covariant $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Server, covariant $this>
|
||||
*/
|
||||
public function servers(): HasMany
|
||||
{
|
||||
return $this->hasMany(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<NotificationChannel, covariant $this>
|
||||
*/
|
||||
public function notificationChannels(): HasMany
|
||||
{
|
||||
return $this->hasMany(NotificationChannel::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<User, covariant $this>
|
||||
*/
|
||||
public function users(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(User::class, 'user_project')->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<SourceControl, covariant $this>
|
||||
*/
|
||||
public function sourceControls(): HasMany
|
||||
{
|
||||
return $this->hasMany(SourceControl::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Tag, covariant $this>
|
||||
*/
|
||||
public function tags(): HasMany
|
||||
{
|
||||
return $this->hasMany(Tag::class);
|
||||
|
@ -3,6 +3,8 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\QueueStatus;
|
||||
use App\SSH\Services\ProcessManager\ProcessManager;
|
||||
use Database\Factories\QueueFactory;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@ -24,6 +26,7 @@
|
||||
*/
|
||||
class Queue extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<QueueFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -48,6 +51,9 @@ class Queue extends AbstractModel
|
||||
'redirect_stderr' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
QueueStatus::RUNNING => 'success',
|
||||
QueueStatus::CREATING => 'warning',
|
||||
@ -63,9 +69,14 @@ public static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::deleting(function (Queue $queue) {
|
||||
static::deleting(function (Queue $queue): void {
|
||||
try {
|
||||
$queue->server->processManager()->handler()->delete($queue->id, $queue->site_id);
|
||||
/** @var Service $service */
|
||||
$service = $queue->server->processManager();
|
||||
/** @var ProcessManager $handler */
|
||||
$handler = $service->handler();
|
||||
|
||||
$handler->delete($queue->id, $queue->site_id);
|
||||
} catch (Throwable $e) {
|
||||
Log::error($e);
|
||||
}
|
||||
@ -74,7 +85,7 @@ public static function boot(): void
|
||||
|
||||
public function getServerIdAttribute(int $value): int
|
||||
{
|
||||
if (! $value) {
|
||||
if ($value === 0) {
|
||||
$value = $this->site->server_id;
|
||||
$this->fill(['server_id' => $this->site->server_id]);
|
||||
$this->save();
|
||||
@ -83,11 +94,17 @@ public function getServerIdAttribute(int $value): int
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, covariant $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Site, covariant $this>
|
||||
*/
|
||||
public function site(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Site::class);
|
||||
|
@ -17,14 +17,15 @@
|
||||
* @property string $content
|
||||
* @property Carbon $created_at
|
||||
* @property Carbon $updated_at
|
||||
* @property Collection<ScriptExecution> $executions
|
||||
* @property Collection<int, ScriptExecution> $executions
|
||||
* @property ?ScriptExecution $lastExecution
|
||||
* @property User $user
|
||||
* @property int $project_id
|
||||
* @property ?int $project_id
|
||||
* @property ?Project $project
|
||||
*/
|
||||
class Script extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\ScriptFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -43,46 +44,65 @@ public static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::deleting(function (Script $script) {
|
||||
static::deleting(function (Script $script): void {
|
||||
$script->executions()->delete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, covariant $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Project, covariant $this>
|
||||
*/
|
||||
public function project(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Project::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
public function getVariables(): array
|
||||
{
|
||||
$variables = [];
|
||||
preg_match_all('/\${(.*?)}/', $this->content, $matches);
|
||||
foreach ($matches[1] as $match) {
|
||||
$variables[] = $match;
|
||||
}
|
||||
$variables = $matches[1];
|
||||
|
||||
return array_unique($variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<ScriptExecution, covariant $this>
|
||||
*/
|
||||
public function executions(): HasMany
|
||||
{
|
||||
return $this->hasMany(ScriptExecution::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne<ScriptExecution, covariant $this>
|
||||
*/
|
||||
public function lastExecution(): HasOne
|
||||
{
|
||||
return $this->hasOne(ScriptExecution::class)->latest();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<Script>
|
||||
*/
|
||||
public static function getByProjectId(int $projectId, int $userId): Builder
|
||||
{
|
||||
return self::query()
|
||||
->where(function (Builder $query) use ($projectId, $userId) {
|
||||
/** @var Builder<Script> $query */
|
||||
$query = static::query();
|
||||
|
||||
return $query
|
||||
->where(function (Builder $query) use ($projectId, $userId): void {
|
||||
$query->where('project_id', $projectId)
|
||||
->orWhere('user_id', $userId)
|
||||
->orWhereNull('project_id');
|
||||
|
@ -13,7 +13,7 @@
|
||||
* @property int $server_log_id
|
||||
* @property ?int $server_id
|
||||
* @property string $user
|
||||
* @property array $variables
|
||||
* @property array<mixed> $variables
|
||||
* @property string $status
|
||||
* @property Carbon $created_at
|
||||
* @property Carbon $updated_at
|
||||
@ -23,6 +23,7 @@
|
||||
*/
|
||||
class ScriptExecution extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\ScriptExecutionFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -41,12 +42,18 @@ class ScriptExecution extends AbstractModel
|
||||
'variables' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
ScriptExecutionStatus::EXECUTING => 'warning',
|
||||
ScriptExecutionStatus::COMPLETED => 'success',
|
||||
ScriptExecutionStatus::FAILED => 'danger',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Script, covariant $this>
|
||||
*/
|
||||
public function script(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Script::class);
|
||||
@ -56,7 +63,7 @@ public function getContent(): string
|
||||
{
|
||||
$content = $this->script->content;
|
||||
foreach ($this->variables as $variable => $value) {
|
||||
if (is_string($value) && ! empty($value)) {
|
||||
if (is_string($value) && ($value !== '' && $value !== '0')) {
|
||||
$content = str_replace('${'.$variable.'}', $value, $content);
|
||||
}
|
||||
}
|
||||
@ -64,11 +71,17 @@ public function getContent(): string
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<ServerLog, covariant $this>
|
||||
*/
|
||||
public function serverLog(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ServerLog::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, covariant $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
|
@ -19,6 +19,7 @@
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Illuminate\Filesystem\FilesystemAdapter;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@ -31,43 +32,43 @@
|
||||
* @property string $name
|
||||
* @property string $ssh_user
|
||||
* @property string $ip
|
||||
* @property string $local_ip
|
||||
* @property ?string $local_ip
|
||||
* @property int $port
|
||||
* @property string $os
|
||||
* @property string $type
|
||||
* @property array $type_data
|
||||
* @property array<string, mixed> $type_data
|
||||
* @property string $provider
|
||||
* @property int $provider_id
|
||||
* @property array $provider_data
|
||||
* @property array $authentication
|
||||
* @property array<string, mixed> $provider_data
|
||||
* @property array<string, mixed> $authentication
|
||||
* @property string $public_key
|
||||
* @property string $status
|
||||
* @property bool $auto_update
|
||||
* @property int $available_updates
|
||||
* @property int $security_updates
|
||||
* @property int $progress
|
||||
* @property string $progress_step
|
||||
* @property int|float $progress
|
||||
* @property ?string $progress_step
|
||||
* @property Project $project
|
||||
* @property User $creator
|
||||
* @property ServerProvider $serverProvider
|
||||
* @property ServerLog[] $logs
|
||||
* @property Site[] $sites
|
||||
* @property Service[] $services
|
||||
* @property Database[] $databases
|
||||
* @property DatabaseUser[] $databaseUsers
|
||||
* @property FirewallRule[] $firewallRules
|
||||
* @property CronJob[] $cronJobs
|
||||
* @property Queue[] $queues
|
||||
* @property Backup[] $backups
|
||||
* @property Queue[] $daemons
|
||||
* @property SshKey[] $sshKeys
|
||||
* @property Tag[] $tags
|
||||
* @property Collection<int, ServerLog> $logs
|
||||
* @property Collection<int, Site> $sites
|
||||
* @property Collection<int, Service> $services
|
||||
* @property Collection<int, Database> $databases
|
||||
* @property Collection<int, DatabaseUser> $databaseUsers
|
||||
* @property Collection<int, FirewallRule> $firewallRules
|
||||
* @property Collection<int, CronJob> $cronJobs
|
||||
* @property Collection<int, Queue> $queues
|
||||
* @property Collection<int, Backup> $backups
|
||||
* @property Collection<int, SshKey> $sshKeys
|
||||
* @property Collection<int, Tag> $tags
|
||||
* @property string $hostname
|
||||
* @property int $updates
|
||||
* @property Carbon $last_update_check
|
||||
* @property ?Carbon $last_update_check
|
||||
*/
|
||||
class Server extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\ServerFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -106,7 +107,7 @@ class Server extends AbstractModel
|
||||
'auto_update' => 'boolean',
|
||||
'available_updates' => 'integer',
|
||||
'security_updates' => 'integer',
|
||||
'progress' => 'integer',
|
||||
'progress' => 'float',
|
||||
'updates' => 'integer',
|
||||
'last_update_check' => 'datetime',
|
||||
];
|
||||
@ -119,17 +120,19 @@ public static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::deleting(function (Server $server) {
|
||||
static::deleting(function (Server $server): void {
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$server->sites()->each(function (Site $site) {
|
||||
$server->sites()->each(function ($site): void {
|
||||
/** @var Site $site */
|
||||
$site->queues()->delete();
|
||||
$site->ssls()->delete();
|
||||
$site->deployments()->delete();
|
||||
$site->deploymentScript()->delete();
|
||||
});
|
||||
$server->sites()->delete();
|
||||
$server->logs()->each(function (ServerLog $log) {
|
||||
$server->logs()->each(function ($log): void {
|
||||
/** @var ServerLog $log */
|
||||
$log->delete();
|
||||
});
|
||||
$server->services()->delete();
|
||||
@ -155,6 +158,9 @@ public static function boot(): void
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
ServerStatus::READY => 'success',
|
||||
ServerStatus::INSTALLING => 'warning',
|
||||
@ -178,76 +184,121 @@ public function isInstallationFailed(): bool
|
||||
return $this->status === ServerStatus::INSTALLATION_FAILED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Project, covariant $this>
|
||||
*/
|
||||
public function project(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Project::class, 'project_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, covariant $this>
|
||||
*/
|
||||
public function creator(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<ServerProvider, covariant $this>
|
||||
*/
|
||||
public function serverProvider(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ServerProvider::class, 'provider_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<ServerLog, covariant $this>
|
||||
*/
|
||||
public function logs(): HasMany
|
||||
{
|
||||
return $this->hasMany(ServerLog::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Site, covariant $this>
|
||||
*/
|
||||
public function sites(): HasMany
|
||||
{
|
||||
return $this->hasMany(Site::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Service, covariant $this>
|
||||
*/
|
||||
public function services(): HasMany
|
||||
{
|
||||
return $this->hasMany(Service::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Database, covariant $this>
|
||||
*/
|
||||
public function databases(): HasMany
|
||||
{
|
||||
return $this->hasMany(Database::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<DatabaseUser, covariant $this>
|
||||
*/
|
||||
public function databaseUsers(): HasMany
|
||||
{
|
||||
return $this->hasMany(DatabaseUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<FirewallRule, covariant $this>
|
||||
*/
|
||||
public function firewallRules(): HasMany
|
||||
{
|
||||
return $this->hasMany(FirewallRule::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<CronJob, covariant $this>
|
||||
*/
|
||||
public function cronJobs(): HasMany
|
||||
{
|
||||
return $this->hasMany(CronJob::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Queue, covariant $this>
|
||||
*/
|
||||
public function queues(): HasMany
|
||||
{
|
||||
return $this->hasMany(Queue::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Backup, covariant $this>
|
||||
*/
|
||||
public function backups(): HasMany
|
||||
{
|
||||
return $this->hasMany(Backup::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Queue, covariant $this>
|
||||
*/
|
||||
public function daemons(): HasMany
|
||||
{
|
||||
return $this->queues()->whereNull('site_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Metric, covariant $this>
|
||||
*/
|
||||
public function metrics(): HasMany
|
||||
{
|
||||
return $this->hasMany(Metric::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<SshKey, covariant $this>
|
||||
*/
|
||||
public function sshKeys(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(SshKey::class, 'server_ssh_keys')
|
||||
@ -255,6 +306,9 @@ public function sshKeys(): BelongsToMany
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MorphToMany<Tag, covariant $this>
|
||||
*/
|
||||
public function tags(): MorphToMany
|
||||
{
|
||||
return $this->morphToMany(Tag::class, 'taggable');
|
||||
@ -269,6 +323,9 @@ public function getSshUser(): string
|
||||
return config('core.ssh_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
public function getSshUsers(): array
|
||||
{
|
||||
$users = ['root', $this->getSshUser()];
|
||||
@ -278,11 +335,11 @@ public function getSshUsers(): array
|
||||
return array_unique($users);
|
||||
}
|
||||
|
||||
public function service($type, $version = null): ?Service
|
||||
public function service(string $type, mixed $version = null): ?Service
|
||||
{
|
||||
/* @var Service $service */
|
||||
/** @var ?Service $service */
|
||||
$service = $this->services()
|
||||
->where(function ($query) use ($type, $version) {
|
||||
->where(function ($query) use ($type, $version): void {
|
||||
$query->where('type', $type);
|
||||
if ($version) {
|
||||
$query->where('version', $version);
|
||||
@ -293,9 +350,9 @@ public function service($type, $version = null): ?Service
|
||||
return $service;
|
||||
}
|
||||
|
||||
public function defaultService($type): ?Service
|
||||
public function defaultService(string $type): ?Service
|
||||
{
|
||||
/* @var Service $service */
|
||||
/** @var ?Service $service */
|
||||
$service = $this->services()
|
||||
->where('type', $type)
|
||||
->where('is_default', 1)
|
||||
@ -303,13 +360,13 @@ public function defaultService($type): ?Service
|
||||
|
||||
// If no default service found, get the first service with status ready or stopped
|
||||
if (! $service) {
|
||||
/** @var Service $service */
|
||||
/** @var ?Service $service */
|
||||
$service = $this->services()
|
||||
->where('type', $type)
|
||||
->whereIn('status', [ServiceStatus::READY, ServiceStatus::STOPPED])
|
||||
->first();
|
||||
if ($service) {
|
||||
$service->is_default = 1;
|
||||
$service->is_default = true;
|
||||
$service->save();
|
||||
}
|
||||
}
|
||||
@ -322,10 +379,14 @@ public function ssh(?string $user = null): \App\Helpers\SSH|SSHFake
|
||||
return SSH::init($this, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function installedPHPVersions(): array
|
||||
{
|
||||
$versions = [];
|
||||
$phps = $this->services()->where('type', 'php')->get(['version']);
|
||||
/** @var Service $php */
|
||||
foreach ($phps as $php) {
|
||||
$versions[] = $php->version;
|
||||
}
|
||||
@ -333,10 +394,14 @@ public function installedPHPVersions(): array
|
||||
return $versions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function installedNodejsVersions(): array
|
||||
{
|
||||
$versions = [];
|
||||
$nodes = $this->services()->where('type', 'nodejs')->get(['version']);
|
||||
/** @var Service $node */
|
||||
foreach ($nodes as $node) {
|
||||
$versions[] = $node->version;
|
||||
}
|
||||
@ -348,19 +413,25 @@ public function type(): ServerType
|
||||
{
|
||||
$typeClass = config('core.server_types_class')[$this->type];
|
||||
|
||||
return new $typeClass($this);
|
||||
/** @var ServerType $type */
|
||||
$type = new $typeClass($this);
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
public function provider(): \App\ServerProviders\ServerProvider
|
||||
{
|
||||
$providerClass = config('core.server_providers_class')[$this->provider];
|
||||
|
||||
return new $providerClass($this->serverProvider, $this);
|
||||
/** @var \App\ServerProviders\ServerProvider $provider */
|
||||
$provider = new $providerClass($this->serverProvider ?? new ServerProvider, $this);
|
||||
|
||||
return $provider;
|
||||
}
|
||||
|
||||
public function webserver(?string $version = null): ?Service
|
||||
{
|
||||
if (! $version) {
|
||||
if ($version === null || $version === '' || $version === '0') {
|
||||
return $this->defaultService('webserver');
|
||||
}
|
||||
|
||||
@ -369,7 +440,7 @@ public function webserver(?string $version = null): ?Service
|
||||
|
||||
public function database(?string $version = null): ?Service
|
||||
{
|
||||
if (! $version) {
|
||||
if ($version === null || $version === '' || $version === '0') {
|
||||
return $this->defaultService('database');
|
||||
}
|
||||
|
||||
@ -378,7 +449,7 @@ public function database(?string $version = null): ?Service
|
||||
|
||||
public function firewall(?string $version = null): ?Service
|
||||
{
|
||||
if (! $version) {
|
||||
if ($version === null || $version === '' || $version === '0') {
|
||||
return $this->defaultService('firewall');
|
||||
}
|
||||
|
||||
@ -387,7 +458,7 @@ public function firewall(?string $version = null): ?Service
|
||||
|
||||
public function processManager(?string $version = null): ?Service
|
||||
{
|
||||
if (! $version) {
|
||||
if ($version === null || $version === '' || $version === '0') {
|
||||
return $this->defaultService('process_manager');
|
||||
}
|
||||
|
||||
@ -396,7 +467,7 @@ public function processManager(?string $version = null): ?Service
|
||||
|
||||
public function php(?string $version = null): ?Service
|
||||
{
|
||||
if (! $version) {
|
||||
if ($version === null || $version === '' || $version === '0') {
|
||||
return $this->defaultService('php');
|
||||
}
|
||||
|
||||
@ -405,7 +476,7 @@ public function php(?string $version = null): ?Service
|
||||
|
||||
public function nodejs(?string $version = null): ?Service
|
||||
{
|
||||
if (! $version) {
|
||||
if ($version === null || $version === '' || $version === '0') {
|
||||
return $this->defaultService('nodejs');
|
||||
}
|
||||
|
||||
@ -414,7 +485,7 @@ public function nodejs(?string $version = null): ?Service
|
||||
|
||||
public function memoryDatabase(?string $version = null): ?Service
|
||||
{
|
||||
if (! $version) {
|
||||
if ($version === null || $version === '' || $version === '0') {
|
||||
return $this->defaultService('memory_database');
|
||||
}
|
||||
|
||||
@ -423,20 +494,23 @@ public function memoryDatabase(?string $version = null): ?Service
|
||||
|
||||
public function monitoring(?string $version = null): ?Service
|
||||
{
|
||||
if (! $version) {
|
||||
if ($version === null || $version === '' || $version === '0') {
|
||||
return $this->defaultService('monitoring');
|
||||
}
|
||||
|
||||
return $this->service('monitoring', $version);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function sshKey(): array
|
||||
{
|
||||
/** @var FilesystemAdapter $storageDisk */
|
||||
$storageDisk = Storage::disk(config('core.key_pairs_disk'));
|
||||
|
||||
return [
|
||||
'public_key' => Str::replace("\n", '', Storage::disk(config('core.key_pairs_disk'))->get($this->id.'.pub')),
|
||||
'public_key' => str(Storage::disk(config('core.key_pairs_disk'))->get($this->id.'.pub'))->replace("\n", '')->toString(),
|
||||
'public_key_path' => $storageDisk->path($this->id.'.pub'),
|
||||
'private_key_path' => $storageDisk->path((string) $this->id),
|
||||
];
|
||||
@ -479,7 +553,7 @@ public function checkForUpdates(): void
|
||||
|
||||
public function getAvailableUpdatesAttribute(?int $value): int
|
||||
{
|
||||
if (! $value) {
|
||||
if ($value === null || $value === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Support\Facades\File;
|
||||
@ -18,12 +19,13 @@
|
||||
* @property string $type
|
||||
* @property string $name
|
||||
* @property string $disk
|
||||
* @property bool $is_remote
|
||||
* @property Server $server
|
||||
* @property ?Site $site
|
||||
* @property bool $is_remote
|
||||
*/
|
||||
class ServerLog extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\ServerLogFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -45,7 +47,7 @@ public static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::deleting(function (ServerLog $log) {
|
||||
self::deleting(function (ServerLog $log): void {
|
||||
if ($log->is_remote) {
|
||||
try {
|
||||
if (Storage::disk($log->disk)->exists($log->name)) {
|
||||
@ -63,11 +65,17 @@ public function getRouteKey(): string
|
||||
return 'log';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Site, $this>
|
||||
*/
|
||||
public function site(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Site::class);
|
||||
@ -84,7 +92,7 @@ public function download(): StreamedResponse
|
||||
|
||||
$this->server->ssh()->download($tmpPath, $this->name);
|
||||
|
||||
dispatch(function () use ($tmpPath) {
|
||||
dispatch(function () use ($tmpPath): void {
|
||||
if (File::exists($tmpPath)) {
|
||||
File::delete($tmpPath);
|
||||
}
|
||||
@ -98,18 +106,22 @@ public function download(): StreamedResponse
|
||||
return Storage::disk($this->disk)->download($this->name);
|
||||
}
|
||||
|
||||
public static function getRemote($query, bool $active = true, ?Site $site = null)
|
||||
/**
|
||||
* @param Builder<ServerLog> $query
|
||||
* @return Builder<ServerLog>
|
||||
*/
|
||||
public static function getRemote(Builder $query, bool $active = true, ?Site $site = null): Builder
|
||||
{
|
||||
$query->where('is_remote', $active);
|
||||
|
||||
if ($site) {
|
||||
if ($site instanceof \App\Models\Site) {
|
||||
$query->where('name', 'like', $site->path.'%');
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function write($buf): void
|
||||
public function write(string $buf): void
|
||||
{
|
||||
if (Str::contains($buf, 'VITO_SSH_ERROR')) {
|
||||
$buf = str_replace('VITO_SSH_ERROR', '', $buf);
|
||||
@ -121,14 +133,14 @@ public function write($buf): void
|
||||
}
|
||||
}
|
||||
|
||||
public function getContent($lines = null): ?string
|
||||
public function getContent(?int $lines = null): ?string
|
||||
{
|
||||
if ($this->is_remote) {
|
||||
return $this->server->os()->tail($this->name, $lines ?? 150);
|
||||
}
|
||||
|
||||
if (Storage::disk($this->disk)->exists($this->name)) {
|
||||
if ($lines) {
|
||||
if ($lines !== null && $lines !== 0) {
|
||||
return tail(Storage::disk($this->disk)->path($this->name), $lines);
|
||||
}
|
||||
|
||||
@ -140,9 +152,9 @@ public function getContent($lines = null): ?string
|
||||
return "Log file doesn't exist!";
|
||||
}
|
||||
|
||||
public static function log(Server $server, string $type, string $content, ?Site $site = null): static
|
||||
public static function log(Server $server, string $type, string $content, ?Site $site = null): ServerLog
|
||||
{
|
||||
$log = new static([
|
||||
$log = new self([
|
||||
'server_id' => $server->id,
|
||||
'site_id' => $site?->id,
|
||||
'name' => $server->id.'-'.strtotime('now').'-'.$type.'.log',
|
||||
@ -155,9 +167,9 @@ public static function log(Server $server, string $type, string $content, ?Site
|
||||
return $log;
|
||||
}
|
||||
|
||||
public static function make(Server $server, string $type): ServerLog
|
||||
public static function newLog(Server $server, string $type): ServerLog
|
||||
{
|
||||
return new static([
|
||||
return new self([
|
||||
'server_id' => $server->id,
|
||||
'name' => $server->id.'-'.strtotime('now').'-'.$type.'.log',
|
||||
'type' => $type,
|
||||
@ -169,11 +181,11 @@ public function forSite(Site|int $site): ServerLog
|
||||
{
|
||||
if ($site instanceof Site) {
|
||||
$site = $site->id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_int($site)) {
|
||||
$this->site_id = $site;
|
||||
}
|
||||
$this->site_id = $site;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -12,15 +12,16 @@
|
||||
* @property int $user_id
|
||||
* @property string $profile
|
||||
* @property string $provider
|
||||
* @property array $credentials
|
||||
* @property array<string, string> $credentials
|
||||
* @property bool $connected
|
||||
* @property User $user
|
||||
* @property ?int $project_id
|
||||
* @property Server[] $servers
|
||||
* @property Project $project
|
||||
* @property ?Project $project
|
||||
*/
|
||||
class ServerProvider extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\ServerProviderFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -39,16 +40,25 @@ class ServerProvider extends AbstractModel
|
||||
'project_id' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, covariant $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getCredentials(): array
|
||||
{
|
||||
return $this->credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Server, covariant $this>
|
||||
*/
|
||||
public function servers(): HasMany
|
||||
{
|
||||
return $this->hasMany(Server::class, 'provider_id');
|
||||
@ -58,25 +68,40 @@ public function provider(): \App\ServerProviders\ServerProvider
|
||||
{
|
||||
$providerClass = config('core.server_providers_class')[$this->provider];
|
||||
|
||||
return new $providerClass($this);
|
||||
/** @var \App\ServerProviders\ServerProvider $provider */
|
||||
$provider = new $providerClass($this, new Server);
|
||||
|
||||
return $provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Project, covariant $this>
|
||||
*/
|
||||
public function project(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Project::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<ServerProvider>
|
||||
*/
|
||||
public static function getByProjectId(int $projectId): Builder
|
||||
{
|
||||
return self::query()
|
||||
->where(function (Builder $query) use ($projectId) {
|
||||
/** @var Builder<ServerProvider> $query */
|
||||
$query = static::query();
|
||||
|
||||
return $query
|
||||
->where(function (Builder $query) use ($projectId): void {
|
||||
$query->where('project_id', $projectId)->orWhereNull('project_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
public static function regions(?int $id): array
|
||||
{
|
||||
if (! $id) {
|
||||
if ($id === null || $id === 0) {
|
||||
return [];
|
||||
}
|
||||
/** @var ?ServerProvider $profile */
|
||||
@ -95,9 +120,12 @@ public static function regions(?int $id): array
|
||||
return $regions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
public static function plans(?int $id, ?string $region): array
|
||||
{
|
||||
if (! $id) {
|
||||
if ($id === null || $id === 0) {
|
||||
return [];
|
||||
}
|
||||
$profile = self::find($id);
|
||||
|
@ -5,7 +5,11 @@
|
||||
use App\Actions\Service\Manage;
|
||||
use App\Enums\ServiceStatus;
|
||||
use App\Exceptions\ServiceInstallationFailed;
|
||||
use App\SSH\Services\Firewall\Firewall;
|
||||
use App\SSH\Services\PHP\PHP;
|
||||
use App\SSH\Services\ProcessManager\ProcessManager;
|
||||
use App\SSH\Services\ServiceInterface;
|
||||
use App\SSH\Services\Webserver\Webserver;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Support\Str;
|
||||
@ -13,7 +17,7 @@
|
||||
/**
|
||||
* @property int $server_id
|
||||
* @property string $type
|
||||
* @property array $type_data
|
||||
* @property array<string, mixed> $type_data
|
||||
* @property string $name
|
||||
* @property string $version
|
||||
* @property string $unit
|
||||
@ -24,6 +28,7 @@
|
||||
*/
|
||||
class Service extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\ServiceFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -48,13 +53,16 @@ public static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::creating(function (Service $service) {
|
||||
static::creating(function (Service $service): void {
|
||||
if (array_key_exists($service->name, config('core.service_units'))) {
|
||||
$service->unit = config('core.service_units')[$service->name][$service->server->os][$service->version];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
ServiceStatus::READY => 'success',
|
||||
ServiceStatus::INSTALLING => 'warning',
|
||||
@ -70,22 +78,28 @@ public static function boot(): void
|
||||
ServiceStatus::DISABLED => 'gray',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, covariant $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
public function handler(): ServiceInterface
|
||||
public function handler(): ServiceInterface|Webserver|PHP|Firewall|\App\SSH\Services\Database\Database|ProcessManager
|
||||
{
|
||||
$handler = config('core.service_handlers')[$this->name];
|
||||
|
||||
return new $handler($this);
|
||||
/** @var ServiceInterface $service */
|
||||
$service = new $handler($this);
|
||||
|
||||
return $service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ServiceInstallationFailed
|
||||
*/
|
||||
public function validateInstall($result): void
|
||||
public function validateInstall(string $result): void
|
||||
{
|
||||
if (! Str::contains($result, 'Active: active')) {
|
||||
throw new ServiceInstallationFailed;
|
||||
|
@ -22,9 +22,9 @@
|
||||
/**
|
||||
* @property int $server_id
|
||||
* @property string $type
|
||||
* @property array $type_data
|
||||
* @property array<string, string> $type_data
|
||||
* @property string $domain
|
||||
* @property array $aliases
|
||||
* @property array<int, string> $aliases
|
||||
* @property string $web_directory
|
||||
* @property string $path
|
||||
* @property string $php_version
|
||||
@ -39,23 +39,24 @@
|
||||
* @property string $user
|
||||
* @property bool $force_ssl
|
||||
* @property Server $server
|
||||
* @property ServerLog[] $logs
|
||||
* @property Deployment[] $deployments
|
||||
* @property Command[] $commands
|
||||
* @property Collection<int, ServerLog> $logs
|
||||
* @property Collection<int, Deployment> $deployments
|
||||
* @property Collection<int, Command> $commands
|
||||
* @property ?GitHook $gitHook
|
||||
* @property DeploymentScript $deploymentScript
|
||||
* @property Queue[] $queues
|
||||
* @property Ssl[] $ssls
|
||||
* @property ?DeploymentScript $deploymentScript
|
||||
* @property Collection<int, Queue> $queues
|
||||
* @property Collection<int, Ssl> $ssls
|
||||
* @property ?Ssl $activeSsl
|
||||
* @property string $ssh_key_name
|
||||
* @property ?SourceControl $sourceControl
|
||||
* @property Collection<LoadBalancerServer> $loadBalancerServers
|
||||
*
|
||||
* @TODO: Add nodejs_version column
|
||||
* @property Collection<int, LoadBalancerServer> $loadBalancerServers
|
||||
* @property Project $project
|
||||
*/
|
||||
class Site extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\SiteFactory> */
|
||||
use HasFactory;
|
||||
|
||||
use HasProjectThroughServer;
|
||||
|
||||
protected $fillable = [
|
||||
@ -89,6 +90,9 @@ class Site extends AbstractModel
|
||||
'force_ssl' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
SiteStatus::READY => 'success',
|
||||
SiteStatus::INSTALLING => 'warning',
|
||||
@ -100,14 +104,17 @@ public static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::deleting(function (Site $site) {
|
||||
$site->queues()->each(fn (Queue $queue) => $queue->delete());
|
||||
static::deleting(function (Site $site): void {
|
||||
$site->queues()->each(function ($queue): void {
|
||||
/** @var Queue $queue */
|
||||
$queue->delete();
|
||||
});
|
||||
$site->ssls()->delete();
|
||||
$site->deployments()->delete();
|
||||
$site->deploymentScript()->delete();
|
||||
});
|
||||
|
||||
static::created(function (Site $site) {
|
||||
static::created(function (Site $site): void {
|
||||
$site->deploymentScript()->create([
|
||||
'name' => 'default',
|
||||
'content' => '',
|
||||
@ -130,51 +137,81 @@ public function isInstallationFailed(): bool
|
||||
return $this->status === SiteStatus::INSTALLATION_FAILED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Server, covariant $this>
|
||||
*/
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<ServerLog, covariant $this>
|
||||
*/
|
||||
public function logs(): HasMany
|
||||
{
|
||||
return $this->hasMany(ServerLog::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Deployment, covariant $this>
|
||||
*/
|
||||
public function deployments(): HasMany
|
||||
{
|
||||
return $this->hasMany(Deployment::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Command, covariant $this>
|
||||
*/
|
||||
public function commands(): HasMany
|
||||
{
|
||||
return $this->hasMany(Command::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne<GitHook, covariant $this>
|
||||
*/
|
||||
public function gitHook(): HasOne
|
||||
{
|
||||
return $this->hasOne(GitHook::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne<DeploymentScript, covariant $this>
|
||||
*/
|
||||
public function deploymentScript(): HasOne
|
||||
{
|
||||
return $this->hasOne(DeploymentScript::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Queue, covariant $this>
|
||||
*/
|
||||
public function queues(): HasMany
|
||||
{
|
||||
return $this->hasMany(Queue::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Ssl, covariant $this>
|
||||
*/
|
||||
public function ssls(): HasMany
|
||||
{
|
||||
return $this->hasMany(Ssl::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MorphToMany<Tag, covariant $this>
|
||||
*/
|
||||
public function tags(): MorphToMany
|
||||
{
|
||||
return $this->morphToMany(Tag::class, 'taggable');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<SourceControl, covariant $this>
|
||||
*/
|
||||
public function sourceControl(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(SourceControl::class)->withTrashed();
|
||||
@ -198,7 +235,10 @@ public function type(): SiteType
|
||||
{
|
||||
$typeClass = config('core.site_types_class.'.$this->type);
|
||||
|
||||
return new $typeClass($this);
|
||||
/** @var SiteType $type */
|
||||
$type = new $typeClass($this);
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
public function php(): ?Service
|
||||
@ -213,23 +253,27 @@ public function php(): ?Service
|
||||
/**
|
||||
* @throws SSHError
|
||||
*/
|
||||
public function changePHPVersion($version): void
|
||||
public function changePHPVersion(string $version): void
|
||||
{
|
||||
/** @var Webserver $handler */
|
||||
$handler = $this->server->webserver()->handler();
|
||||
$handler->changePHPVersion($this, $version);
|
||||
$webserver = $this->webserver();
|
||||
$webserver->changePHPVersion($this, $version);
|
||||
|
||||
if ($this->isIsolated()) {
|
||||
/** @var PHP $php */
|
||||
$php = $this->server->php()->handler();
|
||||
$php->removeFpmPool($this->user, $this->php_version, $this->id);
|
||||
$php->createFpmPool($this->user, $version, $this->id);
|
||||
/** @var Service $php */
|
||||
$php = $this->server->php();
|
||||
/** @var PHP $phpHandler */
|
||||
$phpHandler = $php->handler();
|
||||
$phpHandler->removeFpmPool($this->user, $this->php_version, $this->id);
|
||||
$phpHandler->createFpmPool($this->user, $version);
|
||||
}
|
||||
|
||||
$this->php_version = $version;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne<Ssl, covariant $this>
|
||||
*/
|
||||
public function activeSsl(): HasOne
|
||||
{
|
||||
return $this->hasOne(Ssl::class)
|
||||
@ -318,6 +362,9 @@ public function getEnv(): string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function environmentVariables(?Deployment $deployment = null): array
|
||||
{
|
||||
return [
|
||||
@ -325,7 +372,7 @@ public function environmentVariables(?Deployment $deployment = null): array
|
||||
'DOMAIN' => $this->domain,
|
||||
'BRANCH' => $this->branch ?? '',
|
||||
'REPOSITORY' => $this->repository ?? '',
|
||||
'COMMIT_ID' => $deployment?->commit_id ?? '',
|
||||
'COMMIT_ID' => $deployment->commit_id ?? '',
|
||||
'PHP_VERSION' => $this->php_version,
|
||||
'PHP_PATH' => '/usr/bin/php'.$this->php_version,
|
||||
];
|
||||
@ -338,12 +385,18 @@ public function isIsolated(): bool
|
||||
|
||||
public function webserver(): Webserver
|
||||
{
|
||||
/** @var Webserver $webserver */
|
||||
$webserver = $this->server->webserver()->handler();
|
||||
/** @var Service $webserver */
|
||||
$webserver = $this->server->webserver();
|
||||
|
||||
return $webserver;
|
||||
/** @var Webserver $handler */
|
||||
$handler = $webserver->handler();
|
||||
|
||||
return $handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<LoadBalancerServer, covariant $this>
|
||||
*/
|
||||
public function loadBalancerServers(): HasMany
|
||||
{
|
||||
return $this->hasMany(LoadBalancerServer::class, 'load_balancer_id');
|
||||
|
@ -11,15 +11,17 @@
|
||||
|
||||
/**
|
||||
* @property string $provider
|
||||
* @property array $provider_data
|
||||
* @property ?string $profile
|
||||
* @property array<string, string> $provider_data
|
||||
* @property string $profile
|
||||
* @property ?string $url
|
||||
* @property string $access_token
|
||||
* @property ?int $project_id
|
||||
*/
|
||||
class SourceControl extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\SourceControlFactory> */
|
||||
use HasFactory;
|
||||
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
@ -41,28 +43,43 @@ public function provider(): SourceControlProvider
|
||||
{
|
||||
$providerClass = config('core.source_control_providers_class')[$this->provider];
|
||||
|
||||
return new $providerClass($this);
|
||||
/** @var SourceControlProvider $provider */
|
||||
$provider = new $providerClass($this);
|
||||
|
||||
return $provider;
|
||||
}
|
||||
|
||||
public function getRepo(?string $repo = null): ?array
|
||||
public function getRepo(string $repo): mixed
|
||||
{
|
||||
return $this->provider()->getRepo($repo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Site, covariant $this>
|
||||
*/
|
||||
public function sites(): HasMany
|
||||
{
|
||||
return $this->hasMany(Site::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Project, covariant $this>
|
||||
*/
|
||||
public function project(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Project::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<SourceControl>
|
||||
*/
|
||||
public static function getByProjectId(int $projectId): Builder
|
||||
{
|
||||
return self::query()
|
||||
->where(function (Builder $query) use ($projectId) {
|
||||
/** @var Builder<SourceControl> $query */
|
||||
$query = static::query();
|
||||
|
||||
return $query
|
||||
->where(function (Builder $query) use ($projectId): void {
|
||||
$query->where('project_id', $projectId)->orWhereNull('project_id');
|
||||
});
|
||||
}
|
||||
|
@ -16,7 +16,9 @@
|
||||
*/
|
||||
class SshKey extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\SshKeyFactory> */
|
||||
use HasFactory;
|
||||
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
@ -30,11 +32,17 @@ class SshKey extends AbstractModel
|
||||
'public_key' => 'encrypted',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, covariant $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<Server, covariant $this>
|
||||
*/
|
||||
public function servers(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Server::class, 'server_ssh_keys')
|
||||
|
@ -17,7 +17,7 @@
|
||||
* @property Carbon $expires_at
|
||||
* @property string $status
|
||||
* @property Site $site
|
||||
* @property ?array $domains
|
||||
* @property array<int, string>|string|null $domains
|
||||
* @property int $log_id
|
||||
* @property string $email
|
||||
* @property bool $is_active
|
||||
@ -28,6 +28,7 @@
|
||||
*/
|
||||
class Ssl extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\SslFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -58,6 +59,9 @@ class Ssl extends AbstractModel
|
||||
'is_active' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public static array $statusColors = [
|
||||
SslStatus::CREATED => 'success',
|
||||
SslStatus::CREATING => 'warning',
|
||||
@ -65,6 +69,9 @@ class Ssl extends AbstractModel
|
||||
SslStatus::FAILED => 'danger',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Site, covariant $this>
|
||||
*/
|
||||
public function site(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Site::class);
|
||||
@ -85,6 +92,9 @@ public function validateSetup(string $result): bool
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
public function getDomains(): array
|
||||
{
|
||||
if (! empty($this->domains) && is_array($this->domains)) {
|
||||
@ -97,6 +107,9 @@ public function getDomains(): array
|
||||
return $this->domains;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<ServerLog, covariant $this>
|
||||
*/
|
||||
public function log(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ServerLog::class);
|
||||
|
@ -11,12 +11,13 @@
|
||||
* @property int $user_id
|
||||
* @property string $profile
|
||||
* @property string $provider
|
||||
* @property array $credentials
|
||||
* @property array<string, string> $credentials
|
||||
* @property User $user
|
||||
* @property int $project_id
|
||||
* @property ?int $project_id
|
||||
*/
|
||||
class StorageProvider extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\StorageProviderFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -33,6 +34,9 @@ class StorageProvider extends AbstractModel
|
||||
'project_id' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, covariant $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
@ -42,23 +46,38 @@ public function provider(): \App\StorageProviders\StorageProvider
|
||||
{
|
||||
$providerClass = config('core.storage_providers_class')[$this->provider];
|
||||
|
||||
return new $providerClass($this);
|
||||
/** @var \App\StorageProviders\StorageProvider $provider */
|
||||
$provider = new $providerClass($this);
|
||||
|
||||
return $provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Backup, covariant $this>
|
||||
*/
|
||||
public function backups(): HasMany
|
||||
{
|
||||
return $this->hasMany(Backup::class, 'storage_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Project, covariant $this>
|
||||
*/
|
||||
public function project(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Project::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<StorageProvider>
|
||||
*/
|
||||
public static function getByProjectId(int $projectId): Builder
|
||||
{
|
||||
return self::query()
|
||||
->where(function (Builder $query) use ($projectId) {
|
||||
/** @var Builder<StorageProvider> $query */
|
||||
$query = static::query();
|
||||
|
||||
return $query
|
||||
->where(function (Builder $query) use ($projectId): void {
|
||||
$query->where('project_id', $projectId)->orWhereNull('project_id');
|
||||
});
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
class Tag extends AbstractModel
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\TagFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
@ -30,25 +31,40 @@ class Tag extends AbstractModel
|
||||
'project_id' => 'int',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Project, covariant $this>
|
||||
*/
|
||||
public function project(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Project::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MorphToMany<Server, covariant $this>
|
||||
*/
|
||||
public function servers(): MorphToMany
|
||||
{
|
||||
return $this->morphedByMany(Server::class, 'taggable');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MorphToMany<Site, covariant $this>
|
||||
*/
|
||||
public function sites(): MorphToMany
|
||||
{
|
||||
return $this->morphedByMany(Site::class, 'taggable');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<Tag>
|
||||
*/
|
||||
public static function getByProjectId(int $projectId): Builder
|
||||
{
|
||||
return self::query()
|
||||
->where(function (Builder $query) use ($projectId) {
|
||||
/** @var Builder<Tag> $query */
|
||||
$query = static::query();
|
||||
|
||||
return $query
|
||||
->where(function (Builder $query) use ($projectId): void {
|
||||
$query->where('project_id', $projectId)->orWhereNull('project_id');
|
||||
});
|
||||
}
|
||||
|
@ -26,18 +26,19 @@
|
||||
* @property string $profile_photo_path
|
||||
* @property string $two_factor_recovery_codes
|
||||
* @property string $two_factor_secret
|
||||
* @property SshKey[] $sshKeys
|
||||
* @property SourceControl[] $sourceControls
|
||||
* @property ServerProvider[] $serverProviders
|
||||
* @property Script[] $scripts
|
||||
* @property StorageProvider[] $storageProviders
|
||||
* @property StorageProvider[] $connectedStorageProviders
|
||||
* @property Collection $tokens
|
||||
* @property Collection<int, SshKey> $sshKeys
|
||||
* @property Collection<int, SourceControl> $sourceControls
|
||||
* @property Collection<int, ServerProvider> $serverProviders
|
||||
* @property Collection<int, Server> $servers
|
||||
* @property Collection<int, Script> $scripts
|
||||
* @property Collection<int, StorageProvider> $storageProviders
|
||||
* @property Collection<int, StorageProvider> $connectedStorageProviders
|
||||
* @property Collection<int, PersonalAccessToken> $tokens
|
||||
* @property string $profile_photo_url
|
||||
* @property string $timezone
|
||||
* @property int $current_project_id
|
||||
* @property Project $currentProject
|
||||
* @property Collection<Project> $projects
|
||||
* @property ?int $current_project_id
|
||||
* @property ?Project $currentProject
|
||||
* @property Collection<int, Project> $projects
|
||||
* @property string $role
|
||||
* @property Carbon $created_at
|
||||
* @property Carbon $updated_at
|
||||
@ -45,7 +46,10 @@
|
||||
class User extends Authenticatable implements FilamentUser
|
||||
{
|
||||
use HasApiTokens;
|
||||
|
||||
/** @use HasFactory<\Database\Factories\UserFactory> */
|
||||
use HasFactory;
|
||||
|
||||
use HasTimezoneTimestamps;
|
||||
use Notifiable;
|
||||
use TwoFactorAuthenticatable;
|
||||
@ -69,41 +73,65 @@ class User extends Authenticatable implements FilamentUser
|
||||
protected $appends = [
|
||||
];
|
||||
|
||||
/**
|
||||
* @return HasMany<Server, covariant $this>
|
||||
*/
|
||||
public function servers(): HasMany
|
||||
{
|
||||
return $this->hasMany(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<SshKey, covariant $this>
|
||||
*/
|
||||
public function sshKeys(): HasMany
|
||||
{
|
||||
return $this->hasMany(SshKey::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<SourceControl, covariant $this>
|
||||
*/
|
||||
public function sourceControls(): HasMany
|
||||
{
|
||||
return $this->hasMany(SourceControl::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<ServerProvider, covariant $this>
|
||||
*/
|
||||
public function serverProviders(): HasMany
|
||||
{
|
||||
return $this->hasMany(ServerProvider::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne<SourceControl, covariant $this>
|
||||
*/
|
||||
public function sourceControl(string $provider): HasOne
|
||||
{
|
||||
return $this->hasOne(SourceControl::class)->where('provider', $provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<StorageProvider, covariant $this>
|
||||
*/
|
||||
public function storageProviders(): HasMany
|
||||
{
|
||||
return $this->hasMany(StorageProvider::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne<StorageProvider, covariant $this>
|
||||
*/
|
||||
public function storageProvider(string $provider): HasOne
|
||||
{
|
||||
return $this->hasOne(StorageProvider::class)->where('provider', $provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<Project>|BelongsToMany<Project, covariant $this>
|
||||
*/
|
||||
public function allProjects(): Builder|BelongsToMany
|
||||
{
|
||||
if ($this->isAdmin()) {
|
||||
@ -113,12 +141,18 @@ public function allProjects(): Builder|BelongsToMany
|
||||
return $this->projects();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<Project, covariant $this>
|
||||
*/
|
||||
public function projects(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Project::class, 'user_project')
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne<Project, covariant $this>
|
||||
*/
|
||||
public function currentProject(): HasOne
|
||||
{
|
||||
return $this->HasOne(Project::class, 'id', 'current_project_id');
|
||||
@ -126,6 +160,7 @@ public function currentProject(): HasOne
|
||||
|
||||
public function createDefaultProject(): Project
|
||||
{
|
||||
/** @var ?Project $project */
|
||||
$project = $this->projects()->first();
|
||||
|
||||
if (! $project) {
|
||||
@ -147,15 +182,24 @@ public function isAdmin(): bool
|
||||
return $this->role === UserRole::ADMIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Script, covariant $this>
|
||||
*/
|
||||
public function scripts(): HasMany
|
||||
{
|
||||
return $this->hasMany(Script::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<Server>
|
||||
*/
|
||||
public function allServers(): Builder
|
||||
{
|
||||
return Server::query()->whereHas('project', function (Builder $query) {
|
||||
$query->whereHas('users', function ($query) {
|
||||
/** @var Builder<Server> $query */
|
||||
$query = Server::query();
|
||||
|
||||
return $query->whereHas('project', function (Builder $query): void {
|
||||
$query->whereHas('users', function ($query): void {
|
||||
$query->where('user_id', $this->id);
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user