Compare commits

..

9 Commits
1.8.0 ... 1.9.0

136 changed files with 1738 additions and 2213 deletions

View File

@ -102,7 +102,7 @@ private function getInterval(array $input): Expression
)->diffInHours();
}
if ($periodInHours <= 1) {
if (abs($periodInHours) <= 1) {
return DB::raw("strftime('%Y-%m-%d %H:%M:00', created_at) as date_interval");
}

View File

@ -19,6 +19,7 @@ public function add(User $user, array $input): void
'user_id' => $user->id,
'provider' => $input['provider'],
'label' => $input['label'],
'project_id' => isset($input['global']) && $input['global'] ? null : $user->current_project_id,
]);
$this->validateType($channel, $input);
$channel->data = $channel->provider()->createData($input);

View File

@ -0,0 +1,34 @@
<?php
namespace App\Actions\NotificationChannels;
use App\Models\NotificationChannel;
use App\Models\User;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class EditChannel
{
public function edit(NotificationChannel $notificationChannel, User $user, array $input): void
{
$this->validate($input);
$notificationChannel->label = $input['label'];
$notificationChannel->project_id = isset($input['global']) && $input['global'] ? null : $user->current_project_id;
$notificationChannel->save();
}
/**
* @throws ValidationException
*/
private function validate(array $input): void
{
$rules = [
'label' => [
'required',
],
];
Validator::make($input, $rules)->validate();
}
}

View File

