API Feature (#334)

This commit is contained in:
Saeed Vaziry
2024-11-01 16:49:57 +01:00
committed by GitHub
parent da7b24640e
commit 417bf73e44
143 changed files with 36520 additions and 586 deletions

View File

@ -9,7 +9,7 @@
class CreateCronJob
{
public function create(Server $server, array $input): void
public function create(Server $server, array $input): CronJob
{
$cronJob = new CronJob([
'server_id' => $server->id,
@ -23,6 +23,8 @@ public function create(Server $server, array $input): void
$server->cron()->update($cronJob->user, CronJob::crontab($server, $cronJob->user));
$cronJob->status = CronjobStatus::READY;
$cronJob->save();
return $cronJob;
}
public static function rules(array $input): array

View File

@ -20,7 +20,7 @@ public function create(Server $server, array $input, array $links = []): Databas
'server_id' => $server->id,
'username' => $input['username'],
'password' => $input['password'],
'host' => isset($input['remote']) && $input['remote'] ? $input['host'] : 'localhost',
'host' => (isset($input['remote']) && $input['remote']) || isset($input['host']) ? $input['host'] : 'localhost',
'databases' => $links,
]);
/** @var Database $databaseHandler */

View File

@ -13,7 +13,7 @@ class LinkUser
/**
* @throws ValidationException
*/
public function link(DatabaseUser $databaseUser, array $input): void
public function link(DatabaseUser $databaseUser, array $input): DatabaseUser
{
if (! isset($input['databases']) || ! is_array($input['databases'])) {
$input['databases'] = [];
@ -43,6 +43,10 @@ public function link(DatabaseUser $databaseUser, array $input): void
);
$databaseUser->save();
$databaseUser->refresh();
return $databaseUser;
}
public static function rules(Server $server, array $input): array

View File

@ -6,28 +6,28 @@
use App\Enums\ServerProvider;
use App\Enums\ServerStatus;
use App\Facades\Notifier;
use App\Models\Project;
use App\Models\Server;
use App\Models\User;
use App\Notifications\ServerInstallationFailed;
use App\Notifications\ServerInstallationSucceed;
use App\ValidationRules\RestrictedIPAddressesRule;
use Exception;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
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
public function create(User $creator, Project $project, array $input): Server
{
$server = new Server([
'project_id' => $creator->currentProject->id,
'project_id' => $project->id,
'user_id' => $creator->id,
'name' => $input['name'],
'ssh_user' => config('core.server_providers_default_user')[$input['provider']][$input['os']],
@ -76,7 +76,9 @@ public function create(User $creator, array $input): Server
} catch (Exception $e) {
$server->provider()->delete();
DB::rollBack();
throw $e;
throw ValidationException::withMessages([
'provider' => $e->getMessage(),
]);
}
}
@ -112,7 +114,7 @@ function () use ($server) {
$bus->onConnection('ssh')->dispatch();
}
public static function rules(array $input): array
public static function rules(Project $project, array $input): array
{
$rules = [
'provider' => [
@ -132,15 +134,18 @@ public static function rules(array $input): array
],
'server_provider' => [
Rule::when(function () use ($input) {
return $input['provider'] != ServerProvider::CUSTOM;
return isset($input['provider']) && $input['provider'] != ServerProvider::CUSTOM;
}, [
'required',
'exists:server_providers,id,user_id,'.auth()->user()->id,
Rule::exists('server_providers', 'id')->where(function (Builder $query) use ($project) {
$query->where('project_id', $project->id)
->orWhereNull('project_id');
}),
]),
],
'ip' => [
Rule::when(function () use ($input) {
return $input['provider'] == ServerProvider::CUSTOM;
return isset($input['provider']) && $input['provider'] == ServerProvider::CUSTOM;
}, [
'required',
new RestrictedIPAddressesRule,
@ -148,7 +153,7 @@ public static function rules(array $input): array
],
'port' => [
Rule::when(function () use ($input) {
return $input['provider'] == ServerProvider::CUSTOM;
return isset($input['provider']) && $input['provider'] == ServerProvider::CUSTOM;
}, [
'required',
'numeric',
@ -176,6 +181,7 @@ private static function providerRules(array $input): array
{
if (
! isset($input['provider']) ||
! isset($input['server_provider']) ||
! in_array($input['provider'], config('core.server_providers')) ||
$input['provider'] == ServerProvider::CUSTOM
) {

View File

@ -2,6 +2,7 @@
namespace App\Actions\ServerProvider;
use App\Models\Project;
use App\Models\ServerProvider;
use App\Models\User;
use App\ServerProviders\ServerProvider as ServerProviderContract;
@ -14,7 +15,7 @@ class CreateServerProvider
/**
* @throws ValidationException
*/
public function create(User $user, array $input): ServerProvider
public function create(User $user, Project $project, array $input): ServerProvider
{
$provider = static::getProvider($input['provider']);
@ -33,7 +34,7 @@ public function create(User $user, array $input): ServerProvider
$serverProvider->profile = $input['name'];
$serverProvider->provider = $input['provider'];
$serverProvider->credentials = $provider->credentialData($input);
$serverProvider->project_id = isset($input['global']) && $input['global'] ? null : $user->current_project_id;
$serverProvider->project_id = isset($input['global']) && $input['global'] ? null : $project->id;
$serverProvider->save();
return $serverProvider;
@ -46,9 +47,9 @@ private static function getProvider($name): ServerProviderContract
return new $providerClass;
}
public static function rules(): array
public static function rules(array $input): array
{
return [
$rules = [
'name' => [
'required',
],
@ -58,10 +59,16 @@ public static function rules(): array
Rule::notIn('custom'),
],
];
return array_merge($rules, static::providerRules($input));
}
public static function providerRules(array $input): array
private static function providerRules(array $input): array
{
if (! isset($input['provider'])) {
return [];
}
return static::getProvider($input['provider'])->credentialValidationRules($input);
}
}

View File

@ -3,17 +3,16 @@
namespace App\Actions\ServerProvider;
use App\Models\ServerProvider;
use Exception;
use Illuminate\Validation\ValidationException;
class DeleteServerProvider
{
/**
* @throws Exception
*/
public function delete(ServerProvider $serverProvider): void
{
if ($serverProvider->servers()->exists()) {
throw new Exception('This server provider is being used by a server.');
throw ValidationException::withMessages([
'provider' => 'This server provider is being used by a server.',
]);
}
$serverProvider->delete();

View File

@ -2,17 +2,19 @@
namespace App\Actions\ServerProvider;
use App\Models\Project;
use App\Models\ServerProvider;
use App\Models\User;
class EditServerProvider
{
public function edit(ServerProvider $serverProvider, User $user, array $input): void
public function edit(ServerProvider $serverProvider, Project $project, array $input): ServerProvider
{
$serverProvider->profile = $input['name'];
$serverProvider->project_id = isset($input['global']) && $input['global'] ? null : $user->current_project_id;
$serverProvider->project_id = isset($input['global']) && $input['global'] ? null : $project->id;
$serverProvider->save();
return $serverProvider;
}
public static function rules(): array

View File

@ -8,6 +8,9 @@
class Uninstall
{
/*
* @TODO: Implement the uninstaller for all service handlers
*/
public function uninstall(Service $service): void
{
Validator::make([

View File

@ -19,9 +19,6 @@
class CreateSite
{
/**
* @throws SourceControlIsNotConnected
*/
public function create(Server $server, array $input): Site
{
DB::beginTransaction();
@ -88,13 +85,12 @@ public function create(Server $server, array $input): Site
return $site;
} catch (Exception $e) {
DB::rollBack();
throw $e;
throw ValidationException::withMessages([
'type' => $e->getMessage(),
]);
}
}
/**
* @throws ValidationException
*/
public static function rules(Server $server, array $input): array
{
$rules = [

View File

@ -2,6 +2,7 @@
namespace App\Actions\SourceControl;
use App\Models\Project;
use App\Models\SourceControl;
use App\Models\User;
use Illuminate\Support\Arr;
@ -10,13 +11,13 @@
class ConnectSourceControl
{
public function connect(User $user, array $input): void
public function connect(User $user, Project $project, array $input): SourceControl
{
$sourceControl = new SourceControl([
'provider' => $input['provider'],
'profile' => $input['name'],
'url' => Arr::has($input, 'url') ? $input['url'] : null,
'project_id' => isset($input['global']) && $input['global'] ? null : $user->current_project_id,
'project_id' => isset($input['global']) && $input['global'] ? null : $project->id,
]);
$sourceControl->provider_data = $sourceControl->provider()->createData($input);
@ -29,6 +30,8 @@ public function connect(User $user, array $input): void
}
$sourceControl->save();
return $sourceControl;
}
public static function rules(array $input): array

View File

@ -3,13 +3,16 @@
namespace App\Actions\SourceControl;
use App\Models\SourceControl;
use Illuminate\Validation\ValidationException;
class DeleteSourceControl
{
public function delete(SourceControl $sourceControl): void
{
if ($sourceControl->sites()->exists()) {
throw new \Exception('This source control is being used by a site.');
throw ValidationException::withMessages([
'source_control' => __('This source control is being used by a site.'),
]);
}
$sourceControl->delete();

View File

@ -2,59 +2,47 @@
namespace App\Actions\SourceControl;
use App\Models\Project;
use App\Models\SourceControl;
use App\Models\User;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
class EditSourceControl
{
public function edit(SourceControl $sourceControl, User $user, array $input): void
public function edit(SourceControl $sourceControl, Project $project, array $input): SourceControl
{
$sourceControl->profile = $input['name'];
$sourceControl->url = $input['url'] ?? null;
$sourceControl->project_id = isset($input['global']) && $input['global'] ? null : $user->current_project_id;
$sourceControl->project_id = isset($input['global']) && $input['global'] ? null : $project->id;
$sourceControl->provider_data = $sourceControl->provider()->createData($input);
$sourceControl->provider_data = $sourceControl->provider()->editData($input);
if (! $sourceControl->provider()->connect()) {
throw ValidationException::withMessages([
'token' => __('Cannot connect to :provider or invalid token!', ['provider' => $sourceControl->provider]
),
'token' => __('Cannot connect to :provider or invalid token!', ['provider' => $sourceControl->provider]),
]);
}
$sourceControl->save();
return $sourceControl;
}
public static function rules(array $input): array
public static function rules(SourceControl $sourceControl, array $input): array
{
$rules = [
'name' => [
'required',
],
'provider' => [
'required',
Rule::in(config('core.source_control_providers')),
],
];
return array_merge($rules, static::providerRules($input));
return array_merge($rules, static::providerRules($sourceControl, $input));
}
/**
* @throws ValidationException
*/
private static function providerRules(array $input): array
private static function providerRules(SourceControl $sourceControl, array $input): array
{
if (! isset($input['provider'])) {
return [];
}
$sourceControl = new SourceControl([
'provider' => $input['provider'],
]);
return $sourceControl->provider()->createRules($input);
return $sourceControl->provider()->editRules($input);
}
}

View File

@ -2,6 +2,7 @@
namespace App\Actions\StorageProvider;
use App\Models\Project;
use App\Models\StorageProvider;
use App\Models\User;
use Illuminate\Validation\Rule;
@ -12,13 +13,13 @@ class CreateStorageProvider
/**
* @throws ValidationException
*/
public function create(User $user, array $input): void
public function create(User $user, Project $project, array $input): StorageProvider
{
$storageProvider = new StorageProvider([
'user_id' => $user->id,
'provider' => $input['provider'],
'profile' => $input['name'],
'project_id' => isset($input['global']) && $input['global'] ? null : $user->current_project_id,
'project_id' => isset($input['global']) && $input['global'] ? null : $project->id,
]);
$storageProvider->credentials = $storageProvider->provider()->credentialData($input);
@ -36,6 +37,8 @@ public function create(User $user, array $input): void
}
$storageProvider->save();
return $storageProvider;
}
public static function rules(array $input): array

View File

@ -3,17 +3,16 @@
namespace App\Actions\StorageProvider;
use App\Models\StorageProvider;
use Exception;
use Illuminate\Validation\ValidationException;
class DeleteStorageProvider
{
/**
* @throws Exception
*/
public function delete(StorageProvider $storageProvider): void
{
if ($storageProvider->backups()->exists()) {
throw new Exception('This storage provider is being used by a backup.');
throw ValidationException::withMessages([
'provider' => __('This storage provider is being used by a backup.'),
]);
}
$storageProvider->delete();

View File

@ -2,18 +2,20 @@
namespace App\Actions\StorageProvider;
use App\Models\Project;
use App\Models\StorageProvider;
use App\Models\User;
use Illuminate\Validation\ValidationException;
class EditStorageProvider
{
public function edit(StorageProvider $storageProvider, User $user, array $input): void
public function edit(StorageProvider $storageProvider, Project $project, array $input): StorageProvider
{
$storageProvider->profile = $input['name'];
$storageProvider->project_id = isset($input['global']) && $input['global'] ? null : $user->current_project_id;
$storageProvider->project_id = isset($input['global']) && $input['global'] ? null : $project->id;
$storageProvider->save();
return $storageProvider;
}
/**

View File

@ -1,61 +0,0 @@
<?php
namespace App\Actions\Tag;
use App\Models\Server;
use App\Models\Site;
use App\Models\Tag;
use App\Models\User;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
/**
* @deprecated
*/
class AttachTag
{
public function attach(User $user, array $input): Tag
{
$this->validate($input);
/** @var Server|Site $taggable */
$taggable = $input['taggable_type']::findOrFail($input['taggable_id']);
$tag = Tag::query()->where('name', $input['name'])->first();
if ($tag) {
if (! $taggable->tags->contains($tag->id)) {
$taggable->tags()->attach($tag->id);
}
return $tag;
}
$tag = new Tag([
'project_id' => $user->currentProject->id,
'name' => $input['name'],
'color' => config('core.tag_colors')[array_rand(config('core.tag_colors'))],
]);
$tag->save();
$taggable->tags()->attach($tag->id);
return $tag;
}
private function validate(array $input): void
{
Validator::make($input, [
'name' => [
'required',
],
'taggable_id' => [
'required',
'integer',
],
'taggable_type' => [
'required',
Rule::in(config('core.taggable_types')),
],
])->validate();
}
}

View File

@ -1,39 +0,0 @@
<?php
namespace App\Actions\Tag;
use App\Models\Server;
use App\Models\Site;
use App\Models\Tag;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
/**
* @deprecated
*/
class DetachTag
{
public function detach(Tag $tag, array $input): void
{
$this->validate($input);
/** @var Server|Site $taggable */
$taggable = $input['taggable_type']::findOrFail($input['taggable_id']);
$taggable->tags()->detach($tag->id);
}
private function validate(array $input): void
{
Validator::make($input, [
'taggable_id' => [
'required',
'integer',
],
'taggable_type' => [
'required',
Rule::in(config('core.taggable_types')),
],
])->validate();
}
}