mirror of
https://github.com/vitodeploy/vito.git
synced 2025-07-01 05:56:16 +00:00
init
This commit is contained in:
85
app/Actions/Backup/CreateBackup.php
Normal file
85
app/Actions/Backup/CreateBackup.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Backup;
|
||||
|
||||
use App\Enums\DatabaseStatus;
|
||||
use App\Models\Backup;
|
||||
use App\Models\Database;
|
||||
use App\Models\Server;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateBackup
|
||||
{
|
||||
/**
|
||||
* @throws AuthorizationException
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function create($type, Server $server, User $user, array $input): Backup
|
||||
{
|
||||
$this->validate($type, $server, $user, $input);
|
||||
|
||||
if ($type == 'database') {
|
||||
Gate::forUser($user)->authorize('viewAny', [Database::class, $server]);
|
||||
}
|
||||
|
||||
$backup = new Backup([
|
||||
'name' => $input['name'],
|
||||
'type' => $type,
|
||||
'server_id' => $server->id,
|
||||
'database_id' => $input['database'] ?? null,
|
||||
'storage_id' => $input['storage'],
|
||||
'interval' => $input['interval'],
|
||||
'keep_backups' => $input['keep_backups'],
|
||||
'status' => 'running',
|
||||
]);
|
||||
$backup->save();
|
||||
|
||||
$backup->run();
|
||||
|
||||
return $backup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validate($type, Server $server, User $user, array $input): void
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required',
|
||||
'storage' => [
|
||||
'required',
|
||||
Rule::exists('storage_providers', 'id')
|
||||
->where('user_id', $user->id)
|
||||
->where('connected', 1),
|
||||
],
|
||||
'keep_backups' => [
|
||||
'required',
|
||||
'numeric',
|
||||
'min:1',
|
||||
],
|
||||
'interval' => [
|
||||
'required',
|
||||
Rule::in([
|
||||
'0 * * * *',
|
||||
'0 0 * * *',
|
||||
'0 0 * * 0',
|
||||
'0 0 1 * *',
|
||||
]),
|
||||
],
|
||||
];
|
||||
if ($type === 'database') {
|
||||
$rules['database'] = [
|
||||
'required',
|
||||
Rule::exists('databases', 'id')
|
||||
->where('server_id', $server->id)
|
||||
->where('status', DatabaseStatus::READY),
|
||||
];
|
||||
}
|
||||
Validator::make($input, $rules)->validateWithBag('createBackup');
|
||||
}
|
||||
}
|
48
app/Actions/CronJob/CreateCronJob.php
Executable file
48
app/Actions/CronJob/CreateCronJob.php
Executable file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\CronJob;
|
||||
|
||||
use App\Enums\CronjobStatus;
|
||||
use App\Models\CronJob;
|
||||
use App\Models\Server;
|
||||
use App\ValidationRules\CronRule;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateCronJob
|
||||
{
|
||||
public function create(Server $server, array $input): void
|
||||
{
|
||||
$this->validate($input);
|
||||
|
||||
$cronJob = new CronJob([
|
||||
'server_id' => $server->id,
|
||||
'user' => $input['user'],
|
||||
'command' => $input['command'],
|
||||
'frequency' => $input['frequency'],
|
||||
'status' => CronjobStatus::CREATING,
|
||||
]);
|
||||
$cronJob->save();
|
||||
$cronJob->addToServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validate(array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'command' => [
|
||||
'required',
|
||||
],
|
||||
'user' => [
|
||||
'required',
|
||||
'in:root,'.config('core.ssh_user'),
|
||||
],
|
||||
'frequency' => [
|
||||
'required',
|
||||
new CronRule(),
|
||||
],
|
||||
])->validateWithBag('createCronJob');
|
||||
}
|
||||
}
|
58
app/Actions/Database/CreateDatabase.php
Executable file
58
app/Actions/Database/CreateDatabase.php
Executable file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Database;
|
||||
|
||||
use App\Models\Database;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateDatabase
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function create(Server $server, array $input): Database
|
||||
{
|
||||
$this->validate($server, $input);
|
||||
|
||||
$database = new Database([
|
||||
'server_id' => $server->id,
|
||||
'name' => $input['name'],
|
||||
]);
|
||||
$database->save();
|
||||
$database->createOnServer();
|
||||
|
||||
return $database;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validate(Server $server, array $input): void
|
||||
{
|
||||
$rules = [
|
||||
'name' => [
|
||||
'required',
|
||||
'alpha_dash',
|
||||
Rule::unique('databases', 'name')->where('server_id', $server->id),
|
||||
],
|
||||
];
|
||||
if (isset($input['user']) && $input['user']) {
|
||||
$rules['username'] = [
|
||||
'required',
|
||||
'alpha_dash',
|
||||
Rule::unique('database_users', 'username')->where('server_id', $server->id),
|
||||
];
|
||||
$rules['password'] = [
|
||||
'required',
|
||||
'min:6',
|
||||
];
|
||||
}
|
||||
if (isset($input['remote']) && $input['remote']) {
|
||||
$rules['host'] = 'required';
|
||||
}
|
||||
Validator::make($input, $rules)->validate();
|
||||
}
|
||||
}
|
53
app/Actions/Database/CreateDatabaseUser.php
Executable file
53
app/Actions/Database/CreateDatabaseUser.php
Executable file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Database;
|
||||
|
||||
use App\Models\DatabaseUser;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateDatabaseUser
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function create(Server $server, array $input): DatabaseUser
|
||||
{
|
||||
$this->validate($server, $input);
|
||||
|
||||
$databaseUser = new DatabaseUser([
|
||||
'server_id' => $server->id,
|
||||
'username' => $input['username'],
|
||||
'password' => $input['password'],
|
||||
'host' => isset($input['remote']) && $input['remote'] ? $input['host'] : 'localhost',
|
||||
]);
|
||||
$databaseUser->save();
|
||||
$databaseUser->createOnServer();
|
||||
|
||||
return $databaseUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validate(Server $server, array $input): void
|
||||
{
|
||||
$rules = [
|
||||
'username' => [
|
||||
'required',
|
||||
'alpha_dash',
|
||||
Rule::unique('database_users', 'username')->where('server_id', $server->id),
|
||||
],
|
||||
'password' => [
|
||||
'required',
|
||||
'min:6',
|
||||
],
|
||||
];
|
||||
if (isset($input['remote']) && $input['remote']) {
|
||||
$rules['host'] = 'required';
|
||||
}
|
||||
Validator::make($input, $rules)->validate();
|
||||
}
|
||||
}
|
55
app/Actions/Database/InstallPHPMyAdmin.php
Normal file
55
app/Actions/Database/InstallPHPMyAdmin.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Database;
|
||||
|
||||
use App\Models\Server;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class InstallPHPMyAdmin
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function install(Server $server, array $input): Service
|
||||
{
|
||||
$this->validate($input);
|
||||
|
||||
$phpMyAdmin = $server->defaultService('phpmyadmin');
|
||||
if ($phpMyAdmin) {
|
||||
if ($phpMyAdmin->status === 'ready') {
|
||||
throw ValidationException::withMessages([
|
||||
'install' => __('Already installed'),
|
||||
])->errorBag('installPHPMyAdmin');
|
||||
}
|
||||
$phpMyAdmin->delete();
|
||||
}
|
||||
$phpMyAdmin = new Service([
|
||||
'server_id' => $server->id,
|
||||
'type' => 'phpmyadmin',
|
||||
'type_data' => [
|
||||
'allowed_ip' => $input['allowed_ip'],
|
||||
'php' => $server->defaultService('php')->version,
|
||||
],
|
||||
'name' => 'phpmyadmin',
|
||||
'version' => '5.1.2',
|
||||
'status' => 'installing',
|
||||
'is_default' => 1,
|
||||
]);
|
||||
$phpMyAdmin->save();
|
||||
$phpMyAdmin->install();
|
||||
|
||||
return $phpMyAdmin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validate(array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'allowed_ip' => 'required',
|
||||
])->validateWithBag('installPHPMyAdmin');
|
||||
}
|
||||
}
|
30
app/Actions/Database/LinkUser.php
Executable file
30
app/Actions/Database/LinkUser.php
Executable file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Database;
|
||||
|
||||
use App\Models\Database;
|
||||
use App\Models\DatabaseUser;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class LinkUser
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function link(DatabaseUser $databaseUser, array $databases): void
|
||||
{
|
||||
$dbs = Database::query()
|
||||
->where('server_id', $databaseUser->server_id)
|
||||
->whereIn('name', $databases)
|
||||
->count();
|
||||
if (count($databases) !== $dbs) {
|
||||
throw ValidationException::withMessages(['databases' => __('Databases not found!')])
|
||||
->errorBag('linkUser');
|
||||
}
|
||||
|
||||
$databaseUser->databases = $databases;
|
||||
$databaseUser->unlinkUser();
|
||||
$databaseUser->linkUser();
|
||||
$databaseUser->save();
|
||||
}
|
||||
}
|
64
app/Actions/FirewallRule/CreateRule.php
Executable file
64
app/Actions/FirewallRule/CreateRule.php
Executable file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\FirewallRule;
|
||||
|
||||
use App\Enums\FirewallRuleStatus;
|
||||
use App\Models\FirewallRule;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateRule
|
||||
{
|
||||
public function create(Server $server, array $input): FirewallRule
|
||||
{
|
||||
$this->validate($server, $input);
|
||||
|
||||
$rule = new FirewallRule([
|
||||
'server_id' => $server->id,
|
||||
'type' => $input['type'],
|
||||
'protocol' => $input['protocol'],
|
||||
'port' => $input['port'],
|
||||
'source' => $input['source'],
|
||||
'mask' => $input['mask'],
|
||||
'status' => FirewallRuleStatus::CREATING,
|
||||
]);
|
||||
$rule->save();
|
||||
$rule->addToServer();
|
||||
|
||||
return $rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validate(Server $server, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'type' => [
|
||||
'required',
|
||||
'in:allow,deny',
|
||||
],
|
||||
'protocol' => [
|
||||
'required',
|
||||
'in:'.implode(',', array_keys(config('core.firewall_protocols_port'))),
|
||||
],
|
||||
'port' => [
|
||||
'required',
|
||||
'numeric',
|
||||
'min:1',
|
||||
'max:65535',
|
||||
Rule::unique('firewall_rules', 'port')->where('server_id', $server->id),
|
||||
],
|
||||
'source' => [
|
||||
'required',
|
||||
'ip',
|
||||
],
|
||||
'mask' => [
|
||||
'required',
|
||||
'numeric',
|
||||
],
|
||||
])->validateWithBag('createRule');
|
||||
}
|
||||
}
|
55
app/Actions/NotificationChannels/AddChannel.php
Normal file
55
app/Actions/NotificationChannels/AddChannel.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\NotificationChannels;
|
||||
|
||||
use App\Models\NotificationChannel;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class AddChannel
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function add(User $user, array $input): void
|
||||
{
|
||||
$this->validate($input);
|
||||
$channel = new NotificationChannel([
|
||||
'user_id' => $user->id,
|
||||
'provider' => $input['provider'],
|
||||
'label' => $input['label'],
|
||||
]);
|
||||
$this->validateType($channel, $input);
|
||||
$channel->data = $channel->provider()->data($input);
|
||||
$channel->save();
|
||||
|
||||
if (! $channel->provider()->connect()) {
|
||||
$channel->delete();
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'provider' => __('Could not connect'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validate(array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'provider' => 'required|in:'.implode(',', config('core.notification_channels_providers')),
|
||||
'label' => 'required',
|
||||
])->validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validateType(NotificationChannel $channel, array $input): void
|
||||
{
|
||||
Validator::make($input, $channel->provider()->validationRules())
|
||||
->validate();
|
||||
}
|
||||
}
|
52
app/Actions/PHP/InstallNewPHP.php
Executable file
52
app/Actions/PHP/InstallNewPHP.php
Executable file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\PHP;
|
||||
|
||||
use App\Enums\ServiceStatus;
|
||||
use App\Models\Server;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class InstallNewPHP
|
||||
{
|
||||
public function install(Server $server, array $input): void
|
||||
{
|
||||
$this->validate($server, $input);
|
||||
|
||||
$php = new Service([
|
||||
'server_id' => $server->id,
|
||||
'type' => 'php',
|
||||
'type_data' => [
|
||||
'extensions' => [],
|
||||
'settings' => config('core.php_settings'),
|
||||
],
|
||||
'name' => 'php',
|
||||
'version' => $input['version'],
|
||||
'status' => ServiceStatus::INSTALLING,
|
||||
'is_default' => false,
|
||||
]);
|
||||
$php->save();
|
||||
$php->install();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validate(Server $server, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'version' => [
|
||||
'required',
|
||||
Rule::in(config('core.php_versions')),
|
||||
],
|
||||
])->validateWithBag('installPHP');
|
||||
|
||||
if (in_array($input['version'], $server->installedPHPVersions())) {
|
||||
throw ValidationException::withMessages(
|
||||
['version' => __('This version is already installed')]
|
||||
)->errorBag('installPHP');
|
||||
}
|
||||
}
|
||||
}
|
46
app/Actions/PHP/InstallPHPExtension.php
Executable file
46
app/Actions/PHP/InstallPHPExtension.php
Executable file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\PHP;
|
||||
|
||||
use App\Models\Service;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class InstallPHPExtension
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function handle(Service $service, array $input): Service
|
||||
{
|
||||
$typeData = $service->type_data;
|
||||
$typeData['extensions'] = $typeData['extensions'] ?? [];
|
||||
$service->type_data = $typeData;
|
||||
$service->save();
|
||||
|
||||
$this->validate($service, $input);
|
||||
|
||||
$service->handler()->installExtension($input['name']);
|
||||
|
||||
return $service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validate(Service $service, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'name' => [
|
||||
'required',
|
||||
'in:'.implode(',', config('core.php_extensions')),
|
||||
],
|
||||
])->validateWithBag('installPHPExtension');
|
||||
|
||||
if (in_array($input['name'], $service->type_data['extensions'])) {
|
||||
throw ValidationException::withMessages(
|
||||
['name' => __('This extension already installed')]
|
||||
)->errorBag('installPHPExtension');
|
||||
}
|
||||
}
|
||||
}
|
39
app/Actions/PHP/UninstallPHP.php
Executable file
39
app/Actions/PHP/UninstallPHP.php
Executable file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\PHP;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class UninstallPHP
|
||||
{
|
||||
public function uninstall(Server $server, string $version): void
|
||||
{
|
||||
$this->validate($server, $version);
|
||||
|
||||
$php = $server->services()->where('type', 'php')->where('version', $version)->first();
|
||||
|
||||
$php->uninstall();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validate(Server $server, string $version): void
|
||||
{
|
||||
$php = $server->services()->where('type', 'php')->where('version', $version)->first();
|
||||
|
||||
if (! $php) {
|
||||
throw ValidationException::withMessages(
|
||||
['version' => __('This version has not been installed yet!')]
|
||||
);
|
||||
}
|
||||
|
||||
$hasSite = $server->sites()->where('php_version', $version)->first();
|
||||
if ($hasSite) {
|
||||
throw ValidationException::withMessages(
|
||||
['version' => __('Cannot uninstall this version because some sites are using it!')]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
40
app/Actions/PHP/UpdatePHPIni.php
Executable file
40
app/Actions/PHP/UpdatePHPIni.php
Executable file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\PHP;
|
||||
|
||||
use App\Models\Service;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Throwable;
|
||||
|
||||
class UpdatePHPIni
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function update(Service $service, string $ini): void
|
||||
{
|
||||
$tmpName = Str::random(10).strtotime('now');
|
||||
try {
|
||||
Storage::disk('local')->put($tmpName, $ini);
|
||||
$service->server->ssh('root')->upload(
|
||||
Storage::disk('local')->path($tmpName),
|
||||
"/etc/php/$service->version/cli/php.ini"
|
||||
);
|
||||
$this->deleteTempFile($tmpName);
|
||||
} catch (Throwable) {
|
||||
$this->deleteTempFile($tmpName);
|
||||
throw ValidationException::withMessages([
|
||||
'ini' => __("Couldn't update php.ini file!"),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function deleteTempFile(string $name): void
|
||||
{
|
||||
if (Storage::disk('local')->exists($name)) {
|
||||
Storage::disk('local')->delete($name);
|
||||
}
|
||||
}
|
||||
}
|
65
app/Actions/Queue/CreateQueue.php
Normal file
65
app/Actions/Queue/CreateQueue.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Queue;
|
||||
|
||||
use App\Enums\QueueStatus;
|
||||
use App\Models\Queue;
|
||||
use App\Models\Server;
|
||||
use App\Models\Site;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateQueue
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function create(mixed $queueable, array $input): void
|
||||
{
|
||||
$this->validate($input);
|
||||
|
||||
$queue = new Queue([
|
||||
'server_id' => $queueable instanceof Server ? $queueable->id : $queueable->server_id,
|
||||
'site_id' => $queueable instanceof Site ? $queueable->id : null,
|
||||
'command' => $input['command'],
|
||||
'user' => $input['user'],
|
||||
'auto_start' => $input['auto_start'],
|
||||
'auto_restart' => $input['auto_restart'],
|
||||
'numprocs' => $input['numprocs'],
|
||||
'status' => QueueStatus::CREATING,
|
||||
]);
|
||||
$queue->save();
|
||||
$queue->deploy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validate(array $input): void
|
||||
{
|
||||
$rules = [
|
||||
'command' => [
|
||||
'required',
|
||||
],
|
||||
'user' => [
|
||||
'required',
|
||||
'in:root,'.config('core.ssh_user'),
|
||||
],
|
||||
'auto_start' => [
|
||||
'required',
|
||||
'in:0,1',
|
||||
],
|
||||
'auto_restart' => [
|
||||
'required',
|
||||
'in:0,1',
|
||||
],
|
||||
'numprocs' => [
|
||||
'required',
|
||||
'numeric',
|
||||
'min:1',
|
||||
],
|
||||
];
|
||||
|
||||
Validator::make($input, $rules)->validateWithBag('createQueue');
|
||||
}
|
||||
}
|
47
app/Actions/SSL/CreateSSL.php
Normal file
47
app/Actions/SSL/CreateSSL.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\SSL;
|
||||
|
||||
use App\Enums\SslType;
|
||||
use App\Models\Site;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateSSL
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function create(Site $site, array $input): void
|
||||
{
|
||||
$this->validate($input);
|
||||
|
||||
if ($input['type'] == SslType::LETSENCRYPT) {
|
||||
$site->createFreeSsl();
|
||||
}
|
||||
|
||||
if ($input['type'] == SslType::CUSTOM) {
|
||||
$site->createCustomSsl($input['certificate'], $input['private']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validate(array $input): void
|
||||
{
|
||||
$rules = [
|
||||
'type' => [
|
||||
'required',
|
||||
Rule::in(SslType::getValues()),
|
||||
],
|
||||
];
|
||||
if (isset($input['type']) && $input['type'] == SslType::CUSTOM) {
|
||||
$rules['certificate'] = 'required';
|
||||
$rules['private'] = 'required';
|
||||
}
|
||||
|
||||
Validator::make($input, $rules)->validateWithBag('createSSL');
|
||||
}
|
||||
}
|
41
app/Actions/Script/CreateScript.php
Normal file
41
app/Actions/Script/CreateScript.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Script;
|
||||
|
||||
use App\Models\Script;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateScript
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function handle(User $creator, array $input): Script
|
||||
{
|
||||
$this->validateInputs($input);
|
||||
|
||||
$script = new Script([
|
||||
'user_id' => $creator->id,
|
||||
'name' => $input['name'],
|
||||
'content' => $input['content'],
|
||||
]);
|
||||
$script->save();
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateInputs(array $input): void
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required',
|
||||
'content' => 'required',
|
||||
];
|
||||
|
||||
Validator::make($input, $rules)->validateWithBag('createScript');
|
||||
}
|
||||
}
|
17
app/Actions/Script/GetScripts.php
Executable file
17
app/Actions/Script/GetScripts.php
Executable file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Script;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
|
||||
class GetScripts
|
||||
{
|
||||
public function handle(User $user): LengthAwarePaginator
|
||||
{
|
||||
return $user->scripts()
|
||||
->orderBy('id', 'desc')
|
||||
->paginate(6)
|
||||
->onEachSide(1);
|
||||
}
|
||||
}
|
37
app/Actions/Script/UpdateScript.php
Normal file
37
app/Actions/Script/UpdateScript.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Script;
|
||||
|
||||
use App\Models\Script;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class UpdateScript
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function handle(Script $script, array $input): Script
|
||||
{
|
||||
$this->validateInputs($input);
|
||||
|
||||
$script->name = $input['name'];
|
||||
$script->content = $input['content'];
|
||||
$script->save();
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateInputs(array $input): void
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required',
|
||||
'content' => 'required',
|
||||
];
|
||||
|
||||
Validator::make($input, $rules)->validateWithBag('updateScript');
|
||||
}
|
||||
}
|
183
app/Actions/Server/CreateServer.php
Executable file
183
app/Actions/Server/CreateServer.php
Executable file
@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use App\Enums\FirewallRuleStatus;
|
||||
use App\Exceptions\ServerProviderError;
|
||||
use App\Jobs\Installation\ContinueInstallation;
|
||||
use App\Models\Server;
|
||||
use App\Models\User;
|
||||
use App\ValidationRules\RestrictedIPAddressesRule;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Throwable;
|
||||
|
||||
class CreateServer
|
||||
{
|
||||
/**
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function create(User $creator, array $input): Server
|
||||
{
|
||||
$this->validateInputs($input);
|
||||
|
||||
$server = new Server([
|
||||
'user_id' => $creator->id,
|
||||
'name' => $input['name'],
|
||||
'ssh_user' => config('core.server_providers_default_user')[$input['provider']][$input['os']],
|
||||
'ip' => $input['ip'],
|
||||
'port' => $input['port'] ?? 22,
|
||||
'os' => $input['os'],
|
||||
'type' => $input['type'],
|
||||
'provider' => $input['provider'],
|
||||
'authentication' => [
|
||||
'user' => config('core.ssh_user'),
|
||||
'pass' => Str::random(10),
|
||||
'root_pass' => Str::random(10),
|
||||
],
|
||||
'progress' => 0,
|
||||
'progress_step' => 'Initializing',
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
if ($server->provider != 'custom') {
|
||||
$server->provider_id = $input['server_provider'];
|
||||
}
|
||||
|
||||
// validate type
|
||||
$this->validateType($server, $input);
|
||||
$server->type_data = $server->type()->data($input);
|
||||
|
||||
// validate provider
|
||||
$this->validateProvider($server, $input);
|
||||
$server->provider_data = $server->provider()->data($input);
|
||||
|
||||
// save
|
||||
$server->save();
|
||||
|
||||
// create firewall rules
|
||||
$this->createFirewallRules($server);
|
||||
|
||||
// create instance
|
||||
$server->provider()->create();
|
||||
|
||||
// add services
|
||||
$server->type()->createServices($input);
|
||||
|
||||
// install server
|
||||
if ($server->provider == 'custom') {
|
||||
$server->install();
|
||||
} else {
|
||||
$server->progress_step = __('Installation will begin in 3 minutes!');
|
||||
$server->save();
|
||||
dispatch(new ContinueInstallation($server))
|
||||
->delay(now()->addMinutes(3))
|
||||
->onQueue('default');
|
||||
}
|
||||
DB::commit();
|
||||
|
||||
return $server;
|
||||
} catch (Exception $e) {
|
||||
$server->provider()->delete();
|
||||
DB::rollBack();
|
||||
if ($e instanceof ServerProviderError) {
|
||||
throw ValidationException::withMessages([
|
||||
'provider' => __('Provider Error: ').$e->getMessage(),
|
||||
])->errorBag('createServer');
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateInputs(array $input): void
|
||||
{
|
||||
$rules = [
|
||||
'provider' => 'required|in:'.implode(',', config('core.server_providers')),
|
||||
'name' => 'required',
|
||||
'os' => 'required|in:'.implode(',', config('core.operating_systems')),
|
||||
'type' => [
|
||||
'required',
|
||||
Rule::in(config('core.server_types')),
|
||||
],
|
||||
];
|
||||
|
||||
Validator::make($input, $rules)->validate();
|
||||
|
||||
if ($input['provider'] != 'custom') {
|
||||
$rules['server_provider'] = 'required|exists:server_providers,id,user_id,'.auth()->user()->id;
|
||||
}
|
||||
|
||||
if ($input['provider'] == 'custom') {
|
||||
$rules['ip'] = [
|
||||
'required',
|
||||
'ip',
|
||||
new RestrictedIPAddressesRule(),
|
||||
];
|
||||
$rules['port'] = [
|
||||
'required',
|
||||
'numeric',
|
||||
'min:1',
|
||||
'max:65535',
|
||||
];
|
||||
}
|
||||
|
||||
Validator::make($input, $rules)->validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateType(Server $server, array $input): void
|
||||
{
|
||||
Validator::make($input, $server->type()->createValidationRules($input))
|
||||
->validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateProvider(Server $server, array $input): void
|
||||
{
|
||||
Validator::make($input, $server->provider()->createValidationRules($input))
|
||||
->validate();
|
||||
}
|
||||
|
||||
private function createFirewallRules(Server $server): void
|
||||
{
|
||||
$server->firewallRules()->createMany([
|
||||
[
|
||||
'type' => 'allow',
|
||||
'protocol' => 'ssh',
|
||||
'port' => 22,
|
||||
'source' => '0.0.0.0',
|
||||
'mask' => 0,
|
||||
'status' => FirewallRuleStatus::READY,
|
||||
],
|
||||
[
|
||||
'type' => 'allow',
|
||||
'protocol' => 'http',
|
||||
'port' => 80,
|
||||
'source' => '0.0.0.0',
|
||||
'mask' => 0,
|
||||
'status' => FirewallRuleStatus::READY,
|
||||
],
|
||||
[
|
||||
'type' => 'allow',
|
||||
'protocol' => 'https',
|
||||
'port' => 443,
|
||||
'source' => '0.0.0.0',
|
||||
'mask' => 0,
|
||||
'status' => FirewallRuleStatus::READY,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
33
app/Actions/Server/DeleteServer.php
Executable file
33
app/Actions/Server/DeleteServer.php
Executable file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class DeleteServer
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function delete(Server $server, array $input): void
|
||||
{
|
||||
$this->validateDelete($input);
|
||||
|
||||
DB::transaction(function () use ($server) {
|
||||
$server->cleanDelete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validateDelete(array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'confirm' => 'required|in:delete',
|
||||
])->validateWithBag('deleteServer');
|
||||
}
|
||||
}
|
55
app/Actions/Server/EditServer.php
Executable file
55
app/Actions/Server/EditServer.php
Executable file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use App\Models\Server;
|
||||
use App\ValidationRules\RestrictedIPAddressesRule;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class EditServer
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function edit(Server $server, array $input): Server
|
||||
{
|
||||
$this->validate($input);
|
||||
|
||||
$checkConnection = false;
|
||||
if (isset($input['name'])) {
|
||||
$server->name = $input['name'];
|
||||
}
|
||||
if (isset($input['ip'])) {
|
||||
if ($server->ip !== $input['ip']) {
|
||||
$checkConnection = true;
|
||||
}
|
||||
$server->ip = $input['ip'];
|
||||
}
|
||||
if (isset($input['port'])) {
|
||||
if ($server->port !== $input['port']) {
|
||||
$checkConnection = true;
|
||||
}
|
||||
$server->port = $input['port'];
|
||||
}
|
||||
$server->save();
|
||||
|
||||
if ($checkConnection) {
|
||||
$server->checkConnection();
|
||||
}
|
||||
|
||||
return $server;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validate(array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'ip' => [
|
||||
new RestrictedIPAddressesRule(),
|
||||
],
|
||||
])->validateWithBag('editServer');
|
||||
}
|
||||
}
|
14
app/Actions/Server/GetServers.php
Executable file
14
app/Actions/Server/GetServers.php
Executable file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class GetServers
|
||||
{
|
||||
public function handle(): Collection
|
||||
{
|
||||
return Server::query()->latest()->get();
|
||||
}
|
||||
}
|
77
app/Actions/ServerProvider/CreateServerProvider.php
Normal file
77
app/Actions/ServerProvider/CreateServerProvider.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\ServerProvider;
|
||||
|
||||
use App\Contracts\ServerProvider as ServerProviderContract;
|
||||
use App\Models\ServerProvider;
|
||||
use App\Models\User;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateServerProvider
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function create(User $user, array $input): ServerProvider
|
||||
{
|
||||
$this->validateInput($input);
|
||||
|
||||
$provider = $this->getProvider($input['provider']);
|
||||
|
||||
$this->validateProvider($provider, $input);
|
||||
|
||||
try {
|
||||
$provider->connect($input);
|
||||
} catch (Exception) {
|
||||
throw ValidationException::withMessages([
|
||||
'provider' => [
|
||||
__("Couldn't connect to provider. Please check your credentials and try again later."),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
$serverProvider = new ServerProvider();
|
||||
$serverProvider->user_id = $user->id;
|
||||
$serverProvider->profile = $input['name'];
|
||||
$serverProvider->provider = $input['provider'];
|
||||
$serverProvider->credentials = $provider->credentialData($input);
|
||||
$serverProvider->save();
|
||||
|
||||
return $serverProvider;
|
||||
}
|
||||
|
||||
private function getProvider($name): ServerProviderContract
|
||||
{
|
||||
$providerClass = config('core.server_providers_class.'.$name);
|
||||
|
||||
return new $providerClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateInput(array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'name' => [
|
||||
'required',
|
||||
],
|
||||
'provider' => [
|
||||
'required',
|
||||
Rule::in(config('core.server_providers')),
|
||||
Rule::notIn('custom'),
|
||||
],
|
||||
])->validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateProvider(ServerProviderContract $provider, array $input): void
|
||||
{
|
||||
Validator::make($input, $provider->credentialValidationRules($input))->validate();
|
||||
}
|
||||
}
|
30
app/Actions/Site/ChangePHPVersion.php
Executable file
30
app/Actions/Site/ChangePHPVersion.php
Executable file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Site;
|
||||
|
||||
use App\Models\Site;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class ChangePHPVersion
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function handle(Site $site, array $input): void
|
||||
{
|
||||
$this->validate($site, $input);
|
||||
|
||||
$site->changePHPVersion($input['php_version']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validate(Site $site, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'php_version' => 'required|in:'.implode(',', $site->server->installedPHPVersions()),
|
||||
])->validateWithBag('changePHPVersion');
|
||||
}
|
||||
}
|
51
app/Actions/Site/CreateRedirect.php
Normal file
51
app/Actions/Site/CreateRedirect.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Site;
|
||||
|
||||
use App\Models\Redirect;
|
||||
use App\Models\Site;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateRedirect
|
||||
{
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function handle(Site $site, array $input): void
|
||||
{
|
||||
$this->validate($input);
|
||||
|
||||
$redirect = new Redirect([
|
||||
'site_id' => $site->id,
|
||||
'mode' => $input['mode'],
|
||||
'from' => $input['from'],
|
||||
'to' => $input['to'],
|
||||
]);
|
||||
$redirect->save();
|
||||
$redirect->addToServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validate(array $input): void
|
||||
{
|
||||
$rules = [
|
||||
'mode' => [
|
||||
'required',
|
||||
'in:301,302',
|
||||
],
|
||||
'from' => [
|
||||
'required',
|
||||
],
|
||||
'to' => [
|
||||
'required',
|
||||
'url',
|
||||
],
|
||||
];
|
||||
|
||||
Validator::make($input, $rules)->validateWithBag('createRedirect');
|
||||
}
|
||||
}
|
118
app/Actions/Site/CreateSite.php
Executable file
118
app/Actions/Site/CreateSite.php
Executable file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Site;
|
||||
|
||||
use App\Enums\SiteStatus;
|
||||
use App\Exceptions\SourceControlIsNotConnected;
|
||||
use App\Models\Server;
|
||||
use App\Models\Site;
|
||||
use App\ValidationRules\DomainRule;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateSite
|
||||
{
|
||||
/**
|
||||
* @throws SourceControlIsNotConnected
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function create(Server $server, array $input): Site
|
||||
{
|
||||
$this->validateInputs($server, $input);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$site = new Site([
|
||||
'server_id' => $server->id,
|
||||
'type' => $input['type'],
|
||||
'domain' => $input['domain'],
|
||||
'aliases' => isset($input['alias']) ? [$input['alias']] : [],
|
||||
'path' => '/home/'.$server->ssh_user.'/'.$input['domain'],
|
||||
'status' => SiteStatus::INSTALLING,
|
||||
]);
|
||||
|
||||
// fields based on type
|
||||
$site->fill($site->type()->createFields($input));
|
||||
|
||||
// check has access to repository
|
||||
try {
|
||||
if ($site->sourceControl()) {
|
||||
$site->sourceControl()->getRepo($site->repository);
|
||||
}
|
||||
} catch (SourceControlIsNotConnected) {
|
||||
throw ValidationException::withMessages([
|
||||
'source_control' => __('Source control is not connected'),
|
||||
]);
|
||||
}
|
||||
|
||||
// detect php version
|
||||
if ($site->type()->language() === 'php') {
|
||||
$site->php_version = $input['php_version'];
|
||||
}
|
||||
|
||||
// validate type
|
||||
$this->validateType($site, $input);
|
||||
|
||||
// set type data
|
||||
$site->type_data = $site->type()->data($input);
|
||||
|
||||
// save
|
||||
$site->save();
|
||||
|
||||
// create default deployment script
|
||||
$site->deploymentScript()->create([
|
||||
'name' => 'default',
|
||||
'content' => '',
|
||||
]);
|
||||
|
||||
// install server
|
||||
$site->install();
|
||||
|
||||
DB::commit();
|
||||
|
||||
return $site;
|
||||
} catch (Exception $e) {
|
||||
DB::rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateInputs(Server $server, array $input): void
|
||||
{
|
||||
$rules = [
|
||||
'type' => [
|
||||
'required',
|
||||
Rule::in(config('core.site_types')),
|
||||
],
|
||||
'domain' => [
|
||||
'required',
|
||||
new DomainRule(),
|
||||
Rule::unique('sites', 'domain')->where(function ($query) use ($server) {
|
||||
return $query->where('server_id', $server->id);
|
||||
}),
|
||||
],
|
||||
'alias' => [
|
||||
new DomainRule(),
|
||||
],
|
||||
];
|
||||
|
||||
Validator::make($input, $rules)->validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateType(Site $site, array $input): void
|
||||
{
|
||||
$rules = $site->type()->createValidationRules($input);
|
||||
|
||||
Validator::make($input, $rules)->validate();
|
||||
}
|
||||
}
|
32
app/Actions/Site/DeleteSite.php
Executable file
32
app/Actions/Site/DeleteSite.php
Executable file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Site;
|
||||
|
||||
use App\Models\Site;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class DeleteSite
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function handle(Site $site, array $input): void
|
||||
{
|
||||
$this->validateDelete($input);
|
||||
|
||||
$site->update(['status' => 'deleting']);
|
||||
|
||||
$site->remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validateDelete(array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'confirm' => 'required|in:delete',
|
||||
])->validateWithBag('deleteSite');
|
||||
}
|
||||
}
|
41
app/Actions/Site/EditSite.php
Executable file
41
app/Actions/Site/EditSite.php
Executable file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Site;
|
||||
|
||||
use App\Models\Site;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class EditSite
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function handle(Site $site, array $input): Site
|
||||
{
|
||||
// validate type
|
||||
$this->validateType($site, $input);
|
||||
|
||||
// set type data
|
||||
$site->type_data = $site->type()->data($input);
|
||||
|
||||
// save
|
||||
$site->port = $input['port'] ?? null;
|
||||
$site->save();
|
||||
|
||||
// edit
|
||||
$site->type()->edit();
|
||||
|
||||
return $site;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateType(Site $site, array $input): void
|
||||
{
|
||||
$rules = $site->type()->editValidationRules($input);
|
||||
|
||||
Validator::make($input, $rules)->validateWithBag('editSite');
|
||||
}
|
||||
}
|
14
app/Actions/Site/GetSites.php
Executable file
14
app/Actions/Site/GetSites.php
Executable file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Site;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class GetSites
|
||||
{
|
||||
public function handle(Server $server): Collection
|
||||
{
|
||||
return $server->sites()->orderBy('id', 'desc')->get();
|
||||
}
|
||||
}
|
30
app/Actions/Site/UpdateBranch.php
Executable file
30
app/Actions/Site/UpdateBranch.php
Executable file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Site;
|
||||
|
||||
use App\Models\Site;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class UpdateBranch
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function update(Site $site, array $input): void
|
||||
{
|
||||
$this->validate($input);
|
||||
|
||||
$site->updateBranch($input['branch']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validate(array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'branch' => 'required',
|
||||
])->validateWithBag('updateBranch');
|
||||
}
|
||||
}
|
32
app/Actions/Site/UpdateDeploymentScript.php
Executable file
32
app/Actions/Site/UpdateDeploymentScript.php
Executable file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Site;
|
||||
|
||||
use App\Models\Site;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class UpdateDeploymentScript
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function update(Site $site, array $input): void
|
||||
{
|
||||
$this->validate($input);
|
||||
|
||||
$site->deploymentScript()->update([
|
||||
'content' => $input['script'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validate(array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'script' => 'required',
|
||||
])->validateWithBag('updateDeploymentScript');
|
||||
}
|
||||
}
|
18
app/Actions/Site/UpdateEnv.php
Executable file
18
app/Actions/Site/UpdateEnv.php
Executable file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Site;
|
||||
|
||||
use App\Models\Site;
|
||||
|
||||
class UpdateEnv
|
||||
{
|
||||
public function handle(Site $site, array $input): void
|
||||
{
|
||||
$typeData = $site->type_data;
|
||||
$typeData['env'] = $input['env'];
|
||||
$site->type_data = $typeData;
|
||||
$site->save();
|
||||
|
||||
$site->deployEnv();
|
||||
}
|
||||
}
|
35
app/Actions/SourceControl/ConnectSourceControl.php
Normal file
35
app/Actions/SourceControl/ConnectSourceControl.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\SourceControl;
|
||||
|
||||
use App\Models\SourceControl;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class ConnectSourceControl
|
||||
{
|
||||
public function connect(string $provider, array $input): void
|
||||
{
|
||||
$sourceControl = SourceControl::query()
|
||||
->where('provider', $provider)
|
||||
->first();
|
||||
if (! $sourceControl) {
|
||||
$sourceControl = new SourceControl([
|
||||
'provider' => $provider,
|
||||
]);
|
||||
}
|
||||
|
||||
if (! $input['token']) {
|
||||
$sourceControl->delete();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$sourceControl->access_token = $input['token'];
|
||||
if (! $sourceControl->provider()->connect()) {
|
||||
throw ValidationException::withMessages([
|
||||
'token' => __('Cannot connect to :provider or invalid token!', ['provider' => $provider]),
|
||||
]);
|
||||
}
|
||||
$sourceControl->save();
|
||||
}
|
||||
}
|
43
app/Actions/SshKey/CreateSshKey.php
Normal file
43
app/Actions/SshKey/CreateSshKey.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\SshKey;
|
||||
|
||||
use App\Models\SshKey;
|
||||
use App\Models\User;
|
||||
use App\ValidationRules\SshKeyRule;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class CreateSshKey
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function create(User $user, array $input): SshKey
|
||||
{
|
||||
$this->validate($input);
|
||||
|
||||
$key = new SshKey([
|
||||
'user_id' => $user->id,
|
||||
'name' => $input['name'],
|
||||
'public_key' => $input['public_key'],
|
||||
]);
|
||||
$key->save();
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validate(array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'name' => 'required',
|
||||
'public_key' => [
|
||||
'required',
|
||||
new SshKeyRule(),
|
||||
],
|
||||
])->validate();
|
||||
}
|
||||
}
|
30
app/Actions/StorageProvider/AddStorageProvider.php
Normal file
30
app/Actions/StorageProvider/AddStorageProvider.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\StorageProvider;
|
||||
|
||||
use App\Models\StorageProvider;
|
||||
use App\Models\User;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class AddStorageProvider
|
||||
{
|
||||
use ValidateProvider;
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function add(User $user, array $input): mixed
|
||||
{
|
||||
$this->validate($user, $input);
|
||||
|
||||
$storageProvider = new StorageProvider([
|
||||
'user_id' => $user->id,
|
||||
'provider' => $input['provider'],
|
||||
'label' => $input['label'],
|
||||
'connected' => false,
|
||||
]);
|
||||
$storageProvider->save();
|
||||
|
||||
return $storageProvider->provider()->connect();
|
||||
}
|
||||
}
|
34
app/Actions/StorageProvider/HandleProviderCallback.php
Executable file
34
app/Actions/StorageProvider/HandleProviderCallback.php
Executable file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\StorageProvider;
|
||||
|
||||
use App\Models\StorageProvider;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
use Laravel\Socialite\Two\User;
|
||||
use Throwable;
|
||||
|
||||
class HandleProviderCallback
|
||||
{
|
||||
public function callback(Request $request, string $provider): string|RedirectResponse
|
||||
{
|
||||
try {
|
||||
$providerId = $request->session()->get('storage_provider_id');
|
||||
/** @var StorageProvider $storageProvider */
|
||||
$storageProvider = StorageProvider::query()->findOrFail($providerId);
|
||||
/** @var User $oauthUser */
|
||||
$oauthUser = Socialite::driver($provider)->user();
|
||||
$storageProvider->token = $oauthUser->token;
|
||||
$storageProvider->refresh_token = $oauthUser->refreshToken;
|
||||
$storageProvider->token_expires_at = now()->addSeconds($oauthUser->expiresIn);
|
||||
$storageProvider->connected = true;
|
||||
$storageProvider->save();
|
||||
/** @TODO toast success message */
|
||||
} catch (Throwable) {
|
||||
/** @TODO toast failed message */
|
||||
}
|
||||
|
||||
return redirect()->route('storage-providers');
|
||||
}
|
||||
}
|
28
app/Actions/StorageProvider/ValidateProvider.php
Executable file
28
app/Actions/StorageProvider/ValidateProvider.php
Executable file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\StorageProvider;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
trait ValidateProvider
|
||||
{
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validate(User $user, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'label' => [
|
||||
'required',
|
||||
Rule::unique('storage_providers', 'label')->where('user_id', $user->id),
|
||||
],
|
||||
'provider' => [
|
||||
'required',
|
||||
Rule::in(config('core.storage_providers')),
|
||||
],
|
||||
])->validateWithBag('addStorageProvider');
|
||||
}
|
||||
}
|
25
app/Actions/User/UpdateUserPassword.php
Executable file
25
app/Actions/User/UpdateUserPassword.php
Executable file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\User;
|
||||
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class UpdateUserPassword
|
||||
{
|
||||
/**
|
||||
* Validate and update the user's password.
|
||||
*/
|
||||
public function update($user, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'current_password' => ['required', 'string', 'current-password'],
|
||||
'password' => ['required', 'string'],
|
||||
'password_confirmation' => ['required', 'same:password'],
|
||||
])->validate();
|
||||
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($input['password']),
|
||||
])->save();
|
||||
}
|
||||
}
|
44
app/Actions/User/UpdateUserProfileInformation.php
Executable file
44
app/Actions/User/UpdateUserProfileInformation.php
Executable file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\User;
|
||||
|
||||
use App\Models\User;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateUserProfileInformation
|
||||
{
|
||||
/**
|
||||
* Validate and update the given user's profile information.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function update(User $user, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
|
||||
])->validateWithBag('updateProfileInformation');
|
||||
|
||||
if ($input['email'] !== $user->email) {
|
||||
$this->updateVerifiedUser($user, $input);
|
||||
} else {
|
||||
$user->forceFill([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given verified user's profile information.
|
||||
*/
|
||||
protected function updateVerifiedUser(User $user, array $input): void
|
||||
{
|
||||
$user->forceFill([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
])->save();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user