@ -2,8 +2,11 @@
namespace App\Actions\PHP;
use App\Enums\PHPIniType;
use App\Models\Server;
use App\SSH\Services\PHP\PHP;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
class GetPHPIni
@ -18,7 +21,7 @@ public function getIni(Server $server, array $input): string
/** @var PHP $handler */
$handler = $php->handler();
return $handler->getPHPIni();
return $handler->getPHPIni($input['type']);
} catch (\Throwable $e) {
throw ValidationException::withMessages(
['ini' => $e->getMessage()]
@ -28,6 +31,13 @@ public function getIni(Server $server, array $input): string
public function validate(Server $server, array $input): void
{
Validator::make($input, [
'type' => [
'required',
Rule::in([PHPIniType::CLI, PHPIniType::FPM]),
],
])->validate();
if (! isset($input['version']) || ! in_array($input['version'], $server->installedPHPVersions())) {
throw ValidationException::withMessages(
['version' => __('This version is not installed')]

View File

@ -2,10 +2,13 @@
namespace App\Actions\PHP;
use App\Enums\PHPIniType;
use App\Models\Server;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Throwable;
@ -22,19 +25,19 @@ public function update(Server $server, array $input): void
$tmpName = Str::random(10).strtotime('now');
try {
/** @var \Illuminate\Filesystem\FilesystemAdapter $storageDisk */
/** @var FilesystemAdapter $storageDisk */
$storageDisk = Storage::disk('local');
$storageDisk->put($tmpName, $input['ini']);
$service->server->ssh('root')->upload(
$storageDisk->path($tmpName),
"/etc/php/$service->version/cli/php.ini"
sprintf('/etc/php/%s/%s/php.ini', $service->version, $input['type'])
);
$this->deleteTempFile($tmpName);
} catch (Throwable) {
$this->deleteTempFile($tmpName);
throw ValidationException::withMessages([
'ini' => __("Couldn't update php.ini file!"),
'ini' => __("Couldn't update php.ini (:type) file!", ['type' => $input['type']]),
]);
}
@ -56,6 +59,10 @@ public function validate(Server $server, array $input): void
'string',
],
'version' => 'required|string',
'type' => [
'required',
Rule::in([PHPIniType::CLI, PHPIniType::FPM]),
],
])->validate();
if (! in_array($input['version'], $server->installedPHPVersions())) {

View File

@ -38,6 +38,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->save();
return $serverProvider;

View File

@ -0,0 +1,34 @@
<?php
namespace App\Actions\ServerProvider;
use App\Models\ServerProvider;
use App\Models\User;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class EditServerProvider
{
public function edit(ServerProvider $serverProvider, User $user, array $input): void
{
$this->validate($input);
$serverProvider->profile = $input['name'];
$serverProvider->project_id = isset($input['global']) && $input['global'] ? null : $user->current_project_id;
$serverProvider->save();
}
/**
* @throws ValidationException
*/
private function validate(array $input): void
{
$rules = [
'name' => [
'required',
],
];
Validator::make($input, $rules)->validate();
}
}

View File

@ -14,7 +14,7 @@ public function edit(SourceControl $sourceControl, User $user, array $input): vo
$this->validate($input);
$sourceControl->profile = $input['name'];
$sourceControl->url = isset($input['url']) ? $input['url'] : null;
$sourceControl->url = $input['url'] ?? null;
$sourceControl->project_id = isset($input['global']) && $input['global'] ? null : $user->current_project_id;
$this->validateProvider($sourceControl, $input);

View File

@ -21,6 +21,7 @@ public function create(User $user, array $input): void
'user_id' => $user->id,
'provider' => $input['provider'],
'profile' => $input['name'],
'project_id' => isset($input['global']) && $input['global'] ? null : $user->current_project_id,
]);
$this->validateProvider($input, $storageProvider->provider()->validationRules());

View File

@ -0,0 +1,34 @@
<?php
namespace App\Actions\StorageProvider;
use App\Models\StorageProvider;
use App\Models\User;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class EditStorageProvider
{
public function edit(StorageProvider $storageProvider, User $user, array $input): void
{
$this->validate($input);
$storageProvider->profile = $input['name'];
$storageProvider->project_id = isset($input['global']) && $input['global'] ? null : $user->current_project_id;
$storageProvider->save();
}
/**
* @throws ValidationException
*/
private function validate(array $input): void
{
$rules = [
'name' => [
'required',
],
];
Validator::make($input, $rules)->validate();
}
}

10
app/Enums/PHPIniType.php Normal file
View File

@ -0,0 +1,10 @@
<?php
namespace App\Enums;
final class PHPIniType
{
const CLI = 'cli';
const FPM = 'fpm';
}

View File

@ -4,6 +4,4 @@
use Exception;
class DeploymentScriptIsEmptyException extends Exception
{
}
class DeploymentScriptIsEmptyException extends Exception {}

View File

@ -4,6 +4,4 @@
use Exception;
class SourceControlIsNotConnected extends Exception
{
}
class SourceControlIsNotConnected extends Exception {}

View File

@ -81,7 +81,7 @@ public function updateIni(Server $server, Request $request): RedirectResponse
app(UpdatePHPIni::class)->update($server, $request->input());
Toast::success('PHP ini updated!');
Toast::success(__('PHP ini (:type) updated!', ['type' => $request->input('type')]));
return back()->with([
'ini' => $request->input('ini'),

View File

@ -29,7 +29,7 @@ public function store(Server $server, Request $request): HtmxResponse
{
$this->authorize('manage', $server);
/** @var \App\Models\SshKey $key */
/** @var SshKey $key */
$key = app(CreateSshKey::class)->create(
$request->user(),
$request->input()

View File

@ -35,7 +35,9 @@ public function create(Request $request): View
$this->authorize('create', [Server::class, $user->currentProject]);
$provider = $request->query('provider', old('provider', \App\Enums\ServerProvider::CUSTOM));
$serverProviders = ServerProvider::query()->where('provider', $provider)->get();
$serverProviders = ServerProvider::getByProjectId(auth()->user()->current_project_id)
->where('provider', $provider)
->get();
return view('servers.create', [
'serverProviders' => $serverProviders,

View File

@ -3,6 +3,7 @@
namespace App\Http\Controllers\Settings;
use App\Actions\NotificationChannels\AddChannel;
use App\Actions\NotificationChannels\EditChannel;
use App\Facades\Toast;
use App\Helpers\HtmxResponse;
use App\Http\Controllers\Controller;
@ -13,11 +14,17 @@
class NotificationChannelController extends Controller
{
public function index(): View
public function index(Request $request): View
{
return view('settings.notification-channels.index', [
'channels' => NotificationChannel::query()->latest()->get(),
]);
$data = [
'channels' => NotificationChannel::getByProjectId(auth()->user()->current_project_id)->get(),
];
if ($request->has('edit')) {
$data['editChannel'] = NotificationChannel::find($request->input('edit'));
}
return view('settings.notification-channels.index', $data);
}
public function add(Request $request): HtmxResponse
@ -32,6 +39,19 @@ public function add(Request $request): HtmxResponse
return htmx()->redirect(route('settings.notification-channels'));
}
public function update(NotificationChannel $notificationChannel, Request $request): HtmxResponse
{
app(EditChannel::class)->edit(
$notificationChannel,
$request->user(),
$request->input(),
);
Toast::success('Channel updated.');
return htmx()->redirect(route('settings.notification-channels'));
}
public function delete(int $id): RedirectResponse
{
$channel = NotificationChannel::query()->findOrFail($id);

View File

@ -68,7 +68,7 @@ public function delete(Project $project): RedirectResponse
return back();
}
public function switch($projectId): RedirectResponse
public function switch(Request $request, $projectId): RedirectResponse
{
/** @var User $user */
$user = auth()->user();
@ -81,6 +81,11 @@ public function switch($projectId): RedirectResponse
$user->current_project_id = $project->id;
$user->save();
// check if the referer is settings/*
if (str_contains($request->headers->get('referer'), 'settings')) {
return redirect()->to($request->headers->get('referer'));
}
return redirect()->route('servers');
}
}

View File

@ -4,6 +4,7 @@
use App\Actions\ServerProvider\CreateServerProvider;
use App\Actions\ServerProvider\DeleteServerProvider;
use App\Actions\ServerProvider\EditServerProvider;
use App\Facades\Toast;
use App\Helpers\HtmxResponse;
use App\Http\Controllers\Controller;
@ -14,11 +15,17 @@
class ServerProviderController extends Controller
{
public function index(): View
public function index(Request $request): View
{
return view('settings.server-providers.index', [
'providers' => auth()->user()->serverProviders,
]);
$data = [
'providers' => ServerProvider::getByProjectId(auth()->user()->current_project_id)->get(),
];
if ($request->has('edit')) {
$data['editProvider'] = ServerProvider::find($request->input('edit'));
}
return view('settings.server-providers.index', $data);
}
public function connect(Request $request): HtmxResponse
@ -33,6 +40,19 @@ public function connect(Request $request): HtmxResponse
return htmx()->redirect(route('settings.server-providers'));
}
public function update(ServerProvider $serverProvider, Request $request): HtmxResponse
{
app(EditServerProvider::class)->edit(
$serverProvider,
$request->user(),
$request->input(),
);
Toast::success('Provider updated.');
return htmx()->redirect(route('settings.server-providers'));
}
public function delete(ServerProvider $serverProvider): RedirectResponse
{
try {

View File

@ -18,7 +18,7 @@ class SourceControlController extends Controller
public function index(Request $request): View
{
$data = [
'sourceControls' => SourceControl::getByCurrentProject(),
'sourceControls' => SourceControl::getByProjectId(auth()->user()->current_project_id)->get(),
];
if ($request->has('edit')) {

View File

@ -4,6 +4,7 @@
use App\Actions\StorageProvider\CreateStorageProvider;
use App\Actions\StorageProvider\DeleteStorageProvider;
use App\Actions\StorageProvider\EditStorageProvider;
use App\Facades\Toast;
use App\Helpers\HtmxResponse;
use App\Http\Controllers\Controller;
@ -14,11 +15,17 @@
class StorageProviderController extends Controller
{
public function index(): View
public function index(Request $request): View
{
return view('settings.storage-providers.index', [
'providers' => auth()->user()->storageProviders,
]);
$data = [
'providers' => StorageProvider::getByProjectId(auth()->user()->current_project_id)->get(),
];
if ($request->has('edit')) {
$data['editProvider'] = StorageProvider::find($request->input('edit'));
}
return view('settings.storage-providers.index', $data);
}
public function connect(Request $request): HtmxResponse
@ -33,6 +40,19 @@ public function connect(Request $request): HtmxResponse
return htmx()->redirect(route('settings.storage-providers'));
}
public function update(StorageProvider $storageProvider, Request $request): HtmxResponse
{
app(EditStorageProvider::class)->edit(
$storageProvider,
$request->user(),
$request->input(),
);
Toast::success('Provider updated.');
return htmx()->redirect(route('settings.storage-providers'));
}
public function delete(StorageProvider $storageProvider): RedirectResponse
{
try {

View File

@ -20,7 +20,7 @@ class TrustProxies extends Middleware
* @var int
*/
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |

View File

@ -3,7 +3,9 @@
namespace App\Models;
use App\Notifications\NotificationInterface;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Notifications\Notifiable;
/**
@ -12,6 +14,7 @@
* @property array data
* @property string label
* @property bool connected
* @property int $project_id
*/
class NotificationChannel extends AbstractModel
{
@ -24,6 +27,7 @@ class NotificationChannel extends AbstractModel
'data',
'connected',
'is_default',
'project_id',
];
protected $casts = [
@ -47,4 +51,16 @@ public static function notifyAll(NotificationInterface $notification): void
$channel->notify($notification);
}
}
public function project(): BelongsTo
{
return $this->belongsTo(Project::class);
}
public static function getByProjectId(int $projectId): Builder
{
return self::query()
->where('project_id', $projectId)
->orWhereNull('project_id');
}
}

View File

@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
@ -13,6 +14,7 @@
* @property array $credentials
* @property bool $connected
* @property User $user
* @property ?int $project_id
*/
class ServerProvider extends AbstractModel
{
@ -24,12 +26,14 @@ class ServerProvider extends AbstractModel
'provider',
'credentials',
'connected',
'project_id',
];
protected $casts = [
'user_id' => 'integer',
'credentials' => 'encrypted:array',
'connected' => 'boolean',
'project_id' => 'integer',
];
public function user(): BelongsTo
@ -46,4 +50,16 @@ public function servers(): HasMany
{
return $this->hasMany(Server::class, 'provider_id');
}
public function project(): BelongsTo
{
return $this->belongsTo(Project::class);
}
public static function getByProjectId(int $projectId): Builder
{
return self::query()
->where('project_id', $projectId)
->orWhereNull('project_id');
}
}

View File

@ -3,7 +3,7 @@
namespace App\Models;
use App\SourceControlProviders\SourceControlProvider;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
@ -57,10 +57,10 @@ public function project(): BelongsTo
return $this->belongsTo(Project::class);
}
public static function getByCurrentProject(): Collection
public static function getByProjectId(int $projectId): Builder
{
return self::query()
->where('project_id', auth()->user()->current_project_id)
->orWhereNull('project_id')->get();
->where('project_id', $projectId)
->orWhereNull('project_id');
}
}

View File

@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
@ -12,6 +13,7 @@
* @property string $provider
* @property array $credentials
* @property User $user
* @property int $project_id
*/
class StorageProvider extends AbstractModel
{
@ -22,11 +24,13 @@ class StorageProvider extends AbstractModel
'profile',
'provider',
'credentials',
'project_id',
];
protected $casts = [
'user_id' => 'integer',
'credentials' => 'encrypted:array',
'project_id' => 'integer',
];
public function user(): BelongsTo
@ -45,4 +49,16 @@ public function backups(): HasMany
{
return $this->hasMany(Backup::class, 'storage_id');
}
public function project(): BelongsTo
{
return $this->belongsTo(Project::class);
}
public static function getByProjectId(int $projectId): Builder
{
return self::query()
->where('project_id', $projectId)
->orWhereNull('project_id');
}
}

View File

@ -106,24 +106,6 @@ public function storageProvider(string $provider): HasOne
return $this->hasOne(StorageProvider::class)->where('provider', $provider);
}
public function connectedStorageProviders(): HasMany
{
return $this->storageProviders()->where('connected', true);
}
public function connectedSourceControls(): array
{
$connectedSourceControls = [];
$sourceControls = $this->sourceControls()
->where('connected', 1)
->get(['provider']);
foreach ($sourceControls as $sourceControl) {
$connectedSourceControls[] = $sourceControl->provider;
}
return $connectedSourceControls;
}
public function projects(): BelongsToMany
{
return $this->belongsToMany(Project::class, 'user_project')->withTimestamps();
@ -134,11 +116,6 @@ public function currentProject(): HasOne
return $this->HasOne(Project::class, 'id', 'current_project_id');
}
public function isMemberOfProject(Project $project): bool
{
return $project->user_id === $this->id;
}
public function createDefaultProject(): Project
{
$project = $this->projects()->first();

View File

@ -7,7 +7,5 @@
abstract class AbstractNotificationChannel implements NotificationChannelInterface
{
public function __construct(protected NotificationChannel $notificationChannel)
{
}
public function __construct(protected NotificationChannel $notificationChannel) {}
}

View File

@ -7,9 +7,7 @@
class SiteInstallationFailed extends AbstractNotification
{
public function __construct(protected Site $site)
{
}
public function __construct(protected Site $site) {}
public function rawText(): string
{

View File

@ -7,9 +7,7 @@
class SiteInstallationSucceed extends AbstractNotification
{
public function __construct(protected Site $site)
{
}
public function __construct(protected Site $site) {}
public function rawText(): string
{

View File

@ -7,9 +7,7 @@
class SourceControlDisconnected extends AbstractNotification
{
public function __construct(protected SourceControl $sourceControl)
{
}
public function __construct(protected SourceControl $sourceControl) {}
public function rawText(): string
{

View File

@ -6,9 +6,7 @@
class Cron
{
public function __construct(protected Server $server)
{
}
public function __construct(protected Server $server) {}
public function update(string $user, string $cron): void
{

View File

@ -10,9 +10,7 @@ class OS
{
use HasScripts;
public function __construct(protected Server $server)
{
}
public function __construct(protected Server $server) {}
public function installDependencies(): void
{

View File

@ -6,9 +6,7 @@
abstract class AbstractService implements ServiceInterface
{
public function __construct(protected Service $service)
{
}
public function __construct(protected Service $service) {}
public function creationRules(array $input): array
{

View File

@ -0,0 +1,14 @@
wget https://downloads.mariadb.com/MariaDB/mariadb_repo_setup
chmod +x mariadb_repo_setup
sudo DEBIAN_FRONTEND=noninteractive ./mariadb_repo_setup \
--mariadb-server-version="mariadb-10.11"
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install mariadb-server mariadb-backup -y
sudo systemctl unmask mysql.service
sudo service mysql start

View File

@ -0,0 +1,14 @@
wget https://downloads.mariadb.com/MariaDB/mariadb_repo_setup
chmod +x mariadb_repo_setup
sudo DEBIAN_FRONTEND=noninteractive ./mariadb_repo_setup \
--mariadb-server-version="mariadb-10.6"
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install mariadb-server mariadb-backup -y
sudo systemctl unmask mysql.service
sudo service mysql start

View File

@ -0,0 +1,14 @@
wget https://downloads.mariadb.com/MariaDB/mariadb_repo_setup
chmod +x mariadb_repo_setup
sudo DEBIAN_FRONTEND=noninteractive ./mariadb_repo_setup \
--mariadb-server-version="mariadb-11.4"
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install mariadb-server mariadb-backup -y
sudo systemctl unmask mysql.service
sudo service mysql start

View File

@ -4,6 +4,4 @@
use App\SSH\Services\AbstractService;
abstract class AbstractFirewall extends AbstractService implements Firewall
{
}
abstract class AbstractFirewall extends AbstractService implements Firewall {}

View File

@ -102,12 +102,10 @@ public function installComposer(): void
);
}
public function getPHPIni(): string
public function getPHPIni(string $type): string
{
return $this->service->server->ssh()->exec(
$this->getScript('get-php-ini.sh', [
'version' => $this->service->version,
])
return $this->service->server->os()->readFile(
sprintf('/etc/php/%s/%s/php.ini', $this->service->version, $type)
);
}
}

View File

@ -1,3 +0,0 @@
if ! cat /etc/php/__version__/cli/php.ini; then
echo 'VITO_SSH_ERROR' && exit 1
fi

View File

@ -4,6 +4,4 @@
use App\SSH\Services\AbstractService;
abstract class AbstractWebserver extends AbstractService implements Webserver
{
}
abstract class AbstractWebserver extends AbstractService implements Webserver {}

View File

@ -27,6 +27,7 @@ server {
fastcgi_pass unix:/var/run/php/php__php_version__-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
location ~ /\.(?!well-known).* {

View File

@ -23,6 +23,7 @@ server {
fastcgi_pass unix:/var/run/php/php__php_version__-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
location ~ /\.(?!well-known).* {

View File

@ -7,7 +7,5 @@
abstract class AbstractStorage implements Storage
{
public function __construct(protected Server $server, protected StorageProvider $storageProvider)
{
}
public function __construct(protected Server $server, protected StorageProvider $storageProvider) {}
}

View File

@ -6,9 +6,7 @@
class Systemd
{
public function __construct(protected Server $server)
{
}
public function __construct(protected Server $server) {}
public function status(string $unit): string
{

View File

@ -2,6 +2,4 @@
namespace App\SiteTypes;
class Laravel extends PHPSite
{
}
class Laravel extends PHPSite {}

View File

@ -3,9 +3,9 @@
namespace App\ValidationRules;
use Cron\CronExpression;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\ValidationRule;
class CronRule implements Rule
class CronRule implements ValidationRule
{
private bool $acceptCustom;
@ -14,13 +14,14 @@ public function __construct(bool $acceptCustom = false)
$this->acceptCustom = $acceptCustom;
}
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, \Closure $fail): void
{
return CronExpression::isValidExpression($value) || ($this->acceptCustom && $value === 'custom');
}
public function message(): string
{
return __('Invalid frequency');
if (CronExpression::isValidExpression($value)) {
return;
}
if ($this->acceptCustom && $value === 'custom') {
return;
}
$fail('Invalid frequency')->translate();
}
}

View File

@ -2,21 +2,19 @@
namespace App\ValidationRules;
use Illuminate\Contracts\Validation\Rule;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class DomainRule implements Rule
class DomainRule implements ValidationRule
{
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if ($value) {
return preg_match("/^(?!\-)(?:[a-zA-Z\d\-]{0,62}[a-zA-Z\d]\.){1,126}(?!\d+)[a-zA-Z\d]{1,63}$/", $value);
if (! $value) {
return;
}
return true;
}
public function message(): string
{
return __('Domain is not valid');
if (preg_match("/^(?!\-)(?:[a-zA-Z\d\-]{0,62}[a-zA-Z\d]\.){1,126}(?!\d+)[a-zA-Z\d]{1,63}$/", $value) === 1) {
return;
}
$fail('Domain is not valid')->translate();
}
}

View File

@ -2,27 +2,16 @@
namespace App\ValidationRules;
use Illuminate\Contracts\Validation\Rule;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class RestrictedIPAddressesRule implements Rule
class RestrictedIPAddressesRule implements ValidationRule
{
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
public function validate(string $attribute, mixed $value, Closure $fail): void
{
return ! in_array($value, config('core.restricted_ip_addresses'));
}
/**
* @return array|\Illuminate\Contracts\Translation\Translator|string|null
*/
public function message()
{
return __('IP address is restricted.');
if (! in_array($value, config('core.restricted_ip_addresses'))) {
return;
}
$fail('IP address is restricted')->translate();
}
}

View File

@ -2,35 +2,21 @@
namespace App\ValidationRules;
use Illuminate\Contracts\Validation\Rule;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Exception\NoKeyLoadedException;
class SshKeyRule implements Rule
class SshKeyRule implements ValidationRule
{
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
public function validate(string $attribute, mixed $value, Closure $fail): void
{
try {
PublicKeyLoader::load($value);
return true;
} catch (NoKeyLoadedException $e) {
return false;
return;
} catch (NoKeyLoadedException) {
$fail('Invalid key')->translate();
}
}
/**
* @return array|\Illuminate\Contracts\Translation\Translator|string|null
*/
public function message()
{
return __('Invalid key');
}
}

View File

@ -8,9 +8,7 @@
class ServerLayout extends Component
{
public function __construct(public Server $server)
{
}
public function __construct(public Server $server) {}
public function render(): View
{

View File

@ -8,9 +8,7 @@
class SiteLayout extends Component
{
public function __construct(public Site $site)
{
}
public function __construct(public Site $site) {}
public function render(): View
{

View File

@ -12,7 +12,7 @@
"ext-ftp": "*",
"aws/aws-sdk-php": "^3.158",
"laravel/fortify": "^1.17",
"laravel/framework": "^10.0",
"laravel/framework": "^11.0",
"laravel/tinker": "^2.8",
"phpseclib/phpseclib": "~3.0"
},
@ -21,7 +21,7 @@
"laravel/pint": "^1.10",
"laravel/sail": "^1.18",
"mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^7.0",
"nunomaduro/collision": "^8.1",
"phpunit/phpunit": "^10.0",
"spatie/laravel-ignition": "^2.0"
},

1386
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,9 @@
'mysql80',
'mariadb103',
'mariadb104',
'mariadb106',
'mariadb1011',
'mariadb114',
'postgresql12',
'postgresql13',
'postgresql14',
@ -50,6 +53,9 @@
'mysql80' => 'mysql',
'mariadb103' => 'mariadb',
'mariadb104' => 'mariadb',
'mariadb106' => 'mariadb',
'mariadb1011' => 'mariadb',
'mariadb114' => 'mariadb',
'postgresql12' => 'postgresql',
'postgresql13' => 'postgresql',
'postgresql14' => 'postgresql',
@ -63,6 +69,9 @@
'mariadb' => '10.3',
'mariadb103' => '10.3',
'mariadb104' => '10.4',
'mariadb106' => '10.6',
'mariadb1011' => '10.11',
'mariadb114' => '11.4',
'postgresql12' => '12',
'postgresql13' => '13',
'postgresql14' => '14',
@ -193,14 +202,23 @@
\App\Enums\OperatingSystem::UBUNTU20 => [
'10.3' => 'mariadb',
'10.4' => 'mariadb',
'10.6' => 'mariadb',
'10.11' => 'mariadb',
'11.4' => 'mariadb',
],
\App\Enums\OperatingSystem::UBUNTU22 => [
'10.3' => 'mariadb',
'10.4' => 'mariadb',
'10.6' => 'mariadb',
'10.11' => 'mariadb',
'11.4' => 'mariadb',
],
\App\Enums\OperatingSystem::UBUNTU24 => [
'10.3' => 'mariadb',
'10.4' => 'mariadb',
'10.6' => 'mariadb',
'10.11' => 'mariadb',
'11.4' => 'mariadb',
],
],
'postgresql' => [

View File

@ -1,29 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->string('profile_photo_path', 2048)->nullable();
$table->text('two_factor_secret')->nullable();
$table->text('two_factor_recovery_codes')->nullable();
$table->string('timezone')->default('UTC')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('users');
}
}

View File

@ -1,22 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePasswordResetsTable extends Migration
{
public function up(): void
{
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->index();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
}
public function down(): void
{
Schema::dropIfExists('password_reset_tokens');
}
}

View File

@ -1,70 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Get the migration connection name.
*/
public function getConnection(): ?string
{
return config('telescope.storage.database.connection');
}
/**
* Run the migrations.
*/
public function up(): void
{
$schema = Schema::connection($this->getConnection());
$schema->create('telescope_entries', function (Blueprint $table) {
$table->bigIncrements('sequence');
$table->uuid('uuid');
$table->uuid('batch_id');
$table->string('family_hash')->nullable();
$table->boolean('should_display_on_index')->default(true);
$table->string('type', 20);
$table->longText('content');
$table->dateTime('created_at')->nullable();
$table->unique('uuid');
$table->index('batch_id');
$table->index('family_hash');
$table->index('created_at');
$table->index(['type', 'should_display_on_index']);
});
$schema->create('telescope_entries_tags', function (Blueprint $table) {
$table->uuid('entry_uuid');
$table->string('tag');
$table->primary(['entry_uuid', 'tag']);
$table->index('tag');
$table->foreign('entry_uuid')
->references('uuid')
->on('telescope_entries')
->onDelete('cascade');
});
$schema->create('telescope_monitoring', function (Blueprint $table) {
$table->string('tag')->primary();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
$schema = Schema::connection($this->getConnection());
$schema->dropIfExists('telescope_entries_tags');
$schema->dropIfExists('telescope_entries');
$schema->dropIfExists('telescope_monitoring');
}
};

View File

@ -1,26 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
}
public function down(): void
{
Schema::dropIfExists('failed_jobs');
}
};

View File

@ -1,27 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->string('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamp('expires_at')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('personal_access_tokens');
}
};

View File

@ -1,25 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->text('payload');
$table->integer('last_activity')->index();
});
}
public function down(): void
{
Schema::dropIfExists('sessions');
}
};

View File

@ -1,38 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('servers', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->string('name')->index();
$table->string('ssh_user')->nullable();
$table->ipAddress('ip')->index()->nullable();
$table->ipAddress('local_ip')->nullable();
$table->unsignedInteger('provider_id')->nullable();
$table->integer('port')->default(22);
$table->string('os');
$table->string('type');
$table->json('type_data')->nullable();
$table->string('provider');
$table->json('provider_data')->nullable();
$table->longText('authentication')->nullable();
$table->longText('public_key')->nullable();
$table->string('status')->default('installing');
$table->integer('progress')->default(0);
$table->string('progress_step')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('servers');
}
};

View File

@ -1,30 +0,0 @@
<?php
use App\Enums\ServiceStatus;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('services', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('server_id');
$table->string('type');
$table->json('type_data')->nullable();
$table->string('name');
$table->string('version');
$table->string('status')->default(ServiceStatus::INSTALLING);
$table->boolean('is_default')->default(1);
$table->string('unit')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('services');
}
};

View File

@ -1,26 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('jobs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('queue')->index();
$table->longText('payload');
$table->integer('attempts');
$table->integer('reserved_at')->nullable();
$table->integer('available_at');
$table->integer('created_at');
});
}
public function down(): void
{
Schema::dropIfExists('jobs');
}
};

View File

@ -1,26 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('server_logs', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('server_id');
$table->unsignedBigInteger('site_id')->nullable();
$table->string('type');
$table->string('name');
$table->string('disk');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('server_logs');
}
};

View File

@ -1,35 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('sites', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('server_id')->index();
$table->string('type');
$table->json('type_data')->nullable();
$table->string('domain')->index();
$table->json('aliases')->nullable();
$table->string('web_directory')->nullable();
$table->string('path');
$table->string('php_version')->nullable();
$table->string('source_control')->nullable();
$table->string('repository')->nullable();
$table->string('branch')->nullable();
$table->integer('port')->nullable();
$table->string('status')->default('installing');
$table->integer('progress')->default(0)->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('sites');
}
};

View File

@ -1,24 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('source_controls', function (Blueprint $table) {
$table->id();
$table->string('provider');
$table->json('provider_data')->nullable();
$table->longText('access_token')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('source_controls');
}
};

View File

@ -1,27 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('deployments', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('site_id');
$table->unsignedBigInteger('deployment_script_id');
$table->unsignedInteger('log_id')->nullable();
$table->json('commit_data')->nullable();
$table->string('commit_id')->nullable();
$table->string('status');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('deployments');
}
};

View File

@ -1,25 +0,0 @@
<?php
use App\Enums\DatabaseStatus;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('databases', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('server_id');
$table->string('name');
$table->string('status')->default(DatabaseStatus::CREATING);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('databases');
}
};

View File

@ -1,28 +0,0 @@
<?php
use App\Enums\DatabaseUserStatus;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('database_users', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('server_id');
$table->string('username');
$table->longText('password')->nullable();
$table->json('databases')->nullable();
$table->string('host')->default('localhost');
$table->string('status')->default(DatabaseUserStatus::CREATING);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('database_users');
}
};

View File

@ -1,29 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('firewall_rules', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('server_id');
$table->string('type');
$table->string('protocol');
$table->integer('port');
$table->ipAddress('source')->default('0.0.0.0');
$table->string('mask')->nullable();
$table->text('note')->nullable();
$table->string('status')->default('creating');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('firewall_rules');
}
};

View File

@ -1,27 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('cron_jobs', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('server_id');
$table->text('command');
$table->string('user');
$table->string('frequency');
$table->boolean('hidden')->default(0);
$table->string('status');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('cron_jobs');
}
};

View File

@ -1,24 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('deployment_scripts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('site_id');
$table->string('name')->nullable();
$table->longText('content')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('deployment_scripts');
}
};

View File

@ -1,29 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('ssls', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('site_id');
$table->string('type')->default('letsencrypt');
$table->string('domains')->nullable();
$table->longText('certificate')->nullable();
$table->longText('pk')->nullable();
$table->longText('ca')->nullable();
$table->timestamp('expires_at');
$table->string('status');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('ssls');
}
};

