diff --git a/README.md b/README.md
index 970203cd..e90cb564 100644
--- a/README.md
+++ b/README.md
@@ -54,3 +54,4 @@ ## Credits
- Prettier
- Postcss
- Flowbite
+- svgrepo.com
diff --git a/app/Actions/Service/Create.php b/app/Actions/Service/Create.php
new file mode 100644
index 00000000..bfb75cc8
--- /dev/null
+++ b/app/Actions/Service/Create.php
@@ -0,0 +1,55 @@
+validate($server, $input);
+
+ $service = new Service([
+ 'name' => $input['type'],
+ 'type' => $input['type'],
+ 'version' => $input['version'],
+ 'status' => ServiceStatus::INSTALLING,
+ ]);
+
+ Validator::make($input, $service->handler()->creationRules($input))->validate();
+
+ $service->type_data = $service->handler()->creationData($input);
+
+ $service->save();
+
+ $service->handler()->create();
+
+ dispatch(function () use ($service) {
+ $service->handler()->install();
+ $service->status = ServiceStatus::READY;
+ $service->save();
+ })->catch(function () use ($service) {
+ $service->handler()->delete();
+ $service->delete();
+ })->onConnection('ssh');
+
+ return $service;
+ }
+
+ private function validate(Server $server, array $input): void
+ {
+ Validator::make($input, [
+ 'type' => [
+ 'required',
+ Rule::in(config('core.add_on_services')),
+ Rule::unique('services', 'type')->where('server_id', $server->id),
+ ],
+ 'version' => 'required',
+ ])->validate();
+ }
+}
diff --git a/app/Enums/SiteType.php b/app/Enums/SiteType.php
index 128d3f6a..21d4a367 100644
--- a/app/Enums/SiteType.php
+++ b/app/Enums/SiteType.php
@@ -11,4 +11,6 @@ final class SiteType
const LARAVEL = 'laravel';
const WORDPRESS = 'wordpress';
+
+ const PHPMYADMIN = 'phpmyadmin';
}
diff --git a/app/Http/Controllers/ServiceController.php b/app/Http/Controllers/ServiceController.php
index 6a5e7ce1..6969126f 100644
--- a/app/Http/Controllers/ServiceController.php
+++ b/app/Http/Controllers/ServiceController.php
@@ -2,11 +2,14 @@
namespace App\Http\Controllers;
+use App\Actions\Service\Create;
use App\Facades\Toast;
+use App\Helpers\HtmxResponse;
use App\Models\Server;
use App\Models\Service;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
+use Illuminate\Http\Request;
class ServiceController extends Controller
{
@@ -62,4 +65,13 @@ public function disable(Server $server, Service $service): RedirectResponse
return back();
}
+
+ public function install(Server $server, Request $request): HtmxResponse
+ {
+ app(Create::class)->create($server, $request->input());
+
+ Toast::success('Service is being uninstalled!');
+
+ return htmx()->back();
+ }
}
diff --git a/app/Models/Service.php b/app/Models/Service.php
index 6c30d880..4516ae24 100755
--- a/app/Models/Service.php
+++ b/app/Models/Service.php
@@ -4,6 +4,7 @@
use App\Actions\Service\Manage;
use App\Exceptions\ServiceInstallationFailed;
+use App\SSH\Services\AddOnServices\AbstractAddOnService;
use App\SSH\Services\Database\Database as DatabaseHandler;
use App\SSH\Services\Firewall\Firewall as FirewallHandler;
use App\SSH\Services\PHP\PHP as PHPHandler;
@@ -53,7 +54,9 @@ public static function boot(): void
parent::boot();
static::creating(function (Service $service) {
- $service->unit = config('core.service_units')[$service->name][$service->server->os][$service->version];
+ if (array_key_exists($service->name, config('core.service_units'))) {
+ $service->unit = config('core.service_units')[$service->name][$service->server->os][$service->version];
+ }
});
}
@@ -63,7 +66,7 @@ public function server(): BelongsTo
}
public function handler(
- ): PHPHandler|WebserverHandler|DatabaseHandler|FirewallHandler|ProcessManagerHandler|RedisHandler {
+ ): PHPHandler|WebserverHandler|DatabaseHandler|FirewallHandler|ProcessManagerHandler|RedisHandler|AbstractAddOnService {
$handler = config('core.service_handlers')[$this->name];
return new $handler($this);
@@ -81,26 +84,26 @@ public function validateInstall($result): void
public function start(): void
{
- app(Manage::class)->start($this);
+ $this->unit && app(Manage::class)->start($this);
}
public function stop(): void
{
- app(Manage::class)->stop($this);
+ $this->unit && app(Manage::class)->stop($this);
}
public function restart(): void
{
- app(Manage::class)->restart($this);
+ $this->unit && app(Manage::class)->restart($this);
}
public function enable(): void
{
- app(Manage::class)->enable($this);
+ $this->unit && app(Manage::class)->enable($this);
}
public function disable(): void
{
- app(Manage::class)->disable($this);
+ $this->unit && app(Manage::class)->disable($this);
}
}
diff --git a/app/SSH/OS/OS.php b/app/SSH/OS/OS.php
index fe0befb9..87dc0ac1 100644
--- a/app/SSH/OS/OS.php
+++ b/app/SSH/OS/OS.php
@@ -131,4 +131,21 @@ public function runScript(string $path, string $script, ?int $siteId = null): Se
return $ssh->log;
}
+
+ public function download(string $url, string $path): string
+ {
+ return $this->server->ssh()->exec(
+ $this->getScript('download.sh', [
+ 'url' => $url,
+ 'path' => $path,
+ ])
+ );
+ }
+
+ public function unzip(string $path): string
+ {
+ return $this->server->ssh()->exec(
+ 'unzip '.$path
+ );
+ }
}
diff --git a/app/SSH/OS/scripts/download.sh b/app/SSH/OS/scripts/download.sh
new file mode 100644
index 00000000..c5a7c7bc
--- /dev/null
+++ b/app/SSH/OS/scripts/download.sh
@@ -0,0 +1,3 @@
+if ! wget __url__ -O __path__; then
+ echo 'VITO_SSH_ERROR' && exit 1
+fi
diff --git a/app/SSH/PHPMyAdmin/PHPMyAdmin.php b/app/SSH/PHPMyAdmin/PHPMyAdmin.php
new file mode 100644
index 00000000..a8160fd1
--- /dev/null
+++ b/app/SSH/PHPMyAdmin/PHPMyAdmin.php
@@ -0,0 +1,23 @@
+server->ssh()->exec(
+ $this->getScript('install.sh', [
+ 'version' => $site->type_data['version'],
+ 'path' => $site->path,
+ ]),
+ 'install-phpmyadmin',
+ $site->id
+ );
+ }
+}
diff --git a/app/SSH/PHPMyAdmin/scripts/install.sh b/app/SSH/PHPMyAdmin/scripts/install.sh
new file mode 100755
index 00000000..34b7cf01
--- /dev/null
+++ b/app/SSH/PHPMyAdmin/scripts/install.sh
@@ -0,0 +1,25 @@
+sudo rm -rf phpmyadmin
+
+sudo rm -rf __path__
+
+if ! wget https://files.phpmyadmin.net/phpMyAdmin/__version__/phpMyAdmin-__version__-all-languages.zip; then
+ echo 'VITO_SSH_ERROR' && exit 1
+fi
+
+if ! unzip phpMyAdmin-__version__-all-languages.zip; then
+ echo 'VITO_SSH_ERROR' && exit 1
+fi
+
+if ! rm -rf phpMyAdmin-__version__-all-languages.zip; then
+ echo 'VITO_SSH_ERROR' && exit 1
+fi
+
+if ! mv phpMyAdmin-__version__-all-languages __path__; then
+ echo 'VITO_SSH_ERROR' && exit 1
+fi
+
+if ! mv __path__/config.sample.inc.php __path__/config.inc.php; then
+ echo 'VITO_SSH_ERROR' && exit 1
+fi
+
+echo "PHPMyAdmin installed!"
diff --git a/app/SSH/Services/AddOnServices/AbstractAddOnService.php b/app/SSH/Services/AddOnServices/AbstractAddOnService.php
new file mode 100644
index 00000000..442ae168
--- /dev/null
+++ b/app/SSH/Services/AddOnServices/AbstractAddOnService.php
@@ -0,0 +1,18 @@
+ [
+ 'required',
+ Rule::in($this->site->server->installedPHPVersions()),
+ ],
+ 'version' => 'required|string',
+ ];
+ }
+
+ public function createFields(array $input): array
+ {
+ return [
+ 'web_directory' => '',
+ 'php_version' => $input['php_version'] ?? '',
+ ];
+ }
+
+ public function data(array $input): array
+ {
+ return [
+ 'version' => $input['version'],
+ ];
+ }
+
+ public function install(): void
+ {
+ $this->site->server->webserver()->handler()->createVHost($this->site);
+ $this->progress(30);
+ app(\App\SSH\PHPMyAdmin\PHPMyAdmin::class)->install($this->site);
+ $this->progress(65);
+ }
+}
diff --git a/config/core.php b/config/core.php
index 4068070e..02843c8f 100755
--- a/config/core.php
+++ b/config/core.php
@@ -13,6 +13,7 @@
use App\ServerProviders\Vultr;
use App\SiteTypes\Laravel;
use App\SiteTypes\PHPBlank;
+use App\SiteTypes\PHPMyAdmin;
use App\SiteTypes\PHPSite;
use App\SiteTypes\Wordpress;
use App\SourceControlProviders\Bitbucket;
@@ -177,6 +178,9 @@
'ufw' => Ufw::class,
'supervisor' => Supervisor::class,
],
+ 'add_on_services' => [
+ // add-on services
+ ],
'service_units' => [
'nginx' => [
'ubuntu_18' => [
@@ -320,12 +324,14 @@
\App\Enums\SiteType::PHP_BLANK,
\App\Enums\SiteType::LARAVEL,
\App\Enums\SiteType::WORDPRESS,
+ \App\Enums\SiteType::PHPMYADMIN,
],
'site_types_class' => [
\App\Enums\SiteType::PHP => PHPSite::class,
\App\Enums\SiteType::PHP_BLANK => PHPBlank::class,
\App\Enums\SiteType::LARAVEL => Laravel::class,
\App\Enums\SiteType::WORDPRESS => Wordpress::class,
+ \App\Enums\SiteType::PHPMYADMIN => PHPMyAdmin::class,
],
/*
diff --git a/public/static/images/supervisor.svg b/public/static/images/supervisor.svg
index 40866cd0..3203fe52 100644
--- a/public/static/images/supervisor.svg
+++ b/public/static/images/supervisor.svg
@@ -1 +1,9 @@
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/public/static/images/ufw.svg b/public/static/images/ufw.svg
index 0cf1d561..2843aa38 100644
--- a/public/static/images/ufw.svg
+++ b/public/static/images/ufw.svg
@@ -1 +1,9 @@
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/resources/views/application/phpmyadmin-app.blade.php b/resources/views/application/phpmyadmin-app.blade.php
new file mode 100644
index 00000000..48133ac4
--- /dev/null
+++ b/resources/views/application/phpmyadmin-app.blade.php
@@ -0,0 +1,6 @@
+
+
+ PHPMyAdmin is installed and ready to use!
+ Open
+
+
diff --git a/resources/views/application/wordpress-app.blade.php b/resources/views/application/wordpress-app.blade.php
index 7cb80a65..eb08473b 100644
--- a/resources/views/application/wordpress-app.blade.php
+++ b/resources/views/application/wordpress-app.blade.php
@@ -3,7 +3,7 @@
{{ __("Your Wordpress site is installed and ready to use! ") }}
-
+
{{ __("Open Website") }}
diff --git a/resources/views/components/heroicons/o-no-symbol.blade.php b/resources/views/components/heroicons/o-no-symbol.blade.php
new file mode 100644
index 00000000..bc8cf23c
--- /dev/null
+++ b/resources/views/components/heroicons/o-no-symbol.blade.php
@@ -0,0 +1,14 @@
+
diff --git a/resources/views/components/icon-button.blade.php b/resources/views/components/icon-button.blade.php
index 433ba864..7fe0ca30 100644
--- a/resources/views/components/icon-button.blade.php
+++ b/resources/views/components/icon-button.blade.php
@@ -1,5 +1,6 @@
@props([
"href",
+ "disabled" => false,
])
@php
@@ -7,12 +8,12 @@
"inline-flex w-max items-center justify-center px-2 py-1 font-semibold capitalize outline-0 transition hover:opacity-50 focus:ring focus:ring-primary-200 disabled:opacity-25 dark:focus:ring-primary-700 dark:focus:ring-opacity-40";
@endphp
-@if (isset($href))
+@if (isset($href) && ! $disabled)
merge(["class" => $class]) }}>
{{ $slot }}
@else
-