View File

@ -1,26 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('redirects', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('site_id');
$table->integer('mode');
$table->text('from');
$table->text('to');
$table->string('status')->default('creating');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('redirects');
}
};

View File

@ -1,31 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('queues', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('server_id')->nullable();
$table->unsignedBigInteger('site_id');
$table->text('command');
$table->string('user');
$table->boolean('auto_start')->default(1);
$table->boolean('auto_restart')->default(1);
$table->integer('numprocs')->default(8);
$table->boolean('redirect_stderr')->default(1);
$table->string('stdout_logfile')->nullable();
$table->string('status');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('queues');
}
};

View File

@ -1,24 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('ssh_keys', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->string('name');
$table->longText('public_key');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('ssh_keys');
}
};

View File

@ -1,24 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('server_ssh_keys', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('server_id');
$table->unsignedBigInteger('ssh_key_id');
$table->string('status');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('server_ssh_keys');
}
};

View File

@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('git_hooks', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('site_id');
$table->unsignedBigInteger('source_control_id');
$table->string('secret')->unique()->index();
$table->json('events');
$table->json('actions');
$table->string('hook_id')->nullable();
$table->json('hook_response')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('git_hooks');
}
};

View File

@ -1,26 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('server_providers', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->string('profile')->nullable();
$table->string('provider');
$table->longText('credentials');
$table->boolean('connected')->default(1);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('server_providers');
}
};

View File

@ -1,24 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('scripts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->string('name');
$table->longText('content');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('scripts');
}
};

View File

@ -1,25 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('script_executions', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('script_id');
$table->unsignedBigInteger('server_id');
$table->string('user')->nullable();
$table->timestamp('finished_at')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('script_executions');
}
};

View File

@ -1,26 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('notification_channels', function (Blueprint $table) {
$table->id();
$table->string('provider');
$table->string('label');
$table->json('data')->nullable();
$table->boolean('connected')->default(false);
$table->boolean('is_default')->default(false);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('notification_channels');
}
};

View File

@ -1,27 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateStorageProvidersTable extends Migration
{
public function up(): void
{
Schema::create('storage_providers', function (Blueprint $table) {
$table->id();
$table->string('provider');
$table->string('label')->nullable();
$table->string('token', 1000)->nullable();
$table->string('refresh_token', 1000)->nullable();
$table->boolean('connected')->default(1);
$table->timestamp('token_expires_at')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('storage_providers');
}
}

View File

@ -1,29 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('backups', function (Blueprint $table) {
$table->id();
$table->string('type');
$table->string('name');
$table->unsignedBigInteger('server_id');
$table->unsignedBigInteger('storage_id');
$table->unsignedBigInteger('database_id')->nullable();
$table->string('interval');
$table->bigInteger('keep_backups');
$table->string('status');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('backups');
}
};

View File

@ -1,26 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('backup_files', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('backup_id');
$table->string('name');
$table->bigInteger('size')->nullable();
$table->string('status');
$table->timestamp('restored_at')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('backup_files');
}
};

View File

@ -1,19 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
public function up(): void
{
if (DB::getDriverName() === 'mysql') {
DB::statement('ALTER TABLE firewall_rules MODIFY mask varchar(10) null');
}
}
public function down(): void
{
//
}
};

View File

@ -1,22 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('sites', function (Blueprint $table) {
$table->longText('ssh_key')->nullable()->after('repository');
});
}
public function down(): void
{
Schema::table('sites', function (Blueprint $table) {
$table->dropColumn('ssh_key');
});
}
};

View File

@ -1,22 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('source_controls', function (Blueprint $table) {
$table->string('profile')->after('provider')->nullable();
});
}
public function down(): void
{
Schema::table('source_controls', function (Blueprint $table) {
$table->dropColumn('profile');
});
}
};

View File

@ -1,22 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('sites', function (Blueprint $table) {
$table->unsignedBigInteger('source_control_id')->nullable()->after('source_control');
});
}
public function down(): void
{
Schema::table('sites', function (Blueprint $table) {
$table->dropColumn('source_control_id');
});
}
};

View File

@ -1,33 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('storage_providers', function (Blueprint $table) {
$table->unsignedBigInteger('user_id')->after('id');
$table->string('profile')->after('user_id');
$table->longText('credentials')->nullable()->after('provider');
});
Schema::table('storage_providers', function (Blueprint $table) {
$table->dropColumn(['token', 'refresh_token', 'token_expires_at', 'label', 'connected']);
});
}
public function down(): void
{
Schema::table('storage_providers', function (Blueprint $table) {
$table->string('token')->nullable();
$table->string('refresh_token')->nullable();
$table->string('token_expires_at')->nullable();
$table->string('label')->nullable();
});
Schema::table('storage_providers', function (Blueprint $table) {
$table->dropColumn(['user_id', 'profile', 'credentials']);
});
}
};

View File

@ -1,22 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('backups', function (Blueprint $table) {
$table->dropColumn('name');
});
}
public function down(): void
{
Schema::table('backups', function (Blueprint $table) {
$table->string('name')->nullable();
});
}
};

View File

@ -1,22 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('backup_files', function (Blueprint $table) {
$table->string('restored_to')->after('status')->nullable();
});
}
public function down(): void
{
Schema::table('backup_files', function (Blueprint $table) {
$table->dropColumn('restored_to');
});
}
};

View File

@ -1,32 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->timestamp('two_factor_confirmed_at')
->after('two_factor_recovery_codes')
->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn([
'two_factor_confirmed_at',
]);
});
}
};

View File

@ -1,23 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('projects', function (Blueprint $table) {
$table->id();
$table->bigInteger('user_id');
$table->string('name');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('projects');
}
};

View File

@ -1,27 +0,0 @@
<?php
use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->unsignedBigInteger('current_project_id')->nullable()->after('timezone');
});
User::query()->each(function (User $user) {
$project = $user->createDefaultProject();
$user->servers()->update(['project_id' => $project->id]);
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('current_project_id');
});
}
};

View File

@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('server_logs', function (Blueprint $table) {
$table->boolean('is_remote')->default(false);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('server_logs', function (Blueprint $table) {
$table->dropColumn('is_remote');
});
}
};

View File

@ -1,37 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('metrics', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('server_id');
$table->decimal('load', 5, 2);
$table->decimal('memory_total', 15, 0);
$table->decimal('memory_used', 15, 0);
$table->decimal('memory_free', 15, 0);
$table->decimal('disk_total', 15, 0);
$table->decimal('disk_used', 15, 0);
$table->decimal('disk_free', 15, 0);
$table->timestamps();
$table->index(['server_id', 'created_at']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('metrics');
}
};

View File

@ -1,31 +0,0 @@
<?php
use App\Enums\UserRole;
use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('role')->default(UserRole::USER);
});
User::query()->update(['role' => UserRole::ADMIN]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('role');
});
}
};

View File

@ -1,38 +0,0 @@
<?php
use App\Models\Project;
use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('user_project', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('project_id');
$table->timestamps();
});
Project::all()->each(function (Project $project) {
$project->users()->attach($project->user_id);
});
User::all()->each(function (User $user) {
$user->current_project_id = $user->projects()->first()?->id;
$user->save();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('user_project');
}
};

Some files were not shown because too many files have changed in this diff Show More